Imported Upstream version 1.1.11 upstream upstream/1.1.11
authorPhilippe Coval <philippe.coval@eurogiciel.fr>
Fri, 1 Mar 2013 10:33:00 +0000 (11:33 +0100)
committerPhilippe Coval <philippe.coval@eurogiciel.fr>
Fri, 1 Mar 2013 10:33:00 +0000 (11:33 +0100)
581 files changed:
3rd-party/dirsplit/CMakeLists.txt [new file with mode: 0644]
3rd-party/dirsplit/ChangeLog [new file with mode: 0644]
3rd-party/dirsplit/README [new file with mode: 0644]
3rd-party/dirsplit/dirsplit [new file with mode: 0755]
3rd-party/dirsplit/dirsplit.1 [new file with mode: 0644]
3rd-party/geteltorito.1 [new file with mode: 0644]
3rd-party/geteltorito/README.geteltorito [new file with mode: 0644]
3rd-party/geteltorito/geteltorito.pl [new file with mode: 0644]
3rd-party/zisofs_tools/CHANGES [new file with mode: 0644]
3rd-party/zisofs_tools/CMakeLists.txt [new file with mode: 0644]
3rd-party/zisofs_tools/COPYING [new file with mode: 0644]
3rd-party/zisofs_tools/INSTALL [new file with mode: 0644]
3rd-party/zisofs_tools/MCONFIG.in [new file with mode: 0644]
3rd-party/zisofs_tools/MRULES [new file with mode: 0644]
3rd-party/zisofs_tools/Makefile [new file with mode: 0644]
3rd-party/zisofs_tools/README [new file with mode: 0644]
3rd-party/zisofs_tools/aclocal.m4 [new file with mode: 0644]
3rd-party/zisofs_tools/compress.c [new file with mode: 0644]
3rd-party/zisofs_tools/config.h.in [new file with mode: 0644]
3rd-party/zisofs_tools/configure [new file with mode: 0755]
3rd-party/zisofs_tools/configure.in [new file with mode: 0644]
3rd-party/zisofs_tools/copytime.c [new file with mode: 0644]
3rd-party/zisofs_tools/hash.c [new file with mode: 0644]
3rd-party/zisofs_tools/install-sh [new file with mode: 0644]
3rd-party/zisofs_tools/iso9660.c [new file with mode: 0644]
3rd-party/zisofs_tools/iso9660.h [new file with mode: 0644]
3rd-party/zisofs_tools/mkzftree.1 [new file with mode: 0644]
3rd-party/zisofs_tools/mkzftree.c [new file with mode: 0644]
3rd-party/zisofs_tools/mkzftree.h [new file with mode: 0644]
3rd-party/zisofs_tools/uncompress.c [new file with mode: 0644]
3rd-party/zisofs_tools/util.c [new file with mode: 0644]
3rd-party/zisofs_tools/version [new file with mode: 0644]
3rd-party/zisofs_tools/walk.c [new file with mode: 0644]
3rd-party/zisofs_tools/workers.c [new file with mode: 0644]
3rd-party/zisofs_tools/zisofs-tools.spec [new file with mode: 0644]
3rd-party/zisofs_tools/zisofs-tools.spec.in [new file with mode: 0644]
3rd-party/zisofs_tools/zisofs.magic [new file with mode: 0644]
ABOUT [new file with mode: 0644]
CMakeLists.txt [new file with mode: 0644]
COPYING [new file with mode: 0644]
Changelog [new file with mode: 0644]
FAQ [new file with mode: 0644]
FORK [new file with mode: 0644]
INSTALL [new file with mode: 0644]
Makefile [new file with mode: 0644]
START [new file with mode: 0644]
TODO [new file with mode: 0644]
VERSION [new file with mode: 0644]
doc/ANNOUNCEMENTs/AN-2.0 [new file with mode: 0644]
doc/ANNOUNCEMENTs/AN-2.01 [new file with mode: 0644]
doc/ANNOUNCEMENTs/AN-2.01.01a01 [new file with mode: 0644]
doc/ANNOUNCEMENTs/AN-2.01.01a03 [new file with mode: 0644]
doc/ANNOUNCEMENTs/AN-2.01.01a04 [new file with mode: 0644]
doc/ANNOUNCEMENTs/AN-2.01.01a05 [new file with mode: 0644]
doc/ANNOUNCEMENTs/AN-2.01.01a06 [new file with mode: 0644]
doc/ANNOUNCEMENTs/AN-2.01.01a07 [new file with mode: 0644]
doc/ANNOUNCEMENTs/AN-2.01.01a08 [new file with mode: 0644]
doc/DOC-OVERVIEW [new file with mode: 0644]
doc/PORTABILITY [new file with mode: 0644]
doc/READMEs/README.ATAPI [new file with mode: 0644]
doc/READMEs/README.ATAPI.setup [new file with mode: 0644]
doc/READMEs/README.audio [new file with mode: 0644]
doc/READMEs/README.cdplus [new file with mode: 0644]
doc/READMEs/README.cdtext [new file with mode: 0644]
doc/READMEs/README.copy [new file with mode: 0644]
doc/READMEs/README.multi [new file with mode: 0644]
doc/READMEs/README.netscsid [new file with mode: 0644]
doc/READMEs/README.sony [new file with mode: 0644]
doc/READMEs/README.suidroot [new file with mode: 0644]
doc/READMEs/README.verify [new file with mode: 0644]
doc/WHY [new file with mode: 0644]
doc/genisoimage/README [new file with mode: 0644]
doc/genisoimage/README.alphaboot [new file with mode: 0644]
doc/genisoimage/README.compression [new file with mode: 0644]
doc/genisoimage/README.eltorito [new file with mode: 0644]
doc/genisoimage/README.graft_dirs [new file with mode: 0644]
doc/genisoimage/README.hfs_boot [new file with mode: 0644]
doc/genisoimage/README.hfs_magic [new file with mode: 0644]
doc/genisoimage/README.hide [new file with mode: 0644]
doc/genisoimage/README.hppaboot [new file with mode: 0644]
doc/genisoimage/README.joliet [new file with mode: 0644]
doc/genisoimage/README.macosx [new file with mode: 0644]
doc/genisoimage/README.mipsboot [new file with mode: 0644]
doc/genisoimage/README.mipselboot [new file with mode: 0644]
doc/genisoimage/README.mkhybrid [new file with mode: 0644]
doc/genisoimage/README.prep_boot [new file with mode: 0644]
doc/genisoimage/README.releasenotes [new file with mode: 0644]
doc/genisoimage/README.rootinfo [new file with mode: 0644]
doc/genisoimage/README.session [new file with mode: 0644]
doc/genisoimage/README.sort [new file with mode: 0644]
doc/genisoimage/README.sparcboot [new file with mode: 0644]
doc/genisoimage/README.sunx86boot [new file with mode: 0644]
doc/icedax/FAQ [new file with mode: 0644]
doc/icedax/Frontends [new file with mode: 0644]
doc/icedax/HOWTOUSE [new file with mode: 0644]
doc/icedax/NEEDED [new file with mode: 0644]
doc/icedax/OtherProgs [new file with mode: 0644]
doc/icedax/README [new file with mode: 0644]
doc/icedax/THANKS [new file with mode: 0644]
doc/icedax/TODO [new file with mode: 0644]
doc/icedax/cdda_links [new file with mode: 0644]
doc/icedax/tracknames.pl [new file with mode: 0755]
doc/icedax/tracknames.txt [new file with mode: 0644]
doc/plattforms/README.aix5l [new file with mode: 0644]
doc/plattforms/README.freebsd [new file with mode: 0644]
doc/plattforms/README.linux [new file with mode: 0644]
doc/plattforms/README.parallel [new file with mode: 0644]
doc/plattforms/README.sunos [new file with mode: 0644]
doc/plattforms/README.win32 [new file with mode: 0644]
doc/wodim/README.DiskT@2 [new file with mode: 0644]
doc/wodim/README.WORM [new file with mode: 0644]
doc/wodim/README.cdrw [new file with mode: 0644]
doc/wodim/README.clone [new file with mode: 0644]
doc/wodim/README.raw [new file with mode: 0644]
genisoimage/CMakeLists.txt [new file with mode: 0644]
genisoimage/COPYING [new file with mode: 0644]
genisoimage/ChangeLog [new file with mode: 0644]
genisoimage/ChangeLog.mkhybrid [new file with mode: 0644]
genisoimage/RELEASE [new file with mode: 0644]
genisoimage/TODO [new file with mode: 0644]
genisoimage/apple.c [new file with mode: 0644]
genisoimage/apple.h [new file with mode: 0644]
genisoimage/apple_driver.8 [new file with mode: 0644]
genisoimage/apple_driver.c [new file with mode: 0644]
genisoimage/boot-alpha.c [new file with mode: 0644]
genisoimage/boot-hppa.c [new file with mode: 0644]
genisoimage/boot-mips.c [new file with mode: 0644]
genisoimage/boot-mipsel.c [new file with mode: 0644]
genisoimage/boot.c [new file with mode: 0644]
genisoimage/bootinfo.h [new file with mode: 0644]
genisoimage/bswap.h [new file with mode: 0644]
genisoimage/checksum.c [new file with mode: 0644]
genisoimage/checksum.h [new file with mode: 0644]
genisoimage/config.h [new file with mode: 0644]
genisoimage/defaults.h [new file with mode: 0644]
genisoimage/desktop.c [new file with mode: 0644]
genisoimage/diag/README [new file with mode: 0644]
genisoimage/diag/devdump.1 [new file with mode: 0644]
genisoimage/diag/dump.c [new file with mode: 0644]
genisoimage/diag/isodebug.1 [new file with mode: 0644]
genisoimage/diag/isodebug.c [new file with mode: 0644]
genisoimage/diag/isodump.1 [new file with mode: 0644]
genisoimage/diag/isodump.c [new file with mode: 0644]
genisoimage/diag/isoinfo.1 [new file with mode: 0644]
genisoimage/diag/isoinfo.c [new file with mode: 0644]
genisoimage/diag/isovfy.1 [new file with mode: 0644]
genisoimage/diag/isovfy.c [new file with mode: 0644]
genisoimage/diskmbr.h [new file with mode: 0644]
genisoimage/dvd_file.c [new file with mode: 0644]
genisoimage/dvd_file.h [new file with mode: 0644]
genisoimage/dvd_reader.c [new file with mode: 0644]
genisoimage/dvd_reader.h [new file with mode: 0644]
genisoimage/eltorito.c [new file with mode: 0644]
genisoimage/endian.c [new file with mode: 0644]
genisoimage/endianconv.h [new file with mode: 0644]
genisoimage/exclude.c [new file with mode: 0644]
genisoimage/exclude.h [new file with mode: 0644]
genisoimage/files.c [new file with mode: 0644]
genisoimage/fnmatch.c [new file with mode: 0644]
genisoimage/fnmatch.h [new file with mode: 0644]
genisoimage/genisoimage.1 [new file with mode: 0644]
genisoimage/genisoimage.c [new file with mode: 0644]
genisoimage/genisoimage.h [new file with mode: 0644]
genisoimage/genisoimagerc.5 [new file with mode: 0644]
genisoimage/getopt.c [new file with mode: 0644]
genisoimage/getopt.h [new file with mode: 0644]
genisoimage/getopt1.c [new file with mode: 0644]
genisoimage/hash.c [new file with mode: 0644]
genisoimage/hdisk.pl [new file with mode: 0755]
genisoimage/ifo_read.c [new file with mode: 0644]
genisoimage/ifo_read.h [new file with mode: 0644]
genisoimage/ifo_types.h [new file with mode: 0644]
genisoimage/iso9660.h [new file with mode: 0644]
genisoimage/joliet.c [new file with mode: 0644]
genisoimage/jte.c [new file with mode: 0644]
genisoimage/jte.h [new file with mode: 0644]
genisoimage/mac_label.c [new file with mode: 0644]
genisoimage/mac_label.h [new file with mode: 0644]
genisoimage/mactypes.h [new file with mode: 0644]
genisoimage/magic [new file with mode: 0644]
genisoimage/mapping [new file with mode: 0644]
genisoimage/match.c [new file with mode: 0644]
genisoimage/match.h [new file with mode: 0644]
genisoimage/md5.c [new file with mode: 0644]
genisoimage/md5.h [new file with mode: 0644]
genisoimage/mkhybrid.8 [new file with mode: 0644]
genisoimage/more.mapping [new file with mode: 0644]
genisoimage/multi.c [new file with mode: 0644]
genisoimage/name.c [new file with mode: 0644]
genisoimage/rock.c [new file with mode: 0644]
genisoimage/rsync.c [new file with mode: 0644]
genisoimage/scsi.c [new file with mode: 0644]
genisoimage/scsi.h [new file with mode: 0644]
genisoimage/sha1.c [new file with mode: 0644]
genisoimage/sha1.h [new file with mode: 0644]
genisoimage/sha256.c [new file with mode: 0644]
genisoimage/sha256.h [new file with mode: 0644]
genisoimage/sha512.c [new file with mode: 0644]
genisoimage/sha512.h [new file with mode: 0644]
genisoimage/stream.c [new file with mode: 0644]
genisoimage/sunlabel.h [new file with mode: 0644]
genisoimage/tree.c [new file with mode: 0644]
genisoimage/udf.c [new file with mode: 0644]
genisoimage/udf.h [new file with mode: 0644]
genisoimage/udf_fs.h [new file with mode: 0644]
genisoimage/vms.c [new file with mode: 0644]
genisoimage/vms.h [new file with mode: 0644]
genisoimage/volume.c [new file with mode: 0644]
genisoimage/write.c [new file with mode: 0644]
icedax/CMakeLists.txt [new file with mode: 0644]
icedax/Changelog [new file with mode: 0644]
icedax/GPL [new file with mode: 0644]
icedax/aifc.c [new file with mode: 0644]
icedax/aifc.h [new file with mode: 0644]
icedax/aiff.c [new file with mode: 0644]
icedax/aiff.h [new file with mode: 0644]
icedax/base64.c [new file with mode: 0644]
icedax/base64.h [new file with mode: 0644]
icedax/byteorder.h [new file with mode: 0644]
icedax/cd_extra.c [new file with mode: 0644]
icedax/cd_text.c [new file with mode: 0644]
icedax/cdda2mp3 [new symlink]
icedax/cdda2mp3.new [new file with mode: 0644]
icedax/cdda2ogg [new file with mode: 0755]
icedax/cdda2ogg.1 [new file with mode: 0644]
icedax/cdda2ogg.mk1 [new file with mode: 0644]
icedax/config.h [new file with mode: 0644]
icedax/configure [new file with mode: 0755]
icedax/configure.in [new file with mode: 0644]
icedax/exitcodes.h [new file with mode: 0644]
icedax/global.h [new file with mode: 0644]
icedax/icedax.1 [new file with mode: 0644]
icedax/icedax.c [new file with mode: 0644]
icedax/icedax.h [new file with mode: 0644]
icedax/inf2cdtext.pl [new file with mode: 0755]
icedax/interface.c [new file with mode: 0644]
icedax/interface.h [new file with mode: 0644]
icedax/ioctl.c [new file with mode: 0644]
icedax/ioctl.h [new file with mode: 0644]
icedax/lconfig.h [new file with mode: 0644]
icedax/lconfig.h.in [new file with mode: 0644]
icedax/list_audio_tracks.1 [new file with mode: 0644]
icedax/local.cnf.in [new file with mode: 0644]
icedax/lowlevel.h [new file with mode: 0644]
icedax/mycdrom.h [new file with mode: 0644]
icedax/mytype.h [new file with mode: 0644]
icedax/pitchplay [new file with mode: 0755]
icedax/pitchplay.1 [new file with mode: 0644]
icedax/raw.c [new file with mode: 0644]
icedax/raw.h [new file with mode: 0644]
icedax/readmult [new file with mode: 0755]
icedax/readmult.1 [new file with mode: 0644]
icedax/resample.c [new file with mode: 0644]
icedax/resample.h [new file with mode: 0644]
icedax/ringbuff.c [new file with mode: 0644]
icedax/ringbuff.h [new file with mode: 0644]
icedax/scsi_cmds.c [new file with mode: 0644]
icedax/scsi_cmds.h [new file with mode: 0644]
icedax/semshm.c [new file with mode: 0644]
icedax/semshm.h [new file with mode: 0644]
icedax/setuid.c [new file with mode: 0644]
icedax/setuid.h [new file with mode: 0644]
icedax/sha.h [new file with mode: 0644]
icedax/sha_func.c [new file with mode: 0644]
icedax/sndconfig.c [new file with mode: 0644]
icedax/sndconfig.h [new file with mode: 0644]
icedax/sndfile.h [new file with mode: 0644]
icedax/sun.c [new file with mode: 0644]
icedax/sun.h [new file with mode: 0644]
icedax/toc.c [new file with mode: 0644]
icedax/toc.h [new file with mode: 0644]
icedax/version.sed [new file with mode: 0644]
icedax/wav.c [new file with mode: 0644]
icedax/wav.h [new file with mode: 0644]
include/AddNetworkBits.cmake [new file with mode: 0644]
include/AddScgBits.cmake [new file with mode: 0644]
include/AddSchilyBits.cmake [new file with mode: 0644]
include/CMakeLists.txt [new file with mode: 0644]
include/align.h.in [new file with mode: 0644]
include/allocax.h [new file with mode: 0644]
include/avoffset.h [new file with mode: 0644]
include/btorder.h [new file with mode: 0644]
include/ccomdefs.h [new file with mode: 0644]
include/deflts.h [new file with mode: 0644]
include/device.h [new file with mode: 0644]
include/dirdefs.h [new file with mode: 0644]
include/fctldefs.h [new file with mode: 0644]
include/getargs.h [new file with mode: 0644]
include/getcwd.h [new file with mode: 0644]
include/glibc_elf.h [new file with mode: 0644]
include/intcvt.h [new file with mode: 0644]
include/jmpdefs.h [new file with mode: 0644]
include/libport.h [new file with mode: 0644]
include/librmt.h [new file with mode: 0644]
include/maxpath.h [new file with mode: 0644]
include/mconfig.h [new file with mode: 0644]
include/mmapdefs.h [new file with mode: 0644]
include/patmatch.h [new file with mode: 0644]
include/prototyp.h [new file with mode: 0644]
include/rmtio.h [new file with mode: 0644]
include/schily.h [new file with mode: 0644]
include/sigblk.h [new file with mode: 0644]
include/sigdefs.h [new file with mode: 0644]
include/standard.h [new file with mode: 0644]
include/statdefs.h [new file with mode: 0644]
include/stdxlib.h [new file with mode: 0644]
include/stkframe.h [new file with mode: 0644]
include/strdefs.h [new file with mode: 0644]
include/termcap.h [new file with mode: 0644]
include/test_BITFIELDS_HTOL.c [new file with mode: 0644]
include/test_VA_LIST_IS_ARRAY.c [new file with mode: 0644]
include/timedefs.h [new file with mode: 0644]
include/ttydefs.h [new file with mode: 0644]
include/unixstd.h [new file with mode: 0644]
include/unls.h [new file with mode: 0644]
include/usal [new symlink]
include/utimdefs.h [new file with mode: 0644]
include/utypes.h [new file with mode: 0644]
include/vadefs.h [new file with mode: 0644]
include/waitdefs.h [new file with mode: 0644]
include/xconfig.h.in [new file with mode: 0644]
libedc/CMakeLists.txt [new file with mode: 0644]
libedc/README [new file with mode: 0644]
libedc/crctable.out [new file with mode: 0644]
libedc/ecc.h [new file with mode: 0644]
libedc/edc_ecc.c [new file with mode: 0644]
libedc/edcspeed.c [new file with mode: 0644]
libedc/encoder_tables [new file with mode: 0644]
libedc/l2sq_table [new file with mode: 0644]
libedc/scramble_table [new file with mode: 0644]
libhfs_iso/CMakeLists.txt [new file with mode: 0644]
libhfs_iso/README [new file with mode: 0644]
libhfs_iso/block.c [new file with mode: 0644]
libhfs_iso/block.h [new file with mode: 0644]
libhfs_iso/btree.c [new file with mode: 0644]
libhfs_iso/btree.h [new file with mode: 0644]
libhfs_iso/data.c [new file with mode: 0644]
libhfs_iso/data.h [new file with mode: 0644]
libhfs_iso/file.c [new file with mode: 0644]
libhfs_iso/file.h [new file with mode: 0644]
libhfs_iso/gdata.c [new file with mode: 0644]
libhfs_iso/hfs.c [new file with mode: 0644]
libhfs_iso/hfs.h [new file with mode: 0644]
libhfs_iso/hybrid.h [new file with mode: 0644]
libhfs_iso/internal.h [new file with mode: 0644]
libhfs_iso/low.c [new file with mode: 0644]
libhfs_iso/low.h [new file with mode: 0644]
libhfs_iso/node.c [new file with mode: 0644]
libhfs_iso/node.h [new file with mode: 0644]
libhfs_iso/record.c [new file with mode: 0644]
libhfs_iso/record.h [new file with mode: 0644]
libhfs_iso/volume.c [new file with mode: 0644]
libhfs_iso/volume.h [new file with mode: 0644]
libparanoia/CMakeLists.txt [new file with mode: 0644]
libparanoia/README.interface [new file with mode: 0644]
libparanoia/README.paranoia [new file with mode: 0644]
libparanoia/cdda_paranoia.h [new file with mode: 0644]
libparanoia/gap.c [new file with mode: 0644]
libparanoia/gap.h [new file with mode: 0644]
libparanoia/isort.c [new file with mode: 0644]
libparanoia/isort.h [new file with mode: 0644]
libparanoia/overlap.c [new file with mode: 0644]
libparanoia/overlap.h [new file with mode: 0644]
libparanoia/overlapdef.txt [new file with mode: 0644]
libparanoia/p_block.c [new file with mode: 0644]
libparanoia/p_block.h [new file with mode: 0644]
libparanoia/paranoia.c [new file with mode: 0644]
libparanoia/pmalloc.c [new file with mode: 0644]
libparanoia/pmalloc.h [new file with mode: 0644]
librols/CMakeLists.txt [new file with mode: 0644]
librols/astoi.c [new file with mode: 0644]
librols/astoll.c [new file with mode: 0644]
librols/astoull.c [new file with mode: 0644]
librols/breakline.c [new file with mode: 0644]
librols/cmpbytes.c [new file with mode: 0644]
librols/comerr.c [new file with mode: 0644]
librols/default.c [new file with mode: 0644]
librols/error.c [new file with mode: 0644]
librols/fexec.c [new file with mode: 0644]
librols/fillbytes.c [new file with mode: 0644]
librols/findbytes.c [new file with mode: 0644]
librols/getargs.c [new file with mode: 0644]
librols/getav0.c [new file with mode: 0644]
librols/getdomainname.c [new file with mode: 0644]
librols/geterrno.c [new file with mode: 0644]
librols/gethostid.c [new file with mode: 0644]
librols/gethostname.c [new file with mode: 0644]
librols/getpagesize.c [new file with mode: 0644]
librols/handlecond.c [new file with mode: 0644]
librols/movebytes.c [new file with mode: 0644]
librols/raisecond.c [new file with mode: 0644]
librols/rename.c [new file with mode: 0644]
librols/saveargs.c [new file with mode: 0644]
librols/seterrno.c [new file with mode: 0644]
librols/snprintf.c [new file with mode: 0644]
librols/spawn.c [new file with mode: 0644]
librols/stdio/cvmod.c [new file with mode: 0644]
librols/stdio/dat.c [new file with mode: 0644]
librols/stdio/fcons.c [new file with mode: 0644]
librols/stdio/fdown.c [new file with mode: 0644]
librols/stdio/fdup.c [new file with mode: 0644]
librols/stdio/ffileread.c [new file with mode: 0644]
librols/stdio/ffilewrite.c [new file with mode: 0644]
librols/stdio/fgetline.c [new file with mode: 0644]
librols/stdio/file_raise.c [new file with mode: 0644]
librols/stdio/fileclose.c [new file with mode: 0644]
librols/stdio/fileluopen.c [new file with mode: 0644]
librols/stdio/filemopen.c [new file with mode: 0644]
librols/stdio/fileopen.c [new file with mode: 0644]
librols/stdio/filepos.c [new file with mode: 0644]
librols/stdio/fileread.c [new file with mode: 0644]
librols/stdio/filereopen.c [new file with mode: 0644]
librols/stdio/fileseek.c [new file with mode: 0644]
librols/stdio/filesize.c [new file with mode: 0644]
librols/stdio/filestat.c [new file with mode: 0644]
librols/stdio/filewrite.c [new file with mode: 0644]
librols/stdio/flag.c [new file with mode: 0644]
librols/stdio/flush.c [new file with mode: 0644]
librols/stdio/fpipe.c [new file with mode: 0644]
librols/stdio/niread.c [new file with mode: 0644]
librols/stdio/niwrite.c [new file with mode: 0644]
librols/stdio/nixread.c [new file with mode: 0644]
librols/stdio/nixwrite.c [new file with mode: 0644]
librols/stdio/openfd.c [new file with mode: 0644]
librols/stdio/peekc.c [new file with mode: 0644]
librols/stdio/schilyio.h [new file with mode: 0644]
librols/strcatl.c [new file with mode: 0644]
librols/strdup.c [new file with mode: 0644]
librols/streql.c [new file with mode: 0644]
librols/swabbytes.c [new file with mode: 0644]
librols/usleep.c [new file with mode: 0644]
libunls/CMakeLists.txt [new file with mode: 0644]
libunls/nls.h [new file with mode: 0644]
libunls/nls_base.c [new file with mode: 0644]
libunls/nls_config.c [new file with mode: 0644]
libunls/nls_cp10000.c [new file with mode: 0644]
libunls/nls_cp10006.c [new file with mode: 0644]
libunls/nls_cp10007.c [new file with mode: 0644]
libunls/nls_cp10029.c [new file with mode: 0644]
libunls/nls_cp10079.c [new file with mode: 0644]
libunls/nls_cp10081.c [new file with mode: 0644]
libunls/nls_cp1250.c [new file with mode: 0644]
libunls/nls_cp1251.c [new file with mode: 0644]
libunls/nls_cp437.c [new file with mode: 0644]
libunls/nls_cp737.c [new file with mode: 0644]
libunls/nls_cp775.c [new file with mode: 0644]
libunls/nls_cp850.c [new file with mode: 0644]
libunls/nls_cp852.c [new file with mode: 0644]
libunls/nls_cp855.c [new file with mode: 0644]
libunls/nls_cp857.c [new file with mode: 0644]
libunls/nls_cp860.c [new file with mode: 0644]
libunls/nls_cp861.c [new file with mode: 0644]
libunls/nls_cp862.c [new file with mode: 0644]
libunls/nls_cp863.c [new file with mode: 0644]
libunls/nls_cp864.c [new file with mode: 0644]
libunls/nls_cp865.c [new file with mode: 0644]
libunls/nls_cp866.c [new file with mode: 0644]
libunls/nls_cp869.c [new file with mode: 0644]
libunls/nls_cp874.c [new file with mode: 0644]
libunls/nls_file.c [new file with mode: 0644]
libunls/nls_iconv.c [new file with mode: 0644]
libunls/nls_iso8859-1.c [new file with mode: 0644]
libunls/nls_iso8859-14.c [new file with mode: 0644]
libunls/nls_iso8859-15.c [new file with mode: 0644]
libunls/nls_iso8859-2.c [new file with mode: 0644]
libunls/nls_iso8859-3.c [new file with mode: 0644]
libunls/nls_iso8859-4.c [new file with mode: 0644]
libunls/nls_iso8859-5.c [new file with mode: 0644]
libunls/nls_iso8859-6.c [new file with mode: 0644]
libunls/nls_iso8859-7.c [new file with mode: 0644]
libunls/nls_iso8859-8.c [new file with mode: 0644]
libunls/nls_iso8859-9.c [new file with mode: 0644]
libunls/nls_koi8-r.c [new file with mode: 0644]
libunls/nls_koi8-u.c [new file with mode: 0644]
libusal/CMakeLists.txt [new file with mode: 0644]
libusal/pg.h [new file with mode: 0644]
libusal/rdummy.c [new file with mode: 0644]
libusal/scsi-aix.c [new file with mode: 0644]
libusal/scsi-amigaos.c [new file with mode: 0644]
libusal/scsi-apollo.c [new file with mode: 0644]
libusal/scsi-beos.c [new file with mode: 0644]
libusal/scsi-bsd-os.c [new file with mode: 0644]
libusal/scsi-bsd.c [new file with mode: 0644]
libusal/scsi-dos.c [new file with mode: 0644]
libusal/scsi-hpux.c [new file with mode: 0644]
libusal/scsi-linux-ata.c [new file with mode: 0644]
libusal/scsi-linux-pg.c [new file with mode: 0644]
libusal/scsi-linux-sg.c [new file with mode: 0644]
libusal/scsi-mac-iokit.c [new file with mode: 0644]
libusal/scsi-next.c [new file with mode: 0644]
libusal/scsi-openserver.c [new file with mode: 0644]
libusal/scsi-os2.c [new file with mode: 0644]
libusal/scsi-osf.c [new file with mode: 0644]
libusal/scsi-qnx.c [new file with mode: 0644]
libusal/scsi-remote.c [new file with mode: 0644]
libusal/scsi-sgi.c [new file with mode: 0644]
libusal/scsi-sun.c [new file with mode: 0644]
libusal/scsi-unixware.c [new file with mode: 0644]
libusal/scsi-vms.c [new file with mode: 0644]
libusal/scsi-wnt.c [new file with mode: 0644]
libusal/scsierrs.c [new file with mode: 0644]
libusal/scsihack.c [new file with mode: 0644]
libusal/scsihelp.c [new file with mode: 0644]
libusal/scsiopen.c [new file with mode: 0644]
libusal/scsitransp.c [new file with mode: 0644]
libusal/usal/aspi-dos.h [new file with mode: 0644]
libusal/usal/aspi-win32.h [new file with mode: 0644]
libusal/usal/scsicdb.h [new file with mode: 0644]
libusal/usal/scsidefs.h [new file with mode: 0644]
libusal/usal/scsireg.h [new file with mode: 0644]
libusal/usal/scsisense.h [new file with mode: 0644]
libusal/usal/scsitransp.h [new file with mode: 0644]
libusal/usal/spti-wnt.h [new file with mode: 0644]
libusal/usal/srb_os2.h [new file with mode: 0644]
libusal/usal/usalcmd.h [new file with mode: 0644]
libusal/usal/usalio.h [new file with mode: 0644]
libusal/usal/usalops.h [new file with mode: 0644]
libusal/usalsettarget.c [new file with mode: 0644]
libusal/usaltimes.c [new file with mode: 0644]
libusal/usaltimes.h [new file with mode: 0644]
misc/MKNOD.hpux [new file with mode: 0755]
misc/MKNOD.hpux-800 [new file with mode: 0755]
misc/burnstuff [new file with mode: 0755]
misc/make_diskt@2.sh [new file with mode: 0644]
misc/rc.pp [new file with mode: 0755]
misc/shared_lib_patch_incomplete.diff [new file with mode: 0644]
netscsid/CMakeLists.txt [new file with mode: 0644]
netscsid/netscsid.c [new file with mode: 0644]
netscsid/netscsid.dfl [new file with mode: 0644]
readom/CMakeLists.txt [new file with mode: 0644]
readom/io.c [new file with mode: 0644]
readom/readom.1 [new file with mode: 0644]
readom/readom.c [new file with mode: 0644]
wodim/CMakeLists.txt [new file with mode: 0644]
wodim/audiosize.c [new file with mode: 0644]
wodim/auheader.h [new file with mode: 0644]
wodim/auinfo.c [new file with mode: 0644]
wodim/cd_misc.c [new file with mode: 0644]
wodim/cdr_drv.c [new file with mode: 0644]
wodim/cdtext.c [new file with mode: 0644]
wodim/cdtext.h [new file with mode: 0644]
wodim/clone.c [new file with mode: 0644]
wodim/crc16.c [new file with mode: 0644]
wodim/crc16.h [new file with mode: 0644]
wodim/cue.c [new file with mode: 0644]
wodim/defaults.c [new file with mode: 0644]
wodim/defaults.h [new file with mode: 0644]
wodim/diskid.c [new file with mode: 0644]
wodim/drv_7501.c [new file with mode: 0644]
wodim/drv_jvc.c [new file with mode: 0644]
wodim/drv_mmc.c [new file with mode: 0644]
wodim/drv_philips.c [new file with mode: 0644]
wodim/drv_simul.c [new file with mode: 0644]
wodim/drv_sony.c [new file with mode: 0644]
wodim/fifo.c [new file with mode: 0644]
wodim/getnum.c [new file with mode: 0644]
wodim/iso9660.h [new file with mode: 0644]
wodim/isosize.c [new file with mode: 0644]
wodim/misc.c [new file with mode: 0644]
wodim/mmcvendor.h [new file with mode: 0644]
wodim/modes.c [new file with mode: 0644]
wodim/movesect.c [new file with mode: 0644]
wodim/movesect.h [new file with mode: 0644]
wodim/scsi_cdr.c [new file with mode: 0644]
wodim/scsi_cdr_mmc4.c [new file with mode: 0644]
wodim/scsi_mmc.c [new file with mode: 0644]
wodim/scsi_mmc4.c [new file with mode: 0644]
wodim/scsi_scan.c [new file with mode: 0644]
wodim/scsi_scan.h [new file with mode: 0644]
wodim/scsimmc.h [new file with mode: 0644]
wodim/sector.c [new file with mode: 0644]
wodim/subchan.c [new file with mode: 0644]
wodim/wm_packet.c [new file with mode: 0644]
wodim/wm_session.c [new file with mode: 0644]
wodim/wm_track.c [new file with mode: 0644]
wodim/wodim.1 [new file with mode: 0644]
wodim/wodim.c [new file with mode: 0644]
wodim/wodim.dfl [new file with mode: 0644]
wodim/wodim.h [new file with mode: 0644]
wodim/xio.c [new file with mode: 0644]
wodim/xio.h [new file with mode: 0644]

diff --git a/3rd-party/dirsplit/CMakeLists.txt b/3rd-party/dirsplit/CMakeLists.txt
new file mode 100644 (file)
index 0000000..497774c
--- /dev/null
@@ -0,0 +1,3 @@
+PROJECT (DIRSPLIT C)
+INSTALL(PROGRAMS dirsplit DESTINATION bin)
+INSTALL(FILES dirsplit.1 DESTINATION share/man/man1)
diff --git a/3rd-party/dirsplit/ChangeLog b/3rd-party/dirsplit/ChangeLog
new file mode 100644 (file)
index 0000000..b5cd780
--- /dev/null
@@ -0,0 +1,27 @@
+*0.3.3: 2006/03
+
+* code refactoring, much more readable now
+* dropped the "du" exploration mode
+* dropped the read-from-file mode and input "correct" cludge
+       * Use the new -T option to specify arbitrary input, and avoid dupes.
+       * Use the new option -F to follow symlinks
+* option name fixes
+* new option simple/stupid mode
+       * no space-efficiency optimisation, instead trying to store in alphabetic
+         order
+
+0.3.2:
+
+* cosmetic, correct usage and long help
+
+0.3.1:
+
+* proper fix for the = filenames
+
+0.3:
+
+* rewrite of some data input code, now using internal directory scanning
+(exploration) go get data, not trusting du -a crap
+* estimative calculation for filesystem overhead for directory entries
+* workaround for = in filenames
+* much, much more
diff --git a/3rd-party/dirsplit/README b/3rd-party/dirsplit/README
new file mode 100644 (file)
index 0000000..3867a12
--- /dev/null
@@ -0,0 +1,7 @@
+Package: dirsplit
+License: GPLv2 (until I change my mind)
+Purpose: put files from a directory structure in subdirectories of specified
+size or create catalogues for mkisofs so that generated volumes waste as few
+space as possible
+Algrorithm: randomising FirstFit or BestFit
+Usage:   Selfexplaining
diff --git a/3rd-party/dirsplit/dirsplit b/3rd-party/dirsplit/dirsplit
new file mode 100755 (executable)
index 0000000..1348976
--- /dev/null
@@ -0,0 +1,611 @@
+#!/usr/bin/perl
+#                              -*- Mode: Perl -*-
+# dirsplit ---
+# Author           : Eduard Bloch ( blade@debian.org )
+# Last Modified On : Sun, 06 Feb 2005 14:59:51 +0100
+# Status           : Working, but use with caution!
+# License: GPLv2
+
+my $version="0.3.3";
+
+require v5.8.1;
+use strict;
+use List::Util 'shuffle';
+use Getopt::Long qw(:config no_ignore_case bundling);
+use File::Basename;
+use File::Path;
+use Cwd 'abs_path';
+
+my $ret=0;
+my $max="4488M";
+my $prefix="vol_";
+my $acc=20;
+my $emode=1;
+my $bsize=2048;
+my $ofac =50;
+my $opt_help;
+my $opt_longhelp;
+my $opt_sim;
+my $opt_dir;
+my $opt_flat;
+my $opt_move;
+my $opt_ver;
+my $opt_sln;
+my $opt_ln;
+my $opt_filter;
+my $opt_simple;
+my $opt_follow;
+my $get_ver;
+my $opt_listfile;
+
+
+my %options = (
+   "h|help"                => \$opt_help,
+   "d|dirhier"            => \$opt_dir,
+   "flat"            => \$opt_flat,
+   "f|filter=s"            => \$opt_filter,
+   "F|follow"            => \$opt_follow,
+   "e|expmode=i"            => \$emode,
+   "o|overhead=i"            => \$ofac,
+   "b|blksize=i"            => \$bsize,
+   "n|no-act"            => \$opt_sim,
+   "m|move"            => \$opt_move,
+   "l|symlink"            => \$opt_sln,
+   "L|hardlink"           => \$opt_ln,
+   "v|verbose"            => \$opt_ver,
+   "s|size=s"             => \$max,
+   "S|simple"             => \$opt_simple,
+   "T|input=s"       => \$opt_listfile,
+   "p|prefix=s"              => \$prefix,
+   "a|accuracy=i"            => \$acc,
+   "H|longhelp"            => \$opt_longhelp,
+   "version"                 => \$get_ver
+);
+
+&show_help(1) unless ( GetOptions(%options));
+&show_help(1) if $opt_help;
+&show_longhelp if $opt_longhelp;
+if($get_ver) {
+   print $version;
+   exit 0;
+}
+
+# ignore the old dirhier setting since it is default now and disable the flag when opt_flat is specified
+$opt_dir = !$opt_flat;
+
+$opt_ver = 1 if $opt_sim;
+$opt_move=1 if ($opt_sln || $opt_ln);
+
+# big list @sizes containing the "items" (object sizes)
+# %names hash mapping "items" (size as key) to arrays with filenames/subarrays for coalesced files
+my @sizes;
+my %names;
+
+# result containts the calculated output. In simple mode, an
+# array (bins) of atoms (files or filelists). Otherwise, sizes
+# instead of atoms, to be resolved with %names.
+my @result;
+
+my $inputdir;
+
+$max=fixnr($max);
+# about 400kB for iso headers
+$max-=420000;
+
+# init default value
+my $globwaste=0;
+
+
+if(-d $ARGV[0] || (-d readlink($ARGV[0]))) {
+   syswrite(STDOUT,"Building file list, please wait...\n");
+   # save the absolut path before doing anyhting
+   $inputdir=Cwd::abs_path($ARGV[0]);
+   &explore($inputdir);
+}
+elsif($opt_listfile) {
+   if($opt_listfile eq "-") {
+      &parseListe(\*STDIN);
+   }
+   else {
+      open(my $in, "<", $opt_listfile) || die "Cannot open list file $opt_listfile\n";
+      &parseListe($in);
+   }
+}
+else {
+   die "Error: please specify a directory\n";
+}
+
+# check for pointless requests
+my $testsize=0;
+for(@sizes) {
+   die "Too large object(s) ($_) for the given max size: @{$names{$_}} (maybe coalesced in arrays, check manually)\n" if($_>$max);
+
+   $testsize+=$_;
+}
+
+$acc=1 if ($testsize <= $max); # just generate a list, more trials are pointless
+print "\nSumm: $testsize\n" if($opt_ver);
+die "Nothing to do!\n" if($testsize<4096); # looks like just an empty dir
+
+if(!$opt_simple) {
+   syswrite(STDOUT, "Calculating, please wait...\n");
+   my $starttime=time;
+   $globwaste=$max*@sizes;
+   for(1..$acc) {
+      syswrite(STDOUT,".");
+      my @tmp;
+      #my $waste = bp_bestfit($max, \@in, \@tmp);
+      my $waste = bp_firstfit($max, \@sizes, \@tmp);
+      #print "D: waste - $waste\n";
+      if($waste < $globwaste) {
+         $globwaste=$waste;
+         @result=@tmp;
+      }
+      if($starttime && time > $starttime+10) {
+         syswrite(STDOUT,"\nSpent already over 10s (for $_ iterations)\nHint: reduce accuracy to make it faster!\n");
+         undef $starttime;
+      }
+      @sizes=shuffle(@sizes);
+   }
+
+}
+
+print "\nCalculated, using ".(scalar @result)." volumes.\n";
+print "Wasted: $globwaste Byte (estimated, check mkisofs -print-size ...)\n";
+
+# and the real work
+my $i=0;
+my $inDirLen=length($inputdir);
+for(@result) {
+   $i++;
+   my $o;
+   open($o, ">$prefix$i.list") if(! ($opt_move || $opt_sim));
+   my $dirPrefix=dirname($prefix);
+   my $prefixBase=basename($prefix);
+   my $dirPrefixAbs=Cwd::abs_path($dirPrefix);
+
+   for(@{$_}) {
+      my $stuffRef;
+      
+      # For simple mode, the files/atoms are already resolved, otherwise take
+      # the next with appropriate size. 
+      my $item= $opt_simple ? $_ : shift(@{$names{$_}});
+
+      # make reference point to an array with our files, create a list if needed
+      if(ref($item) eq "ARRAY") {
+         $stuffRef=$item;
+      }
+      else {
+         $stuffRef=[$item];
+      }
+
+      for my $file (@$stuffRef) {
+         my $relFile=substr($file,$inDirLen+1);
+         my $base=basename($relFile);
+         if($opt_move) {
+            my $targetsubdir = $dirPrefixAbs."/$prefixBase$i";
+            $targetsubdir .= "/".dirname($relFile) if($opt_dir);
+            print "$file -> $targetsubdir/$base\n" if($opt_ver);
+            if(!$opt_sim) {
+               mkpath $targetsubdir || die "Problems creating $targetsubdir\n";
+               # last check
+               die "Could not create $targetsubdir?\n" if(!(-d $targetsubdir && -w $targetsubdir));
+               if($opt_sln) {
+                  symlink($file, "$targetsubdir/$base");
+               }
+               elsif($opt_ln) {
+                  if(-d $file && !-l $file) {
+                     mkdir "$targetsubdir/$base";
+                  }
+                  else {
+                     link($file, "$targetsubdir/$base");
+                  }
+               }
+               else {
+                  rename($file, "$targetsubdir/$base");
+               }
+            }
+         }
+         else {
+            # escape = in mkisofs catalogs, they are used as separator
+            my $isoname = ($opt_dir?$relFile : $base);
+            $isoname=~s/=/\\=/g;
+            my $sourcefile=$file;
+            $sourcefile=~s/=/\\=/g;
+            print "$i: /$isoname=$sourcefile\n" if $opt_ver;
+            print $o "/$isoname=$sourcefile\n" if(!$opt_sim);
+         }
+      }
+   }
+   close($o) if($o);
+}
+
+exit $ret;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# recursive function
+# parameter: directory
+# mode 1: descend as far as possible and index all non-directories
+# mode 2++:
+# put all files of a dir into coaleseced-object, then descend into each dir
+sub explore {
+   (my $dir) = @_;
+   my @stuff;
+   my @dirs;
+   my @files;
+
+   opendir(DIR, $dir) || die "Could not open $dir\n";
+   @stuff=readdir(DIR);
+   
+   if($opt_simple) {
+      @stuff=sort { lc($a) cmp lc($b) } @stuff;
+   }
+      
+   foreach my $f (@stuff) {
+      next if ($f eq "." || $f eq "..");
+      #print "\$f=$opt_filter;\n";
+      
+      $f="$dir/$f" if($dir ne ".");
+
+      if ($opt_filter) {
+         next unless (eval("\$f=~$opt_filter;"));
+      }
+
+      if(-l $f && ! $opt_follow) {
+         push(@files, $f);
+      }
+      elsif(-d $f) {
+         push(@dirs, $f);
+      }
+      else {
+         push(@files, $f);
+      }
+   }
+   closedir(DIR);
+
+   if( (@dirs + @files) == 0 ) {
+      # this one is empty, register for cosmetics reason
+      &insitem(getsize($dir), $dir);
+      return;
+   }
+   
+   # recurse on directories
+   &explore($_) for(@dirs);
+
+   # and now process files
+   if($emode==1) {
+      &insitem(getsize($_), $_) for(@files);
+   }
+   else {
+      # handle coalesced objects - first some sanity checks and splitting if
+      # required
+
+      my $filesum=0;
+      for(@files) {
+         my $tmp=getsize($_);
+         if($tmp>$max) {
+            # already too large, stop right here
+            die "Too large file ($_) for the given max size $max, aborting...\n";
+         }
+         $filesum += $tmp;
+      };
+
+      # handle coal. objects becoming too large
+      if($filesum>$max) {
+         # too large coal. object...
+         if($emode==3) {
+            # don't coalesc in this mode, do like mode 1 above, leave them alone
+            &insitem(getsize($_), $_) for(@files);
+            return;
+         }
+         # a bit complicated, split file set while creating coal.objects
+         if($emode==4) {
+            my $partsum=0;
+            my @sorted=sort(@files);
+            my @tmpvol;
+            for(my $i=0;$i<=$#sorted;$i++) {
+#            print "D: i: $i, partsum: $partsum, file: $sorted[$i]\n";
+               my $tmp=getsize($sorted[$i]);
+               $partsum+=$tmp;
+               if($partsum>$max) {
+                  # undo the last step then build the coal.object
+                  $partsum-=$tmp;
+                  $i--;
+
+                  &insitem($partsum, \@tmpvol);
+                  # reset temporaries
+                  undef @tmpvol;
+                  undef $partsum;
+               }
+               else {
+                  push(@tmpvol, $sorted[$i]);
+               }
+            }
+            return;
+         }
+      }
+
+      # ok, building a coalesced object for simple cases
+      if($filesum) {
+         &insitem($filesum, \@files);
+      }
+   }
+}
+
+my $simplePos=0;
+my @simpleBinSizes;
+
+# args: size, object (filename or list reference)
+sub insitem {
+   my ($size, $object) = @_;
+   # normaly, put the items into the pool for calculation. In simple mode, calculate here
+   
+   push(@sizes, $size);
+   push(@{$names{$size}},$object);
+
+   if($opt_simple) {
+      # now the simplest method to fill the bins, just take a new one when the
+      # object-to-be-added no longer fits
+      if($simpleBinSizes[$simplePos]+$size > $max) {
+         $globwaste += ( $max-$simpleBinSizes[$simplePos] );
+         $simplePos++;
+      };
+      $simpleBinSizes[$simplePos]+=$size;
+      push( @{$result[$simplePos]}, $object);
+   }
+   
+}
+
+sub getsize {
+   (my $file) = @_;
+   my $size = ((stat($file))[7]);
+   my $rest = ($size % $bsize);
+   $size = ($size + $bsize - $rest) if ($rest);
+   return 1+int(200 + $ofac*length(basename($file)) + $size);
+}
+   
+sub parseListe {
+   my $fh=${$_[0]};
+   while(<$fh>) {
+      if(/^(\w+)\s+(.+)/) {
+         &insitem(fixnr($1), $2);
+      }
+   }
+}
+
+sub fixnr {
+   # args: 
+   # Number
+   # optional: default multiplier
+   my $fac;
+   my $nr;
+   if($_[0]=~/(\d+)(\D)/) {
+      $nr=$1;
+      $fac=$2;
+   }
+   elsif(defined($_[1])) {
+      $nr=$_[0];
+      $fac=$_[1];
+   }
+   else {
+      return $_[0];
+   }
+   return $nr*1000000000 if($fac eq "g");
+   return $nr*1073741824 if($fac eq "G");
+   return $nr*1000000 if($fac eq "m");
+   return $nr*1048576 if($fac eq "M");
+   return $nr*1000 if($fac eq "k");
+   return $nr*1024 if($fac eq "K");
+   return $nr if($fac eq "b");
+   die "$fac is not a valid multiplier!";
+}
+
+
+sub show_help {
+   print <<EOM
+dirsplit [options] [advanced options] < directory >
+
+ -H|--longhelp Show the long help message with more advanced options
+ -n|--no-act   Only print the commands, no action (implies -v)
+ -s|--size     NUMBER - Size of the medium (default: $max)
+ -e|--expmode  NUMBER - directory exploration mode (recommended, see long help)
+ -m|--move     Move files to target dirs (default: create mkisofs catalogs)
+ -p|--prefix   STRING - first part of catalog/directory name (default: vol_)
+ -h|--help     Show this option summary
+ -v|--verbose  More verbosity
+                   
+The complete help can be displayed with the --longhelp (-H) option.
+The default mode is creating file catalogs useable with:
+    mkisofs -D -r --joliet-long -graft-points -path-list CATALOG
+
+Example:
+dirsplit -m -s 700M -e2 random_data_to_backup/
+EOM
+   ;
+   exit shift;
+}
+
+sub show_longhelp {
+   my $msglong="
+dirsplit [options] [advanced options] < directory >
+ -n|--no-act   Only print the commands, no action (implies -v)
+ -s|--size     NUMBER - Size of the medium (default: $max)
+ -m|--move     Move files to target dirs (default: create mkisofs catalogs)
+ -l|--symlink  similar to -m but just creates symlinks in the target dirs
+ -L|--hardlink like -l but creates hardlinks
+ -p|--prefix   STRING - first part of catalog/directory name (default: vol_)
+ -f|--filter   EXPR - Filter expression, see examples below and perlre manpage
+ --flat        Flat dir mode, don't recreate subdirectory structure (not recommended)
+ -e|--expmode  NUMBER, special exploration modes, used with directory argument
+
+  1: (default) native exploration of the specified directory, but file sizes
+               are rounded up to 2048 blocks plus estimated overhead for
+               filenames (see -o option)
+  2: like 1, but all files in directory are put together (as \"atom\") onto the
+               same medium. This does not apply to subdirectories, however.
+  3: like 2, but don't coalesc files when the size of the \"atom\" becomes too
+               large for the medium size (currently $max)
+  4: like 2, but the max. size of the atoms is limited to $max (storing the
+               rest on another medium)
+
+ -F|--follow   Follow symlinks. Use with care!
+ -b|--blksize  NUMBER, block size of the target filesystem (currently $bsize).
+ -o|--overhead NUMBER, overhead caused by directory entries (as factor for the
+               filename length, default: 50, empiricaly found for Joliet+RR
+               with not-so-deep directory structure). Works in exploration
+               mode.
+ -a|--accuracy NUMBER (1=faster, large number=better efficiency, default: 500)
+ -S|--simple   Simple/stupid/alphabetic mode
+ -T|--input    FILENAME (or - for STDIN):  List with sizes and paths, try:
+               find dir -type f -printf \"%s %p\n\"
+               to get an example. Avoid duplicates! Unit suffixes are allowed.
+ -h|--help     Show this option summary
+ -v|--verbose  More verbosity
+                   
+File sizes are expected to be in bytes, append modifier letters to multiply
+with a factor, eg 200M (b,k,K,m,M,g,G for Bytes, Kb, KiB, Mb, MiB, Gb, GiB).
+The default output mode is creating file catalogs useable with
+    mkisofs -D -r --joliet-long -graft-points -path-list CATALOG
+
+Examples:
+dirsplit -m -s 120M -e4 largedirwithdata/ -p /zipmedia/backup_   #move stuff into splitted backup dirs
+dirsplit -s 700M -e2 music/ # make mkisofs catalogs to burn all music to 700M CDRs, keep single files in each dir together
+dirsplit -s 700M -e2 -f '/other\\/Soundtracks/' music/ # like above, only take files from other/Soundtracks
+dirsplit -s 700M -e2 -f '!/Thumbs.db|Desktop.ini|\\.m3u\$/i' # like above, ignore some junk files and playlists, both letter cases
+
+Bugs: overhead trough blocksize alignment and directory entry storage varies,
+heavily depends on the target filesystem and configuration (see -b and -o).
+
+You should compare the required size of the created catalogs, eg.:
+for x in *list ; do mkisofs -quiet -D -r --joliet-long -graft-points \\
+ -path-list \$x -print-size; done
+(output in blocks of 2048 bytes) with the expected size (-s) and media data
+(cdrecord -v -toc ...). 
+";
+   print $msglong;
+   exit 0;
+}
+
+# Parms: bin size (int), input array (arr reference), output array (arr reference)
+# Returns: wasted space (int)
+sub bp_bestfit {
+   my $max=$_[0];
+   my @in = @{$_[1]};
+   my $target = $_[2];
+   my @out;
+   my @bel;
+
+   my @tmp;
+   push(@tmp,$in[0]);
+   push(@out, \@tmp);
+   $bel[0] = $in[0];
+   shift @in;
+
+   for(@in) {
+      my $bestplace=$#out+1;
+      my $bestwert=$max;
+      for($i=0;$i<=$#out;$i++) {
+         my $rest;
+         $rest=$max-$bel[$i]-$_;
+         if($rest>0 && $rest < $bestwert) {
+            $bestplace=$i;
+            $bestwert=$rest;
+         };
+      }
+      if($bestplace>$#out) {
+         my @bin;
+         $bel[$bestplace]=$_;
+         push(@bin, $_);
+         push(@out,\@bin);
+      }
+      else{
+         $bel[$bestplace]+=$_;
+         push(  @{$out[$bestplace]}    , $_);
+      }
+   }
+   my $ret=0;
+   # count all rests but the last one
+   for($i=0;$i<$#out;$i++) {
+      $ret+=($max-$bel[$i]);
+   }
+   @{$target} = @out;
+   return $ret;
+}
+
+# Parms: bin size (int), input array (arr reference), output array (arr reference)
+# Returns: wasted space (int)
+sub bp_firstfit {
+   my $max=$_[0];
+   my @in = @{$_[1]};
+   my $target = $_[2];
+   my @out;
+   my @bel;
+
+   piece: foreach my $obj (@in) {
+      # first fit, use the first bin with enough free space
+      #       print "F: bin$i: $obj, @{$names{$obj}}\n";
+      for($i=0;$i<=$#out;$i++) {
+         my $newsize=($bel[$i]+$obj);
+#         print "bel[i]: $bel[$i], new?: $newsize to max: $max\n";
+         if( $newsize <= $max ) {
+#            print "F: bin$i: $bel[$i]+$obj=$newsize\n";
+            #fits here
+            $bel[$i]=$newsize;
+            push(  @{$out[$i]} , $obj);
+            next piece; # break
+         }
+      }
+      # neues Bin
+      my @bin;
+      $bel[$i]=$obj;
+#      print "N: bin$i: $bel[$i]=$obj\n";
+      push(@bin, $obj);
+      push(@out,\@bin);
+   }
+   my $ret=0;
+   # sum up all rests except of the one from the last bin
+   for($i=0;$i<$#out;$i++) {
+#           print "hm, bel $i ist :".$bel[$i]." und res:".($max-$bel[$i])."\n";
+      $ret+=($max-$bel[$i]);
+   }
+   @{$target} = @out;
+#      print "wtf, ".join(",", @{$out[0]})."\n";
+   return $ret;
+}
diff --git a/3rd-party/dirsplit/dirsplit.1 b/3rd-party/dirsplit/dirsplit.1
new file mode 100644 (file)
index 0000000..76fdfa5
--- /dev/null
@@ -0,0 +1,27 @@
+.\" DO NOT MODIFY THIS FILE!  It was generated by help2man 1.33.
+.TH DIRSPLIT "1" "March 2004" "dirsplit 0.3" "User Commands"
+.SH NAME
+dirsplit \- splits directory into multiple with equal size
+.SH SYNOPSIS
+dirsplit \fB[options]\fR < directory | content-list-file >
+.SH DESCRIPTION
+displit is designed to for a simple purpose: convert a directory with
+many multiple files (which are all smaller than a certain medium, eg.
+DVD) and "splits" it into "volumes", looking for the optimal order to
+get the best space/medium-number efficiency.
+.P
+The actual action is either adding the files to mkisofs catalogs or real
+moving of files into new directories (or creating links/symlinks).
+The method is not limited to files, whole directories can also be handled this
+way (see various filesystem exploration modes).
+.SH OPTIONS
+.TP
+Run dirsplit \fB\-h\fR to get the basic usage info.
+.TP
+Run dirsplit \fB\-H\fR to get the whole option overview and description.
+.SH EXAMPLES
+Run dirsplit \fB\-H\fR to see the commented examples.
+.SH AUTHOR
+\fBdirsplit\fR is created by Eduard Bloch (blade@debian.org) and is licensed
+under the GPLv2.
+
diff --git a/3rd-party/geteltorito.1 b/3rd-party/geteltorito.1
new file mode 100644 (file)
index 0000000..978da17
--- /dev/null
@@ -0,0 +1,48 @@
+.\"                                      Hey, EMACS: -*- nroff -*-
+.TH GETELTORITO 1 "Mai  6, 2007"
+.\" Please adjust this date whenever revising the manpage.
+.\"
+.\" Some roff macros, for reference:
+.\" .nh        disable hyphenation
+.\" .hy        enable hyphenation
+.\" .ad l      left justify
+.\" .ad b      justify to both left and right margins
+.\" .nf        disable filling
+.\" .fi        enable filling
+.\" .br        insert line break
+.\" .sp <n>    insert n+1 empty lines
+.\" for manpage-specific macros, see man(7)
+.SH NAME
+geteltorito \- an El Torito boot image extractor
+.SH SYNOPSIS
+.B geteltorito
+.RI < image | device >
+.RB [ \-o
+.IR outputfile ]
+.br
+.SH DESCRIPTION
+.B geteltorito
+is a Perl script which extracts the initial/default
+.B El Torito
+boot image from a CD if one exists. It will not extract any of other
+boot images that are allowed by the El Torito standard.
+.PP
+The boot image file is written to
+.B stdout
+and all other information (e.g., image type and size) is written to
+.BR stderr .
+To write the image to a file instead of
+.BR stdout ,
+specify the output filename using
+.B \-o
+.IR filename .
+
+.SH SEE ALSO
+.BR genisoimage (1),
+.BR isoinfo (1).
+.br
+.SH AUTHOR
+geteltorito was written by Rainer Krienke <krienke@uni-koblenz.de>.
+.PP
+This manual page was written by Eduard Bloch <blade@debian.org> based on
+README.geteltorito from geteltorito-0.4 package.
diff --git a/3rd-party/geteltorito/README.geteltorito b/3rd-party/geteltorito/README.geteltorito
new file mode 100644 (file)
index 0000000..383712f
--- /dev/null
@@ -0,0 +1,22 @@
+geteltorito
+===========
+
+Author: Rainer Krienke
+Email:  krienke@uni-koblenz.de
+License: GPL
+Version: 0.4
+Description: A El Torito boot image extractor
+
+call:  geteltorito CD-image > toritoimagefile
+example:geteltorito /dev/sr0  > /tmp/bootimage
+
+The perl-script will extract the initial/default boot image from a CD if
+existant. It will not extract any of other possibly existing bootimages
+that are allowed by the El Torito standard.
+The imagedata are written to STDOUT all other information is written to
+STDERR (eg type and size of image).
+If you want to write the image to a file instead of STDOUT you can
+secify the filename wanted on the commandline using option -o <filename>
+
+Rainer Krienke
+krienke@uni-koblenz.de
diff --git a/3rd-party/geteltorito/geteltorito.pl b/3rd-party/geteltorito/geteltorito.pl
new file mode 100644 (file)
index 0000000..28cdbb3
--- /dev/null
@@ -0,0 +1,214 @@
+#!/usr/bin/perl
+
+use Getopt::Std;
+
+#
+# geteltorito.pl: a bootimage extractor
+# Script that will extract the first El Torito bootimage from a
+# bootable CD image
+# R. Krienke 08/2001
+# krienke@uni-koblenz.de
+# License: GPL
+#
+# Get latest version from:
+# http://www.uni-koblenz.de/~krienke/ftp/noarch/geteltorito
+#
+$utilVersion="0.4"; 
+#
+# Version 0.4
+#    2007/02/01
+#    A patch from Santiago Garcia <manty@debian.org> to use a virtual sector
+#    size (vSecSize) of 512 bytes, as defined on "El Torito" specs and change
+#    unpack of the sector count from n to v to get the correct sector count.
+# Version 0.3
+#    2006/02/21
+#    A patch from  Ben Collins <bcollins@ubuntu.com> to make the 
+#    utility work on PPC machines (change from 'L'-encoding in pack to 'V')
+# Version 0.2
+#    Several patches included from Nathan Stratton Treadway(nathant@ontko.com)
+#    to adjust the platform output as well as fixes for other minor bugs
+# Version 0.1
+#    Initial release
+#
+# For information on El Torito see 
+# http://wikipedia.org/
+# or try this link directly:
+# http://www.phoenix.com/en/Customer+Services/White+Papers-Specs/Platform+System+Software+Documents/default.htm
+
+$vSecSize=512;
+$secSize=2048;
+$ret=undef;$version=undef;$opt_h=undef;$loadSegment=undef;$systemType=undef;
+
+#
+# Read a particular sector from a file
+# sector counting starts at 0, not 1
+#
+sub getSector{
+   my ($secNum, $secCount, $file)=@_;
+   my ($sec, $count);
+
+   open(FILE, $file) || die "Cannot open \"$file\" \n";
+
+   seek(FILE, $secNum*$secSize, 0);
+   $count=read(FILE, $sec, $vSecSize*$secCount, 0) ;
+   if( $count != $vSecSize*$secCount ){
+       warn "Error reading from file \"$file\"\n";
+   }
+   close(FILE);
+
+   return($sec);
+}
+
+
+#
+# Write eltorito data into a file
+#
+sub writeOutputFile{
+   my($name)=shift;
+   my($value)=shift;
+
+   open(OUT, ">".$name)|| die "$0: Cannot open outputfile \"$name\" for writing. Stop.";
+   print OUT $value;
+   close(OUT);
+}
+
+
+#
+# Usage
+#
+sub usage{
+       warn "\n$0 [-hv] [-o outputfilename] cd-image \n",
+           "Script will try to extract an El Torito image from a \n",
+           "bootable CD (or cd-image) given by <cd-image> and write \n",
+           "the data extracted to STDOUT or to a file.\n",
+           "   -h:        This help. \n",
+           "   -v:        Print version of script and exit.\n",
+           "   -o <file>: Write extracted data to file <file> instead of STDOUT.\n",
+           "\n\n";
+       exit 0;    
+}
+
+
+# ---------------------------------------------------------------------
+$ret=getopts('hvo:');
+if( defined($opt_v) ){
+       warn "Version: $utilVersion \n";
+       exit 0;
+}
+
+if( defined($opt_h) || $#ARGV <0 ){
+         usage(0);
+}       
+
+if( defined($opt_o) ){
+   $outputFilename="$opt_o";
+}
+        
+$imageFile=$ARGV[0];
+
+if( ! -r $imageFile ){
+       die "Cannot read image/device \"$imageFile\". Aborting\n";
+}
+
+#
+# Read Sector 17 from CD which should contain a Boot Record Volume
+# descriptor. This descriptor contains at its start the text ($isoIdent)
+# CD001     and ($toritoSpec)
+# EL TORITO SPECIFICATION
+# see http://www.cdpage.com/Compact_Disc_Variations/eltoritoi.html
+# for details
+#
+
+$sector=getSector(17, 1, $imageFile );
+($boot, $isoIdent, $version, $toritoSpec,
+       $unUsed, $bootP)= unpack( "Ca5CA32A32V", $sector );
+
+if( $isoIdent ne "CD001" || $toritoSpec ne "EL TORITO SPECIFICATION" ){
+       die "This data image does not seem to be a bootable CD-image\n";
+}      
+
+#
+# Now fetch the sector of the booting catalog 
+#
+$sector=getSector($bootP, 1, $imageFile );
+
+print STDERR "Booting catalog starts at sector: $bootP \n";
+
+# The first 32 bytes of this sector contains the validation entry for a
+# boot. The first byte has to be 01, the next byte determines the
+# architecture the image is designed for, where 00 is i86, 01 is PowerPC
+# and 02 is Mac. More data give info about manufacturer, etc.  The 
+# final two bytes must contain 0x55 and 0xAA respectively (as 
+# defined by the El Torito standard).
+
+$validateEntry=substr($sector, 0, 32);
+
+($header, $platform, $unUsed, $manufact, $unUsed, $five, $aa)=
+               unpack( "CCvA24vCC", $validateEntry);
+
+if( $header != 1 || $five != 0x55 || $aa != 0xaa ){
+       die "Invalid Validation Entry on image \n";
+}
+
+print STDERR "Manufacturer of CD: $manufact\n";
+print STDERR "Image architecture: ";
+print STDERR "x86" if( $platform == 0 );
+print STDERR "PowerPC" if( $platform == 1 );
+print STDERR "Mac" if( $platform == 2 );
+print STDERR "unknown ($platform)" if( $platform > 2 );
+print STDERR "\n";
+
+#
+# Now we examine the initial/defaultentry which follows the validate
+# entry and has a size of 32 bytes. 
+
+$initialEntry=substr($sector, 32, 32);
+
+($boot, $media, $loadSegment, $systemType, $unUsed, 
+       $sCount, $imgStart, $unUsed)=unpack( "CCvCCvVC", $initialEntry);
+
+if( $boot != 0x88 ){
+       die "Boot indicator in Initial/Default-Entry is not 0x88. CD is not bootable. \n";
+}    
+
+print STDERR "Boot media type is: ";
+if( $media == 0 ){
+       print STDERR "no emulation";
+       $count=0;
+}
+if( $media == 1 ){
+       print STDERR "1.2meg floppy";
+       $count=1200*1024/$vSecSize;  
+}
+if( $media == 2 ){
+       print STDERR "1.44meg floppy";
+       $count=1440*1024/$vSecSize;  
+}
+if( $media == 3 ){
+       print STDERR "2.88meg floppy";
+       $count=2880*1024/$vSecSize;  
+}
+if( $media == 4 ){
+       print STDERR "harddisk";
+       $count=0;
+}
+print STDERR "\n";
+
+# Only use the internal sector counter if the real size is unknown
+# ($count==0)
+$cnt=$count==0?$sCount:$count;
+
+print STDERR "El Torito image starts at sector $imgStart and has $cnt sector(s) of $vSecSize Bytes\n";
+
+# We are there:
+# Now read the bootimage to stdout
+$image=getSector($imgStart, $cnt, $imageFile);
+
+if( length($outputFilename) ){
+   writeOutputFile($outputFilename, $image);
+   print STDERR "\nImage has been written to file \"$outputFilename\".\n";
+}else{
+   print "$image";
+   print STDERR "Image has been written to stdout ....\n"; 
+}
diff --git a/3rd-party/zisofs_tools/CHANGES b/3rd-party/zisofs_tools/CHANGES
new file mode 100644 (file)
index 0000000..5a6fee1
--- /dev/null
@@ -0,0 +1,57 @@
+Changes in zisofs-tools-1.0.6:
+
+       Further portability fixes; use subsecond resolution if available.
+
+Changes in zisofs-tools-1.0.5:
+
+       Portability improvements.
+
+Changes in zisofs-tools-1.0.4:
+
+       Update the documentation.
+
+Changes in zisofs-tools-1.0.3:
+
+       Update cdrtools patch.
+
+Changes in zisofs-tools-1.0.2:
+
+       Add "make install" target :)
+
+Changes in zisofs-tools-1.0.1:
+
+       By default, abort if file modes, times and ownership cannot be
+       set.  Since this isn't always possible, add new option
+       -s/--sloppy to suppress this error.
+
+       Fix man page typo, and add a BUGS section.
+
+       Remove problems with extremely long symlinks.
+
+       Move all command line options into common "opt" structure.
+
+       Fix bug in command line parsing: -z option not recognized.
+
+
+Changes in zisofs-tools-1.0:
+
+       Restructured code; now split into a number of modules.
+
+       Use autoconf for configuration.
+
+       Add support for long options if the platform has
+       getopt_long().
+
+       Support compiling on systems without lchown().
+
+       Support the following new options:
+         -x    Don't descend into other filesystems
+         -X    Same as -x, but don't create mount point directories
+         -l    Don't descend into any subdirectories
+         -L    Same as -l, but don't create stub directories
+         -F    Allow compression or decompression of single files.
+         -V    Explicitly set the verbosity.
+         -w    Display program version.
+
+         Update the mkisofs patch to warn if -z is specified without
+         -r/-R.
diff --git a/3rd-party/zisofs_tools/CMakeLists.txt b/3rd-party/zisofs_tools/CMakeLists.txt
new file mode 100644 (file)
index 0000000..75068bf
--- /dev/null
@@ -0,0 +1,8 @@
+PROJECT (ZISOFSTOOLS C)
+ADD_DEFINITIONS(-Wall -W -Wpointer-arith -Wbad-function-cast -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wnested-externs -Winline -Wshadow -Wcast-align)
+AUX_SOURCE_DIRECTORY(. MKZ_SRCS)
+ADD_EXECUTABLE (mkzftree ${MKZ_SRCS})
+TARGET_LINK_LIBRARIES(mkzftree z)
+SET_TARGET_PROPERTIES(mkzftree PROPERTIES  SKIP_BUILD_RPATH TRUE)
+INSTALL(TARGETS mkzftree DESTINATION bin)
+INSTALL(FILES mkzftree.1 DESTINATION share/man/man1)
diff --git a/3rd-party/zisofs_tools/COPYING b/3rd-party/zisofs_tools/COPYING
new file mode 100644 (file)
index 0000000..d60c31a
--- /dev/null
@@ -0,0 +1,340 @@
+                   GNU GENERAL PUBLIC LICENSE
+                      Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                           Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+\f
+                   GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+\f
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+\f
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+\f
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                           NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                    END OF TERMS AND CONDITIONS
+\f
+           How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    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 of the License, 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year  name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/3rd-party/zisofs_tools/INSTALL b/3rd-party/zisofs_tools/INSTALL
new file mode 100644 (file)
index 0000000..b42a17a
--- /dev/null
@@ -0,0 +1,182 @@
+Basic Installation
+==================
+
+   These are generic installation instructions.
+
+   The `configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation.  It uses
+those values to create a `Makefile' in each directory of the package.
+It may also create one or more `.h' files containing system-dependent
+definitions.  Finally, it creates a shell script `config.status' that
+you can run in the future to recreate the current configuration, a file
+`config.cache' that saves the results of its tests to speed up
+reconfiguring, and a file `config.log' containing compiler output
+(useful mainly for debugging `configure').
+
+   If you need to do unusual things to compile the package, please try
+to figure out how `configure' could check whether to do them, and mail
+diffs or instructions to the address given in the `README' so they can
+be considered for the next release.  If at some point `config.cache'
+contains results you don't want to keep, you may remove or edit it.
+
+   The file `configure.in' is used to create `configure' by a program
+called `autoconf'.  You only need `configure.in' if you want to change
+it or regenerate `configure' using a newer version of `autoconf'.
+
+The simplest way to compile this package is:
+
+  1. `cd' to the directory containing the package's source code and type
+     `./configure' to configure the package for your system.  If you're
+     using `csh' on an old version of System V, you might need to type
+     `sh ./configure' instead to prevent `csh' from trying to execute
+     `configure' itself.
+
+     Running `configure' takes awhile.  While running, it prints some
+     messages telling which features it is checking for.
+
+  2. Type `make' to compile the package.
+
+  3. Optionally, type `make check' to run any self-tests that come with
+     the package.
+
+  4. Type `make install' to install the programs and any data files and
+     documentation.
+
+  5. You can remove the program binaries and object files from the
+     source code directory by typing `make clean'.  To also remove the
+     files that `configure' created (so you can compile the package for
+     a different kind of computer), type `make distclean'.  There is
+     also a `make maintainer-clean' target, but that is intended mainly
+     for the package's developers.  If you use it, you may have to get
+     all sorts of other programs in order to regenerate files that came
+     with the distribution.
+
+Compilers and Options
+=====================
+
+   Some systems require unusual options for compilation or linking that
+the `configure' script does not know about.  You can give `configure'
+initial values for variables by setting them in the environment.  Using
+a Bourne-compatible shell, you can do that on the command line like
+this:
+     CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure
+
+Or on systems that have the `env' program, you can do it like this:
+     env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure
+
+Compiling For Multiple Architectures
+====================================
+
+   You can compile the package for more than one kind of computer at the
+same time, by placing the object files for each architecture in their
+own directory.  To do this, you must use a version of `make' that
+supports the `VPATH' variable, such as GNU `make'.  `cd' to the
+directory where you want the object files and executables to go and run
+the `configure' script.  `configure' automatically checks for the
+source code in the directory that `configure' is in and in `..'.
+
+   If you have to use a `make' that does not supports the `VPATH'
+variable, you have to compile the package for one architecture at a time
+in the source code directory.  After you have installed the package for
+one architecture, use `make distclean' before reconfiguring for another
+architecture.
+
+Installation Names
+==================
+
+   By default, `make install' will install the package's files in
+`/usr/local/bin', `/usr/local/man', etc.  You can specify an
+installation prefix other than `/usr/local' by giving `configure' the
+option `--prefix=PATH'.
+
+   You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files.  If you
+give `configure' the option `--exec-prefix=PATH', the package will use
+PATH as the prefix for installing programs and libraries.
+Documentation and other data files will still use the regular prefix.
+
+   In addition, if you use an unusual directory layout you can give
+options like `--bindir=PATH' to specify different values for particular
+kinds of files.  Run `configure --help' for a list of the directories
+you can set and what kinds of files go in them.
+
+   If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving `configure' the
+option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
+
+Optional Features
+=================
+
+   Some packages pay attention to `--enable-FEATURE' options to
+`configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to `--with-PACKAGE' options, where PACKAGE
+is something like `gnu-as' or `x' (for the X Window System).  The
+`README' should mention any `--enable-' and `--with-' options that the
+package recognizes.
+
+   For packages that use the X Window System, `configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the `configure' options `--x-includes=DIR' and
+`--x-libraries=DIR' to specify their locations.
+
+Specifying the System Type
+==========================
+
+   There may be some features `configure' can not figure out
+automatically, but needs to determine by the type of host the package
+will run on.  Usually `configure' can figure that out, but if it prints
+a message saying it can not guess the host type, give it the
+`--host=TYPE' option.  TYPE can either be a short name for the system
+type, such as `sun4', or a canonical name with three fields:
+     CPU-COMPANY-SYSTEM
+
+See the file `config.sub' for the possible values of each field.  If
+`config.sub' isn't included in this package, then this package doesn't
+need to know the host type.
+
+   If you are building compiler tools for cross-compiling, you can also
+use the `--target=TYPE' option to select the type of system they will
+produce code for and the `--build=TYPE' option to select the type of
+system on which you are compiling the package.
+
+Sharing Defaults
+================
+
+   If you want to set default values for `configure' scripts to share,
+you can create a site shell script called `config.site' that gives
+default values for variables like `CC', `cache_file', and `prefix'.
+`configure' looks for `PREFIX/share/config.site' if it exists, then
+`PREFIX/etc/config.site' if it exists.  Or, you can set the
+`CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all `configure' scripts look for a site script.
+
+Operation Controls
+==================
+
+   `configure' recognizes the following options to control how it
+operates.
+
+`--cache-file=FILE'
+     Use and save the results of the tests in FILE instead of
+     `./config.cache'.  Set FILE to `/dev/null' to disable caching, for
+     debugging `configure'.
+
+`--help'
+     Print a summary of the options to `configure', and exit.
+
+`--quiet'
+`--silent'
+`-q'
+     Do not print messages saying which checks are being made.  To
+     suppress all normal output, redirect it to `/dev/null' (any error
+     messages will still be shown).
+
+`--srcdir=DIR'
+     Look for the package's source code in directory DIR.  Usually
+     `configure' can determine that directory automatically.
+
+`--version'
+     Print the version of Autoconf used to generate the `configure'
+     script, and exit.
+
+`configure' also accepts some other, not widely useful, options.
diff --git a/3rd-party/zisofs_tools/MCONFIG.in b/3rd-party/zisofs_tools/MCONFIG.in
new file mode 100644 (file)
index 0000000..1c0ba11
--- /dev/null
@@ -0,0 +1,38 @@
+# Prefixes
+prefix      = @prefix@
+exec_prefix = @exec_prefix@
+
+# Directory for user binaries
+bindir  = @bindir@
+
+# Man page tree
+mandir  = @mandir@
+
+# System binaries
+sbindir = @sbindir@
+
+# Install into chroot area
+# Useful when making rpms and similar
+INSTALLROOT = 
+
+# Install program
+INSTALL         = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA    = @INSTALL_DATA@
+
+# Compiler and compiler flags
+CC      = @CC@
+CFLAGS  = @CFLAGS@
+
+# Link flags
+LDFLAGS = @LDFLAGS@
+
+# Libraries
+LIBS    = @LIBS@
+
+# Additional library we need to build
+LIBOBJS        = @LIBOBJS@
+
+# ar and ranlib (for making libraries)
+AR     = ar cq
+RANLIB = @RANLIB@
diff --git a/3rd-party/zisofs_tools/MRULES b/3rd-party/zisofs_tools/MRULES
new file mode 100644 (file)
index 0000000..decd202
--- /dev/null
@@ -0,0 +1,22 @@
+# Standard compilation rules (don't use make builtins)
+
+.SUFFIXES: .c .cc .o .s .S .i
+
+.c.o:
+       $(CC) $(CFLAGS) -c $<
+
+.c.s:
+       $(CC) $(CFLAGS) -S -o $@ $<
+
+.c.i:
+       $(CC) $(CFLAGS) -E -o $@ $<
+
+.cc.o:
+       $(CXX) $(CXXFLAGS) -c $<
+
+.cc.s:
+       $(CXX) $(CXXFLAGS) -S -o $@ $<
+
+.cc.i:
+       $(CXX) $(CXXFLAGS) -E -o $@ $<
+
diff --git a/3rd-party/zisofs_tools/Makefile b/3rd-party/zisofs_tools/Makefile
new file mode 100644 (file)
index 0000000..d70dec6
--- /dev/null
@@ -0,0 +1,96 @@
+## -----------------------------------------------------------------------
+##   
+##   Copyright 2001 H. Peter Anvin - All Rights Reserved
+##
+##   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, Inc., 675 Mass Ave, Cambridge MA 02139,
+##   USA; either version 2 of the License, or (at your option) any later
+##   version; incorporated herein by reference.
+##
+## -----------------------------------------------------------------------
+
+##
+## Makefile for mkzftree
+##
+## mkzftree mirrors a tree in a form suitable for "mkisofs -z".
+##
+
+-include MCONFIG
+include MRULES
+
+PROGS     = mkzftree
+MAN1PAGES = mkzftree.1
+
+OBJS =         mkzftree.o walk.o workers.o util.o hash.o iso9660.o copytime.o \
+       compress.o uncompress.o
+
+all: $(PROGS)
+
+spec: zisofs-tools.spec
+
+clean:
+       rm -f *.o *.i *.s version.h $(PROGS)
+
+distclean: clean
+       rm -f MCONFIG config.status config.log config.h *~ \#*
+       rm -f core *.orig *.rej
+       rm -rf *.cache
+
+release:
+       $(MAKE) configure
+       $(MAKE) spec
+       $(MAKE) distclean
+
+mkzftree: $(OBJS)
+       $(CC) $(LDFLAGS) -o mkzftree $(OBJS) $(LIBS)
+
+spotless: distclean
+       rm -f configure config.h.in zisofs-tools.spec
+
+install: all
+       mkdir -p $(INSTALLROOT)$(bindir)
+       $(INSTALL_PROGRAM) $(PROGS) $(INSTALLROOT)$(bindir)
+       mkdir -p $(INSTALLROOT)$(mandir)/man1
+       $(INSTALL_DATA) $(MAN1PAGES) $(INSTALLROOT)$(mandir)/man1
+
+config:        MCONFIG
+
+MCONFIG: configure MCONFIG.in config.h.in
+       ./configure
+
+config.h: MCONFIG
+       : Generated by side effect
+
+config.h.in: configure.in
+       rm -f config.h.in
+       autoheader
+
+configure: configure.in aclocal.m4
+       autoconf
+       rm -f MCONFIG config.cache config.log config.status config.h
+
+#
+# Version header
+#
+VERSION = $(shell cat version)
+
+version.h: version
+       echo "#define ZISOFS_TOOLS_VERSION \"$(VERSION)\"" > version.h
+
+zisofs-tools.spec: zisofs-tools.spec.in version
+       sed -e 's/@@VERSION@@/$(VERSION)/g' < zisofs-tools.spec.in > $@
+
+#
+# Dependencies
+#
+mkzftree.o:    mkzftree.c mkzftree.h config.h version.h
+workers.o:     workers.c mkzftree.h config.h
+compress.o:    compress.c mkzftree.h config.h iso9660.h
+copytime.o:    copytime.c mkzftree.h config.h
+hash.o:                hash.c mkzftree.h config.h
+iso9660.o:     iso9660.c iso9660.h
+uncompress.o:  uncompress.c mkzftree.h config.h iso9660.h
+util.o:                util.c mkzftree.h config.h
+walk.o:                walk.c mkzftree.h config.h
+workers.o:     workers.c mkzftree.h config.h
diff --git a/3rd-party/zisofs_tools/README b/3rd-party/zisofs_tools/README
new file mode 100644 (file)
index 0000000..3bf8960
--- /dev/null
@@ -0,0 +1,44 @@
+                   H. Peter Anvin <hpa@zytor.com>
+                           June 13, 2004
+
+
+User tools for zisofs:
+
+The user tools for zisofs come in two parts: a utility "mkzftree" and
+mkisofs, which is part of the cdrtools package.  cdrtools 1.11a20 or
+later is required.
+
+First create a directory tree containing compressed files:
+
+       mkzftree input_dir compressed_dir
+
+mkzftree will not overwrite an existing directory; you may want to "rm
+-rf" the directory tree if you are doing this from a script:
+
+Second, invoke the patched mkisofs with the -z option:
+
+       mkisofs -z -R [other options] -o compressed.iso compressed_dir
+
+IMPORTANT: you *must* enable RockRidge (-R or -r) since this is an
+extensions to the RockRidge specification.  Without RockRidge, -z will
+have no effect.
+
+Note that if there are files you do not want compressed (for example,
+files involved in booting, or README files you want to be readable
+under all circumstances) you can simply put them in a separate tree
+and not run mkzftree on that tree.
+
+mkzftree will not compress files that end up larger when compressed;
+if you want it to compress the files anyway, you can give the -f
+option to mkzftree.
+
+mkzftree also accepts a -u option (uncompress), which can be used to
+convert a compressed tree back to normal form.  This can be used to
+read a zisofs CD-ROM on a machine without zisofs kernel support.
+
+This version of mkzftree supports a -p option (parallelize.)
+Specifying -p and a parallelism (e.g. -p4) allows files (up to the
+number specified) to compress in parallel.  Depending on your setup
+and your data set size, this might speed things up if you are not
+completely I/O bound.  Use -p0 to completely disable parallel
+execution; this is the default.
diff --git a/3rd-party/zisofs_tools/aclocal.m4 b/3rd-party/zisofs_tools/aclocal.m4
new file mode 100644 (file)
index 0000000..a3d8427
--- /dev/null
@@ -0,0 +1,35 @@
+dnl --------------------------------------------------------------------------
+dnl PA_ADD_CFLAGS()
+dnl
+dnl Attempt to add the given option to CFLAGS, if it doesn't break compilation
+dnl --------------------------------------------------------------------------
+AC_DEFUN(PA_ADD_CFLAGS,
+[AC_MSG_CHECKING([if $CC accepts $1])
+ pa_add_cflags__old_cflags="$CFLAGS"
+ CFLAGS="$CFLAGS $1"
+ AC_TRY_LINK([#include <stdio.h>],
+ [printf("Hello, World!\n");],
+ AC_MSG_RESULT([yes]),
+ AC_MSG_RESULT([no])
+ CFLAGS="$pa_add_cflags__old_cflags")])
+
+dnl ------------------------------------------------------------------------
+dnl  PA_WITH_BOOL
+dnl
+dnl  PA_WITH_BOOL(option, default, help, enable, disable)
+dnl
+dnl  Provides a more convenient way to specify --with-option and
+dnl  --without-option, with a default.  default should be either 0 or 1.
+dnl ------------------------------------------------------------------------
+AC_DEFUN(PA_WITH_BOOL,
+[AC_ARG_WITH([$1], [$3],
+if test ["$withval"] != no; then
+[$4]
+else
+[$5]
+fi,
+if test [$2] -ne 0; then
+[$4]
+else
+[$5]
+fi)])
diff --git a/3rd-party/zisofs_tools/compress.c b/3rd-party/zisofs_tools/compress.c
new file mode 100644 (file)
index 0000000..56f0af0
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* $Id: compress.c,v 1.4 2006/07/04 04:57:42 hpa Exp $ */
+/* ----------------------------------------------------------------------- *
+ *   
+ *   Copyright 2001-2006 H. Peter Anvin - All Rights Reserved
+ *
+ *   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, Inc., 675 Mass Ave, Cambridge MA 02139,
+ *   USA; either version 2 of the License, or (at your option) any later
+ *   version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+#include "mkzftree.h"          /* Must be included first! */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <utime.h>
+#include <unistd.h>
+#include <zlib.h>
+
+#include "iso9660.h"
+
+
+int block_compress_file(FILE *input, FILE *output, off_t size)
+{
+  struct compressed_file_header hdr;
+  Bytef inbuf[CBLOCK_SIZE], outbuf[2*CBLOCK_SIZE];
+  size_t bytes, pointer_bytes, nblocks, block;
+  uLong cbytes;                        /* uLong is a zlib datatype */
+  char *pointer_block, *curptr;
+  off_t position;
+  int i;
+  int force_compress = opt.force;
+  int zerr;
+  int err = EX_SOFTWARE;
+  
+  if ( (sizeof hdr) & 3 ) {
+    fputs("INTERNAL ERROR: header is not a multiple of 4\n", stderr);
+    abort();
+  }
+
+  memset(&hdr, 0, sizeof hdr);
+  memcpy(&hdr.magic, zisofs_magic, sizeof zisofs_magic);
+  hdr.header_size = (sizeof hdr) >> 2;
+  hdr.block_size = CBLOCK_SIZE_LG2;
+  set_731(&hdr.uncompressed_len, size);
+
+  if ( fwrite(&hdr, sizeof hdr, 1, output) != 1 )
+    return EX_CANTCREAT;
+
+  nblocks = (size+CBLOCK_SIZE-1) >> CBLOCK_SIZE_LG2;
+  pointer_bytes = 4*(nblocks+1);
+  pointer_block = xmalloc(pointer_bytes);
+  memset(pointer_block, 0, pointer_bytes);
+
+  if ( fseek(output, pointer_bytes, SEEK_CUR) == -1 ) {
+    err = EX_CANTCREAT;
+    goto free_ptr_bail;
+  }
+
+  curptr = pointer_block;
+  position = sizeof hdr + pointer_bytes;
+  
+  block = 0;
+  while ( (bytes = fread(inbuf, 1, CBLOCK_SIZE, input)) > 0 ) {
+    if ( bytes < CBLOCK_SIZE && block < nblocks-1 ) {
+      err = EX_IOERR;
+      goto free_ptr_bail;
+    }
+
+    /* HACK: If the file has our magic number, always compress */
+    if ( block == 0 && bytes >= sizeof zisofs_magic ) {
+      if ( !memcmp(inbuf, zisofs_magic, sizeof zisofs_magic) )
+       force_compress = 1;
+    }
+
+    set_731(curptr, position); curptr += 4;
+    
+    /* We have two special cases: a zero-length block is defined as all zero,
+       and a block the length of which is equal to the block size is unencoded. */
+
+    for ( i = 0 ; i < (int)CBLOCK_SIZE ; i++ ) {
+      if ( inbuf[i] ) break;
+    }
+
+    if ( i == CBLOCK_SIZE ) {
+      /* All-zero block.  No output */
+    } else {
+      cbytes = 2*CBLOCK_SIZE;
+      if ( (zerr = compress2(outbuf, &cbytes, inbuf, bytes, opt.level))
+          != Z_OK ) {
+       err = (zerr == Z_MEM_ERROR) ? EX_OSERR : EX_SOFTWARE;
+       goto free_ptr_bail;     /* Compression failure */
+      }
+      if ( fwrite(outbuf, 1, cbytes, output) != cbytes ) {
+       err = EX_CANTCREAT;
+       goto free_ptr_bail;
+      }
+      position += cbytes;
+    }
+    block++;
+  }
+
+  /* Set pointer to the end of the final block */
+  set_731(curptr, position);
+
+  /* Now write the pointer table */
+  if ( fseek(output, sizeof hdr, SEEK_SET) == -1 ||
+       fwrite(pointer_block, 1, pointer_bytes, output) != pointer_bytes ) {
+    err = EX_CANTCREAT;
+    goto free_ptr_bail;
+  }
+
+  free(pointer_block);
+
+  /* Now make sure that this was actually the right thing to do */
+  if ( !force_compress && position >= size ) {
+    /* Incompressible file, just copy it */
+    rewind(input);
+    rewind(output);
+
+    position = 0;
+    while ( (bytes = fread(inbuf, 1, CBLOCK_SIZE, input)) > 0 ) {
+      if ( fwrite(inbuf, 1, bytes, output) != bytes )
+       return EX_CANTCREAT;
+      position += bytes;
+    }
+
+    /* Truncate the file to the correct size */
+    fflush(output);
+    ftruncate(fileno(output), position);
+  }
+
+  /* If we get here, we're done! */
+  return 0;
+
+  /* Common bailout code */
+ free_ptr_bail:
+  free(pointer_block);
+  return err;
+}
+
diff --git a/3rd-party/zisofs_tools/config.h.in b/3rd-party/zisofs_tools/config.h.in
new file mode 100644 (file)
index 0000000..c2103bb
--- /dev/null
@@ -0,0 +1,99 @@
+/* config.h.in.  Generated from configure.in by autoheader.  */
+
+/* Define to 1 if you have the <endian.h> header file. */
+#undef HAVE_ENDIAN_H
+
+/* Define to 1 if you have the <getopt.h> header file. */
+#undef HAVE_GETOPT_H
+
+/* Define to 1 if you have the `getopt_long' function */
+#undef HAVE_GETOPT_LONG
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if you have the `lchown' function. */
+#undef HAVE_LCHOWN
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if `struct stat.st_[mca]tim' are struct timespec */
+#undef HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
+
+/* Define to 1 if `struct stat.st_[mca]tim' are struct timeval */
+#undef HAVE_STRUCT_STAT_ST_MTIM_TV_USEC
+
+/* Define to 1 if you have the <sysexits.h> header file. */
+#undef HAVE_SYSEXITS_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define to 1 if you have the `utimes' function. */
+#undef HAVE_UTIMES
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+#undef _FILE_OFFSET_BITS
+
+/* Enable GNU extensions on systems that have them.  */
+#ifndef _GNU_SOURCE
+# undef _GNU_SOURCE
+#endif
+
+/* Define for large files, on AIX-style hosts. */
+#undef _LARGE_FILES
+
+/* Define to empty if `const' does not conform to ANSI C. */
+#undef const
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+   calls it, or to nothing if 'inline' is not supported under any name.  */
+#ifndef __cplusplus
+#undef inline
+#endif
+
+/* Define to `signed long' if <sys/types.h> does not define. */
+#undef off_t
+
+/* Define to `unsigned long' if <sys/types.h> does not define. */
+#undef size_t
+
+/* Define to `signed long' if <sys/types.h> does not define. */
+#undef ssize_t
diff --git a/3rd-party/zisofs_tools/configure b/3rd-party/zisofs_tools/configure
new file mode 100755 (executable)
index 0000000..251af8c
--- /dev/null
@@ -0,0 +1,7907 @@
+#! /bin/sh
+# From configure.in Id: configure.in,v 1.7 2004/07/20 04:04:22 hpa Exp .
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.60a.
+#
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
+# 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## --------------------- ##
+## M4sh Initialization.  ##
+## --------------------- ##
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac
+fi
+BIN_SH=xpg4; export BIN_SH # for Tru64
+DUALCASE=1; export DUALCASE # for MKS sh
+
+
+# PATH needs CR
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  echo "#! /bin/sh" >conf$$.sh
+  echo  "exit 0"   >>conf$$.sh
+  chmod +x conf$$.sh
+  if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+    PATH_SEPARATOR=';'
+  else
+    PATH_SEPARATOR=:
+  fi
+  rm -f conf$$.sh
+fi
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+  as_unset=unset
+else
+  as_unset=false
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.  Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+as_nl='
+'
+IFS=" ""       $as_nl"
+
+# Find who we are.  Look in the path if we contain no directory separator.
+case $0 in
+  *[\\/]* ) as_myself=$0 ;;
+  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+IFS=$as_save_IFS
+
+     ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+  as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+  echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+  { (exit 1); exit 1; }
+fi
+
+# Work around bugs in pre-3.0 UWIN ksh.
+for as_var in ENV MAIL MAILPATH
+do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+  LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+  LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+  LC_TELEPHONE LC_TIME
+do
+  if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+    eval $as_var=C; export $as_var
+  else
+    ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+  fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+        X"$0" : 'X\(//\)$' \| \
+        X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{
+           s//\1/
+           q
+         }
+         /^X\/\(\/\/\)$/{
+           s//\1/
+           q
+         }
+         /^X\/\(\/\).*/{
+           s//\1/
+           q
+         }
+         s/.*/./; q'`
+
+# CDPATH.
+$as_unset CDPATH
+
+
+if test "x$CONFIG_SHELL" = x; then
+  if (eval ":") 2>/dev/null; then
+  as_have_required=yes
+else
+  as_have_required=no
+fi
+
+  if test $as_have_required = yes &&    (eval ":
+(as_func_return () {
+  (exit \$1)
+}
+as_func_success () {
+  as_func_return 0
+}
+as_func_failure () {
+  as_func_return 1
+}
+as_func_ret_success () {
+  return 0
+}
+as_func_ret_failure () {
+  return 1
+}
+
+exitcode=0
+if as_func_success; then
+  :
+else
+  exitcode=1
+  echo as_func_success failed.
+fi
+
+if as_func_failure; then
+  exitcode=1
+  echo as_func_failure succeeded.
+fi
+
+if as_func_ret_success; then
+  :
+else
+  exitcode=1
+  echo as_func_ret_success failed.
+fi
+
+if as_func_ret_failure; then
+  exitcode=1
+  echo as_func_ret_failure succeeded.
+fi
+
+if ( set x; as_func_ret_success y && test x = \"\$1\" ); then
+  :
+else
+  exitcode=1
+  echo positional parameters were not saved.
+fi
+
+test \$exitcode = 0) || { (exit 1); exit 1; }
+
+(
+  as_lineno_1=\$LINENO
+  as_lineno_2=\$LINENO
+  test \"x\$as_lineno_1\" != \"x\$as_lineno_2\" &&
+  test \"x\`expr \$as_lineno_1 + 1\`\" = \"x\$as_lineno_2\") || { (exit 1); exit 1; }
+") 2> /dev/null; then
+  :
+else
+  as_candidate_shells=
+    as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /usr/bin/posix$PATH_SEPARATOR/bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  case $as_dir in
+        /*)
+          for as_base in sh bash ksh sh5; do
+            as_candidate_shells="$as_candidate_shells $as_dir/$as_base"
+          done;;
+       esac
+done
+IFS=$as_save_IFS
+
+
+      for as_shell in $as_candidate_shells $SHELL; do
+        # Try only shells that exist, to save several forks.
+        if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+               { ("$as_shell") 2> /dev/null <<\_ASEOF
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac
+fi
+BIN_SH=xpg4; export BIN_SH # for Tru64
+DUALCASE=1; export DUALCASE # for MKS sh
+
+:
+_ASEOF
+}; then
+  CONFIG_SHELL=$as_shell
+              as_have_required=yes
+              if { "$as_shell" 2> /dev/null <<\_ASEOF
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac
+fi
+BIN_SH=xpg4; export BIN_SH # for Tru64
+DUALCASE=1; export DUALCASE # for MKS sh
+
+:
+(as_func_return () {
+  (exit $1)
+}
+as_func_success () {
+  as_func_return 0
+}
+as_func_failure () {
+  as_func_return 1
+}
+as_func_ret_success () {
+  return 0
+}
+as_func_ret_failure () {
+  return 1
+}
+
+exitcode=0
+if as_func_success; then
+  :
+else
+  exitcode=1
+  echo as_func_success failed.
+fi
+
+if as_func_failure; then
+  exitcode=1
+  echo as_func_failure succeeded.
+fi
+
+if as_func_ret_success; then
+  :
+else
+  exitcode=1
+  echo as_func_ret_success failed.
+fi
+
+if as_func_ret_failure; then
+  exitcode=1
+  echo as_func_ret_failure succeeded.
+fi
+
+if ( set x; as_func_ret_success y && test x = "$1" ); then
+  :
+else
+  exitcode=1
+  echo positional parameters were not saved.
+fi
+
+test $exitcode = 0) || { (exit 1); exit 1; }
+
+(
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2") || { (exit 1); exit 1; }
+
+_ASEOF
+}; then
+  break
+fi
+
+fi
+
+      done
+
+      if test "x$CONFIG_SHELL" != x; then
+  for as_var in BASH_ENV ENV
+        do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+        done
+        export CONFIG_SHELL
+        exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"}
+fi
+
+
+    if test $as_have_required = no; then
+  echo This script requires a shell more modern than all the
+      echo shells that I found on your system.  Please install a
+      echo modern shell, or manually run the script under such a
+      echo shell if you do have one.
+      { (exit 1); exit 1; }
+fi
+
+
+fi
+
+fi
+
+
+
+(eval "as_func_return () {
+  (exit \$1)
+}
+as_func_success () {
+  as_func_return 0
+}
+as_func_failure () {
+  as_func_return 1
+}
+as_func_ret_success () {
+  return 0
+}
+as_func_ret_failure () {
+  return 1
+}
+
+exitcode=0
+if as_func_success; then
+  :
+else
+  exitcode=1
+  echo as_func_success failed.
+fi
+
+if as_func_failure; then
+  exitcode=1
+  echo as_func_failure succeeded.
+fi
+
+if as_func_ret_success; then
+  :
+else
+  exitcode=1
+  echo as_func_ret_success failed.
+fi
+
+if as_func_ret_failure; then
+  exitcode=1
+  echo as_func_ret_failure succeeded.
+fi
+
+if ( set x; as_func_ret_success y && test x = \"\$1\" ); then
+  :
+else
+  exitcode=1
+  echo positional parameters were not saved.
+fi
+
+test \$exitcode = 0") || {
+  echo No shell found that supports shell functions.
+  echo Please tell autoconf@gnu.org about your system,
+  echo including any error possibly output before this
+  echo message
+}
+
+
+
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || {
+
+  # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+  # uniformly replaced by the line number.  The first 'sed' inserts a
+  # line-number line after each line using $LINENO; the second 'sed'
+  # does the real work.  The second script uses 'N' to pair each
+  # line-number line with the line containing $LINENO, and appends
+  # trailing '-' during substitution so that $LINENO is not a special
+  # case at line end.
+  # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+  # scripts with optimization help from Paolo Bonzini.  Blame Lee
+  # E. McMahon (1931-1989) for sed's syntax.  :-)
+  sed -n '
+    p
+    /[$]LINENO/=
+  ' <$as_myself |
+    sed '
+      s/[$]LINENO.*/&-/
+      t lineno
+      b
+      :lineno
+      N
+      :loop
+      s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+      t loop
+      s/-\n.*//
+    ' >$as_me.lineno &&
+  chmod +x "$as_me.lineno" ||
+    { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
+   { (exit 1); exit 1; }; }
+
+  # Don't try to exec as it changes $[0], causing all sort of problems
+  # (the dirname of $[0] is not the place where we might find the
+  # original and so on.  Autoconf is especially sensitive to this).
+  . "./$as_me.lineno"
+  # Exit status is that of the last command.
+  exit
+}
+
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+  as_dirname=dirname
+else
+  as_dirname=false
+fi
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in
+-n*)
+  case `echo 'x\c'` in
+  *c*) ECHO_T='        ';;     # ECHO_T is single tab character.
+  *)   ECHO_C='\c';;
+  esac;;
+*)
+  ECHO_N='-n';;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+  rm -f conf$$.dir/conf$$.file
+else
+  rm -f conf$$.dir
+  mkdir conf$$.dir
+fi
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+  as_ln_s='ln -s'
+  # ... but there are two gotchas:
+  # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+  # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+  # In both cases, we have to default to `cp -p'.
+  ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+    as_ln_s='cp -p'
+elif ln conf$$.file conf$$ 2>/dev/null; then
+  as_ln_s=ln
+else
+  as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p=:
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+# Find out whether ``test -x'' works.  Don't use a zero-byte file, as
+# systems may use methods other than mode bits to determine executability.
+cat >conf$$.file <<_ASEOF
+#! /bin/sh
+exit 0
+_ASEOF
+chmod +x conf$$.file
+if test -x conf$$.file >/dev/null 2>&1; then
+  as_executable_p="test -x"
+else
+  as_executable_p=:
+fi
+rm -f conf$$.file
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+
+exec 7<&0 </dev/null 6>&1
+
+# Name of the host.
+# hostname on some systems (SVR3.2, Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_clean_files=
+ac_config_libobj_dir=.
+LIBOBJS=
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+# Identity of this package.
+PACKAGE_NAME=
+PACKAGE_TARNAME=
+PACKAGE_VERSION=
+PACKAGE_STRING=
+PACKAGE_BUGREPORT=
+
+ac_unique_file="MCONFIG.in"
+ac_default_prefix=/usr
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# ifdef HAVE_STDLIB_H
+#  include <stdlib.h>
+# endif
+#endif
+#ifdef HAVE_STRING_H
+# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+#  include <memory.h>
+# endif
+# include <string.h>
+#endif
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+ac_subst_vars='SHELL
+PATH_SEPARATOR
+PACKAGE_NAME
+PACKAGE_TARNAME
+PACKAGE_VERSION
+PACKAGE_STRING
+PACKAGE_BUGREPORT
+exec_prefix
+prefix
+program_transform_name
+bindir
+sbindir
+libexecdir
+datarootdir
+datadir
+sysconfdir
+sharedstatedir
+localstatedir
+includedir
+oldincludedir
+docdir
+infodir
+htmldir
+dvidir
+pdfdir
+psdir
+libdir
+localedir
+mandir
+DEFS
+ECHO_C
+ECHO_N
+ECHO_T
+LIBS
+build_alias
+host_alias
+target_alias
+CC
+CFLAGS
+LDFLAGS
+CPPFLAGS
+ac_ct_CC
+EXEEXT
+OBJEXT
+CPP
+GREP
+EGREP
+RANLIB
+INSTALL_PROGRAM
+INSTALL_SCRIPT
+INSTALL_DATA
+LIBOBJS
+LTLIBOBJS'
+ac_subst_files=''
+      ac_precious_vars='build_alias
+host_alias
+target_alias
+CC
+CFLAGS
+LDFLAGS
+CPPFLAGS
+CPP'
+
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+# (The list follows the same order as the GNU Coding Standards.)
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datarootdir='${prefix}/share'
+datadir='${datarootdir}'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+docdir='${datarootdir}/doc/${PACKAGE}'
+infodir='${datarootdir}/info'
+htmldir='${docdir}'
+dvidir='${docdir}'
+pdfdir='${docdir}'
+psdir='${docdir}'
+libdir='${exec_prefix}/lib'
+localedir='${datarootdir}/locale'
+mandir='${datarootdir}/man'
+
+ac_prev=
+ac_dashdash=
+for ac_option
+do
+  # If the previous option needs an argument, assign it.
+  if test -n "$ac_prev"; then
+    eval $ac_prev=\$ac_option
+    ac_prev=
+    continue
+  fi
+
+  case $ac_option in
+  *=*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+  *)   ac_optarg=yes ;;
+  esac
+
+  # Accept the important Cygnus configure options, so we can diagnose typos.
+
+  case $ac_dashdash$ac_option in
+  --)
+    ac_dashdash=yes ;;
+
+  -bindir | --bindir | --bindi | --bind | --bin | --bi)
+    ac_prev=bindir ;;
+  -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+    bindir=$ac_optarg ;;
+
+  -build | --build | --buil | --bui | --bu)
+    ac_prev=build_alias ;;
+  -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+    build_alias=$ac_optarg ;;
+
+  -cache-file | --cache-file | --cache-fil | --cache-fi \
+  | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+    ac_prev=cache_file ;;
+  -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+  | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+    cache_file=$ac_optarg ;;
+
+  --config-cache | -C)
+    cache_file=config.cache ;;
+
+  -datadir | --datadir | --datadi | --datad)
+    ac_prev=datadir ;;
+  -datadir=* | --datadir=* | --datadi=* | --datad=*)
+    datadir=$ac_optarg ;;
+
+  -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
+  | --dataroo | --dataro | --datar)
+    ac_prev=datarootdir ;;
+  -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
+  | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
+    datarootdir=$ac_optarg ;;
+
+  -disable-* | --disable-*)
+    ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+   { (exit 1); exit 1; }; }
+    ac_feature=`echo $ac_feature | sed 's/-/_/g'`
+    eval enable_$ac_feature=no ;;
+
+  -docdir | --docdir | --docdi | --doc | --do)
+    ac_prev=docdir ;;
+  -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
+    docdir=$ac_optarg ;;
+
+  -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
+    ac_prev=dvidir ;;
+  -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
+    dvidir=$ac_optarg ;;
+
+  -enable-* | --enable-*)
+    ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+   { (exit 1); exit 1; }; }
+    ac_feature=`echo $ac_feature | sed 's/-/_/g'`
+    eval enable_$ac_feature=\$ac_optarg ;;
+
+  -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+  | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+  | --exec | --exe | --ex)
+    ac_prev=exec_prefix ;;
+  -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+  | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+  | --exec=* | --exe=* | --ex=*)
+    exec_prefix=$ac_optarg ;;
+
+  -gas | --gas | --ga | --g)
+    # Obsolete; use --with-gas.
+    with_gas=yes ;;
+
+  -help | --help | --hel | --he | -h)
+    ac_init_help=long ;;
+  -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+    ac_init_help=recursive ;;
+  -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+    ac_init_help=short ;;
+
+  -host | --host | --hos | --ho)
+    ac_prev=host_alias ;;
+  -host=* | --host=* | --hos=* | --ho=*)
+    host_alias=$ac_optarg ;;
+
+  -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
+    ac_prev=htmldir ;;
+  -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
+  | --ht=*)
+    htmldir=$ac_optarg ;;
+
+  -includedir | --includedir | --includedi | --included | --include \
+  | --includ | --inclu | --incl | --inc)
+    ac_prev=includedir ;;
+  -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+  | --includ=* | --inclu=* | --incl=* | --inc=*)
+    includedir=$ac_optarg ;;
+
+  -infodir | --infodir | --infodi | --infod | --info | --inf)
+    ac_prev=infodir ;;
+  -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+    infodir=$ac_optarg ;;
+
+  -libdir | --libdir | --libdi | --libd)
+    ac_prev=libdir ;;
+  -libdir=* | --libdir=* | --libdi=* | --libd=*)
+    libdir=$ac_optarg ;;
+
+  -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+  | --libexe | --libex | --libe)
+    ac_prev=libexecdir ;;
+  -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+  | --libexe=* | --libex=* | --libe=*)
+    libexecdir=$ac_optarg ;;
+
+  -localedir | --localedir | --localedi | --localed | --locale)
+    ac_prev=localedir ;;
+  -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
+    localedir=$ac_optarg ;;
+
+  -localstatedir | --localstatedir | --localstatedi | --localstated \
+  | --localstate | --localstat | --localsta | --localst | --locals)
+    ac_prev=localstatedir ;;
+  -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+  | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
+    localstatedir=$ac_optarg ;;
+
+  -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+    ac_prev=mandir ;;
+  -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+    mandir=$ac_optarg ;;
+
+  -nfp | --nfp | --nf)
+    # Obsolete; use --without-fp.
+    with_fp=no ;;
+
+  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+  | --no-cr | --no-c | -n)
+    no_create=yes ;;
+
+  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+    no_recursion=yes ;;
+
+  -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+  | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+  | --oldin | --oldi | --old | --ol | --o)
+    ac_prev=oldincludedir ;;
+  -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+  | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+  | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+    oldincludedir=$ac_optarg ;;
+
+  -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+    ac_prev=prefix ;;
+  -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+    prefix=$ac_optarg ;;
+
+  -program-prefix | --program-prefix | --program-prefi | --program-pref \
+  | --program-pre | --program-pr | --program-p)
+    ac_prev=program_prefix ;;
+  -program-prefix=* | --program-prefix=* | --program-prefi=* \
+  | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+    program_prefix=$ac_optarg ;;
+
+  -program-suffix | --program-suffix | --program-suffi | --program-suff \
+  | --program-suf | --program-su | --program-s)
+    ac_prev=program_suffix ;;
+  -program-suffix=* | --program-suffix=* | --program-suffi=* \
+  | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+    program_suffix=$ac_optarg ;;
+
+  -program-transform-name | --program-transform-name \
+  | --program-transform-nam | --program-transform-na \
+  | --program-transform-n | --program-transform- \
+  | --program-transform | --program-transfor \
+  | --program-transfo | --program-transf \
+  | --program-trans | --program-tran \
+  | --progr-tra | --program-tr | --program-t)
+    ac_prev=program_transform_name ;;
+  -program-transform-name=* | --program-transform-name=* \
+  | --program-transform-nam=* | --program-transform-na=* \
+  | --program-transform-n=* | --program-transform-=* \
+  | --program-transform=* | --program-transfor=* \
+  | --program-transfo=* | --program-transf=* \
+  | --program-trans=* | --program-tran=* \
+  | --progr-tra=* | --program-tr=* | --program-t=*)
+    program_transform_name=$ac_optarg ;;
+
+  -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
+    ac_prev=pdfdir ;;
+  -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
+    pdfdir=$ac_optarg ;;
+
+  -psdir | --psdir | --psdi | --psd | --ps)
+    ac_prev=psdir ;;
+  -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
+    psdir=$ac_optarg ;;
+
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil)
+    silent=yes ;;
+
+  -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+    ac_prev=sbindir ;;
+  -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+  | --sbi=* | --sb=*)
+    sbindir=$ac_optarg ;;
+
+  -sharedstatedir | --sharedstatedir | --sharedstatedi \
+  | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+  | --sharedst | --shareds | --shared | --share | --shar \
+  | --sha | --sh)
+    ac_prev=sharedstatedir ;;
+  -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+  | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+  | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+  | --sha=* | --sh=*)
+    sharedstatedir=$ac_optarg ;;
+
+  -site | --site | --sit)
+    ac_prev=site ;;
+  -site=* | --site=* | --sit=*)
+    site=$ac_optarg ;;
+
+  -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+    ac_prev=srcdir ;;
+  -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+    srcdir=$ac_optarg ;;
+
+  -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+  | --syscon | --sysco | --sysc | --sys | --sy)
+    ac_prev=sysconfdir ;;
+  -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+  | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+    sysconfdir=$ac_optarg ;;
+
+  -target | --target | --targe | --targ | --tar | --ta | --t)
+    ac_prev=target_alias ;;
+  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+    target_alias=$ac_optarg ;;
+
+  -v | -verbose | --verbose | --verbos | --verbo | --verb)
+    verbose=yes ;;
+
+  -version | --version | --versio | --versi | --vers | -V)
+    ac_init_version=: ;;
+
+  -with-* | --with-*)
+    ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid package name: $ac_package" >&2
+   { (exit 1); exit 1; }; }
+    ac_package=`echo $ac_package| sed 's/-/_/g'`
+    eval with_$ac_package=\$ac_optarg ;;
+
+  -without-* | --without-*)
+    ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid package name: $ac_package" >&2
+   { (exit 1); exit 1; }; }
+    ac_package=`echo $ac_package | sed 's/-/_/g'`
+    eval with_$ac_package=no ;;
+
+  --x)
+    # Obsolete; use --with-x.
+    with_x=yes ;;
+
+  -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+  | --x-incl | --x-inc | --x-in | --x-i)
+    ac_prev=x_includes ;;
+  -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+  | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+    x_includes=$ac_optarg ;;
+
+  -x-libraries | --x-libraries | --x-librarie | --x-librari \
+  | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+    ac_prev=x_libraries ;;
+  -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+  | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+    x_libraries=$ac_optarg ;;
+
+  -*) { echo "$as_me: error: unrecognized option: $ac_option
+Try \`$0 --help' for more information." >&2
+   { (exit 1); exit 1; }; }
+    ;;
+
+  *=*)
+    ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid variable name: $ac_envvar" >&2
+   { (exit 1); exit 1; }; }
+    eval $ac_envvar=\$ac_optarg
+    export $ac_envvar ;;
+
+  *)
+    # FIXME: should be removed in autoconf 3.0.
+    echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+    expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+      echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+    : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}
+    ;;
+
+  esac
+done
+
+if test -n "$ac_prev"; then
+  ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+  { echo "$as_me: error: missing argument to $ac_option" >&2
+   { (exit 1); exit 1; }; }
+fi
+
+# Be sure to have absolute directory names.
+for ac_var in  exec_prefix prefix bindir sbindir libexecdir datarootdir \
+               datadir sysconfdir sharedstatedir localstatedir includedir \
+               oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
+               libdir localedir mandir
+do
+  eval ac_val=\$$ac_var
+  case $ac_val in
+    [\\/$]* | ?:[\\/]* )  continue;;
+    NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
+  esac
+  { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+   { (exit 1); exit 1; }; }
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+  if test "x$build_alias" = x; then
+    cross_compiling=maybe
+    echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host.
+    If a cross compiler is detected then cross compile mode will be used." >&2
+  elif test "x$build_alias" != "x$host_alias"; then
+    cross_compiling=yes
+  fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+ac_pwd=`pwd` && test -n "$ac_pwd" &&
+ac_ls_di=`ls -di .` &&
+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
+  { echo "$as_me: error: Working directory cannot be determined" >&2
+   { (exit 1); exit 1; }; }
+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
+  { echo "$as_me: error: pwd does not report name of working directory" >&2
+   { (exit 1); exit 1; }; }
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+  ac_srcdir_defaulted=yes
+  # Try the directory containing this script, then the parent directory.
+  ac_confdir=`$as_dirname -- "$0" ||
+$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X"$0" : 'X\(//\)[^/]' \| \
+        X"$0" : 'X\(//\)$' \| \
+        X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$0" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)[^/].*/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\).*/{
+           s//\1/
+           q
+         }
+         s/.*/./; q'`
+  srcdir=$ac_confdir
+  if test ! -r "$srcdir/$ac_unique_file"; then
+    srcdir=..
+  fi
+else
+  ac_srcdir_defaulted=no
+fi
+if test ! -r "$srcdir/$ac_unique_file"; then
+  test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
+  { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2
+   { (exit 1); exit 1; }; }
+fi
+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
+ac_abs_confdir=`(
+       cd "$srcdir" && test -r "./$ac_unique_file" || { echo "$as_me: error: $ac_msg" >&2
+   { (exit 1); exit 1; }; }
+       pwd)`
+# When building in place, set srcdir=.
+if test "$ac_abs_confdir" = "$ac_pwd"; then
+  srcdir=.
+fi
+# Remove unnecessary trailing slashes from srcdir.
+# Double slashes in file names in object file debugging info
+# mess up M-x gdb in Emacs.
+case $srcdir in
+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
+esac
+for ac_var in $ac_precious_vars; do
+  eval ac_env_${ac_var}_set=\${${ac_var}+set}
+  eval ac_env_${ac_var}_value=\$${ac_var}
+  eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
+  eval ac_cv_env_${ac_var}_value=\$${ac_var}
+done
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+  # Omit some internal or obsolete options to make the list less imposing.
+  # This message is too long to be a string in the A/UX 3.1 sh.
+  cat <<_ACEOF
+\`configure' configures this package to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE.  See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+  -h, --help              display this help and exit
+      --help=short        display options specific to this package
+      --help=recursive    display the short help of all the included packages
+  -V, --version           display version information and exit
+  -q, --quiet, --silent   do not print \`checking...' messages
+      --cache-file=FILE   cache test results in FILE [disabled]
+  -C, --config-cache      alias for \`--cache-file=config.cache'
+  -n, --no-create         do not create output files
+      --srcdir=DIR        find the sources in DIR [configure dir or \`..']
+
+Installation directories:
+  --prefix=PREFIX         install architecture-independent files in PREFIX
+                         [$ac_default_prefix]
+  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
+                         [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc.  You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+  --bindir=DIR           user executables [EPREFIX/bin]
+  --sbindir=DIR          system admin executables [EPREFIX/sbin]
+  --libexecdir=DIR       program executables [EPREFIX/libexec]
+  --sysconfdir=DIR       read-only single-machine data [PREFIX/etc]
+  --sharedstatedir=DIR   modifiable architecture-independent data [PREFIX/com]
+  --localstatedir=DIR    modifiable single-machine data [PREFIX/var]
+  --libdir=DIR           object code libraries [EPREFIX/lib]
+  --includedir=DIR       C header files [PREFIX/include]
+  --oldincludedir=DIR    C header files for non-gcc [/usr/include]
+  --datarootdir=DIR      read-only arch.-independent data root [PREFIX/share]
+  --datadir=DIR          read-only architecture-independent data [DATAROOTDIR]
+  --infodir=DIR          info documentation [DATAROOTDIR/info]
+  --localedir=DIR        locale-dependent data [DATAROOTDIR/locale]
+  --mandir=DIR           man documentation [DATAROOTDIR/man]
+  --docdir=DIR           documentation root [DATAROOTDIR/doc/PACKAGE]
+  --htmldir=DIR          html documentation [DOCDIR]
+  --dvidir=DIR           dvi documentation [DOCDIR]
+  --pdfdir=DIR           pdf documentation [DOCDIR]
+  --psdir=DIR            ps documentation [DOCDIR]
+_ACEOF
+
+  cat <<\_ACEOF
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+
+  cat <<\_ACEOF
+
+Optional Features:
+  --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
+  --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
+  --disable-largefile     omit support for large files
+
+Some influential environment variables:
+  CC          C compiler command
+  CFLAGS      C compiler flags
+  LDFLAGS     linker flags, e.g. -L<lib dir> if you have libraries in a
+              nonstandard directory <lib dir>
+  CPPFLAGS    C/C++/Objective C preprocessor flags, e.g. -I<include dir> if
+              you have headers in a nonstandard directory <include dir>
+  CPP         C preprocessor
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+_ACEOF
+ac_status=$?
+fi
+
+if test "$ac_init_help" = "recursive"; then
+  # If there are subdirs, report their specific --help.
+  for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+    test -d "$ac_dir" || continue
+    ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+  ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+  # A ".." for each directory in $ac_dir_suffix.
+  ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'`
+  case $ac_top_builddir_sub in
+  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+  esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+  .)  # We are building in place.
+    ac_srcdir=.
+    ac_top_srcdir=$ac_top_builddir_sub
+    ac_abs_top_srcdir=$ac_pwd ;;
+  [\\/]* | ?:[\\/]* )  # Absolute name.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir
+    ac_abs_top_srcdir=$srcdir ;;
+  *) # Relative name.
+    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_build_prefix$srcdir
+    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+    cd "$ac_dir" || { ac_status=$?; continue; }
+    # Check for guested configure.
+    if test -f "$ac_srcdir/configure.gnu"; then
+      echo &&
+      $SHELL "$ac_srcdir/configure.gnu" --help=recursive
+    elif test -f "$ac_srcdir/configure"; then
+      echo &&
+      $SHELL "$ac_srcdir/configure" --help=recursive
+    else
+      echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+    fi || ac_status=$?
+    cd "$ac_pwd" || { ac_status=$?; break; }
+  done
+fi
+
+test -n "$ac_init_help" && exit $ac_status
+if $ac_init_version; then
+  cat <<\_ACEOF
+configure
+generated by GNU Autoconf 2.60a
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
+2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+  exit
+fi
+cat >config.log <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by $as_me, which was
+generated by GNU Autoconf 2.60a.  Invocation command line was
+
+  $ $0 $@
+
+_ACEOF
+exec 5>>config.log
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null     || echo unknown`
+
+/bin/arch              = `(/bin/arch) 2>/dev/null              || echo unknown`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null       || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+/usr/bin/hostinfo      = `(/usr/bin/hostinfo) 2>/dev/null      || echo unknown`
+/bin/machine           = `(/bin/machine) 2>/dev/null           || echo unknown`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null       || echo unknown`
+/bin/universe          = `(/bin/universe) 2>/dev/null          || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  echo "PATH: $as_dir"
+done
+IFS=$as_save_IFS
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+  for ac_arg
+  do
+    case $ac_arg in
+    -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+    -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+    | -silent | --silent | --silen | --sile | --sil)
+      continue ;;
+    *\'*)
+      ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    esac
+    case $ac_pass in
+    1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;;
+    2)
+      ac_configure_args1="$ac_configure_args1 '$ac_arg'"
+      if test $ac_must_keep_next = true; then
+       ac_must_keep_next=false # Got value, back to normal.
+      else
+       case $ac_arg in
+         *=* | --config-cache | -C | -disable-* | --disable-* \
+         | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+         | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+         | -with-* | --with-* | -without-* | --without-* | --x)
+           case "$ac_configure_args0 " in
+             "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+           esac
+           ;;
+         -* ) ac_must_keep_next=true ;;
+       esac
+      fi
+      ac_configure_args="$ac_configure_args '$ac_arg'"
+      ;;
+    esac
+  done
+done
+$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; }
+$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; }
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log.  We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Use '\'' to represent an apostrophe within the trap.
+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
+trap 'exit_status=$?
+  # Save into config.log some information that might help in debugging.
+  {
+    echo
+
+    cat <<\_ASBOX
+## ---------------- ##
+## Cache variables. ##
+## ---------------- ##
+_ASBOX
+    echo
+    # The following way of writing the cache mishandles newlines in values,
+(
+  for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
+    eval ac_val=\$$ac_var
+    case $ac_val in #(
+    *${as_nl}*)
+      case $ac_var in #(
+      *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5
+echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;;
+      esac
+      case $ac_var in #(
+      _ | IFS | as_nl) ;; #(
+      *) $as_unset $ac_var ;;
+      esac ;;
+    esac
+  done
+  (set) 2>&1 |
+    case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
+    *${as_nl}ac_space=\ *)
+      sed -n \
+       "s/'\''/'\''\\\\'\'''\''/g;
+         s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
+      ;; #(
+    *)
+      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+      ;;
+    esac |
+    sort
+)
+    echo
+
+    cat <<\_ASBOX
+## ----------------- ##
+## Output variables. ##
+## ----------------- ##
+_ASBOX
+    echo
+    for ac_var in $ac_subst_vars
+    do
+      eval ac_val=\$$ac_var
+      case $ac_val in
+      *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+      esac
+      echo "$ac_var='\''$ac_val'\''"
+    done | sort
+    echo
+
+    if test -n "$ac_subst_files"; then
+      cat <<\_ASBOX
+## ------------------- ##
+## File substitutions. ##
+## ------------------- ##
+_ASBOX
+      echo
+      for ac_var in $ac_subst_files
+      do
+       eval ac_val=\$$ac_var
+       case $ac_val in
+       *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+       esac
+       echo "$ac_var='\''$ac_val'\''"
+      done | sort
+      echo
+    fi
+
+    if test -s confdefs.h; then
+      cat <<\_ASBOX
+## ----------- ##
+## confdefs.h. ##
+## ----------- ##
+_ASBOX
+      echo
+      cat confdefs.h
+      echo
+    fi
+    test "$ac_signal" != 0 &&
+      echo "$as_me: caught signal $ac_signal"
+    echo "$as_me: exit $exit_status"
+  } >&5
+  rm -f core *.core core.conftest.* &&
+    rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
+    exit $exit_status
+' 0
+for ac_signal in 1 2 13 15; do
+  trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -f -r conftest* confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer explicitly selected file to automatically selected ones.
+if test -n "$CONFIG_SITE"; then
+  set x "$CONFIG_SITE"
+elif test "x$prefix" != xNONE; then
+  set x "$prefix/share/config.site" "$prefix/etc/config.site"
+else
+  set x "$ac_default_prefix/share/config.site" \
+       "$ac_default_prefix/etc/config.site"
+fi
+shift
+for ac_site_file
+do
+  if test -r "$ac_site_file"; then
+    { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5
+echo "$as_me: loading site script $ac_site_file" >&6;}
+    sed 's/^/| /' "$ac_site_file" >&5
+    . "$ac_site_file"
+  fi
+done
+
+if test -r "$cache_file"; then
+  # Some versions of bash will fail to source /dev/null (special
+  # files actually), so we avoid doing that.
+  if test -f "$cache_file"; then
+    { echo "$as_me:$LINENO: loading cache $cache_file" >&5
+echo "$as_me: loading cache $cache_file" >&6;}
+    case $cache_file in
+      [\\/]* | ?:[\\/]* ) . "$cache_file";;
+      *)                      . "./$cache_file";;
+    esac
+  fi
+else
+  { echo "$as_me:$LINENO: creating cache $cache_file" >&5
+echo "$as_me: creating cache $cache_file" >&6;}
+  >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in $ac_precious_vars; do
+  eval ac_old_set=\$ac_cv_env_${ac_var}_set
+  eval ac_new_set=\$ac_env_${ac_var}_set
+  eval ac_old_val=\$ac_cv_env_${ac_var}_value
+  eval ac_new_val=\$ac_env_${ac_var}_value
+  case $ac_old_set,$ac_new_set in
+    set,)
+      { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,set)
+      { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,);;
+    *)
+      if test "x$ac_old_val" != "x$ac_new_val"; then
+       { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5
+echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+       { echo "$as_me:$LINENO:   former value:  $ac_old_val" >&5
+echo "$as_me:   former value:  $ac_old_val" >&2;}
+       { echo "$as_me:$LINENO:   current value: $ac_new_val" >&5
+echo "$as_me:   current value: $ac_new_val" >&2;}
+       ac_cache_corrupted=:
+      fi;;
+  esac
+  # Pass precious variables to config.status.
+  if test "$ac_new_set" = set; then
+    case $ac_new_val in
+    *\'*) ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+    *) ac_arg=$ac_var=$ac_new_val ;;
+    esac
+    case " $ac_configure_args " in
+      *" '$ac_arg' "*) ;; # Avoid dups.  Use of quotes ensures accuracy.
+      *) ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+    esac
+  fi
+done
+if $ac_cache_corrupted; then
+  { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5
+echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+  { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5
+echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_CC="${ac_tool_prefix}gcc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+  ac_ct_CC=$CC
+  # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_CC="gcc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+else
+  CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+          if test -n "$ac_tool_prefix"; then
+    # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_CC="${ac_tool_prefix}cc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+  fi
+fi
+if test -z "$CC"; then
+  # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+    if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+       ac_prog_rejected=yes
+       continue
+     fi
+    ac_cv_prog_CC="cc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+  # We found a bogon in the path, so make sure we never use it.
+  set dummy $ac_cv_prog_CC
+  shift
+  if test $# != 0; then
+    # We chose a different compiler from the bogus one.
+    # However, it has the same basename, so the bogon will be chosen
+    # first if we set CC to just the basename; use the full file name.
+    shift
+    ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+  fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+  if test -n "$ac_tool_prefix"; then
+  for ac_prog in cl.exe
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+    test -n "$CC" && break
+  done
+fi
+if test -z "$CC"; then
+  ac_ct_CC=$CC
+  for ac_prog in cl.exe
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_CC="$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+  test -n "$ac_ct_CC" && break
+done
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+fi
+
+fi
+
+
+test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&5
+echo "$as_me: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+
+# Provide some information about the compiler.
+echo "$as_me:$LINENO: checking for C compiler version" >&5
+ac_compiler=`set X $ac_compile; echo $2`
+{ (ac_try="$ac_compiler --version >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compiler --version >&5") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (ac_try="$ac_compiler -v >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compiler -v >&5") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (ac_try="$ac_compiler -V >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compiler -V >&5") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+{ echo "$as_me:$LINENO: checking for C compiler default output file name" >&5
+echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6; }
+ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+#
+# List of possible output files, starting from the most likely.
+# The algorithm is not robust to junk in `.', hence go to wildcards (a.*)
+# only as a last resort.  b.out is created by i960 compilers.
+ac_files='a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out'
+#
+# The IRIX 6 linker writes into existing files which may not be
+# executable, retaining their permissions.  Remove them first so a
+# subsequent execution test works.
+ac_rmfiles=
+for ac_file in $ac_files
+do
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;;
+    * ) ac_rmfiles="$ac_rmfiles $ac_file";;
+  esac
+done
+rm -f $ac_rmfiles
+
+if { (ac_try="$ac_link_default"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link_default") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
+# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
+# in a Makefile.  We should not override ac_cv_exeext if it was cached,
+# so that the user can short-circuit this test for compilers unknown to
+# Autoconf.
+for ac_file in $ac_files ''
+do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj )
+       ;;
+    [ab].out )
+       # We found the default executable, but exeext='' is most
+       # certainly right.
+       break;;
+    *.* )
+        if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+       then :; else
+          ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+       fi
+       # We set ac_cv_exeext here because the later test for it is not
+       # safe: cross compilers may not add the suffix if given an `-o'
+       # argument, so we may need to know it at that point already.
+       # Even if this section looks crufty: it has the advantage of
+       # actually working.
+       break;;
+    * )
+       break;;
+  esac
+done
+test "$ac_cv_exeext" = no && ac_cv_exeext=
+
+else
+  ac_file=''
+fi
+
+{ echo "$as_me:$LINENO: result: $ac_file" >&5
+echo "${ECHO_T}$ac_file" >&6; }
+if test -z "$ac_file"; then
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: C compiler cannot create executables
+See \`config.log' for more details." >&5
+echo "$as_me: error: C compiler cannot create executables
+See \`config.log' for more details." >&2;}
+   { (exit 77); exit 77; }; }
+fi
+
+ac_exeext=$ac_cv_exeext
+
+# Check that the compiler produces executables we can run.  If not, either
+# the compiler is broken, or we cross compile.
+{ echo "$as_me:$LINENO: checking whether the C compiler works" >&5
+echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6; }
+# FIXME: These cross compiler hacks should be removed for Autoconf 3.0
+# If not cross compiling, check that we can run a simple program.
+if test "$cross_compiling" != yes; then
+  if { ac_try='./$ac_file'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+    cross_compiling=no
+  else
+    if test "$cross_compiling" = maybe; then
+       cross_compiling=yes
+    else
+       { { echo "$as_me:$LINENO: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+    fi
+  fi
+fi
+{ echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+
+rm -f a.out a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+# Check that the compiler produces executables we can run.  If not, either
+# the compiler is broken, or we cross compile.
+{ echo "$as_me:$LINENO: checking whether we are cross compiling" >&5
+echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6; }
+{ echo "$as_me:$LINENO: result: $cross_compiling" >&5
+echo "${ECHO_T}$cross_compiling" >&6; }
+
+{ echo "$as_me:$LINENO: checking for suffix of executables" >&5
+echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6; }
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'.  For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;;
+    *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+         break;;
+    * ) break;;
+  esac
+done
+else
+  { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest$ac_cv_exeext
+{ echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5
+echo "${ECHO_T}$ac_cv_exeext" >&6; }
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+{ echo "$as_me:$LINENO: checking for suffix of object files" >&5
+echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6; }
+if test "${ac_cv_objext+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  for ac_file in conftest.o conftest.obj conftest.*; do
+  test -f "$ac_file" || continue;
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf ) ;;
+    *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+       break;;
+  esac
+done
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_objext" >&5
+echo "${ECHO_T}$ac_cv_objext" >&6; }
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+{ echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5
+echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6; }
+if test "${ac_cv_c_compiler_gnu+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_compiler_gnu=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_compiler_gnu=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5
+echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6; }
+GCC=`test $ac_compiler_gnu = yes && echo yes`
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5
+echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6; }
+if test "${ac_cv_prog_cc_g+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_save_c_werror_flag=$ac_c_werror_flag
+   ac_c_werror_flag=yes
+   ac_cv_prog_cc_g=no
+   CFLAGS="-g"
+   cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_prog_cc_g=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       CFLAGS=""
+      cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_c_werror_flag=$ac_save_c_werror_flag
+        CFLAGS="-g"
+        cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_prog_cc_g=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+   ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_g" >&6; }
+if test "$ac_test_CFLAGS" = set; then
+  CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+  if test "$GCC" = yes; then
+    CFLAGS="-g -O2"
+  else
+    CFLAGS="-g"
+  fi
+else
+  if test "$GCC" = yes; then
+    CFLAGS="-O2"
+  else
+    CFLAGS=
+  fi
+fi
+{ echo "$as_me:$LINENO: checking for $CC option to accept ISO C89" >&5
+echo $ECHO_N "checking for $CC option to accept ISO C89... $ECHO_C" >&6; }
+if test "${ac_cv_prog_cc_c89+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh.  */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+     char **p;
+     int i;
+{
+  return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+  char *s;
+  va_list v;
+  va_start (v,p);
+  s = g (p, va_arg (v,int));
+  va_end (v);
+  return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default.  It has
+   function prototypes and stuff, but not '\xHH' hex character constants.
+   These don't provoke an error unfortunately, instead are silently treated
+   as 'x'.  The following induces an error, until -std is added to get
+   proper ANSI mode.  Curiously '\x00'!='x' always comes out true, for an
+   array size at least.  It's necessary to write '\x00'==0 to get something
+   that's true only with -std.  */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+   inside strings and character constants.  */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0]  ||  f (e, argv, 1) != argv[1];
+  ;
+  return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+       -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+  CC="$ac_save_CC $ac_arg"
+  rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_prog_cc_c89=$ac_arg
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext
+  test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+  x)
+    { echo "$as_me:$LINENO: result: none needed" >&5
+echo "${ECHO_T}none needed" >&6; } ;;
+  xno)
+    { echo "$as_me:$LINENO: result: unsupported" >&5
+echo "${ECHO_T}unsupported" >&6; } ;;
+  *)
+    CC="$CC $ac_cv_prog_cc_c89"
+    { echo "$as_me:$LINENO: result: $ac_cv_prog_cc_c89" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+cat >>confdefs.h <<\_ACEOF
+#define _GNU_SOURCE 1
+_ACEOF
+
+
+
+# Check whether --enable-largefile was given.
+if test "${enable_largefile+set}" = set; then
+  enableval=$enable_largefile;
+fi
+
+if test "$enable_largefile" != no; then
+
+  { echo "$as_me:$LINENO: checking for special C compiler options needed for large files" >&5
+echo $ECHO_N "checking for special C compiler options needed for large files... $ECHO_C" >&6; }
+if test "${ac_cv_sys_largefile_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_sys_largefile_CC=no
+     if test "$GCC" != yes; then
+       ac_save_CC=$CC
+       while :; do
+        # IRIX 6.2 and later do not support large files by default,
+        # so use the C compiler's -n32 option if that helps.
+        cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+    We can't simply define LARGE_OFF_T to be 9223372036854775807,
+    since some C++ compilers masquerading as C compilers
+    incorrectly reject 9223372036854775807.  */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+                      && LARGE_OFF_T % 2147483647 == 1)
+                     ? 1 : -1];
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+        rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext
+        CC="$CC -n32"
+        rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_sys_largefile_CC=' -n32'; break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext
+        break
+       done
+       CC=$ac_save_CC
+       rm -f conftest.$ac_ext
+    fi
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_sys_largefile_CC" >&5
+echo "${ECHO_T}$ac_cv_sys_largefile_CC" >&6; }
+  if test "$ac_cv_sys_largefile_CC" != no; then
+    CC=$CC$ac_cv_sys_largefile_CC
+  fi
+
+  { echo "$as_me:$LINENO: checking for _FILE_OFFSET_BITS value needed for large files" >&5
+echo $ECHO_N "checking for _FILE_OFFSET_BITS value needed for large files... $ECHO_C" >&6; }
+if test "${ac_cv_sys_file_offset_bits+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  while :; do
+  ac_cv_sys_file_offset_bits=no
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+    We can't simply define LARGE_OFF_T to be 9223372036854775807,
+    since some C++ compilers masquerading as C compilers
+    incorrectly reject 9223372036854775807.  */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+                      && LARGE_OFF_T % 2147483647 == 1)
+                     ? 1 : -1];
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#define _FILE_OFFSET_BITS 64
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+    We can't simply define LARGE_OFF_T to be 9223372036854775807,
+    since some C++ compilers masquerading as C compilers
+    incorrectly reject 9223372036854775807.  */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+                      && LARGE_OFF_T % 2147483647 == 1)
+                     ? 1 : -1];
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_sys_file_offset_bits=64; break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  break
+done
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_sys_file_offset_bits" >&5
+echo "${ECHO_T}$ac_cv_sys_file_offset_bits" >&6; }
+if test "$ac_cv_sys_file_offset_bits" != no; then
+
+cat >>confdefs.h <<_ACEOF
+#define _FILE_OFFSET_BITS $ac_cv_sys_file_offset_bits
+_ACEOF
+
+fi
+rm -f conftest*
+  { echo "$as_me:$LINENO: checking for _LARGE_FILES value needed for large files" >&5
+echo $ECHO_N "checking for _LARGE_FILES value needed for large files... $ECHO_C" >&6; }
+if test "${ac_cv_sys_large_files+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  while :; do
+  ac_cv_sys_large_files=no
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+    We can't simply define LARGE_OFF_T to be 9223372036854775807,
+    since some C++ compilers masquerading as C compilers
+    incorrectly reject 9223372036854775807.  */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+                      && LARGE_OFF_T % 2147483647 == 1)
+                     ? 1 : -1];
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#define _LARGE_FILES 1
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+    We can't simply define LARGE_OFF_T to be 9223372036854775807,
+    since some C++ compilers masquerading as C compilers
+    incorrectly reject 9223372036854775807.  */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+                      && LARGE_OFF_T % 2147483647 == 1)
+                     ? 1 : -1];
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_sys_large_files=1; break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  break
+done
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_sys_large_files" >&5
+echo "${ECHO_T}$ac_cv_sys_large_files" >&6; }
+if test "$ac_cv_sys_large_files" != no; then
+
+cat >>confdefs.h <<_ACEOF
+#define _LARGE_FILES $ac_cv_sys_large_files
+_ACEOF
+
+fi
+rm -f conftest*
+fi
+
+{ echo "$as_me:$LINENO: checking for an ANSI C-conforming const" >&5
+echo $ECHO_N "checking for an ANSI C-conforming const... $ECHO_C" >&6; }
+if test "${ac_cv_c_const+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+/* FIXME: Include the comments suggested by Paul. */
+#ifndef __cplusplus
+  /* Ultrix mips cc rejects this.  */
+  typedef int charset[2];
+  const charset cs;
+  /* SunOS 4.1.1 cc rejects this.  */
+  char const *const *pcpcc;
+  char **ppc;
+  /* NEC SVR4.0.2 mips cc rejects this.  */
+  struct point {int x, y;};
+  static struct point const zero = {0,0};
+  /* AIX XL C 1.02.0.0 rejects this.
+     It does not let you subtract one const X* pointer from another in
+     an arm of an if-expression whose if-part is not a constant
+     expression */
+  const char *g = "string";
+  pcpcc = &g + (g ? g-g : 0);
+  /* HPUX 7.0 cc rejects these. */
+  ++pcpcc;
+  ppc = (char**) pcpcc;
+  pcpcc = (char const *const *) ppc;
+  { /* SCO 3.2v4 cc rejects this.  */
+    char *t;
+    char const *s = 0 ? (char *) 0 : (char const *) 0;
+
+    *t++ = 0;
+    if (s) return 0;
+  }
+  { /* Someone thinks the Sun supposedly-ANSI compiler will reject this.  */
+    int x[] = {25, 17};
+    const int *foo = &x[0];
+    ++foo;
+  }
+  { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */
+    typedef const int *iptr;
+    iptr p = 0;
+    ++p;
+  }
+  { /* AIX XL C 1.02.0.0 rejects this saying
+       "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */
+    struct s { int j; const int *ap[3]; };
+    struct s *b; b->j = 5;
+  }
+  { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */
+    const int foo = 10;
+    if (!foo) return 0;
+  }
+  return !cs[0] && !zero.x;
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_c_const=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_cv_c_const=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_c_const" >&5
+echo "${ECHO_T}$ac_cv_c_const" >&6; }
+if test $ac_cv_c_const = no; then
+
+cat >>confdefs.h <<\_ACEOF
+#define const
+_ACEOF
+
+fi
+
+{ echo "$as_me:$LINENO: checking for inline" >&5
+echo $ECHO_N "checking for inline... $ECHO_C" >&6; }
+if test "${ac_cv_c_inline+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_c_inline=no
+for ac_kw in inline __inline__ __inline; do
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#ifndef __cplusplus
+typedef int foo_t;
+static $ac_kw foo_t static_foo () {return 0; }
+$ac_kw foo_t foo () {return 0; }
+#endif
+
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_c_inline=$ac_kw
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  test "$ac_cv_c_inline" != no && break
+done
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_c_inline" >&5
+echo "${ECHO_T}$ac_cv_c_inline" >&6; }
+
+
+case $ac_cv_c_inline in
+  inline | yes) ;;
+  *)
+    case $ac_cv_c_inline in
+      no) ac_val=;;
+      *) ac_val=$ac_cv_c_inline;;
+    esac
+    cat >>confdefs.h <<_ACEOF
+#ifndef __cplusplus
+#define inline $ac_val
+#endif
+_ACEOF
+    ;;
+esac
+
+
+{ echo "$as_me:$LINENO: checking if $CC accepts -Wall" >&5
+echo $ECHO_N "checking if $CC accepts -Wall... $ECHO_C" >&6; }
+ pa_add_cflags__old_cflags="$CFLAGS"
+ CFLAGS="$CFLAGS -Wall"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdio.h>
+int
+main ()
+{
+printf("Hello, World!\n");
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+ CFLAGS="$pa_add_cflags__old_cflags"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+{ echo "$as_me:$LINENO: checking if $CC accepts -W" >&5
+echo $ECHO_N "checking if $CC accepts -W... $ECHO_C" >&6; }
+ pa_add_cflags__old_cflags="$CFLAGS"
+ CFLAGS="$CFLAGS -W"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdio.h>
+int
+main ()
+{
+printf("Hello, World!\n");
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+ CFLAGS="$pa_add_cflags__old_cflags"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+{ echo "$as_me:$LINENO: checking if $CC accepts -Wpointer-arith" >&5
+echo $ECHO_N "checking if $CC accepts -Wpointer-arith... $ECHO_C" >&6; }
+ pa_add_cflags__old_cflags="$CFLAGS"
+ CFLAGS="$CFLAGS -Wpointer-arith"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdio.h>
+int
+main ()
+{
+printf("Hello, World!\n");
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+ CFLAGS="$pa_add_cflags__old_cflags"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+{ echo "$as_me:$LINENO: checking if $CC accepts -Wbad-function-cast" >&5
+echo $ECHO_N "checking if $CC accepts -Wbad-function-cast... $ECHO_C" >&6; }
+ pa_add_cflags__old_cflags="$CFLAGS"
+ CFLAGS="$CFLAGS -Wbad-function-cast"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdio.h>
+int
+main ()
+{
+printf("Hello, World!\n");
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+ CFLAGS="$pa_add_cflags__old_cflags"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+{ echo "$as_me:$LINENO: checking if $CC accepts -Wcast-equal" >&5
+echo $ECHO_N "checking if $CC accepts -Wcast-equal... $ECHO_C" >&6; }
+ pa_add_cflags__old_cflags="$CFLAGS"
+ CFLAGS="$CFLAGS -Wcast-equal"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdio.h>
+int
+main ()
+{
+printf("Hello, World!\n");
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+ CFLAGS="$pa_add_cflags__old_cflags"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+{ echo "$as_me:$LINENO: checking if $CC accepts -Wstrict-prototypes" >&5
+echo $ECHO_N "checking if $CC accepts -Wstrict-prototypes... $ECHO_C" >&6; }
+ pa_add_cflags__old_cflags="$CFLAGS"
+ CFLAGS="$CFLAGS -Wstrict-prototypes"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdio.h>
+int
+main ()
+{
+printf("Hello, World!\n");
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+ CFLAGS="$pa_add_cflags__old_cflags"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+{ echo "$as_me:$LINENO: checking if $CC accepts -Wmissing-prototypes" >&5
+echo $ECHO_N "checking if $CC accepts -Wmissing-prototypes... $ECHO_C" >&6; }
+ pa_add_cflags__old_cflags="$CFLAGS"
+ CFLAGS="$CFLAGS -Wmissing-prototypes"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdio.h>
+int
+main ()
+{
+printf("Hello, World!\n");
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+ CFLAGS="$pa_add_cflags__old_cflags"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+{ echo "$as_me:$LINENO: checking if $CC accepts -Wmissing-declarations" >&5
+echo $ECHO_N "checking if $CC accepts -Wmissing-declarations... $ECHO_C" >&6; }
+ pa_add_cflags__old_cflags="$CFLAGS"
+ CFLAGS="$CFLAGS -Wmissing-declarations"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdio.h>
+int
+main ()
+{
+printf("Hello, World!\n");
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+ CFLAGS="$pa_add_cflags__old_cflags"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+{ echo "$as_me:$LINENO: checking if $CC accepts -Wnested-externs" >&5
+echo $ECHO_N "checking if $CC accepts -Wnested-externs... $ECHO_C" >&6; }
+ pa_add_cflags__old_cflags="$CFLAGS"
+ CFLAGS="$CFLAGS -Wnested-externs"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdio.h>
+int
+main ()
+{
+printf("Hello, World!\n");
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+ CFLAGS="$pa_add_cflags__old_cflags"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+{ echo "$as_me:$LINENO: checking if $CC accepts -Winline" >&5
+echo $ECHO_N "checking if $CC accepts -Winline... $ECHO_C" >&6; }
+ pa_add_cflags__old_cflags="$CFLAGS"
+ CFLAGS="$CFLAGS -Winline"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdio.h>
+int
+main ()
+{
+printf("Hello, World!\n");
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+ CFLAGS="$pa_add_cflags__old_cflags"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+{ echo "$as_me:$LINENO: checking if $CC accepts -Wshadow" >&5
+echo $ECHO_N "checking if $CC accepts -Wshadow... $ECHO_C" >&6; }
+ pa_add_cflags__old_cflags="$CFLAGS"
+ CFLAGS="$CFLAGS -Wshadow"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdio.h>
+int
+main ()
+{
+printf("Hello, World!\n");
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+ CFLAGS="$pa_add_cflags__old_cflags"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+{ echo "$as_me:$LINENO: checking if $CC accepts -Wcast-align" >&5
+echo $ECHO_N "checking if $CC accepts -Wcast-align... $ECHO_C" >&6; }
+ pa_add_cflags__old_cflags="$CFLAGS"
+ CFLAGS="$CFLAGS -Wcast-align"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdio.h>
+int
+main ()
+{
+printf("Hello, World!\n");
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+ CFLAGS="$pa_add_cflags__old_cflags"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+{ echo "$as_me:$LINENO: checking if $CC accepts -pipe" >&5
+echo $ECHO_N "checking if $CC accepts -pipe... $ECHO_C" >&6; }
+ pa_add_cflags__old_cflags="$CFLAGS"
+ CFLAGS="$CFLAGS -pipe"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdio.h>
+int
+main ()
+{
+printf("Hello, World!\n");
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+ CFLAGS="$pa_add_cflags__old_cflags"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5
+echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6; }
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+  CPP=
+fi
+if test -z "$CPP"; then
+  if test "${ac_cv_prog_CPP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+      # Double quotes because CPP needs to be expanded
+    for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+    do
+      ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+                    Syntax error
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Broken: fails on valid input.
+continue
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  # Broken: success on invalid input.
+continue
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+  break
+fi
+
+    done
+    ac_cv_prog_CPP=$CPP
+
+fi
+  CPP=$ac_cv_prog_CPP
+else
+  ac_cv_prog_CPP=$CPP
+fi
+{ echo "$as_me:$LINENO: result: $CPP" >&5
+echo "${ECHO_T}$CPP" >&6; }
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+                    Syntax error
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Broken: fails on valid input.
+continue
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  # Broken: success on invalid input.
+continue
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+  :
+else
+  { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&5
+echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+{ echo "$as_me:$LINENO: checking for grep that handles long lines and -e" >&5
+echo $ECHO_N "checking for grep that handles long lines and -e... $ECHO_C" >&6; }
+if test "${ac_cv_path_GREP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  # Extract the first word of "grep ggrep" to use in msg output
+if test -z "$GREP"; then
+set dummy grep ggrep; ac_prog_name=$2
+if test "${ac_cv_path_GREP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_path_GREP_found=false
+# Loop through the user's path and test for each of PROGNAME-LIST
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_prog in grep ggrep; do
+  for ac_exec_ext in '' $ac_executable_extensions; do
+    ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
+    { test -f "$ac_path_GREP" && $as_executable_p "$ac_path_GREP"; } || continue
+    # Check for GNU ac_path_GREP and select it if it is found.
+  # Check for GNU $ac_path_GREP
+case `"$ac_path_GREP" --version 2>&1` in
+*GNU*)
+  ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
+*)
+  ac_count=0
+  echo $ECHO_N "0123456789$ECHO_C" >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    echo 'GREP' >> "conftest.nl"
+    "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    ac_count=`expr $ac_count + 1`
+    if test $ac_count -gt ${ac_path_GREP_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_GREP="$ac_path_GREP"
+      ac_path_GREP_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+
+    $ac_path_GREP_found && break 3
+  done
+done
+
+done
+IFS=$as_save_IFS
+
+
+fi
+
+GREP="$ac_cv_path_GREP"
+if test -z "$GREP"; then
+  { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5
+echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+else
+  ac_cv_path_GREP=$GREP
+fi
+
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_path_GREP" >&5
+echo "${ECHO_T}$ac_cv_path_GREP" >&6; }
+ GREP="$ac_cv_path_GREP"
+
+
+{ echo "$as_me:$LINENO: checking for egrep" >&5
+echo $ECHO_N "checking for egrep... $ECHO_C" >&6; }
+if test "${ac_cv_path_EGREP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
+   then ac_cv_path_EGREP="$GREP -E"
+   else
+     # Extract the first word of "egrep" to use in msg output
+if test -z "$EGREP"; then
+set dummy egrep; ac_prog_name=$2
+if test "${ac_cv_path_EGREP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_path_EGREP_found=false
+# Loop through the user's path and test for each of PROGNAME-LIST
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_prog in egrep; do
+  for ac_exec_ext in '' $ac_executable_extensions; do
+    ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
+    { test -f "$ac_path_EGREP" && $as_executable_p "$ac_path_EGREP"; } || continue
+    # Check for GNU ac_path_EGREP and select it if it is found.
+  # Check for GNU $ac_path_EGREP
+case `"$ac_path_EGREP" --version 2>&1` in
+*GNU*)
+  ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
+*)
+  ac_count=0
+  echo $ECHO_N "0123456789$ECHO_C" >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    echo 'EGREP' >> "conftest.nl"
+    "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    ac_count=`expr $ac_count + 1`
+    if test $ac_count -gt ${ac_path_EGREP_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_EGREP="$ac_path_EGREP"
+      ac_path_EGREP_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+
+    $ac_path_EGREP_found && break 3
+  done
+done
+
+done
+IFS=$as_save_IFS
+
+
+fi
+
+EGREP="$ac_cv_path_EGREP"
+if test -z "$EGREP"; then
+  { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5
+echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+else
+  ac_cv_path_EGREP=$EGREP
+fi
+
+
+   fi
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_path_EGREP" >&5
+echo "${ECHO_T}$ac_cv_path_EGREP" >&6; }
+ EGREP="$ac_cv_path_EGREP"
+
+
+{ echo "$as_me:$LINENO: checking for ANSI C header files" >&5
+echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6; }
+if test "${ac_cv_header_stdc+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_header_stdc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_cv_header_stdc=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+  # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "memchr" >/dev/null 2>&1; then
+  :
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "free" >/dev/null 2>&1; then
+  :
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+  if test "$cross_compiling" = yes; then
+  :
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ctype.h>
+#include <stdlib.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+                  (('a' <= (c) && (c) <= 'i') \
+                    || ('j' <= (c) && (c) <= 'r') \
+                    || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+  int i;
+  for (i = 0; i < 256; i++)
+    if (XOR (islower (i), ISLOWER (i))
+       || toupper (i) != TOUPPER (i))
+      return 2;
+  return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  :
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_header_stdc=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+fi
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5
+echo "${ECHO_T}$ac_cv_header_stdc" >&6; }
+if test $ac_cv_header_stdc = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define STDC_HEADERS 1
+_ACEOF
+
+fi
+
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+
+
+
+
+
+
+
+
+
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+                 inttypes.h stdint.h unistd.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$as_ac_Header=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       eval "$as_ac_Header=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+              { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+
+for ac_header in inttypes.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  { echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+              { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+else
+  # Is the header compilable?
+{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$ac_header>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+
+    ;;
+esac
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  eval "$as_ac_Header=\$ac_header_preproc"
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+              { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+for ac_header in sysexits.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  { echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+              { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+else
+  # Is the header compilable?
+{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$ac_header>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+
+    ;;
+esac
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  eval "$as_ac_Header=\$ac_header_preproc"
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+              { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+for ac_header in getopt.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  { echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+              { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+else
+  # Is the header compilable?
+{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$ac_header>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+
+    ;;
+esac
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  eval "$as_ac_Header=\$ac_header_preproc"
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+              { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+for ac_header in endian.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  { echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+              { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+else
+  # Is the header compilable?
+{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$ac_header>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+
+    ;;
+esac
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  eval "$as_ac_Header=\$ac_header_preproc"
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+              { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+{ echo "$as_me:$LINENO: checking for off_t" >&5
+echo $ECHO_N "checking for off_t... $ECHO_C" >&6; }
+if test "${ac_cv_type_off_t+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+typedef off_t ac__type_new_;
+int
+main ()
+{
+if ((ac__type_new_ *) 0)
+  return 0;
+if (sizeof (ac__type_new_))
+  return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_type_off_t=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_cv_type_off_t=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_type_off_t" >&5
+echo "${ECHO_T}$ac_cv_type_off_t" >&6; }
+if test $ac_cv_type_off_t = yes; then
+  :
+else
+
+cat >>confdefs.h <<_ACEOF
+#define off_t signed long
+_ACEOF
+
+fi
+
+{ echo "$as_me:$LINENO: checking for size_t" >&5
+echo $ECHO_N "checking for size_t... $ECHO_C" >&6; }
+if test "${ac_cv_type_size_t+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+typedef size_t ac__type_new_;
+int
+main ()
+{
+if ((ac__type_new_ *) 0)
+  return 0;
+if (sizeof (ac__type_new_))
+  return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_type_size_t=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_cv_type_size_t=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_type_size_t" >&5
+echo "${ECHO_T}$ac_cv_type_size_t" >&6; }
+if test $ac_cv_type_size_t = yes; then
+  :
+else
+
+cat >>confdefs.h <<_ACEOF
+#define size_t unsigned long
+_ACEOF
+
+fi
+
+{ echo "$as_me:$LINENO: checking for ssize_t" >&5
+echo $ECHO_N "checking for ssize_t... $ECHO_C" >&6; }
+if test "${ac_cv_type_ssize_t+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+typedef ssize_t ac__type_new_;
+int
+main ()
+{
+if ((ac__type_new_ *) 0)
+  return 0;
+if (sizeof (ac__type_new_))
+  return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_type_ssize_t=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_cv_type_ssize_t=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_type_ssize_t" >&5
+echo "${ECHO_T}$ac_cv_type_ssize_t" >&6; }
+if test $ac_cv_type_ssize_t = yes; then
+  :
+else
+
+cat >>confdefs.h <<_ACEOF
+#define ssize_t signed long
+_ACEOF
+
+fi
+
+
+
+for ac_func in lchown
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
+if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined __stub_$ac_func || defined __stub___$ac_func
+choke me
+#endif
+
+int
+main ()
+{
+return $ac_func ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       eval "$as_ac_var=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+ac_res=`eval echo '${'$as_ac_var'}'`
+              { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+
+for ac_func in utimes
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
+if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined __stub_$ac_func || defined __stub___$ac_func
+choke me
+#endif
+
+int
+main ()
+{
+return $ac_func ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       eval "$as_ac_var=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+ac_res=`eval echo '${'$as_ac_var'}'`
+              { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+
+{ echo "$as_me:$LINENO: checking for struct stat.st_mtim.tv_usec" >&5
+echo $ECHO_N "checking for struct stat.st_mtim.tv_usec... $ECHO_C" >&6; }
+if test "${ac_cv_member_struct_stat_st_mtim_tv_usec+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/stat.h>
+
+int
+main ()
+{
+static struct stat ac_aggr;
+if (ac_aggr.st_mtim.tv_usec)
+return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_member_struct_stat_st_mtim_tv_usec=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/stat.h>
+
+int
+main ()
+{
+static struct stat ac_aggr;
+if (sizeof ac_aggr.st_mtim.tv_usec)
+return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_member_struct_stat_st_mtim_tv_usec=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_cv_member_struct_stat_st_mtim_tv_usec=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_member_struct_stat_st_mtim_tv_usec" >&5
+echo "${ECHO_T}$ac_cv_member_struct_stat_st_mtim_tv_usec" >&6; }
+if test $ac_cv_member_struct_stat_st_mtim_tv_usec = yes; then
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_STAT_ST_MTIM_TV_USEC 1
+_ACEOF
+
+
+fi
+
+
+
+{ echo "$as_me:$LINENO: checking for struct stat.st_mtim.tv_nsec" >&5
+echo $ECHO_N "checking for struct stat.st_mtim.tv_nsec... $ECHO_C" >&6; }
+if test "${ac_cv_member_struct_stat_st_mtim_tv_nsec+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/stat.h>
+
+int
+main ()
+{
+static struct stat ac_aggr;
+if (ac_aggr.st_mtim.tv_nsec)
+return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_member_struct_stat_st_mtim_tv_nsec=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/stat.h>
+
+int
+main ()
+{
+static struct stat ac_aggr;
+if (sizeof ac_aggr.st_mtim.tv_nsec)
+return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_member_struct_stat_st_mtim_tv_nsec=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_cv_member_struct_stat_st_mtim_tv_nsec=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_member_struct_stat_st_mtim_tv_nsec" >&5
+echo "${ECHO_T}$ac_cv_member_struct_stat_st_mtim_tv_nsec" >&6; }
+if test $ac_cv_member_struct_stat_st_mtim_tv_nsec = yes; then
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC 1
+_ACEOF
+
+
+fi
+
+
+
+
+{ echo "$as_me:$LINENO: checking for library containing compress2" >&5
+echo $ECHO_N "checking for library containing compress2... $ECHO_C" >&6; }
+if test "${ac_cv_search_compress2+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_func_search_save_LIBS=$LIBS
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char compress2 ();
+int
+main ()
+{
+return compress2 ();
+  ;
+  return 0;
+}
+_ACEOF
+for ac_lib in '' z; do
+  if test -z "$ac_lib"; then
+    ac_res="none required"
+  else
+    ac_res=-l$ac_lib
+    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
+  fi
+  rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_search_compress2=$ac_res
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext
+  if test "${ac_cv_search_compress2+set}" = set; then
+  break
+fi
+done
+if test "${ac_cv_search_compress2+set}" = set; then
+  :
+else
+  ac_cv_search_compress2=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_search_compress2" >&5
+echo "${ECHO_T}$ac_cv_search_compress2" >&6; }
+ac_res=$ac_cv_search_compress2
+if test "$ac_res" != no; then
+  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+else
+  { { echo "$as_me:$LINENO: error: zlib not found" >&5
+echo "$as_me: error: zlib not found" >&2;}
+   { (exit cannot continue); exit cannot continue; }; }
+fi
+
+{ echo "$as_me:$LINENO: checking for library containing getopt_long" >&5
+echo $ECHO_N "checking for library containing getopt_long... $ECHO_C" >&6; }
+if test "${ac_cv_search_getopt_long+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_func_search_save_LIBS=$LIBS
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char getopt_long ();
+int
+main ()
+{
+return getopt_long ();
+  ;
+  return 0;
+}
+_ACEOF
+for ac_lib in '' getopt getopt_long; do
+  if test -z "$ac_lib"; then
+    ac_res="none required"
+  else
+    ac_res=-l$ac_lib
+    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
+  fi
+  rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_search_getopt_long=$ac_res
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext
+  if test "${ac_cv_search_getopt_long+set}" = set; then
+  break
+fi
+done
+if test "${ac_cv_search_getopt_long+set}" = set; then
+  :
+else
+  ac_cv_search_getopt_long=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_search_getopt_long" >&5
+echo "${ECHO_T}$ac_cv_search_getopt_long" >&6; }
+ac_res=$ac_cv_search_getopt_long
+if test "$ac_res" != no; then
+  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
+
+for ac_func in getopt_long
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
+if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined __stub_$ac_func || defined __stub___$ac_func
+choke me
+#endif
+
+int
+main ()
+{
+return $ac_func ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       eval "$as_ac_var=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+ac_res=`eval echo '${'$as_ac_var'}'`
+              { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+
+
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ranlib; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_RANLIB+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$RANLIB"; then
+  ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+RANLIB=$ac_cv_prog_RANLIB
+if test -n "$RANLIB"; then
+  { echo "$as_me:$LINENO: result: $RANLIB" >&5
+echo "${ECHO_T}$RANLIB" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_RANLIB"; then
+  ac_ct_RANLIB=$RANLIB
+  # Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_RANLIB"; then
+  ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_RANLIB="ranlib"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
+if test -n "$ac_ct_RANLIB"; then
+  { echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5
+echo "${ECHO_T}$ac_ct_RANLIB" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+  if test "x$ac_ct_RANLIB" = x; then
+    RANLIB=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+    RANLIB=$ac_ct_RANLIB
+  fi
+else
+  RANLIB="$ac_cv_prog_RANLIB"
+fi
+
+ac_aux_dir=
+for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do
+  if test -f "$ac_dir/install-sh"; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install-sh -c"
+    break
+  elif test -f "$ac_dir/install.sh"; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install.sh -c"
+    break
+  elif test -f "$ac_dir/shtool"; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/shtool install -c"
+    break
+  fi
+done
+if test -z "$ac_aux_dir"; then
+  { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" >&5
+echo "$as_me: error: cannot find install-sh or install.sh in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+# These three variables are undocumented and unsupported,
+# and are intended to be withdrawn in a future Autoconf release.
+# They can cause serious problems if a builder's source tree is in a directory
+# whose full name contains unusual characters.
+ac_config_guess="$SHELL $ac_aux_dir/config.guess"  # Please don't use this var.
+ac_config_sub="$SHELL $ac_aux_dir/config.sub"  # Please don't use this var.
+ac_configure="$SHELL $ac_aux_dir/configure"  # Please don't use this var.
+
+
+# Find a good install program.  We prefer a C program (faster),
+# so one script is as good as another.  But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AmigaOS /C/install, which installs bootblocks on floppy discs
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# OS/2's system install, which has a completely different semantic
+# ./install, which can be erroneously created by make from ./install.sh.
+{ echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5
+echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6; }
+if test -z "$INSTALL"; then
+if test "${ac_cv_path_install+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  # Account for people who put trailing slashes in PATH elements.
+case $as_dir/ in
+  ./ | .// | /cC/* | \
+  /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
+  ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \
+  /usr/ucb/* ) ;;
+  *)
+    # OSF1 and SCO ODT 3.0 have their own names for install.
+    # Don't use installbsd from OSF since it installs stuff as root
+    # by default.
+    for ac_prog in ginstall scoinst install; do
+      for ac_exec_ext in '' $ac_executable_extensions; do
+       if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; }; then
+         if test $ac_prog = install &&
+           grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+           # AIX install.  It has an incompatible calling convention.
+           :
+         elif test $ac_prog = install &&
+           grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+           # program-specific install script used by HP pwplus--don't use.
+           :
+         else
+           ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+           break 3
+         fi
+       fi
+      done
+    done
+    ;;
+esac
+done
+IFS=$as_save_IFS
+
+
+fi
+  if test "${ac_cv_path_install+set}" = set; then
+    INSTALL=$ac_cv_path_install
+  else
+    # As a last resort, use the slow shell script.  Don't cache a
+    # value for INSTALL within a source directory, because that will
+    # break other packages using the cache if that directory is
+    # removed, or if the value is a relative name.
+    INSTALL=$ac_install_sh
+  fi
+fi
+{ echo "$as_me:$LINENO: result: $INSTALL" >&5
+echo "${ECHO_T}$INSTALL" >&6; }
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+
+ac_config_headers="$ac_config_headers config.h"
+
+ac_config_files="$ac_config_files MCONFIG"
+
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems.  If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, we kill variables containing newlines.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(
+  for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
+    eval ac_val=\$$ac_var
+    case $ac_val in #(
+    *${as_nl}*)
+      case $ac_var in #(
+      *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5
+echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;;
+      esac
+      case $ac_var in #(
+      _ | IFS | as_nl) ;; #(
+      *) $as_unset $ac_var ;;
+      esac ;;
+    esac
+  done
+
+  (set) 2>&1 |
+    case $as_nl`(ac_space=' '; set) 2>&1` in #(
+    *${as_nl}ac_space=\ *)
+      # `set' does not quote correctly, so add quotes (double-quote
+      # substitution turns \\\\ into \\, and sed turns \\ into \).
+      sed -n \
+       "s/'/'\\\\''/g;
+         s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+      ;; #(
+    *)
+      # `set' quotes correctly as required by POSIX, so do not add quotes.
+      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+      ;;
+    esac |
+    sort
+) |
+  sed '
+     /^ac_cv_env_/b end
+     t clear
+     :clear
+     s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+     t end
+     s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+     :end' >>confcache
+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
+  if test -w "$cache_file"; then
+    test "x$cache_file" != "x/dev/null" &&
+      { echo "$as_me:$LINENO: updating cache $cache_file" >&5
+echo "$as_me: updating cache $cache_file" >&6;}
+    cat confcache >$cache_file
+  else
+    { echo "$as_me:$LINENO: not updating unwritable cache $cache_file" >&5
+echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+  fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+DEFS=-DHAVE_CONFIG_H
+
+ac_libobjs=
+ac_ltlibobjs=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+  # 1. Remove the extension, and $U if already installed.
+  ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
+  ac_i=`echo "$ac_i" | sed "$ac_script"`
+  # 2. Prepend LIBOBJDIR.  When used with automake>=1.10 LIBOBJDIR
+  #    will be set to the directory where LIBOBJS objects are built.
+  ac_libobjs="$ac_libobjs \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+  ac_ltlibobjs="$ac_ltlibobjs \${LIBOBJDIR}$ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+
+: ${CONFIG_STATUS=./config.status}
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5
+echo "$as_me: creating $CONFIG_STATUS" >&6;}
+cat >$CONFIG_STATUS <<_ACEOF
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+SHELL=\${CONFIG_SHELL-$SHELL}
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+## --------------------- ##
+## M4sh Initialization.  ##
+## --------------------- ##
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac
+fi
+BIN_SH=xpg4; export BIN_SH # for Tru64
+DUALCASE=1; export DUALCASE # for MKS sh
+
+
+# PATH needs CR
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  echo "#! /bin/sh" >conf$$.sh
+  echo  "exit 0"   >>conf$$.sh
+  chmod +x conf$$.sh
+  if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+    PATH_SEPARATOR=';'
+  else
+    PATH_SEPARATOR=:
+  fi
+  rm -f conf$$.sh
+fi
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+  as_unset=unset
+else
+  as_unset=false
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.  Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+as_nl='
+'
+IFS=" ""       $as_nl"
+
+# Find who we are.  Look in the path if we contain no directory separator.
+case $0 in
+  *[\\/]* ) as_myself=$0 ;;
+  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+IFS=$as_save_IFS
+
+     ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+  as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+  echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+  { (exit 1); exit 1; }
+fi
+
+# Work around bugs in pre-3.0 UWIN ksh.
+for as_var in ENV MAIL MAILPATH
+do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+  LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+  LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+  LC_TELEPHONE LC_TIME
+do
+  if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+    eval $as_var=C; export $as_var
+  else
+    ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+  fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+        X"$0" : 'X\(//\)$' \| \
+        X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{
+           s//\1/
+           q
+         }
+         /^X\/\(\/\/\)$/{
+           s//\1/
+           q
+         }
+         /^X\/\(\/\).*/{
+           s//\1/
+           q
+         }
+         s/.*/./; q'`
+
+# CDPATH.
+$as_unset CDPATH
+
+
+
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || {
+
+  # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+  # uniformly replaced by the line number.  The first 'sed' inserts a
+  # line-number line after each line using $LINENO; the second 'sed'
+  # does the real work.  The second script uses 'N' to pair each
+  # line-number line with the line containing $LINENO, and appends
+  # trailing '-' during substitution so that $LINENO is not a special
+  # case at line end.
+  # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+  # scripts with optimization help from Paolo Bonzini.  Blame Lee
+  # E. McMahon (1931-1989) for sed's syntax.  :-)
+  sed -n '
+    p
+    /[$]LINENO/=
+  ' <$as_myself |
+    sed '
+      s/[$]LINENO.*/&-/
+      t lineno
+      b
+      :lineno
+      N
+      :loop
+      s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+      t loop
+      s/-\n.*//
+    ' >$as_me.lineno &&
+  chmod +x "$as_me.lineno" ||
+    { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
+   { (exit 1); exit 1; }; }
+
+  # Don't try to exec as it changes $[0], causing all sort of problems
+  # (the dirname of $[0] is not the place where we might find the
+  # original and so on.  Autoconf is especially sensitive to this).
+  . "./$as_me.lineno"
+  # Exit status is that of the last command.
+  exit
+}
+
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+  as_dirname=dirname
+else
+  as_dirname=false
+fi
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in
+-n*)
+  case `echo 'x\c'` in
+  *c*) ECHO_T='        ';;     # ECHO_T is single tab character.
+  *)   ECHO_C='\c';;
+  esac;;
+*)
+  ECHO_N='-n';;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+  rm -f conf$$.dir/conf$$.file
+else
+  rm -f conf$$.dir
+  mkdir conf$$.dir
+fi
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+  as_ln_s='ln -s'
+  # ... but there are two gotchas:
+  # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+  # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+  # In both cases, we have to default to `cp -p'.
+  ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+    as_ln_s='cp -p'
+elif ln conf$$.file conf$$ 2>/dev/null; then
+  as_ln_s=ln
+else
+  as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p=:
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+# Find out whether ``test -x'' works.  Don't use a zero-byte file, as
+# systems may use methods other than mode bits to determine executability.
+cat >conf$$.file <<_ASEOF
+#! /bin/sh
+exit 0
+_ASEOF
+chmod +x conf$$.file
+if test -x conf$$.file >/dev/null 2>&1; then
+  as_executable_p="test -x"
+else
+  as_executable_p=:
+fi
+rm -f conf$$.file
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+
+# Save the log message, to keep $[0] and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by $as_me, which was
+generated by GNU Autoconf 2.60a.  Invocation command line was
+
+  CONFIG_FILES    = $CONFIG_FILES
+  CONFIG_HEADERS  = $CONFIG_HEADERS
+  CONFIG_LINKS    = $CONFIG_LINKS
+  CONFIG_COMMANDS = $CONFIG_COMMANDS
+  $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+# Files that config.status was made for.
+config_files="$ac_config_files"
+config_headers="$ac_config_headers"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+ac_cs_usage="\
+\`$as_me' instantiates files from templates according to the
+current configuration.
+
+Usage: $0 [OPTIONS] [FILE]...
+
+  -h, --help       print this help, then exit
+  -V, --version    print version number and configuration settings, then exit
+  -q, --quiet      do not print progress messages
+  -d, --debug      don't remove temporary files
+      --recheck    update $as_me by reconfiguring in the same conditions
+  --file=FILE[:TEMPLATE]
+                  instantiate the configuration file FILE
+  --header=FILE[:TEMPLATE]
+                  instantiate the configuration header FILE
+
+Configuration files:
+$config_files
+
+Configuration headers:
+$config_headers
+
+Report bugs to <bug-autoconf@gnu.org>."
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+ac_cs_version="\\
+config.status
+configured by $0, generated by GNU Autoconf 2.60a,
+  with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
+
+Copyright (C) 2006 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='$ac_pwd'
+srcdir='$srcdir'
+INSTALL='$INSTALL'
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+# If no file are specified by the user, then we need to provide default
+# value.  By we need to know if files were specified by the user.
+ac_need_defaults=:
+while test $# != 0
+do
+  case $1 in
+  --*=*)
+    ac_option=`expr "X$1" : 'X\([^=]*\)='`
+    ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+    ac_shift=:
+    ;;
+  *)
+    ac_option=$1
+    ac_optarg=$2
+    ac_shift=shift
+    ;;
+  esac
+
+  case $ac_option in
+  # Handling of the options.
+  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+    ac_cs_recheck=: ;;
+  --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+    echo "$ac_cs_version"; exit ;;
+  --debug | --debu | --deb | --de | --d | -d )
+    debug=: ;;
+  --file | --fil | --fi | --f )
+    $ac_shift
+    CONFIG_FILES="$CONFIG_FILES $ac_optarg"
+    ac_need_defaults=false;;
+  --header | --heade | --head | --hea )
+    $ac_shift
+    CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg"
+    ac_need_defaults=false;;
+  --he | --h)
+    # Conflict between --help and --header
+    { echo "$as_me: error: ambiguous option: $1
+Try \`$0 --help' for more information." >&2
+   { (exit 1); exit 1; }; };;
+  --help | --hel | -h )
+    echo "$ac_cs_usage"; exit ;;
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil | --si | --s)
+    ac_cs_silent=: ;;
+
+  # This is an error.
+  -*) { echo "$as_me: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&2
+   { (exit 1); exit 1; }; } ;;
+
+  *) ac_config_targets="$ac_config_targets $1"
+     ac_need_defaults=false ;;
+
+  esac
+  shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+  exec 6>/dev/null
+  ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+if \$ac_cs_recheck; then
+  echo "running CONFIG_SHELL=$SHELL $SHELL $0 "$ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6
+  CONFIG_SHELL=$SHELL
+  export CONFIG_SHELL
+  exec $SHELL "$0"$ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+exec 5>>config.log
+{
+  echo
+  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+  echo "$ac_log"
+} >&5
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+  case $ac_config_target in
+    "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
+    "MCONFIG") CONFIG_FILES="$CONFIG_FILES MCONFIG" ;;
+
+  *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5
+echo "$as_me: error: invalid argument: $ac_config_target" >&2;}
+   { (exit 1); exit 1; }; };;
+  esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used.  Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+  test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+  test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
+fi
+
+# Have a temporary directory for convenience.  Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+  tmp=
+  trap 'exit_status=$?
+  { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status
+' 0
+  trap '{ (exit 1); exit 1; }' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+  tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+  test -n "$tmp" && test -d "$tmp"
+}  ||
+{
+  tmp=./conf$$-$RANDOM
+  (umask 077 && mkdir "$tmp")
+} ||
+{
+   echo "$me: cannot create a temporary directory in ." >&2
+   { (exit 1); exit 1; }
+}
+
+#
+# Set up the sed scripts for CONFIG_FILES section.
+#
+
+# No need to generate the scripts if there are no CONFIG_FILES.
+# This happens for instance when ./config.status config.h
+if test -n "$CONFIG_FILES"; then
+
+_ACEOF
+
+
+
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+  cat >conf$$subs.sed <<_ACEOF
+SHELL!$SHELL$ac_delim
+PATH_SEPARATOR!$PATH_SEPARATOR$ac_delim
+PACKAGE_NAME!$PACKAGE_NAME$ac_delim
+PACKAGE_TARNAME!$PACKAGE_TARNAME$ac_delim
+PACKAGE_VERSION!$PACKAGE_VERSION$ac_delim
+PACKAGE_STRING!$PACKAGE_STRING$ac_delim
+PACKAGE_BUGREPORT!$PACKAGE_BUGREPORT$ac_delim
+exec_prefix!$exec_prefix$ac_delim
+prefix!$prefix$ac_delim
+program_transform_name!$program_transform_name$ac_delim
+bindir!$bindir$ac_delim
+sbindir!$sbindir$ac_delim
+libexecdir!$libexecdir$ac_delim
+datarootdir!$datarootdir$ac_delim
+datadir!$datadir$ac_delim
+sysconfdir!$sysconfdir$ac_delim
+sharedstatedir!$sharedstatedir$ac_delim
+localstatedir!$localstatedir$ac_delim
+includedir!$includedir$ac_delim
+oldincludedir!$oldincludedir$ac_delim
+docdir!$docdir$ac_delim
+infodir!$infodir$ac_delim
+htmldir!$htmldir$ac_delim
+dvidir!$dvidir$ac_delim
+pdfdir!$pdfdir$ac_delim
+psdir!$psdir$ac_delim
+libdir!$libdir$ac_delim
+localedir!$localedir$ac_delim
+mandir!$mandir$ac_delim
+DEFS!$DEFS$ac_delim
+ECHO_C!$ECHO_C$ac_delim
+ECHO_N!$ECHO_N$ac_delim
+ECHO_T!$ECHO_T$ac_delim
+LIBS!$LIBS$ac_delim
+build_alias!$build_alias$ac_delim
+host_alias!$host_alias$ac_delim
+target_alias!$target_alias$ac_delim
+CC!$CC$ac_delim
+CFLAGS!$CFLAGS$ac_delim
+LDFLAGS!$LDFLAGS$ac_delim
+CPPFLAGS!$CPPFLAGS$ac_delim
+ac_ct_CC!$ac_ct_CC$ac_delim
+EXEEXT!$EXEEXT$ac_delim
+OBJEXT!$OBJEXT$ac_delim
+CPP!$CPP$ac_delim
+GREP!$GREP$ac_delim
+EGREP!$EGREP$ac_delim
+RANLIB!$RANLIB$ac_delim
+INSTALL_PROGRAM!$INSTALL_PROGRAM$ac_delim
+INSTALL_SCRIPT!$INSTALL_SCRIPT$ac_delim
+INSTALL_DATA!$INSTALL_DATA$ac_delim
+LIBOBJS!$LIBOBJS$ac_delim
+LTLIBOBJS!$LTLIBOBJS$ac_delim
+_ACEOF
+
+  if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 53; then
+    break
+  elif $ac_last_try; then
+    { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
+echo "$as_me: error: could not make $CONFIG_STATUS" >&2;}
+   { (exit 1); exit 1; }; }
+  else
+    ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+  fi
+done
+
+ac_eof=`sed -n '/^CEOF[0-9]*$/s/CEOF/0/p' conf$$subs.sed`
+if test -n "$ac_eof"; then
+  ac_eof=`echo "$ac_eof" | sort -nru | sed 1q`
+  ac_eof=`expr $ac_eof + 1`
+fi
+
+cat >>$CONFIG_STATUS <<_ACEOF
+cat >"\$tmp/subs-1.sed" <<\CEOF$ac_eof
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b end
+_ACEOF
+sed '
+s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g
+s/^/s,@/; s/!/@,|#_!!_#|/
+:n
+t n
+s/'"$ac_delim"'$/,g/; t
+s/$/\\/; p
+N; s/^.*\n//; s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g; b n
+' >>$CONFIG_STATUS <conf$$subs.sed
+rm -f conf$$subs.sed
+cat >>$CONFIG_STATUS <<_ACEOF
+:end
+s/|#_!!_#|//g
+CEOF$ac_eof
+_ACEOF
+
+
+# VPATH may cause trouble with some makes, so we remove $(srcdir),
+# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+  ac_vpsub='/^[         ]*VPATH[        ]*=/{
+s/:*\$(srcdir):*/:/
+s/:*\${srcdir}:*/:/
+s/:*@srcdir@:*/:/
+s/^\([^=]*=[    ]*\):*/\1/
+s/:*$//
+s/^[^=]*=[      ]*$//
+}'
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+fi # test -n "$CONFIG_FILES"
+
+
+for ac_tag in  :F $CONFIG_FILES  :H $CONFIG_HEADERS
+do
+  case $ac_tag in
+  :[FHLC]) ac_mode=$ac_tag; continue;;
+  esac
+  case $ac_mode$ac_tag in
+  :[FHL]*:*);;
+  :L* | :C*:*) { { echo "$as_me:$LINENO: error: Invalid tag $ac_tag." >&5
+echo "$as_me: error: Invalid tag $ac_tag." >&2;}
+   { (exit 1); exit 1; }; };;
+  :[FH]-) ac_tag=-:-;;
+  :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+  esac
+  ac_save_IFS=$IFS
+  IFS=:
+  set x $ac_tag
+  IFS=$ac_save_IFS
+  shift
+  ac_file=$1
+  shift
+
+  case $ac_mode in
+  :L) ac_source=$1;;
+  :[FH])
+    ac_file_inputs=
+    for ac_f
+    do
+      case $ac_f in
+      -) ac_f="$tmp/stdin";;
+      *) # Look for the file first in the build tree, then in the source tree
+        # (if the path is not absolute).  The absolute path cannot be DOS-style,
+        # because $ac_f cannot contain `:'.
+        test -f "$ac_f" ||
+          case $ac_f in
+          [\\/$]*) false;;
+          *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+          esac ||
+          { { echo "$as_me:$LINENO: error: cannot find input file: $ac_f" >&5
+echo "$as_me: error: cannot find input file: $ac_f" >&2;}
+   { (exit 1); exit 1; }; };;
+      esac
+      ac_file_inputs="$ac_file_inputs $ac_f"
+    done
+
+    # Let's still pretend it is `configure' which instantiates (i.e., don't
+    # use $as_me), people would be surprised to read:
+    #    /* config.h.  Generated by config.status.  */
+    configure_input="Generated from "`IFS=:
+         echo $* | sed 's|^[^:]*/||;s|:[^:]*/|, |g'`" by configure."
+    if test x"$ac_file" != x-; then
+      configure_input="$ac_file.  $configure_input"
+      { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+    fi
+
+    case $ac_tag in
+    *:-:* | *:-) cat >"$tmp/stdin";;
+    esac
+    ;;
+  esac
+
+  ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X"$ac_file" : 'X\(//\)[^/]' \| \
+        X"$ac_file" : 'X\(//\)$' \| \
+        X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$ac_file" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)[^/].*/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\).*/{
+           s//\1/
+           q
+         }
+         s/.*/./; q'`
+  { as_dir="$ac_dir"
+  case $as_dir in #(
+  -*) as_dir=./$as_dir;;
+  esac
+  test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || {
+    as_dirs=
+    while :; do
+      case $as_dir in #(
+      *\'*) as_qdir=`echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #(
+      *) as_qdir=$as_dir;;
+      esac
+      as_dirs="'$as_qdir' $as_dirs"
+      as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X"$as_dir" : 'X\(//\)[^/]' \| \
+        X"$as_dir" : 'X\(//\)$' \| \
+        X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)[^/].*/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\).*/{
+           s//\1/
+           q
+         }
+         s/.*/./; q'`
+      test -d "$as_dir" && break
+    done
+    test -z "$as_dirs" || eval "mkdir $as_dirs"
+  } || test -d "$as_dir" || { { echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5
+echo "$as_me: error: cannot create directory $as_dir" >&2;}
+   { (exit 1); exit 1; }; }; }
+  ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+  ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+  # A ".." for each directory in $ac_dir_suffix.
+  ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'`
+  case $ac_top_builddir_sub in
+  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+  esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+  .)  # We are building in place.
+    ac_srcdir=.
+    ac_top_srcdir=$ac_top_builddir_sub
+    ac_abs_top_srcdir=$ac_pwd ;;
+  [\\/]* | ?:[\\/]* )  # Absolute name.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir
+    ac_abs_top_srcdir=$srcdir ;;
+  *) # Relative name.
+    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_build_prefix$srcdir
+    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+  case $ac_mode in
+  :F)
+  #
+  # CONFIG_FILE
+  #
+
+  case $INSTALL in
+  [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
+  *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;;
+  esac
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+
+case `sed -n '/datarootdir/ {
+  p
+  q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p
+' $ac_file_inputs` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+  { echo "$as_me:$LINENO: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+  ac_datarootdir_hack='
+  s&@datadir@&$datadir&g
+  s&@docdir@&$docdir&g
+  s&@infodir@&$infodir&g
+  s&@localedir@&$localedir&g
+  s&@mandir@&$mandir&g
+    s&\\\${datarootdir}&$datarootdir&g' ;;
+esac
+_ACEOF
+
+# Neutralize VPATH when `$srcdir' = `.'.
+# Shell code in configure.ac might set extrasub.
+# FIXME: do we really want to maintain this feature?
+cat >>$CONFIG_STATUS <<_ACEOF
+  sed "$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s&@configure_input@&$configure_input&;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+s&@INSTALL@&$ac_INSTALL&;t t
+$ac_datarootdir_hack
+" $ac_file_inputs | sed -f "$tmp/subs-1.sed" >$tmp/out
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+  { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } &&
+  { ac_out=`sed -n '/^[         ]*datarootdir[  ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } &&
+  { echo "$as_me:$LINENO: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined.  Please make sure it is defined." >&5
+echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined.  Please make sure it is defined." >&2;}
+
+  rm -f "$tmp/stdin"
+  case $ac_file in
+  -) cat "$tmp/out"; rm -f "$tmp/out";;
+  *) rm -f "$ac_file"; mv "$tmp/out" $ac_file;;
+  esac
+ ;;
+  :H)
+  #
+  # CONFIG_HEADER
+  #
+_ACEOF
+
+# Transform confdefs.h into a sed script `conftest.defines', that
+# substitutes the proper values into config.h.in to produce config.h.
+rm -f conftest.defines conftest.tail
+# First, append a space to every undef/define line, to ease matching.
+echo 's/$/ /' >conftest.defines
+# Then, protect against being on the right side of a sed subst, or in
+# an unquoted here document, in config.status.  If some macros were
+# called several times there might be several #defines for the same
+# symbol, which is useless.  But do not sort them, since the last
+# AC_DEFINE must be honored.
+ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]*
+# These sed commands are passed to sed as "A NAME B PARAMS C VALUE D", where
+# NAME is the cpp macro being defined, VALUE is the value it is being given.
+# PARAMS is the parameter list in the macro definition--in most cases, it's
+# just an empty string.
+ac_dA='s,^\\([  #]*\\)[^        ]*\\([  ]*'
+ac_dB='\\)[     (].*,\\1define\\2'
+ac_dC=' '
+ac_dD=' ,'
+
+uniq confdefs.h |
+  sed -n '
+       t rset
+       :rset
+       s/^[     ]*#[    ]*define[       ][      ]*//
+       t ok
+       d
+       :ok
+       s/[\\&,]/\\&/g
+       s/^\('"$ac_word_re"'\)\(([^()]*)\)[      ]*\(.*\)/ '"$ac_dA"'\1'"$ac_dB"'\2'"${ac_dC}"'\3'"$ac_dD"'/p
+       s/^\('"$ac_word_re"'\)[  ]*\(.*\)/'"$ac_dA"'\1'"$ac_dB$ac_dC"'\2'"$ac_dD"'/p
+  ' >>conftest.defines
+
+# Remove the space that was appended to ease matching.
+# Then replace #undef with comments.  This is necessary, for
+# example, in the case of _POSIX_SOURCE, which is predefined and required
+# on some systems where configure will not decide to define it.
+# (The regexp can be short, since the line contains either #define or #undef.)
+echo 's/ $//
+s,^[    #]*u.*,/* & */,' >>conftest.defines
+
+# Break up conftest.defines:
+ac_max_sed_lines=50
+
+# First sed command is:         sed -f defines.sed $ac_file_inputs >"$tmp/out1"
+# Second one is:        sed -f defines.sed "$tmp/out1" >"$tmp/out2"
+# Third one will be:    sed -f defines.sed "$tmp/out2" >"$tmp/out1"
+# et cetera.
+ac_in='$ac_file_inputs'
+ac_out='"$tmp/out1"'
+ac_nxt='"$tmp/out2"'
+
+while :
+do
+  # Write a here document:
+    cat >>$CONFIG_STATUS <<_ACEOF
+    # First, check the format of the line:
+    cat >"\$tmp/defines.sed" <<\\CEOF
+/^[     ]*#[    ]*undef[        ][      ]*$ac_word_re[  ]*\$/b def
+/^[     ]*#[    ]*define[       ][      ]*$ac_word_re[(         ]/b def
+b
+:def
+_ACEOF
+  sed ${ac_max_sed_lines}q conftest.defines >>$CONFIG_STATUS
+  echo 'CEOF
+    sed -f "$tmp/defines.sed"' "$ac_in >$ac_out" >>$CONFIG_STATUS
+  ac_in=$ac_out; ac_out=$ac_nxt; ac_nxt=$ac_in
+  sed 1,${ac_max_sed_lines}d conftest.defines >conftest.tail
+  grep . conftest.tail >/dev/null || break
+  rm -f conftest.defines
+  mv conftest.tail conftest.defines
+done
+rm -f conftest.defines conftest.tail
+
+echo "ac_result=$ac_in" >>$CONFIG_STATUS
+cat >>$CONFIG_STATUS <<\_ACEOF
+  if test x"$ac_file" != x-; then
+    echo "/* $configure_input  */" >"$tmp/config.h"
+    cat "$ac_result" >>"$tmp/config.h"
+    if diff $ac_file "$tmp/config.h" >/dev/null 2>&1; then
+      { echo "$as_me:$LINENO: $ac_file is unchanged" >&5
+echo "$as_me: $ac_file is unchanged" >&6;}
+    else
+      rm -f $ac_file
+      mv "$tmp/config.h" $ac_file
+    fi
+  else
+    echo "/* $configure_input  */"
+    cat "$ac_result"
+  fi
+  rm -f "$tmp/out12"
+ ;;
+
+
+  esac
+
+done # for ac_tag
+
+
+{ (exit 0); exit 0; }
+_ACEOF
+chmod +x $CONFIG_STATUS
+ac_clean_files=$ac_clean_files_save
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded.  So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status.  When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+  ac_cs_success=:
+  ac_config_status_args=
+  test "$silent" = yes &&
+    ac_config_status_args="$ac_config_status_args --quiet"
+  exec 5>/dev/null
+  $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+  exec 5>>config.log
+  # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+  # would make configure fail if this is the last instruction.
+  $ac_cs_success || { (exit 1); exit 1; }
+fi
+
diff --git a/3rd-party/zisofs_tools/configure.in b/3rd-party/zisofs_tools/configure.in
new file mode 100644 (file)
index 0000000..4143ec5
--- /dev/null
@@ -0,0 +1,58 @@
+dnl
+dnl autoconf input file to generate MCONFIG
+dnl
+
+AC_PREREQ(2.57)
+AC_REVISION([$Id: configure.in,v 1.7 2004/07/20 04:04:22 hpa Exp $])
+AC_INIT(MCONFIG.in)
+AC_PREFIX_DEFAULT(/usr)
+
+AC_PROG_CC
+AC_GNU_SOURCE
+AC_SYS_LARGEFILE
+AC_C_CONST
+AC_C_INLINE
+
+PA_ADD_CFLAGS(-Wall)
+PA_ADD_CFLAGS(-W)
+PA_ADD_CFLAGS(-Wpointer-arith)
+PA_ADD_CFLAGS(-Wbad-function-cast)
+PA_ADD_CFLAGS(-Wcast-equal)
+PA_ADD_CFLAGS(-Wstrict-prototypes)
+PA_ADD_CFLAGS(-Wmissing-prototypes)
+PA_ADD_CFLAGS(-Wmissing-declarations)
+PA_ADD_CFLAGS(-Wnested-externs)
+PA_ADD_CFLAGS(-Winline)
+PA_ADD_CFLAGS(-Wshadow)
+PA_ADD_CFLAGS(-Wcast-align)
+PA_ADD_CFLAGS(-pipe)
+
+AC_CHECK_HEADERS(inttypes.h)
+AC_CHECK_HEADERS(sysexits.h)
+AC_CHECK_HEADERS(getopt.h)
+AC_CHECK_HEADERS(endian.h)
+
+AC_CHECK_TYPE(off_t, signed long)
+AC_CHECK_TYPE(size_t, unsigned long)
+AC_CHECK_TYPE(ssize_t, signed long)
+
+AC_CHECK_FUNCS(lchown)
+AC_CHECK_FUNCS(utimes)
+
+AC_CHECK_MEMBERS(struct stat.st_mtim.tv_usec, , , [#include <sys/stat.h>])
+AH_TEMPLATE([HAVE_STRUCT_STAT_ST_MTIM_TV_USEC],
+          [Define to 1 if `struct stat.st_[mca]tim' are struct timeval])
+AC_CHECK_MEMBERS(struct stat.st_mtim.tv_nsec, , , [#include <sys/stat.h>])
+AH_TEMPLATE([HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC], 
+          [Define to 1 if `struct stat.st_[mca]tim' are struct timespec])
+
+AC_SEARCH_LIBS(compress2, z, , [AC_MSG_ERROR(zlib not found, cannot continue)])
+AC_SEARCH_LIBS(getopt_long, [getopt getopt_long])
+AC_CHECK_FUNCS(getopt_long)
+AH_TEMPLATE([HAVE_GETOPT_LONG], [Define to 1 if you have the `getopt_long' function])
+
+AC_PROG_RANLIB
+AC_PROG_INSTALL
+
+AC_CONFIG_HEADER(config.h)
+AC_OUTPUT(MCONFIG)
diff --git a/3rd-party/zisofs_tools/copytime.c b/3rd-party/zisofs_tools/copytime.c
new file mode 100644 (file)
index 0000000..82cff7d
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* $Id: copytime.c,v 1.2 2006/07/04 04:57:42 hpa Exp $ */
+/* ----------------------------------------------------------------------- *
+ *   
+ *   Copyright 2004 H. Peter Anvin - All Rights Reserved
+ *
+ *   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, Inc., 53 Temple Place Ste 330,
+ *   Bostom MA 02111-1307, USA; either version 2 of the License, or
+ *   (at your option) any later version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * copytime.c
+ *
+ * Copy time(s) from a struct stat
+ */
+
+#include "mkzftree.h"          /* Must be included first! */
+
+#include <utime.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+int copytime(const char *filename, const struct stat *st)
+{
+#if defined(HAVE_UTIMES) && (defined(HAVE_STRUCT_STAT_ST_MTIM_TV_USEC) || \
+                            defined(HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC))
+  
+  struct timeval tv[2];
+  
+# ifdef HAVE_STRUCT_STAT_ST_MTIM_TV_USEC
+  tv[0] = st->st_atim;
+  tv[1] = st->st_mtim;
+# else
+  tv[0].tv_sec  = st->st_atim.tv_sec;
+  tv[0].tv_usec = st->st_atim.tv_nsec / 1000;
+  tv[1].tv_sec  = st->st_mtim.tv_sec;
+  tv[1].tv_usec = st->st_mtim.tv_nsec / 1000;
+# endif
+  return utimes(filename, tv);
+  
+#else
+  
+  struct utimbuf ut; 
+  
+  ut.actime  = st->st_atime;
+  ut.modtime = st->st_mtime;
+  return utime(filename, &ut);
+  
+#endif
+}
diff --git a/3rd-party/zisofs_tools/hash.c b/3rd-party/zisofs_tools/hash.c
new file mode 100644 (file)
index 0000000..6c906ea
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+#ident "$Id: hash.c,v 1.3 2006/07/04 04:57:42 hpa Exp $"
+/* ----------------------------------------------------------------------- *
+ *   
+ *   Copyright 2001 H. Peter Anvin - All Rights Reserved
+ *
+ *   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, Inc., 675 Mass Ave, Cambridge MA 02139,
+ *   USA; either version 2 of the License, or (at your option) any later
+ *   version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * hash.c
+ *
+ * Hash table used to find hard-linked files
+ */
+
+#include "mkzftree.h"          /* Must be included first! */
+
+#define HASH_BUCKETS     2683
+
+struct file_hash {
+  struct file_hash *next;
+  struct stat st;
+  const char *outfile_name;
+};
+
+static struct file_hash *hashp[HASH_BUCKETS];
+
+const char *hash_find_file(struct stat *st)
+{
+  int bucket = (st->st_ino + st->st_dev) % HASH_BUCKETS;
+  struct file_hash *hp;
+
+  for ( hp = hashp[bucket] ; hp ; hp = hp->next ) {
+    if ( hp->st.st_ino   == st->st_ino &&
+        hp->st.st_dev   == st->st_dev &&
+        hp->st.st_mode  == st->st_mode &&
+        hp->st.st_nlink == st->st_nlink &&
+        hp->st.st_uid   == st->st_uid &&
+        hp->st.st_gid   == st->st_gid &&
+        hp->st.st_size  == st->st_size &&
+        hp->st.st_mtime == st->st_mtime ) {
+      /* Good enough, it's the same file */
+      return hp->outfile_name;
+    }
+  }
+  return NULL;                 /* No match */
+}
+
+/* Note: the stat structure is the input file; the name
+   is the output file to link to */
+void hash_insert_file(struct stat *st, const char *outfile)
+{
+  int bucket = (st->st_ino + st->st_dev) % HASH_BUCKETS;
+  struct file_hash *hp = xmalloc(sizeof(struct file_hash));
+
+  hp->next         = hashp[bucket];
+  memcpy(&hp->st, st, sizeof(struct stat));
+  hp->outfile_name = xstrdup(outfile);
+
+  hashp[bucket]    = hp;
+}
+
+
diff --git a/3rd-party/zisofs_tools/install-sh b/3rd-party/zisofs_tools/install-sh
new file mode 100644 (file)
index 0000000..89fc9b0
--- /dev/null
@@ -0,0 +1,238 @@
+#! /bin/sh
+#
+# install - install a program, script, or datafile
+# This comes from X11R5.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.
+#
+
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+mkdirprog="${MKDIRPROG-mkdir}"
+
+tranformbasename=""
+transform_arg=""
+instcmd="$mvprog"
+chmodcmd="$chmodprog 0755"
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+dir_arg=""
+
+while [ x"$1" != x ]; do
+    case $1 in
+       -c) instcmd="$cpprog"
+           shift
+           continue;;
+
+       -d) dir_arg=true
+           shift
+           continue;;
+
+       -m) chmodcmd="$chmodprog $2"
+           shift
+           shift
+           continue;;
+
+       -o) chowncmd="$chownprog $2"
+           shift
+           shift
+           continue;;
+
+       -g) chgrpcmd="$chgrpprog $2"
+           shift
+           shift
+           continue;;
+
+       -s) stripcmd="$stripprog"
+           shift
+           continue;;
+
+       -t=*) transformarg=`echo $1 | sed 's/-t=//'`
+           shift
+           continue;;
+
+       -b=*) transformbasename=`echo $1 | sed 's/-b=//'`
+           shift
+           continue;;
+
+       *)  if [ x"$src" = x ]
+           then
+               src=$1
+           else
+               # this colon is to work around a 386BSD /bin/sh bug
+               :
+               dst=$1
+           fi
+           shift
+           continue;;
+    esac
+done
+
+if [ x"$src" = x ]
+then
+       echo "install:  no input file specified"
+       exit 1
+else
+       true
+fi
+
+if [ x"$dir_arg" != x ]; then
+       dst=$src
+       src=""
+       
+       if [ -d $dst ]; then
+               instcmd=:
+       else
+               instcmd=mkdir
+       fi
+else
+
+# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
+# might cause directories to be created, which would be especially bad 
+# if $src (and thus $dsttmp) contains '*'.
+
+       if [ -f $src -o -d $src ]
+       then
+               true
+       else
+               echo "install:  $src does not exist"
+               exit 1
+       fi
+       
+       if [ x"$dst" = x ]
+       then
+               echo "install:  no destination specified"
+               exit 1
+       else
+               true
+       fi
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+       if [ -d $dst ]
+       then
+               dst="$dst"/`basename $src`
+       else
+               true
+       fi
+fi
+
+## this sed command emulates the dirname command
+dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
+
+# Make sure that the destination directory exists.
+#  this part is taken from Noah Friedman's mkinstalldirs script
+
+# Skip lots of stat calls in the usual case.
+if [ ! -d "$dstdir" ]; then
+defaultIFS='   
+'
+IFS="${IFS-${defaultIFS}}"
+
+oIFS="${IFS}"
+# Some sh's can't handle IFS=/ for some reason.
+IFS='%'
+set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
+IFS="${oIFS}"
+
+pathcomp=''
+
+while [ $# -ne 0 ] ; do
+       pathcomp="${pathcomp}${1}"
+       shift
+
+       if [ ! -d "${pathcomp}" ] ;
+        then
+               $mkdirprog "${pathcomp}"
+       else
+               true
+       fi
+
+       pathcomp="${pathcomp}/"
+done
+fi
+
+if [ x"$dir_arg" != x ]
+then
+       $doit $instcmd $dst &&
+
+       if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
+       if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
+       if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
+       if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
+else
+
+# If we're going to rename the final executable, determine the name now.
+
+       if [ x"$transformarg" = x ] 
+       then
+               dstfile=`basename $dst`
+       else
+               dstfile=`basename $dst $transformbasename | 
+                       sed $transformarg`$transformbasename
+       fi
+
+# don't allow the sed command to completely eliminate the filename
+
+       if [ x"$dstfile" = x ] 
+       then
+               dstfile=`basename $dst`
+       else
+               true
+       fi
+
+# Make a temp file name in the proper directory.
+
+       dsttmp=$dstdir/#inst.$$#
+
+# Move or copy the file name to the temp name
+
+       $doit $instcmd $src $dsttmp &&
+
+       trap "rm -f ${dsttmp}" 0 &&
+
+# and set any options; do chmod last to preserve setuid bits
+
+# If any of these fail, we abort the whole thing.  If we want to
+# ignore errors from any of these, just make sure not to ignore
+# errors from the above "$doit $instcmd $src $dsttmp" command.
+
+       if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
+       if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
+       if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
+       if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
+
+# Now rename the file to the real destination.
+
+       $doit $rmcmd -f $dstdir/$dstfile &&
+       $doit $mvcmd $dsttmp $dstdir/$dstfile 
+
+fi &&
+
+
+exit 0
diff --git a/3rd-party/zisofs_tools/iso9660.c b/3rd-party/zisofs_tools/iso9660.c
new file mode 100644 (file)
index 0000000..c5b0abd
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* $Id: iso9660.c,v 1.1 2001/07/27 14:37:08 hpa Exp $ */
+/* ----------------------------------------------------------------------- *
+ *   
+ *   Copyright 2001 H. Peter Anvin - All Rights Reserved
+ *
+ *   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, Inc., 675 Mass Ave, Cambridge MA 02139,
+ *   USA; either version 2 of the License, or (at your option) any later
+ *   version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+#include "iso9660.h"
+
+/* zisofs magic */
+
+const unsigned char zisofs_magic[8] = {
+  0x37, 0xE4, 0x53, 0x96, 0xC9, 0xDB, 0xD6, 0x07
+};
+
+/* iso9660 integer formats */
+
+void
+set_721(void *pnt, unsigned int i)
+{
+  unsigned char *p = (unsigned char *)pnt;
+  p[0] = i & 0xff;
+  p[1] = (i >> 8) & 0xff;
+}
+
+unsigned int
+get_721(void *pnt)
+{
+  unsigned char *p = (unsigned char *)pnt;
+  return ((unsigned int)p[0]) + ((unsigned int)p[1] << 8);
+}
+
+void
+set_722(void *pnt, unsigned int i)
+{
+  unsigned char *p = (unsigned char *)pnt;
+  p[0] = (i >> 8) & 0xff;
+  p[1] = i & 0xff;
+}
+
+unsigned int
+get_722(void *pnt)
+{
+  unsigned char *p = (unsigned char *)pnt;
+  return ((unsigned int)p[0] << 8) + ((unsigned int)p[1]);
+}
+
+void
+set_723(void *pnt, unsigned int i)
+{
+  unsigned char *p = (unsigned char *)pnt;
+  p[3] = p[0] = i & 0xff;
+  p[2] = p[1] = (i >> 8) & 0xff;
+}
+
+#define get_723(x) get_721(x)
+
+void
+set_731(void *pnt, unsigned int i)
+{
+  unsigned char *p = (unsigned char *)pnt;
+  p[0] = i & 0xff;
+  p[1] = (i >> 8) & 0xff;
+  p[2] = (i >> 16) & 0xff;
+  p[3] = (i >> 24) & 0xff;
+}
+
+unsigned int
+get_731(void *pnt)
+{
+  unsigned char *p = (unsigned char *)pnt;
+  return ((unsigned int)p[0]) + ((unsigned int)p[1] << 8) +
+    ((unsigned int)p[2] << 16) + ((unsigned int)p[3] << 24);
+}
+
+void
+set_732(void *pnt, unsigned int i)
+{
+  unsigned char *p = (unsigned char *)pnt;
+  p[3] = i & 0xff;
+  p[2] = (i >> 8) & 0xff;
+  p[1] = (i >> 16) & 0xff;
+  p[0] = (i >> 24) & 0xff;
+}
+
+unsigned int
+get_732(void *pnt)
+{
+  unsigned char *p = (unsigned char *)pnt;
+  return ((unsigned int)p[0] << 24) + ((unsigned int)p[1] << 16) +
+    ((unsigned int)p[2] << 8) + ((unsigned int)p[3]);
+}
+
+void
+set_733(void *pnt, unsigned int i)
+{
+  unsigned char *p = (unsigned char *)pnt;
+  p[7] = p[0] = i & 0xff;
+  p[6] = p[1] = (i >> 8) & 0xff;
+  p[5] = p[2] = (i >> 16) & 0xff;
+  p[4] = p[3] = (i >> 24) & 0xff;
+}
+
+#define get_733(x) get_731(x)
+
diff --git a/3rd-party/zisofs_tools/iso9660.h b/3rd-party/zisofs_tools/iso9660.h
new file mode 100644 (file)
index 0000000..20249b8
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+#ident "$Id: iso9660.h,v 1.4 2006/07/04 04:57:42 hpa Exp $"
+/* ----------------------------------------------------------------------- *
+ *   
+ *   Copyright 2001 H. Peter Anvin - All Rights Reserved
+ *
+ *   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, Inc., 675 Mass Ave, Cambridge MA 02139,
+ *   USA; either version 2 of the License, or (at your option) any later
+ *   version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+/* zisofs definitions */
+
+#ifndef ISO9660_H
+#define ISO9660_H
+
+#ifndef CBLOCK_SIZE_LG2
+#define CBLOCK_SIZE_LG2        15      /* Compressed block size */
+#endif
+#define CBLOCK_SIZE    (1 << CBLOCK_SIZE_LG2)
+
+/* Compressed file magic */
+extern const unsigned char zisofs_magic[8];
+
+/* VERY VERY VERY IMPORTANT: Must be a multiple of 4 bytes */
+struct compressed_file_header {
+  char magic[8];
+  char uncompressed_len[4];
+  unsigned char header_size;
+  unsigned char block_size;
+  char reserved[2];            /* Reserved for future use, MBZ */
+};
+
+/* iso9660 integer formats */
+void set_721(void *, unsigned int);
+unsigned int get_721(void *);
+void set_722(void *, unsigned int);
+unsigned int get_722(void *);
+void set_723(void *, unsigned int);
+void set_731(void *, unsigned int);
+unsigned int get_731(void *);
+void set_732(void *, unsigned int);
+unsigned int get_732(void *);
+void set_733(void *, unsigned int);
+#define get_723(x) get_721(x)
+#define get_733(x) get_731(x)
+
+#endif /* ISO9660_H */
diff --git a/3rd-party/zisofs_tools/mkzftree.1 b/3rd-party/zisofs_tools/mkzftree.1
new file mode 100644 (file)
index 0000000..fcd3d15
--- /dev/null
@@ -0,0 +1,120 @@
+.\" $Id: mkzftree.1,v 1.13 2004/07/20 04:03:53 hpa Exp $
+.\" -----------------------------------------------------------------------
+.\"   
+.\"   Copyright 2001 H. Peter Anvin - All Rights Reserved
+.\"
+.\"   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, Inc., 675 Mass Ave, Cambridge MA 02139,
+.\"   USA; either version 2 of the License, or (at your option) any later
+.\"   version; incorporated herein by reference.
+.\"
+.\" -----------------------------------------------------------------------
+.TH MKZFTREE "1" "30 July 2001" "zisofs-tools" "H. Peter Anvin"
+.SH NAME
+mkzftree \- Create a zisofs/RockRidge compressed file tree
+.SH SYNOPSIS
+.B mkzftree
+[\fIOPTIONS\fR]... \fIINPUT\fR \fIOUTPUT\fR
+.SH DESCRIPTION
+.PP
+Takes an input file tree (\fIINPUT\fR) and create a corresponding
+compressed file tree (\fIOUTPUT\fR) that can be used with an
+appropriately patched
+.BR mkisofs (8)
+to create a transparent-compression ISO 9660/Rock Ridge filesystem using
+the "ZF" compression records.
+.SH OPTIONS
+.TP
+\fB\-f\fP, \fB\-\-force\fP
+Always compress all files, even if they get larger when compressed.
+.TP
+\fB\-z\fP \fIlevel\fP, \fB\-\-level\fP \fIlevel\fP
+Select compression level (1-9, default is 9).  Lower compression
+levels are faster, but typically result in larger output.
+.TP
+\fB\-u\fP, \fB\-\-uncompress\fP
+Uncompress an already compressed tree.  This can be used to read a
+compressed filesystem on a system which cannot read them natively.
+.TP
+\fB\-p\fP \fIparallelism\fP, \fB\-\-parallelism\fP \fIparallelism\fP
+Compress in parallel.  The
+.I parallelism
+value indicates how many compression threads are allowed to run.
+.TP
+\fB\-x\fP, \fB\-\-one-filesystem\fP
+Do not cross filesystem boundaries, but create directory stubs at
+mount points.
+.TP
+\fB\-X\fP, \fB\-\-strict-one-filesystem\fP
+Do not cross filesystem boundaries, and do not create directory stubs
+at mount points.
+.TP
+\fB\-C\fP \fIpath\fP, \fB\-\-crib-path\fP \fIpath\fP
+Steal ("crib") files from another directory if it looks (based on
+name, size, type and modification time) like they match entries in the
+new filesystem.  The "crib tree" is usually the compressed version of
+an older version of the same workload; this thus allows for
+"incremental rebuilds" of a compressed filesystem tree.  The files are
+hardlinked from the crib tree to the output tree, so if it is
+desirable to keep the link count correct the crib path should be
+deleted before running \fBmkisofs\fP.  The crib tree must be on the
+same filesystem as the output tree.
+.TP
+\fB\-l\fP, \fB\-\-local\fP
+Do not recurse into subdirectories, but create the directories
+themselves.
+.TP
+\fB\-L\fP, \fB\-\-strict-local\fP
+Do not recurse into subdirectories, and do not create directories.
+.TP
+\fB\-F\fP, \fB\-\-file\fP
+Indicates that \fIINPUT\fP may not necessarily be a directory; this
+allows operation on a single file.  Note especially that if \fI\-F\fP
+is specified, and \fIINPUT\fP is a symlink, the symlink itself will be
+copied rather than whatever it happens to point to.
+.TP
+\fB\-s\fP, \fB\-\-sloppy\fP
+Treat file modes, times and ownership data as less than precious
+information and don't abort if they cannot be set.  This may be useful
+if running
+.B mkisofs
+on an input tree you do not own.
+.TP
+\fB\-v\fP, \fB\-\-verbose\fP
+Increase the program verbosity.
+.TP
+\fB\-V\fP \fIvalue\fP, \fB\-\-verbosity\fP \fIvalue\fP
+Set the program verbosity to
+.IR value .
+.TP
+\fB\-q\fP, \fB\-\-quiet\fP
+Issue no messages whatsoever, including error messages.  This is the same
+as specifying
+.IR "\-V\ 0" .
+.TP
+\fB\-h\fP, \fB\-\-help\fP
+Display a brief help message.
+.TP
+\fB\-w\fP, \fB\-\-version\fP
+Display the release version.
+.SH BUGS
+Long options (beginning with \fI\-\-\fP) may not work on all systems.
+See the message printed out by \fImkzftree\ \-h\fP to see if this
+applies to your system.
+.PP
+Inode change times (ctimes) are not copied.  This is a system
+limitation and applies to all file copy programs.
+.PP
+If using the parallel option (\fI\-z\fP) the access times (atimes) on
+directories may or may not be copied.  If it is important that the
+atimes on directories are copied exactly, avoid using \fI\-z\fP.
+.SH AUTHOR
+Written by H. Peter Anvin <hpa@zytor.com>.
+.SH COPYRIGHT
+Copyright \(co 2001-2002 H. Peter Anvin.
+.br
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+.SH "SEE ALSO"
+.BR mkisofs (8)
diff --git a/3rd-party/zisofs_tools/mkzftree.c b/3rd-party/zisofs_tools/mkzftree.c
new file mode 100644 (file)
index 0000000..3551180
--- /dev/null
@@ -0,0 +1,294 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* $Id: mkzftree.c,v 1.18 2006/07/04 04:57:42 hpa Exp $ */
+/* ----------------------------------------------------------------------- *
+ *   
+ *   Copyright 2001 H. Peter Anvin - All Rights Reserved
+ *
+ *   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, Inc., 675 Mass Ave, Cambridge MA 02139,
+ *   USA; either version 2 of the License, or (at your option) any later
+ *   version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * mkzffile.c
+ *
+ *     - Generate block-compression of files for use with
+ *       the "ZF" extension to the iso9660/RockRidge filesystem.
+ *
+ *       The file compression technique used is the "deflate"
+ *       algorithm used by the zlib library; each block must have a
+ *       valid (12-byte) zlib header.  In addition, the file itself
+ *       has the following structure:
+ *
+ *       Byte offset   iso9660 type    Contents
+ *         0           (8 bytes)       Magic number (37 E4 53 96 C9 DB D6 07)
+ *         8           7.3.1           Uncompressed file size
+ *        12           7.1.1           header_size >> 2 (currently 4)
+ *        13           7.1.1           log2(block_size)
+ *        14           (2 bytes)       Reserved, must be zero
+ *
+ * The header may get expanded in the future, at which point the
+ * header size field will be used to increase the space for the
+ * header.
+ *
+ * All implementations are required to support a block_size of 32K
+ * (byte 13 == 15).
+ *
+ * Note that bytes 12 and 13 and the uncompressed length are also
+ * present in the ZF record; THE TWO MUST BOTH BE CONSISTENT AND
+ * CORRECT.
+ *
+ * Given the uncompressed size, block_size, and header_size:
+ *
+ *     Nblocks := ceil(size/block_size)
+ *
+ * After the header follow (nblock+1) 32-bit pointers, recorded as
+ * iso9660 7.3.1 (littleendian); each indicate the byte offset (from
+ * the start of the file) to one block and the first byte beyond the
+ * end of the previous block; the first pointer thus point to the
+ * start of the data area and the last pointer to the first byte
+ * beyond it:
+ *
+ *     block_no := floor(byte_offset/block_size)
+ *
+ *     block_start := read_pointer_731( (header_size+block_no)*4 )
+ *     block_end   := read_pointer_731( (header_size+block_no+1)*4 )
+ *
+ * The block data is compressed according to "zlib".
+ */
+
+#include "mkzftree.h"          /* Must be included first! */
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <limits.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/time.h>
+
+#ifdef HAVE_GETOPT_H
+#include <getopt.h>
+#endif
+
+#include "version.h"
+
+/* Command line options */
+struct cmdline_options opt = {
+  0,                           /* Force compression */
+  9,                           /* Compression level */
+  0,                           /* Parallelism (0 = strictly serial) */
+  0,                           /* One filesystem only */
+  0,                           /* One directory only */
+  1,                           /* Create stub directories */
+  0,                           /* Root may be a file */
+  0,                           /* Be paranoid about metadata */
+  default_verbosity,           /* Default verbosity */
+  block_compress_file          /* Default transformation function */
+};
+
+/* Program name */
+const char *program;
+
+/* Long options */
+#define OPTSTRING "fz:up:xXC:lLFvqV:hw"
+#ifdef HAVE_GETOPT_LONG
+const struct option long_options[] = {
+  { "force",                0,  0,  'f' },
+  { "level",                 1,  0,  'z' },
+  { "uncompress",            0,  0,  'u' },
+  { "parallelism",           1,  0,  'p' },
+  { "one-filesystem",        0,  0,  'x' },
+  { "strict-one-filesystem", 0,  0,  'X' },
+  { "crib-tree",             1,  0,  'C' },
+  { "local",                 0,  0,  'l' },
+  { "strict-local",          0,  0,  'L' },
+  { "file",                  0,  0,  'F' },
+  { "verbose",               0,  0,  'v' },
+  { "quiet",                 0,  0,  'q' },
+  { "verbosity",             1,  0,  'V' },
+  { "help",                  0,  0,  'h' },
+  { "version",               0,  0,  'w' },
+  { 0, 0, 0, 0 }
+};
+#define LO(X) X
+#else
+#define getopt_long(C,V,O,L,I) getopt(C,V,O)
+#define LO(X)
+#endif
+  
+static void usage(enum verbosity level, int err)
+{
+  message(level,
+         "zisofs-tools " ZISOFS_TOOLS_VERSION "\n"
+         "Usage: %s [options] intree outtree\n"
+         LO("  --force                ")"  -f    Always compress, even if result is larger\n"
+         LO("  --level #              ")"  -z #  Set compression level (1-9)\n"
+         LO("  --uncompress           ")"  -u    Uncompress an already compressed tree\n"
+         LO("  --parallelism #        ")"  -p #  Process up to # files in parallel\n"
+         LO("  --one-filesystem       ")"  -x    Do not cross filesystem boundaries\n"
+         LO("  --strict-one-filesystem")"  -X    Same as -x, but don't create stubs dirs\n"
+         LO("  --crib-tree            ")"  -C    Steal \"crib\" files from an old tree\n"
+         LO("  --local                ")"  -l    Do not recurse into subdirectoires\n"
+         LO("  --strict-local         ")"  -L    Same as -l, but don't create stubs dirs\n"
+         LO("  --file                 ")"  -F    Operate possibly on a single file\n"
+         LO("  --sloppy               ")"  -s    Don't abort if metadata cannot be set\n"
+         LO("  --verbose              ")"  -v    Increase message verbosity\n"
+         LO("  --verbosity #          ")"  -V #  Set message verbosity to # (default = %d)\n"
+         LO("  --quiet                ")"  -q    No messages, not even errors (-V 0)\n"
+         LO("  --help                 ")"  -h    Display this message\n"
+         LO("  --version              ")"  -w    Display the program version\n"
+         ,program, (int)default_verbosity);
+  exit(err);
+}
+
+static int opt_atoi(const char *str)
+{
+  char *endptr;
+  long out;
+
+  out = strtol(str, &endptr, 10);
+  if ( *endptr )
+    usage(vl_error, EX_USAGE);
+
+  return (int)out;
+}
+
+
+int main(int argc, char *argv[])
+{
+  const char *in, *out, *crib = NULL;
+  struct stat st;
+  int optch, err;
+
+  program = argv[0];
+
+  while ( (optch = getopt_long(argc, argv, OPTSTRING, long_options, NULL))
+         != EOF ) {
+    switch(optch) {
+    case 'f':
+      opt.force = 1;           /* Always compress */
+      break;
+    case 'z':
+      opt.level = opt_atoi(optarg);
+      if ( opt.level < 1 || opt.level > 9 ) {
+       message(vl_error, "%s: invalid compression level: %d\n",
+               program, optarg);
+       exit(EX_USAGE);
+      }
+      break;
+    case 'v':
+      opt.verbosity++;
+      break;
+    case 'V':
+      opt.verbosity = opt_atoi(optarg);
+      break;
+    case 'q':
+      opt.verbosity = vl_quiet;
+      break;
+    case 'u':
+      opt.munger = block_uncompress_file;
+      break;
+    case 'C':
+      crib = optarg;
+      break;
+    case 'p':
+      opt.parallel = opt_atoi(optarg);
+      break;
+    case 'x':
+      opt.onefs = 1;  opt.do_mkdir = 1;
+      break;
+    case 'l':
+      opt.onedir = 1; opt.do_mkdir = 1;
+      break;
+    case 'X':
+      opt.onefs = 1;  opt.do_mkdir = 0;
+      break;
+    case 'L':
+      opt.onedir = 1; opt.do_mkdir = 0;
+      break;
+    case 'F':
+      opt.file_root = 1;
+      break;
+    case 's':
+      opt.sloppy = 1;
+      break;
+    case 'h':
+      usage(vl_quiet, 0);
+      break;
+    case 'w':
+      message(vl_quiet, "zisofs-tools " ZISOFS_TOOLS_VERSION "\n");
+      exit(0);
+    default:
+      usage(vl_error, EX_USAGE);
+      break;
+    }
+  }
+
+  if ( (argc-optind) != 2 )
+    usage(vl_error, EX_USAGE);
+
+  in  = argv[optind];          /* Input tree */
+  out = argv[optind+1];                /* Output tree */
+
+  umask(077);
+
+  if ( opt.file_root ) {
+    if ( lstat(in, &st) ) {
+      message(vl_error, "%s: %s: %s\n", program, in, strerror(errno));
+      exit(EX_NOINPUT);
+    }
+
+    err = munge_entry(in, out, crib, NULL);
+  } else {
+    /* Special case: we use stat() for the root, not lstat() */
+    if ( stat(in, &st) ) {
+      message(vl_error, "%s: %s: %s\n", program, in, strerror(errno));
+      exit(EX_NOINPUT);
+    }
+    if ( !S_ISDIR(st.st_mode) ) {
+      message(vl_error, "%s: %s: Not a directory\n", program, in);
+      exit(EX_DATAERR);
+    }
+    
+    err = munge_tree(in, out, crib);
+  }    
+
+  wait_for_all_workers();
+    
+  if ( err )
+    exit(err);
+
+  if ( !opt.file_root ) {
+    if ( chown(out, st.st_uid, st.st_gid) && !opt.sloppy ) {
+      message(vl_error, "%s: %s: %s", program, out, strerror(errno));
+      err = EX_CANTCREAT;
+    }
+    if ( chmod(out, st.st_mode) && !opt.sloppy && !err ) {
+      message(vl_error, "%s: %s: %s", program, out, strerror(errno));
+      err = EX_CANTCREAT;
+    }
+    if ( copytime(out, &st) && !opt.sloppy && !err ) {
+      message(vl_error, "%s: %s: %s", program, out, strerror(errno));
+      err = EX_CANTCREAT;
+    }
+  }
+
+  return err;
+}
diff --git a/3rd-party/zisofs_tools/mkzftree.h b/3rd-party/zisofs_tools/mkzftree.h
new file mode 100644 (file)
index 0000000..36e9358
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+#ident "$Id: mkzftree.h,v 1.7 2006/07/04 04:57:42 hpa Exp $"
+/* ----------------------------------------------------------------------- *
+ *   
+ *   Copyright 2001-2006 H. Peter Anvin - All Rights Reserved
+ *
+ *   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, Inc., 675 Mass Ave, Cambridge MA 02139,
+ *   USA; either version 2 of the License, or (at your option) any later
+ *   version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+#ifndef MKZFTREE_H
+#define MKZFTREE_H
+
+/* config.h should be included before any system headers!!!! */
+#include "config.h"
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#ifdef HAVE_INTTYPES_H
+#include <inttypes.h>
+#endif
+#ifdef HAVE_ENDIAN_H
+#include <endian.h>
+#endif
+
+#ifdef HAVE_SYSEXITS_H
+#include <sysexits.h>
+#else
+#define EX_USAGE       64      /* command line usage error */
+#define EX_DATAERR     65      /* data format error */
+#define EX_NOINPUT     66      /* cannot open input */
+#define EX_NOUSER      67      /* addressee unknown */
+#define EX_NOHOST      68      /* host name unknown */
+#define EX_UNAVAILABLE 69      /* service unavailable */
+#define EX_SOFTWARE    70      /* internal software error */
+#define EX_OSERR       71      /* system error (e.g., can't fork) */
+#define EX_OSFILE      72      /* critical OS file missing */
+#define EX_CANTCREAT   73      /* can't create (user) output file */
+#define EX_IOERR       74      /* input/output error */
+#define EX_TEMPFAIL    75      /* temp failure; user is invited to retry */
+#define EX_PROTOCOL    76      /* remote error in protocol */
+#define EX_NOPERM      77      /* permission denied */
+#define EX_CONFIG      78      /* configuration error */
+#endif
+
+/* File transformation functions */  
+typedef int (*munger_func)(FILE *, FILE *, off_t);
+int block_compress_file(FILE *, FILE *, off_t);
+int block_uncompress_file(FILE *, FILE *, off_t);
+
+/* mkzftree.c */
+extern const char *program;    /* Program name */
+enum verbosity {               /* Message verbosity */
+  vl_quiet,                    /* No messages */
+  vl_error,                    /* Error messages only */
+  vl_filename,                 /* Display filenames */
+  vl_crib,                     /* Cribbing files */
+};
+#define default_verbosity vl_error
+struct cmdline_options {
+  int force;                   /* Always compress */
+  int level;                   /* Compression level */
+  int parallel;                        /* Parallelism (0 = strictly serial) */
+  int onefs;                   /* One filesystem only */
+  int onedir;                  /* One directory only */
+  int do_mkdir;                        /* Create stub directories */
+  int file_root;               /* The root may be a file */
+  int sloppy;                  /* Don't make sure metadata is set correctly */
+  enum verbosity verbosity;    /* Message verbosity */
+  munger_func munger;          /* Default action */
+};
+extern struct cmdline_options opt;
+
+/* walk.c */
+int munge_tree(const char *, const char *, const char *);
+int munge_entry(const char *, const char *, const char *, const struct stat *);
+
+/* workers.c */
+void wait_for_all_workers(void);
+int spawn_worker(void);
+void end_worker(int);
+
+/* util.c */
+void *xmalloc(size_t);
+void *xrealloc(void *, size_t);
+char *xstrdup(const char *);
+void message(enum verbosity, const char *, ...);
+
+/* hash.c */
+const char *hash_find_file(struct stat *);
+void hash_insert_file(struct stat *, const char *);
+
+/* copytime.h */
+int copytime(const char *, const struct stat *);
+
+#endif /* MKZFTREE_H */
diff --git a/3rd-party/zisofs_tools/uncompress.c b/3rd-party/zisofs_tools/uncompress.c
new file mode 100644 (file)
index 0000000..c9ba6e4
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* $Id: uncompress.c,v 1.3 2006/07/04 04:57:42 hpa Exp $ */
+/* ----------------------------------------------------------------------- *
+ *   
+ *   Copyright 2001-2006 H. Peter Anvin - All Rights Reserved
+ *
+ *   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, Inc., 675 Mass Ave, Cambridge MA 02139,
+ *   USA; either version 2 of the License, or (at your option) any later
+ *   version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+#include "mkzftree.h"          /* Must be included first! */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <zlib.h>
+
+#include "iso9660.h"
+
+int block_uncompress_file(FILE *input, FILE *output, off_t size)
+{
+  struct compressed_file_header hdr;
+  Bytef *inbuf, *outbuf;
+  int block_shift;
+  char *pointer_block, *pptr;
+  unsigned long nblocks;
+  unsigned long fullsize, block_size, block_size2;
+  size_t ptrblock_bytes;
+  unsigned long cstart, cend, csize;
+  uLong bytes;
+  int zerr;
+  int err = EX_SOFTWARE;
+
+  if ( (bytes = fread(&hdr, 1, sizeof hdr, input)) != sizeof hdr ) {
+    if ( bytes == (size_t)size ) {
+      /* Very short file; not compressed */
+      return ( fwrite(&hdr, 1, bytes, output) != bytes ) ? EX_CANTCREAT : 0;
+    } else {
+      return EX_IOERR;         /* Read error */
+    }
+  }
+
+  if ( memcmp(&hdr.magic, zisofs_magic, sizeof zisofs_magic) ) {
+    inbuf = xmalloc(CBLOCK_SIZE);
+    /* Not compressed */
+    memcpy(inbuf, &hdr, sizeof hdr);
+    bytes = sizeof hdr;
+    do {
+      if ( fwrite(inbuf, 1, bytes, output) != bytes )
+       return EX_CANTCREAT;
+    } while ( (bytes = fread(inbuf, 1, CBLOCK_SIZE, input)) > 0 );
+    free(inbuf);
+    return ferror(input) ? EX_IOERR : 0;
+  }
+
+  /* Now we know the file must be compressed.  Get the pointer table. */
+  if ( fseek(input, hdr.header_size << 2, SEEK_SET) == -1 )
+    return EX_IOERR;
+
+  fullsize    = get_731(hdr.uncompressed_len);
+  block_shift = hdr.block_size;
+  block_size  = 1UL << block_shift;
+  block_size2 = block_size << 1;
+  inbuf  = xmalloc(block_size2);
+  outbuf = xmalloc(block_size);
+
+  nblocks = (fullsize + block_size - 1) >> block_shift;
+
+  ptrblock_bytes = (nblocks+1) * 4;
+  pointer_block = xmalloc(ptrblock_bytes);
+
+  if ( (bytes = fread(pointer_block, 1, ptrblock_bytes, input)) != ptrblock_bytes ) {
+    err = EX_IOERR;
+    goto free_ptr_bail;
+  }
+  
+  pptr = pointer_block;
+  while ( fullsize ) {
+    cstart = get_731(pptr);
+    pptr += 4;
+    cend   = get_731(pptr);
+
+    csize = cend-cstart;
+
+    if ( csize == 0 ) {
+      memset(outbuf, 0, block_size);
+      bytes = block_size;
+    } else {
+      if ( csize > block_size2 ) {
+       err = EX_DATAERR;
+       goto free_ptr_bail;
+      }
+      
+      if ( fseek(input, cstart, SEEK_SET) == -1 ||
+          (bytes = fread(inbuf, 1, csize, input)) != csize ) {
+       err = EX_IOERR;
+       goto free_ptr_bail;
+      }
+      
+      bytes = block_size;              /* Max output buffer size */
+      if ( (zerr = uncompress(outbuf, &bytes, inbuf, csize)) != Z_OK ) {
+       err = (zerr = Z_MEM_ERROR) ? EX_OSERR : EX_DATAERR;
+       goto free_ptr_bail;
+      }
+    }
+      
+    if ( ((fullsize > block_size) && (bytes != block_size))
+        || ((fullsize <= block_size) && (bytes < fullsize)) ) {
+      err = EX_DATAERR;
+      goto free_ptr_bail;
+    }
+    
+    if ( bytes > fullsize )
+      bytes = fullsize;
+    
+    if ( fwrite(outbuf, 1, bytes, output) != bytes ) {
+      err = EX_CANTCREAT;
+      goto free_ptr_bail;
+    }
+
+    fullsize -= bytes;
+  }
+
+  err = 0;
+
+ free_ptr_bail:
+  free(pointer_block);
+  free(inbuf);
+  free(outbuf);
+  return err;
+}
+
+
diff --git a/3rd-party/zisofs_tools/util.c b/3rd-party/zisofs_tools/util.c
new file mode 100644 (file)
index 0000000..1b45cdf
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* $Id: util.c,v 1.3 2006/07/04 04:57:42 hpa Exp $ */
+/* ----------------------------------------------------------------------- *
+ *   
+ *   Copyright 2001-2006 H. Peter Anvin - All Rights Reserved
+ *
+ *   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, Inc., 675 Mass Ave, Cambridge MA 02139,
+ *   USA; either version 2 of the License, or (at your option) any later
+ *   version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+#include "mkzftree.h"          /* Must be included first! */
+
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+
+/* Convenience functions */
+void *xmalloc(size_t size)
+{
+  void *p = malloc(size);
+
+  if ( !p ) {
+    perror(program);
+    exit(EX_OSERR);
+  }
+
+  return p;
+}
+
+char *xstrdup(const char *str)
+{
+  char *s = strdup(str);
+
+  if ( !s ) {
+    perror(program);
+    exit(EX_OSERR);
+  }
+  
+  return s;
+}
+
+void message(enum verbosity level, const char *format, ...)
+{
+  va_list ap;
+
+  va_start(ap, format);
+  if ( opt.verbosity >= level )
+    vfprintf(stderr, format, ap);
+  va_end(ap);
+}
+
diff --git a/3rd-party/zisofs_tools/version b/3rd-party/zisofs_tools/version
new file mode 100644 (file)
index 0000000..238d6e8
--- /dev/null
@@ -0,0 +1 @@
+1.0.7
diff --git a/3rd-party/zisofs_tools/walk.c b/3rd-party/zisofs_tools/walk.c
new file mode 100644 (file)
index 0000000..3b62f73
--- /dev/null
@@ -0,0 +1,323 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+#ident "$Id: walk.c,v 1.7 2006/07/04 04:57:42 hpa Exp $"
+/* ----------------------------------------------------------------------- *
+ *   
+ *   Copyright 2001-2006 H. Peter Anvin - All Rights Reserved
+ *
+ *   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, Inc., 675 Mass Ave, Cambridge MA 02139,
+ *   USA; either version 2 of the License, or (at your option) any later
+ *   version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * walk.c
+ *
+ * Functions to walk the file tree
+ */
+
+#include "mkzftree.h"          /* Must be included first! */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <limits.h>
+#include <string.h>
+#include <errno.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include "iso9660.h"
+
+static int munge_file(const char *inpath, const char *outpath,
+                     const char *cribpath, struct stat *st)
+{
+  FILE *in, *out;
+  int err = 0;
+
+  if ( cribpath ) {
+    struct stat cst;
+    struct compressed_file_header cfh;
+
+    /* Compare as much as we realistically can */
+    if ( !stat(cribpath, &cst) &&
+        st->st_mode == cst.st_mode &&
+        st->st_uid == cst.st_uid &&
+        st->st_gid == cst.st_gid &&
+        st->st_mtime == cst.st_mtime ) {
+      if ( (in = fopen(cribpath, "rb")) ) {
+       int e = fread(&cfh, 1, sizeof cfh, in);
+       fclose(in);
+       /* Attempt to restore the atime */
+       copytime(cribpath, &cst);
+
+       if ( (e == sizeof cfh &&
+             !memcmp(cfh.magic, zisofs_magic, sizeof zisofs_magic) &&
+             (off_t)get_731(cfh.uncompressed_len) == st->st_size) ||
+            (st->st_size == cst.st_size &&
+             (e < (int)(sizeof zisofs_magic) ||
+              memcmp(cfh.magic, zisofs_magic, sizeof zisofs_magic))) ) {
+         /* File is cribbable.  Steal it. */
+         if ( !link(cribpath, outpath) ) {
+           message(vl_crib, "crib: %s -> %s\n", cribpath, outpath);
+           copytime(outpath, st);      /* Set the the atime */
+           return 0;
+         }
+       }
+      }
+    }
+  }
+
+  in = fopen(inpath, "rb");
+  if ( !in )
+    return EX_NOINPUT;
+  out = fopen(outpath, "wb");
+  if ( !out ) {
+    fclose(in);
+    return EX_CANTCREAT;
+  }
+
+  if ( spawn_worker() ) {
+    err = opt.munger(in, out, st->st_size);
+    fclose(in);
+    fclose(out);
+    
+    chown(outpath, st->st_uid, st->st_gid);
+    chmod(outpath, st->st_mode);
+    copytime(outpath, st);
+    
+    end_worker(err);
+  } else {
+    fclose(in);
+    fclose(out);
+  }
+
+  return err;
+}
+
+int munge_tree(const char *intree, const char *outtree, const char *cribtree)
+{
+  char *in_path, *out_path, *crib_path;
+  char *in_file, *out_file, *crib_file;
+  DIR *thisdir;
+  struct dirent *dirent;
+  struct stat dirst;
+  int err = 0;
+  
+  /* Construct buffers with the common filename prefix, and point to the end */
+
+  in_path = xmalloc(strlen(intree) + NAME_MAX + 2);
+  strcpy(in_path, intree);
+  in_file = strchr(in_path, '\0');
+  *in_file++ = '/';
+
+  out_path = xmalloc(strlen(outtree) + NAME_MAX + 2);
+  strcpy(out_path, outtree);
+  out_file = strchr(out_path, '\0');
+  *out_file++ = '/';
+
+  if ( cribtree ) {
+    crib_path = xmalloc(strlen(cribtree) + NAME_MAX + 2);
+    strcpy(crib_path, cribtree);
+    crib_file = strchr(crib_path, '\0');
+    *crib_file++ = '/';
+  } else {
+    crib_path = crib_file = NULL;
+  }
+
+  /* Get directory information */
+  if ( stat(intree, &dirst) ) {
+    message(vl_error, "%s: Failed to stat directory %s: %s\n",
+           program, intree, strerror(errno));
+    return EX_NOINPUT;
+  }
+
+  /* Open the directory */
+  thisdir = opendir(intree);
+  if ( !thisdir ) {
+    message(vl_error, "%s: Failed to open directory %s: %s\n",
+           program, intree, strerror(errno));
+    return EX_NOINPUT;
+  }
+
+  /* Create output directory */
+  if ( mkdir(outtree, 0700) ) {
+    message(vl_error, "%s: Cannot create output directory %s: %s\n",
+           program, outtree, strerror(errno));
+    return EX_CANTCREAT;
+  }
+
+  while ( (dirent = readdir(thisdir)) != NULL ) {
+    if ( !strcmp(dirent->d_name, ".") ||
+        !strcmp(dirent->d_name, "..") )
+      continue;                        /* Ignore . and .. */
+    
+    strcpy(in_file, dirent->d_name);
+    strcpy(out_file, dirent->d_name);
+    if ( crib_file )
+      strcpy(crib_file, dirent->d_name);
+    
+    err = munge_entry(in_path, out_path, crib_path, &dirst);
+    if ( err )
+      break;
+  }
+  closedir(thisdir);
+  
+  free(in_path);
+  free(out_path);
+  
+  return err;
+}
+
+
+int munge_entry(const char *in_path, const char *out_path,
+               const char *crib_path, const struct stat *dirst)
+{
+  struct stat st;
+  int err = 0;
+
+  message(vl_filename, "%s -> %s\n", in_path, out_path);
+
+  if ( lstat(in_path, &st) ) {
+    message(vl_error, "%s: Failed to stat file %s: %s\n",
+           program, in_path, strerror(errno));
+    return EX_NOINPUT;
+  }
+  
+  if ( S_ISREG(st.st_mode) ) {
+    if ( st.st_nlink > 1 ) {
+      /* Hard link. */
+      const char *linkname;
+      
+      if ( (linkname = hash_find_file(&st)) != NULL ) {
+       /* We've seen it before, hard link it */
+       
+       if ( link(linkname, out_path) ) {
+         message(vl_error, "%s: hard link %s -> %s failed: %s\n",
+                 program, out_path, linkname, strerror(errno));
+         return EX_CANTCREAT;
+       }
+      } else {
+       /* First encounter, compress and enter into hash */
+       if ( (err = munge_file(in_path, out_path, crib_path, &st)) != 0 ) {
+         message(vl_error, "%s: %s: %s", program, in_path, strerror(errno));
+         return err;
+       }
+       hash_insert_file(&st, out_path);
+      }
+    } else {
+      /* Singleton file; no funnies */
+      if ( (err = munge_file(in_path, out_path, crib_path, &st)) != 0 ) {
+       message(vl_error, "%s: %s: %s", program, in_path, strerror(errno));
+       return err;
+      }
+    }
+  } else if ( S_ISDIR(st.st_mode) ) {
+    /* Recursion: see recursion */
+    if ( !opt.onedir &&
+        (!opt.onefs || (dirst && dirst->st_dev == st.st_dev)) ) {
+      if ( (err = munge_tree(in_path, out_path, crib_path)) != 0 )
+       return err;
+    } else if ( opt.do_mkdir ) {
+      /* Create stub directories */
+      if ( mkdir(out_path, st.st_mode) ) {
+       message(vl_error, "%s: %s: %s", program, out_path, strerror(errno));
+       return EX_CANTCREAT;
+      }
+    }
+  } else if ( S_ISLNK(st.st_mode) ) {
+    int chars;
+#ifdef PATH_MAX
+#define BUFFER_SLACK PATH_MAX
+#else
+#define BUFFER_SLACK BUFSIZ
+#endif
+    int buffer_len = st.st_size + BUFFER_SLACK + 1;
+    char *buffer = xmalloc(buffer_len);
+    if ( (chars = readlink(in_path, buffer, buffer_len)) < 0 ) {
+      message(vl_error, "%s: readlink failed for %s: %s\n",
+             program, in_path, strerror(errno));
+      return EX_NOINPUT;
+    }
+    buffer[chars] = '\0';
+    if ( symlink(buffer, out_path) ) {
+      message(vl_error, "%s: symlink %s -> %s failed: %s\n",
+             program, out_path, buffer, strerror(errno));
+      return EX_CANTCREAT;
+    }
+    free(buffer);
+  } else {
+    if ( st.st_nlink > 1 ) {
+      /* Hard link. */
+      const char *linkname;
+      
+      if ( (linkname = hash_find_file(&st)) != NULL ) {
+       /* We've seen it before, hard link it */
+       
+       if ( link(linkname, out_path) ) {
+         message(vl_error, "%s: hard link %s -> %s failed: %s\n",
+                 program, out_path, linkname, strerror(errno));
+         return EX_CANTCREAT;
+       }
+      } else {
+       /* First encounter, create and enter into hash */
+       if ( mknod(out_path, st.st_mode, st.st_rdev) ) {
+         message(vl_error, "%s: mknod failed for %s: %s\n",
+                 program, out_path, strerror(errno));
+         return EX_CANTCREAT;
+       }
+       hash_insert_file(&st, out_path);
+      }
+    } else {
+      /* Singleton node; no funnies */
+      if ( mknod(out_path, st.st_mode, st.st_rdev) ) {
+       message(vl_error, "%s: mknod failed for %s: %s\n",
+               program, out_path, strerror(errno));
+       return EX_CANTCREAT;
+      }
+    }
+  }
+  
+  /* This is done by munge_file() for files */
+  if ( !S_ISREG(st.st_mode) ) {
+#ifdef HAVE_LCHOWN
+    if ( lchown(out_path, st.st_uid, st.st_gid) && opt.sloppy && !err ) {
+      message(vl_error, "%s: %s: %s", program, out_path, strerror(errno));
+      err = EX_CANTCREAT;
+    }
+#endif
+    if ( !S_ISLNK(st.st_mode) ) {
+#ifndef HAVE_LCHOWN
+      if ( chown(out_path, st.st_uid, st.st_gid) && !opt.sloppy && !err ) {
+       message(vl_error, "%s: %s: %s", program, out_path, strerror(errno));
+       err = EX_CANTCREAT;
+      }
+#endif
+      if ( chmod(out_path, st.st_mode) && !opt.sloppy && !err ) {
+       message(vl_error, "%s: %s: %s", program, out_path, strerror(errno));
+       err = EX_CANTCREAT;
+      }
+      if ( copytime(out_path, &st) && !opt.sloppy && !err ) {
+       message(vl_error, "%s: %s: %s", program, out_path, strerror(errno));
+       err = EX_CANTCREAT;
+      }
+    }
+  }
+
+  return err;
+}
+
diff --git a/3rd-party/zisofs_tools/workers.c b/3rd-party/zisofs_tools/workers.c
new file mode 100644 (file)
index 0000000..df2fb29
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+#ident "$Id: workers.c,v 1.3 2006/07/04 04:57:42 hpa Exp $"
+/* ----------------------------------------------------------------------- *
+ *   
+ *   Copyright 2001-2006 H. Peter Anvin - All Rights Reserved
+ *
+ *   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, Inc., 675 Mass Ave, Cambridge MA 02139,
+ *   USA; either version 2 of the License, or (at your option) any later
+ *   version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * workers.c
+ *
+ * Parallel job maintenance
+ */
+
+#include "mkzftree.h"          /* Must be included first! */
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <signal.h>
+#include <stdio.h>
+#include <sys/wait.h>
+
+/* Global option */
+extern int parallel;           /* Number of parallel jobs */
+
+/* Functions related to parallel execution */
+static volatile int work_threads = 0;
+static int is_worker = 0;
+
+/* This waits for one worker to finish */
+static void wait_for_one_worker(void)
+{
+  int status;
+
+  if ( wait(&status) > 0 ) {
+    work_threads--;
+    
+    if ( WIFSIGNALED(status) ) {
+      kill(getpid(), WTERMSIG(status));
+      exit(EX_SOFTWARE);
+    } else if ( WEXITSTATUS(status) ) {
+      exit(WEXITSTATUS(status));
+    }
+  }
+}  
+
+/* This waits for *all* workers to finish */
+void wait_for_all_workers(void)
+{
+  while ( work_threads )
+    wait_for_one_worker();
+}
+
+/* This returns 1 if the "job" at hand should be performed */
+int spawn_worker(void)
+{
+  pid_t f;
+  
+  if ( opt.parallel == 0 )
+    return 1;
+
+  fflush(NULL);
+
+  /* Wait for a work slot */
+  while ( work_threads >= opt.parallel )
+    wait_for_one_worker();
+  
+  /* Spawn worker process */
+  work_threads++;              /* Avoids race conditions */
+  f = fork();
+  if ( f == -1 ) {
+    work_threads--;
+    return 1;                  /* Do it ourselves */
+  }
+
+  if ( f == 0 ) {
+    /* Worker process */
+    is_worker = 1;
+    return 1;
+  } else {
+    /* Control process */
+    return 0;
+  }
+}
+
+/* Routine to perform at the end of the job */
+void end_worker(int err)
+{
+  if ( is_worker ) {
+    exit(err);
+  }
+}
+
diff --git a/3rd-party/zisofs_tools/zisofs-tools.spec b/3rd-party/zisofs_tools/zisofs-tools.spec
new file mode 100644 (file)
index 0000000..d6bd234
--- /dev/null
@@ -0,0 +1,50 @@
+Summary: Utilities to create compressed CD-ROM filesystems.
+Name: zisofs-tools
+Version: 1.0.7
+Release: 1
+License: GPL
+Group: Applications/System
+URL: http://www.kernel.org/pub/linux/utils/fs/zisofs/
+Source: http://www.kernel.org/pub/linux/utils/fs/zisofs/zisofs-tools-%{version}.tar.gz
+BuildRoot: %{_tmppath}/%{name}-%{version}-root
+Epoch: 1
+
+%description
+Tools that, in combination with an appropriately patched version of
+mkisofs, allow the creation of compressed CD-ROM filesystems.
+
+%prep
+%setup -q 
+
+%build
+%configure
+make
+
+%install
+rm -rf $RPM_BUILD_ROOT
+make install INSTALLROOT="$RPM_BUILD_ROOT"
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+%files
+%defattr(-,root,root)
+%doc README zisofs.magic
+%{_bindir}/mkzftree
+%{_mandir}/man1/mkzftree.1*
+
+%changelog
+* Mon Jul 20 2004 H. Peter Anvin <hpa@zytor.com> 1.0.6-1
+- Generalize and include in 1.0.6 so rpmbuild -ta works.
+
+* Sat Jun 13 2004 H. Peter Anvin <hpa@zytor.com> 1.0.5-1
+- Revision update.
+
+* Wed Nov  6 2002 H. Peter Anvin <hpa@zytor.com> 1.0.4-1
+- Revision update.
+
+* Thu Nov  8 2001 H. Peter Anvin <hpa@zytor.com> 1.0.3-1
+- Revision update.
+
+* Mon Oct 29 2001 H. Peter Anvin <hpa@zytor.com> 1.0.2-1
+- Initial version.
diff --git a/3rd-party/zisofs_tools/zisofs-tools.spec.in b/3rd-party/zisofs_tools/zisofs-tools.spec.in
new file mode 100644 (file)
index 0000000..e5d7c13
--- /dev/null
@@ -0,0 +1,50 @@
+Summary: Utilities to create compressed CD-ROM filesystems.
+Name: zisofs-tools
+Version: @@VERSION@@
+Release: 1
+License: GPL
+Group: Applications/System
+URL: http://www.kernel.org/pub/linux/utils/fs/zisofs/
+Source: http://www.kernel.org/pub/linux/utils/fs/zisofs/zisofs-tools-%{version}.tar.gz
+BuildRoot: %{_tmppath}/%{name}-%{version}-root
+Epoch: 1
+
+%description
+Tools that, in combination with an appropriately patched version of
+mkisofs, allow the creation of compressed CD-ROM filesystems.
+
+%prep
+%setup -q 
+
+%build
+%configure
+make
+
+%install
+rm -rf $RPM_BUILD_ROOT
+make install INSTALLROOT="$RPM_BUILD_ROOT"
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+%files
+%defattr(-,root,root)
+%doc README zisofs.magic
+%{_bindir}/mkzftree
+%{_mandir}/man1/mkzftree.1*
+
+%changelog
+* Mon Jul 20 2004 H. Peter Anvin <hpa@zytor.com> 1.0.6-1
+- Generalize and include in 1.0.6 so rpmbuild -ta works.
+
+* Sat Jun 13 2004 H. Peter Anvin <hpa@zytor.com> 1.0.5-1
+- Revision update.
+
+* Wed Nov  6 2002 H. Peter Anvin <hpa@zytor.com> 1.0.4-1
+- Revision update.
+
+* Thu Nov  8 2001 H. Peter Anvin <hpa@zytor.com> 1.0.3-1
+- Revision update.
+
+* Mon Oct 29 2001 H. Peter Anvin <hpa@zytor.com> 1.0.2-1
+- Initial version.
diff --git a/3rd-party/zisofs_tools/zisofs.magic b/3rd-party/zisofs_tools/zisofs.magic
new file mode 100644 (file)
index 0000000..9aeb61e
--- /dev/null
@@ -0,0 +1,8 @@
+
+#------------------------------------------------------------------------------
+# zisofs: file(1) magic for zisofs/RockRidge compressed files
+#
+# from H. Peter Anvin <hpa@zytor.com> May 4, 2001
+#
+0      string  \x37\xE4\x53\x96\xC9\xDB\xD6\x07        zisofs/Rockridge compressed file
+>8     lelong          x               - %d bytes
diff --git a/ABOUT b/ABOUT
new file mode 100644 (file)
index 0000000..dd5fa39
--- /dev/null
+++ b/ABOUT
@@ -0,0 +1,60 @@
+
+GENERAL NOTE:
+
+This package is heavily based on cdrtools (by Jörg
+Schilling, see below), however he is not affiliated
+with the debburn development project creating this package.
+
+Cdrtools (see http://cdrecord.berlios.de) 2.01.01a08 from May 2006 was
+the version used as the starting code base for cdrkit.
+
+Jörg Schilling is not responsible for problems caused by the
+use or distribution of this software. Please avoid bothering
+him with issues that are out of his control.
+
+Kudos to the original authors, especially Jörg Schilling, but for
+various reasons we decided that we can only continue to have a burning
+suite without license incompatibilities. For more details about this
+please read the file FORK.
+
+
+This package contains the following software:
+
+- cdda2wav (an digital CD audio extraction program)
+  By Heiko Eißfeldt <heiko@hexco.de>
+
+- wodim (a CD recording program). Originaly based on
+  cdrecord by Jörg Schilling <schilling@fokus.fhg.de> but
+  developed independently now.
+
+- genisoimage (an ISO-9660 filesystem image creator)
+  By Eric Youngdale <eric@andante.org>, Jörg Schilling
+  <schilling@fokus.fhg.de>, James Pearson
+  <jcpearso@ge.ucl.ac.uk> and other contributors.
+
+- mkhybrid (an ISO-9660/HFS filesystem image creator)
+  Link to genisoimage
+
+- several diagnostic programs for ISO-9660, originaly from
+  cdrtools (by Jörg Schilling), 
+
+       -       devdump dump a device or file in hex
+
+       -       isodump dump a device or file based on ISO-9660
+
+       -       isoinfo analyze or list an ISO-9660 image
+
+       -       isovfy verify an ISO-9660 image
+
+- readcd (a stripped down version of usalskeleton)
+  By Jörg Schilling schilling@fokus.fhg.de and
+  may be used to read data CD's, to write to DVD-RAM
+  and to copy Solaris boot CD's
+
+- usalcheck (a program to validate the correct behavior
+  By Jörg Schilling schilling@fokus.fhg.de and
+  of the low level libusal code and the SCSI transport
+  code of the underlying OS).
+
+- libusal (a highly portable SCSI transport library)
+  By Jörg Schilling schilling@fokus.fhg.de
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644 (file)
index 0000000..57edba6
--- /dev/null
@@ -0,0 +1,3 @@
+PROJECT (cdrkit C)
+SUBDIRS(include genisoimage wodim libedc libhfs_iso libparanoia icedax libusal librols libunls readom netscsid 3rd-party/dirsplit)
+
diff --git a/COPYING b/COPYING
new file mode 100644 (file)
index 0000000..de65d3a
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,339 @@
+                   GNU GENERAL PUBLIC LICENSE
+                      Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                           Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+\f
+                   GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+\f
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+\f
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+\f
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                           NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                    END OF TERMS AND CONDITIONS
+\f
+           How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License version 2
+    as published by the Free Software Foundation.
+
+    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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year  name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/Changelog b/Changelog
new file mode 100644 (file)
index 0000000..b1aefc1
--- /dev/null
+++ b/Changelog
@@ -0,0 +1,8360 @@
+cdrkit (1.1.11) RELEASED; urgency=low
+
+  [ Steve McIntyre ]
+  * genisoimage: Fix silly bug in MD5 output in template files. (Debian
+    bug #596681)
+  * genisoimage: Minor tweaks to the the genisoimage.1 man page.
+  * genisoimage: Update references to atterer.org (Debian bug #596860)
+  * genisoimage.1: Make the description of the md5-list format clearer.
+
+  [ Mike Paul ]
+  * genisoimage: Use memmove() instead of strcpy() when cleaning
+    up graft points.
+
+ -- Steve McIntyre <93sam@debian.org>  Fri, 23 Apr 2010 00:30:18 +0100
+
+cdrkit (1.1.10) RELEASED; urgency=low
+
+  [ Steve McIntyre ]
+  * genisoimage: add support for sha256 and sha512 checksum generation
+    when making jigdo files.
+  * genisoimage: checksumming with lots of algorithms can be very
+    time-consuming, so split it out into multiple threads if possible.
+  * genisoimage: allow user to specify which checksum algorithms to run
+    on the command line.
+  * Fix FTBFS with missing xconfig.h. Thanks to Matt Kraai for the patch.
+
+  [ Nikola Pajkovsky ]
+  * genisoimage: fix string overflow breakage when using the -root
+    option (https://bugzilla.redhat.com/show_bug.cgi?id=508449)
+
+  [ Peter Samuelson ]
+  * librols: remove or rename several functions that clash with POSIX.
+    Fix up callers.
+
+ -- Steve McIntyre <93sam@debian.org>  Thu, 14 May 2009 00:28:48 +0100
+
+cdrkit (1.1.9) RELEASED; urgency=low
+
+  [ Steve McIntyre ]
+  * wodim: In -msinfo mode, only suggest dvd+rw-mediainfo in verbose mode.
+    Thanks to Michael Karcher <debian@mkarcher.dialup.fu-berlin.de> for the
+    patch.
+  * genisoimage: undo a mistake in the directory permissions change in
+    the last release. Fixes handling of deep directory structures.
+
+ -- Steve McIntyre <93sam@debian.org>  Sun, 26 Oct 2008 15:43:54 -0700
+
+cdrkit (1.1.8) RELEASED; urgency=low
+
+  [ Steve McIntyre ]
+  * genisoimage/joliet.c: Fix a potential memory corruption bug.
+  * genisoimage/md5.c: Trivial cleanup
+  * genisoimage/genisoimage.[c1]: Add command-line support for
+    -jigdo-template-compress
+  * genisoimage/sha1.h: Fix a type issue that broke sha1 support
+    on 64-bit arches.
+  * genisoimage/checksum.[ch]: Added test code; changed internal
+    layout slightly to make for easier debug.
+  * genisoimage: Applied patch from Roman Rakus <rrakus@redhat.com> to
+    preserve directory permissions.
+  * genisoimage: Add a patch from Ivan Shmakov. "-o -" will now write
+    to stdout, as typical for command line programs. And we will try
+    not to corrupt stdout by default if it's a terminal.
+  * genisoimage/genisoimage.1: Add a mention of -chrp-boot.
+  * genisoimage/mac_label.c: Fix an over-keen s/mkisofs/genisoimage.
+
+ -- Steve McIntyre <93sam@debian.org>  Mon, 25 May 2008 21:22:26 +0100
+
+cdrkit (1.1.7.1) RELEASED; urgency=low
+
+  [ Steve McIntyre ]
+  * Re-spin the 1.1.7 release with a few silly release process errors fixed.
+
+ -- Steve McIntyre <93sam@debian.org>  Mon, 17 Mar 2008 21:25:56 +0000
+
+cdrkit (1.1.7) RELEASED; urgency=low
+
+  [ Harald Hoyer ]
+  * lots of fixes to prevent gcc warnings
+  * Fix for Joliet directory length bug in genisoimage
+       
+  [ Peter Samuelson ]
+  * wodim.1: small fixes.
+
+  [ Steve McIntyre ]
+  * genisoimage/jte.c: add support for bzip2-compressed templates
+  * genisoimage/jte.c: fix bzip2-compressed template data to be
+    compatible with jigdo.
+  * genisoimage/jte.c: fix exclude list handling.
+  * genisoimage/checksum.[ch]: Add a generic infrastructure for
+    checksums so we can use sha1/<whatever> as well as just
+    md5sum. Will make things much faster for generating sha1sums for
+    images and jigdos.
+  * genisoimage/sha1.[ch]: Add GPL-licensed SHA1 implementation.
+  * s/mkisofs/genisoimage/ in ABOUT
+
+ -- Steve McIntyre <93sam@debian.org>  Mon, 17 Mar 2008 20:07:58 +0000
+
+cdrkit (1.1.6) RELEASED; urgency=low
+
+  [ Vladimir Nadvornik ]
+  * genisoimage/eltorito.c: care about inhibit flags when preparing eltorito
+    boot catalog directory entry, avoiding possible crashes
+
+  [ Eduard Bloch]
+  * ALL: customize the base manpage subdirectory below PREFIX using the new
+    MANSUBDIR variable
+  * make sure that the buffer is flushed and drive is ready before closing
+    session
+  * icedax: find libossaudio on OpenBSD and use it
+  * icedax: fixed bug with --devices (unnoticed segfault due to wrong
+    list_devices arguments)
+  * wodim/scsi_scan.h: moved Linux-specific recorder location guesser to an
+    extra method for automatic drive opening, and added an alternative
+    guessing method, using list_devices(...) picking up the first drive having
+    appropriate device type in the inquiry info. This generic method is also
+    used on Linux when the original guesser fails.
+  * wodim/wodim.c: count all track sizes when looking for an appropriate drive
+
+ -- Eduard Bloch <blade@debian.org>  Sun, 06 May 2007 16:39:08 +0200
+
+cdrkit (1.1.5.1) RELEASED; urgency=low
+
+  * resync with cosmetical last-minute changes from Peter Samuelson
+  * Makefile: "release" target extension to make the Debian related source
+    file creation more convinient
+
+ -- Eduard Bloch <blade@debian.org>  Sat, 21 Apr 2007 11:30:35 +0200
+
+cdrkit (1.1.5) RELEASED; urgency=low
+
+  * wodim: explicite warning and more grace time if user manually specifies a size
+    less than 301 sectors, which is likely to be a mistake from copy-pasting
+    of genisoimage -print-size output and omitting the block factor
+  * wodim: Native device name management directly in libusal now, the
+    rewritten device scan method uses it directly. If the backend driver does
+    not implement native names handling, the old-style IDs are displayed.
+  * libusal: native device name management, implemented on Linux and
+    Win32(SPT) for now
+  * libusal: ATA is now mapped directly into the b/t/l namespace, with some
+    workarounds to provide backward compatibility
+  * libusal: For SCSI devices, use only scd* on kernel 2.6 and sg* on kernel
+    2.4 until proper locking scheme is established
+  * libusal: always return a known value in usal_sense_table(...), from a
+    patch from SUSE (cdrkit-dvd-fix.patch)
+  * genisoimage: customized the default APPID string in genisoimage
+  * genisoimage: restored support for iso9660 file sizes up to 4GB-1
+  * genisoimage: forced MAGIC_ERROR definition for older version, thanks 
+    to Thomas Schmidt
+  * genisoimage: avoid pointless warnings on filetype of <root directory>/..
+
+ -- Eduard Bloch <blade@debian.org>  Sat, 21 Apr 2007 10:17:35 +0200
+
+cdrkit (1.1.4) RELEASED; urgency=low
+
+  [ Eduard Bloch ]
+  * On Linux, do device scanning on /dev/sr first and fallback to /dev/sg and
+    others only then, thus having better chances to use the same exclusive
+    lock as other programs when the user provided only the b/t/l
+    device specification, since the Linux kernel is not able to coordinate the
+    locking between the userspace interfaces
+  * some refactoring, moved new Linux specific extensions to scsi-linux-sg.c,
+    more relaxed device opening checks on scanning
+  * some more warnings about b/t/l syntax deprecation
+
+ -- Eduard Bloch <blade@debian.org>  Sun, 01 Apr 2007 21:49:03 +0200
+
+cdrkit (1.1.3) RELEASED; urgency=medium
+
+  [ Eduard Bloch ]
+  * Fixed fishing for transfer size in sysfs, now ready for
+    /dev/class/scsi_generic contents
+  * Fixed /dev/sg%d pattern scan in --devices, now iterating over modern style
+    device files. Thanks to Thomas Schmidt.
+  * Dealing with the last newline char when processing
+    /proc/sys/dev/cdrom/info contents
+  * print the track size in the info message when guessing
+  * added some missing or probably missing definitions in
+    wodim/CMakeLists.txt, restoring the reading from inf files
+  * passing through the real file size to the UDF generator. Creating
+    incorrect iso9660 but having it this way is better than no LFS at all.
+  * removed md5* parts and integration from icedax, patch by
+    Vladimir Nadvornik <nadvornik@suse.cz>
+  * various small bugfixes or cosmetic fixes picked from still GPLed parts of
+    cdrtools-2.01.01a24, excluding meta changes and big tree.c and mkisofs.c
+    refactoring. Stream file name option enabled now.
+  * wodim.1: "you have 4 seconds to abort ..."
+  * defaults.c: Correct fallback to CDR_FIFOSIZE and correct error message
+    on bad input.
+  * tell the user his device is busy on Linux because it's mounted, after
+    looking at /proc/mounts
+
+  [ Peter Samuelson ]
+  * Clean up Linux-2.6 CD/DVD-R drive detection, clearer error messages.
+
+ -- Eduard Bloch <blade@debian.org>  Mon, 26 Mar 2007 17:35:10 +0200
+
+cdrkit (1.1.2) RELEASED; urgency=low
+
+  [ Stefan Huehner ]
+  * more Cstyle cleanups
+
+  [ Eduard Bloch ]
+  * stop confusion and bailing out if burnfree/burnproof options have been
+    explicitely specified
+  * be move carefull with -dummy when the DVD media may not support it
+  * extracting drive's default speed in attach_mdvd()
+  * automatic recorder device guessing code, currently Linux-only
+
+  [ Peter Samuelson ]
+  * Fix icedax cddb query, based on a patch from Heiko Schlenker
+
+ -- Eduard Bloch <blade@debian.org>  Sat, 13 Jan 2007 00:45:38 +0100
+
+cdrkit (1.1.1) RELEASED; urgency=low
+
+  * added geteltorito script from Rainer Krienke
+
+  [ Eduard Bloch ]
+  * more verbose abort message if track is specified with some maintainance
+    command (#369677)
+  * Added more DVD related fixes from SuSE's wodim-1.0pre5cvs-6.src.rpm
+  * --devices option for wodim (modeled after cdrskin's output), working on
+    Linux and Cygwin
+  * Open-By-Device-Letter mode on Cygwin
+  * -msifile=... option to store -msinfo output reliably in a dedicated file
+  * clear profile names printing (using code from libburnia, thanks to Thomas
+    Schmidt)
+  * cleanup with unused embedded CVS revision strings from Schilling and
+    more gcc -Wall correctness
+  * reenabled -format functionality (bug in program function control flow)
+  * get maximum DMA buffer size from sysfs on Linux, where possible
+  * enable BURN-Free by default where possible
+  * setting argv[0] to wodim if someone is cheating and calls it as cdrecord.
+    Avoids confusion and printing of the wrong app name in the help output.
+  * more documentation updates WRT cdda2wav->icedax renaming, more table
+    formating fixes in icedax.1
+  * genisoimage documentation updates, mkisofs name changes
+
+  [ Thomas Schmidt ]
+  * workaround for older libmagic API
+  * code for clear profile name mapping
+
+  [ Peter Samuelson ]
+  * expand where genisoimage looks for the config file - same places
+    mkisofs looks plus a few more.  (We may wish to trim this back some.)
+  * major cleanups to genisoimage.1 manpage; split out the part about
+    .genisoimagerc to a new page genisoimagerc.5.
+
+  [ Steve Langasek ]
+  * allow hppa and alpha boot code to coexist in one ISO image
+
+  [ Arkadiusz Miskiewicz ]
+  * Fake prefix line in the version output of readom to keep compatibility
+    with frontends
+
+ -- Eduard Bloch <blade@debian.org>  Sat, 30 Dec 2006 16:45:40 +0100
+
+cdrkit (1.1.0) RELEASED; urgency=medium
+
+  [ Eduard Bloch ]
+  * replacement of libdeflt, config parser rewrite; more user-friendly,
+    more flexible/tolerant now
+  * config overhaul, much more dynamic checks, including fixes for SunOS and
+    AIX environment, including proper libiconv detection, and processing of
+    LDFLAGS provided by user. Also fixed confusing double-checks for some of
+    the variables in cdda2wav.c.
+  * mass renaming of applications and libraries, see FAQ
+  * dirsplit -S fix, oversized have been possible before
+  * consistent version display
+  * cleanup of libschily, removed unused/superfluous parts (assumed having a
+    modern POSIX compliant environment). Renamed to librols
+    (RemainsOfLibSchily).
+  * reenabled selection of the DVD driver, accidentaly disabled in 1.0, when
+    beeing in non-verbose mode
+  * made dirsplit work with file symlinks
+  * incorporated some OpenSUSE patches:
+    + cdrkit-HZ.patch (with initialized value, *sic*)
+    + cdrkit-dvd-fix.patch (return code tracking)
+    + cdrkit-gcc-workaround.patch
+    + cdrkit-mkisofs-fail-on-large-file.patch (don't just skip them)
+    + cdrkit-mkisofs-grow-check.patch (tolerate grown files)
+    + cdrkit-perms.patch (not breaking on missing device files)
+
+  [ Christian Fromme ]
+  * big cleanup, phase I, getting rid from Cstyle function definitions in
+    applications
+
+  [ Lorenz Minder ]
+  * user output junk filter in icedax/toc.c
+  * flexible ascii conversion buffer
+
+ -- Eduard Bloch <blade@debian.org>  Sat, 02 Dec 2006 18:43:14 +0100
+
+cdrkit (1.0) RELEASED; urgency=low
+
+  [ Eduard Bloch ]
+  * mapping of ATAPI: -> ATA: method on linux-2.6 and some code beautification
+  * added a atexit handler to stop the FIFO process more reliably, since
+    Schilling's constructs seem to terminate the application on too many
+    places
+  * print Burnfree state/preparation messages only with high verbosity
+
+  [ Dennis Vshivkov ]
+  * sorted display of files when needed
+
+  [ Joerg Jaspert]
+  * Remove all the printing of useless messages. This is based on GPLed
+    code, so we follow the letter of the GPL as it is interpreted by 99%
+    of the world, including its authors. Especially as Joerg was never able
+    to give us any clear explanation what other license he may think
+    cdrtools had, despite us asking multiple times. So we have no other
+    choice than to take whats written down, and thats GPL.
+
+ -- Joerg Jaspert <joerg@debian.org>  Mon, 20 Nov 2006 19:25:10 +0100
+
+cdrkit (1.0pre5) RELEASED; urgency=low
+
+  [ Eduard Bloch ]
+  * added better check for capability.h and FATAL_ERROR if it's missing on Linux
+  * wodim.1 updates, ie. moved suid howto to README.suidroot, Linux bashing to
+    README.linux, more notes about non-root usage
+  * more carefull description of the role of previous developer and his own
+    project
+  * fixed libmagic detection
+  * rewrote README.mkisofs, README.win32
+  * better track numbers extraction command in cdda2ogg/cdda2mp3
+  * reenabled (forgotten) support for libedc
+  * table formating fixes in cdda2wav.1, helps small terminals
+  * AIX 5l port
+  * killing FIFO process on ungraceful termination
+  * scsi-linux-sg.c: skipping unallowed devices, cleanup/consolidation of the
+    old workaround(s) for ATA now for SCSI too
+  * renamed error function to schily_error because it started to wreak random
+    havoc after harmless header moving (conflict with incompatible GNU version)
+  * restored scsi-remote.c compilation, moved to libscg sources, used instead
+    of rdummy.c
+  * added optional omiting of DMA speed tests
+
+  [ Vladimir Nadvornik ]
+  * enabled CLONE feature in wodim's config
+
+  [ Modestas Vainius ]
+  * dropped . from the include path and fixed mkisofs source to use the local
+    headers
+
+  [ Lorenz Minder ]
+  * Fix of the joliet_strlen signature
+  * Code refactoring around *cvt* declarations to make the conditional
+    compilation more reliable, especially on BSD and AIX
+  * include/utypes.h: guard to preserve SIZE_T_MAX
+
+  [ Christian Fromme ]
+  * detailed review and correction of author related data in manpages and
+    README files
+
+  [ Peter Samuelson, Tollef Fog Heen ]
+  * typo and grammar fixes in mkisofs.8
+  * Remove several instances of %r in printf-like statements, in
+    preparation for removing the libschily format-string implementation
+
+ -- Eduard Bloch <blade@debian.org>  Wed,  6 Sep 2006 22:05:30 +0200
+
+cdrkit (1.0pre4) RELEASED; urgency=low
+
+  [ Eduard Bloch ]
+  * Added checks for libcam to make (k)FreeBSD compilation work (untested)
+  * added clarifications about changes to all source files
+  * adapted initial message to display the copyright more clearly
+  * adapted copyright and contact information in scgcheck manpage
+  * adapted contact information in btcflash manpage, also added a reference to
+    its original author which has been missing
+
+  [ Peter Samuelson ]
+  * Cleanups: unused macros/defines
+  * Unified and simplified the build-host data crawling methods
+  
+  [ Juergen Weigert ]
+  * Various documentation corrections, replaced cdrecord->wodim where it is
+    appropriate and legal on many visible locations
+
+ -- Eduard Bloch <blade@debian.org>  Mon,  4 Sep 2006 23:36:58 +0200
+
+cdrkit (1.0pre3) unstable; urgency=low
+
+  [ Eduard Bloch ]
+  * Added FAQ ("where wodim name comes from")
+  * Moved the NULL pointer check on cdr_t to a place before it is used for DVD
+    feature checks (otherwise it would crash when run on any pure CD-ROM
+    reader)
+  * Added test for WORDS_BIGENDIAN
+  * copied values from align.h to another set of sizeof-reflecting defines in
+    xconfig.h
+  * workarounds for almost all "you are not allowed to modify that {version
+    checking,quality assurance,other-important-looking-wording}" parts,
+    replacing the output of "schily" where the commend said that we are forced
+    to. One part in cdrecord.c still remains, the comment sounds too dangerous
+    to be touched.
+  * forced FIFO define, suggested by Peter
+
+  [ Peter Samuelson ]
+  * Created cmake test and code snippet for HAVE_C_BITFIELDS
+
+  [ Michael Ablassmeier ]
+  * Typo fixes in mkisofs messages and unified identical ones with a macro
+
+  [Joerg Jaspert]
+  * Released as 1.0pre3
+
+ -- Eduard Bloch <blade@debian.org>  Mon,  4 Sep 2006 09:56:38 +0200
+
+cdrkit (1.0pre2) RELEASED; urgency=low
+
+  * Took zisofs_tools out of the global build system and restored its original
+    Makefile. Its own build system works better.
+
+ -- Eduard Bloch <blade@debian.org>  Sun, 03 Sep 2006 22:14:31 +0200
+
+cdrkit (1.0pre1) RELEASED; urgency=low
+
+  [ See http://bugs.debian.org/$BUGNR for detailed explanations ]
+  * The Big Fork to an independent project called cdrkit
+    + using the last clearly stated GPLed versions of files from
+      cdrtools-2.01.01a08 (closes: #353403, 372486)
+    + we play the upstream role now, using our patches and we like them
+      (closes: #361450)
+    + renamed relevant works to avoid claims of "potential defamation" or
+      "damage of reputation" (closes: #350738)
+    + custom CMake based build system used instead of the original one, since
+      we understand it better (closes: #350739 and hopefully closes: #350254,
+      reopen if not). It seems to be portable among the platforms
+      supported by Debian, it needs a bit of work for porting to non-Linux
+      plattforms, though.
+  * removed most of the anti-linux2.6  program messages (unless being
+    in verbose mode). (closes: #377145)
+  * changed default config file location to /etc/wodim.conf
+  * added more meaningful error message on -dvd-video failure (closes: #324586)
+  * minor cdda2mp3/cdda2ogg scripts fixes suggested by Fabian Pietsch, plus
+    fixes for unreliable encoder detection (closes: #283794, #344443) plus
+    possible override of preset CDDA_DEVICE variable fixed. Made the list of
+    selected audiotracks modifiable, see manpage (closes: #344445)
+  * sync with 4:2.01+01a01-4ubuntu4:
+    + merged README.ATAPI.setup with README.ATAPI.setup.ubuntu. Kernel 2.6 part
+      now in the beginning and reflecting the reality (dev=/dev/drive syntax,
+      no SUID requirement, closes: #304230, 377736)
+    + 02_cdrecord_default_conf.dpatch: changed /dev/cdrom to /dev/cdrw which
+      is more likely to match the correct device on udev using systems
+  * 36_ATA_scanbus_ignore_locked.dpatch to ignore busy devices (eg. hda
+    harddisk) while scanning with dev=ATA 
+    (closes: #310689, #309250, #317793, 360295, 
+  * Included 37_clean_dvdsup.dpatch (closes: #312062) based on
+    cdrtools-2.01.01a04-dvd.patch.bz2 from
+    http://people.mandriva.com/~warly/files/cdrtools/ with few updates to work
+    with a08. Also implements a fallback to ATA: bus in the -scanbus operation
+    (closes: #310689, #278894). This patch is used instead of the old 07_....
+    Enabled permanently, disabled the "cheatcode processing" in debian/rules.
+    Also eliminates some useability problems that have been pushed to our
+    users (closes: #325766, #271114, #312062, #353176).
+  * Updated dirsplit to version 0.3.3, zisofs-tools to 1.0.7 (with a custom
+    CMakeFile.txt for easier integration and config.h updated manually for
+    now)
+  * minor cdda2mp3/cdda2ogg scripts fixes suggested by Fabian Pietsch, plus
+    fixes for unreliable encoder detection (closes: #283794, #344443) plus
+    possible override of preset CDDA_DEVICE variable fixed
+  * added additional script manpages from Oleksandr Moskalenko (closes: #295438)
+  * changed -speed to speed= in cdrecord.1 for consistency (closes: #344214)
+  * Anti-Root-Requirements:
+    + 39_nonroot_skips_rezero_unit.dpatch - don't run rezero_unit() as root
+    which is a) most likely not needed (even admited in the comment) and b)
+    causes the whole scsi transport system to terminate
+    + 40_stop_setuid_games.dpatch - another workaround for problems introduced
+    in a03 - looks like Linux kernel does reject an application trying to
+    change the UID between ioctls
+    (closes: #335253, 374685, 330506, 329308, 374345, 377421)
+  * Ubuntu's 40_fix_bad_spelling.dpatch integrated (typo in wodim.dfl)
+  * increased hash size in mkisofs/hash.c (closes: #327270)
+  * more decent info message about locale detection
+
+ -- Eduard Bloch <blade@debian.org>  Sun, 03 Sep 2006 22:14:31 +0200
+
+cdrkit (2.01.01a08+X.15) UNRELEASED; urgency=low
+
+  * Removed cdrtools-2.01.01a05-ossdvd.patch.bz2 again (threw bogus error
+    messages in TAO mode), used 37_clean_dvdsup.dpatch (from Warly/Mandriva)
+    instead
+
+ -- Eduard Bloch <blade@debian.org>  Wed, 23 Aug 2006 15:03:46 +0200
+
+cdrkit (2.01.01a08+X.15) UNRELEASED; urgency=low
+
+  * Applied cdrtools-2.01.01a05-ossdvd.patch.bz2 slightly adapted to work with
+    a08.
+
+ -- Eduard Bloch <blade@debian.org>  Wed, 23 Aug 2006 15:03:46 +0200
+
+cdrkit (2.01.01a08+X.14) UNRELEASED; urgency=low
+
+  * 39_nonroot_skips_rezero_unit (don't try to run rezero_unit when not beeing
+    root)
+  * 40_stop_setuid_games (dont't try to cheat the kernel with delayed seteuid)
+
+ -- Eduard Bloch <blade@debian.org>  Wed, 23 Aug 2006 14:44:53 +0200
+
+cdrkit (2.01.01a08+X.13) UNRELEASED; urgency=low
+
+  * 34_JTE (Jigdo Template Extraction, by Steve)
+  * 36_ATA_scanbus_ignore_locked (skip busy devices when scaning, by myself)
+  * 38_script_manpages: added as readmult.1 and pitchplay.1, currently no
+    list_audio_tracks script there so moved to scrips/
+
+ -- Eduard Bloch <blade@debian.org>  Wed, 23 Aug 2006 14:35:30 +0200
+
+cdrkit (2.01.01a08+X.12) UNRELEASED; urgency=low
+
+  * 31_gnu-kfreebsd.dpatch with minor adoptions (needs testing!)
+  * 33_extra_arch_boot_support (extra arches, by Steve)
+
+ -- Eduard Bloch <blade@debian.org>  Wed, 23 Aug 2006 14:29:32 +0200
+
+cdrkit (2.01.01a08+X.11) UNRELEASED; urgency=low
+
+  * 26_author_locale (ASCII transliteration of Jörg in the standard credits
+    message)
+  * 28_cdda2wav_interface (Linux friendly cdda2wav behaviour)
+  * 30_doc_typo_fixes (various documentation/message fixes)
+
+ -- Eduard Bloch <blade@debian.org>  Wed, 23 Aug 2006 14:23:03 +0200
+
+cdrkit (2.01.01a08+X.10) UNRELEASED; urgency=low
+
+  * Applied 23_o_excl (exclusive device opening)
+  * Applied 24_debug_tmpfile (more safe/secure log file location)
+  * 25_mkisofs_iconv_manpage (hints about extra charsets)
+
+ -- Eduard Bloch <blade@debian.org>  Wed, 23 Aug 2006 14:20:05 +0200
+
+cdrkit (2.01.01a08+X.09) UNRELEASED; urgency=low
+
+  * Applied 18_donotopen_hda.dpatch - don't insist on opening unrelated IDE
+    devices
+  * 20_rsh-bugfix.dpatch - make really sure that the program does seteuid
+    right or exit
+  * 22_linux_rawio_capability.dpatch: get Linux capabilities as needed
+
+ -- Eduard Bloch <blade@debian.org>  Wed, 23 Aug 2006 14:11:47 +0200
+
+cdrkit (2.01.01a08+X.08) UNRELEASED; urgency=low
+
+  * mkisofs iconv support with log message adapted, added to CMake build
+    system as appropriate
+
+ -- Eduard Bloch <blade@debian.org>  Wed, 23 Aug 2006 13:57:10 +0200
+
+cdrkit (2.01.01a08+X.07) UNRELEASED; urgency=low
+
+  * Applied patches: 07_noadvertising (strip adds for commercial
+    cdrecord-proDVD), 08_privacy (mkisofs revealing the exact command line)
+
+ -- Eduard Bloch <blade@debian.org>  Wed, 23 Aug 2006 13:54:54 +0200
+
+cdrkit (2.01.01a08+X.06) UNRELEASED; urgency=low
+
+  * Applied 06_dautipps - better hints about ATAPI usage howto and
+    -joliet-long workaround
+
+ -- Eduard Bloch <blade@debian.org>  Wed, 23 Aug 2006 13:52:50 +0200
+
+cdrkit (2.01.01a08+X.05) UNRELEASED; urgency=low
+
+  * Bits from 03_script.dpatch by Joerg Jaspert <joerg@debian.org> and Eduard
+    Bloch: Linux-friendly device location for cdda scripts and better encoder
+    selection
+
+ -- Eduard Bloch <blade@debian.org>  Wed, 23 Aug 2006 13:49:56 +0200
+
+cdrkit (2.01.01a08+X.04) UNRELEASED; urgency=low
+
+  * Added bits from 02_paths.dpatch by Joerg Jaspert <joerg@debian.org>:
+    /var/log directory location and SILO relevant paths
+
+ -- Eduard Bloch <blade@debian.org>  Wed, 23 Aug 2006 13:46:55 +0200
+
+cdrkit (2.01.01a08+X.03) UNRELEASED; urgency=low
+
+  * adapted cdrecord/cdrecord.dfl for modern Linux system, based on bits from
+    02_cdrecord_default_conf.dpatch by Zack Cerza <zcerza@coe.neu.edu>
+
+ -- Eduard Bloch <blade@debian.org>  Wed, 23 Aug 2006 13:43:15 +0200
+
+cdrkit (2.01.01a08+X.02) UNRELEASED; urgency=low
+
+  * Converted to use a CMake based filesystem. Generating relevant things with
+    its mechanisms instead of inc/*. Dropped BUILD, INSTALL files, rewrote
+    COMPILE fall to reflect the new build method.
+  * Added GNUmakefile which has rules to bootstrap the CMake build system and
+    then pass the actuall call to it. GNUmakefile is the prefered script used
+    by gmake. Users with other make implementations should run cmake manually.
+
+ -- Eduard Bloch <blade@debian.org>  Wed, 23 Aug 2006 13:35:23 +0200
+
+cdrkit (2.01.01a08+X.01) UNRELEASED; urgency=low
+
+  * moved documentation around, READMEs/ directory contains a structure, moved
+    mkisofs docs from the source directory to it
+
+ -- Eduard Bloch <blade@debian.org>  Tue, 22 Aug 2006 12:40:05 +0200
+
+
+***** Version 2.01 ********
+
+Wed Sep  8 20:26:34 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.297
+       * readcd.c 1.74
+       * cdrecord.c 1.296
+         Version -> 2.01
+
+Sat Sep  4 22:28:05 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsidefs.h 1.28
+       * scsisense.h 2.18
+       * scsicdb.h 2.19
+       * scsireg.h 1.31
+       * scgcmd.h 2.22
+         Cstyle
+
+Wed Aug 25 13:28:57 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.295
+         Warnung fuer Linux-2.6.8.1 neu
+
+Tue Aug 24 01:11:42 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-remote.c 1.16
+         Auch die euid auf pw->pw_uid setzen bevor exec(RSH gemacht wird
+
+Thu Aug 19 12:14:09 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.294
+         Version -> 2.01a38
+
+Thu Aug 19 12:08:26 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.293
+         linuxcheck() im %I% verbessert ;-)
+
+Mon Aug 16 16:42:17 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.292
+         Version -> 2.01a37
+         SuSE Kommentar erweitert.
+
+Sun Aug  8 23:04:39 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_mmc.c 1.10
+         struct features & struct profiles -> LOCAL
+
+Thu Aug  5 10:26:18 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.291
+         Kommentar vor linuxcheck() erweitert
+
+Wed Aug  4 02:30:51 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.290
+         Version -> 2.01a36
+         max_dma ist nun 4/5 der DMA Speed statt 1/2
+         Warnung wegen Linux-2.6 eingebaut
+         Warnung wegen SuSE Linux eingebaut
+
+Sat Jul 31 17:41:06 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.289
+         Version -> 2.01a35
+         Check auf dma_speed > 0, dma_speed Test nur wenn tracks > 0
+
+Mon Jul 19 11:10:00 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-wnt.c 1.45
+         SPTI nicht bei NT-4.0 als Default
+
+Sun Jul 18 01:26:08 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.288
+         Version -> 2.01a34
+         Mehr Tests auf Korektheit der Werte (sinnvoller Bereich in get_dmaspeed())
+         dma_speed nur dann auswerten wenn > 0
+
+Sun Jul 11 02:28:23 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.103
+         CDR_FORCESPEED domumentiert
+
+Sun Jul 11 01:57:27 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * skel.c 1.3
+       * readcd.c 1.73
+       * xio.c 1.11
+         -> NEED_O_BINARY
+
+Sun Jul 11 01:32:49 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * readcd.c 1.72
+       * skel.c 1.2
+         MINGW32 neu
+
+Sun Jul 11 01:30:12 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * xio.c 1.10
+         setmode() auch bei MINGW32
+
+Fri Jul  9 00:05:39 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.287
+         Version -> 2.01a33
+         get_dmaspeed() neu
+         kein nice() bei __DJGPP__
+
+Fri Jun 18 17:46:20 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-wnt.c 1.44
+         if (isdigit(vers) -> if (isdigit(vers[0]) (bug korrigiert
+
+Fri Jun 18 01:17:54 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_dvdplus.c 1.15
+       * drv_dvd.c 1.118
+         long  dvd_next_addr -> LOCAL long  dvd_next_addr
+
+Thu Jun 17 23:20:27 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsierrs.c 2.29
+       * scsitransp.c 1.91
+         Bitfeld Typen fuer printf() auf int casten wegen IRIX cc
+
+Thu Jun 17 11:24:48 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * readcd.c 1.71
+         Verbose Ausgabe fuer Fehlerkorrekturen nochmals angepasst
+
+Sun Jun 13 16:28:28 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * readcd.c 1.70
+         maxtry neu
+
+Sun Jun 13 16:00:20 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * readcd.c 1.69
+         Ausgabe der maximale Anzahl der Retries
+
+Sat Jun 12 15:14:49 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_dvdplus.c 1.14
+       * drv_dvd.c 1.117
+         RAW & TAO Schreibmodi nach check_writemodes() loeschen damit niemand cdrecord -raw fuer DVDs aufruft
+
+Sat Jun 12 13:48:12 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-linux-ata.c 1.7
+         Warntext geaendert
+
+Fri Jun 11 16:49:15 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * readcd.c 1.68
+         Version -> 2.01a32
+         -scanbus funktioniert nun auch wenn dev= nicht angegeben und /etc/default/cdrecord vorhanden
+         Auflistung der defekten Sektoren in allozierter Liste
+
+Thu Jun 10 10:58:19 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.102
+         Schreibfehler
+
+Wed Jun  2 22:54:33 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.101
+         -clone dokumentiert
+
+Tue May 25 17:33:15 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * readcd.c 1.67
+         Vsersion -> 2.01a31
+
+Tue May 25 17:32:29 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * readcd.c 1.66
+         -scanbus neu
+
+Tue May 25 01:36:00 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.161
+       * scsi_cdr.c 1.137
+       * drv_mmc.c 1.157
+         write_buffer() neu und write_buffer() in drv_mmc.c -> yamaha_write_buffer()
+
+Thu May 20 16:42:12 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-linux-sg.c 1.83
+         Kommentar gegen die Debian patches fuer /dev/hd*
+
+Thu May 20 16:24:11 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-linux-ata.c 1.6
+         Bis zu 25 /dev/hd%c Files oeffnen
+
+Thu May 20 16:14:33 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-linux-sg.c 1.82
+         Kommentare um dumme Leute von SuSE davon abzuhalten wichtige Warnungen wegzupatchen
+
+Thu May 20 15:50:38 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.100
+         Kommentar zu benoetigten Root Rechten neu
+
+Thu May 20 15:35:52 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.286
+         Bessere Kommentare gegen SuSE die cdrecord nicht als root laufen lasse wollen
+
+Wed May 19 00:54:29 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.285
+         Make sure you are root. nur ausgeben wenn euid != 0
+
+Wed May 19 00:47:48 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.284
+         Version -> 2.01a29
+         reload geht nun auch fuer Notebook Laufwerke wieder
+
+Wed May 19 00:45:26 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.160
+       * scsi_mmc.c 1.9
+         print_format_capacities() neu
+
+Wed May 19 00:27:28 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.99
+         Bessere beschreibung der Hintergruende fuer eine gute Wahl der FIFO Groesse (fs=)
+
+Mon May 17 00:38:17 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.98
+         Bessere Dokumentation fuer DVD
+
+Mon May 17 00:18:21 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsilog.c 1.17
+         Besserer Kommentar
+
+Sun May 16 23:46:51 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.156
+         bei OPC "Power calibration area almost full" nicht als Fehler auffassen
+
+Sun May 16 17:01:24 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.97
+         Bessere Dokumentation der driver= Option
+
+Sun May 16 01:37:11 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.96
+         Diverse kleinere Schreibfehler beseitigt
+
+Sun May 16 01:26:52 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.95
+         Eißfeldt -> Ei\*sfeldt
+         Âµsec -> \*msec
+
+Sat May 15 23:14:18 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * subchan.c 1.19
+         index Variable -> curindex wegen GCC Shadow Warnung
+
+Sun May  9 17:59:31 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * skel.c 1.1
+         date and time created 04/05/09 16:59:31 by joerg
+
+Fri Apr 23 00:51:24 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-wnt.c 1.43
+         Padding fuer ASPI CMD Struktur damit auch 32 Byte Sense Daten von SPTI gehen
+
+Wed Apr 21 01:48:32 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-wnt.c 1.42
+         Support fuer SPTI & Kontroller mit mehr als einem SCSI Bus
+         Bei SPTI ist SENSE_LEN max nun 32
+
+Sun Apr 18 13:26:43 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-linux-sg.c 1.81
+         MAX-SCG -> 256 wegen Linux USB Implementierung
+
+Fri Apr 16 15:29:34 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_scan.c 1.19
+         Bis zu 256 Busse scannen.
+
+Thu Apr 15 16:35:46 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.283
+         Version -> 2.01a28
+
+Mon Apr 12 16:13:47 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.94
+         Read Book -> Red Book
+
+Tue Apr  6 11:59:03 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.282
+         Bessere Fehlermeldung bei fehlendem -pad/-shorttrack
+
+Mon Mar 15 01:59:49 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.281
+         Kommentar fuer cuefile= & -raw
+
+Wed Mar 10 21:54:36 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * readcd.c 1.65
+       * cdrecord.1 1.93
+       * cdrecord.c 1.280
+         ts= Doku besser
+
+Mon Mar  8 00:43:39 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-linux-sg.c 1.80
+         Fehler if (sp->u_sense.cmd_sense != 0 -> if (sp->u_sense.cmd_sense[0] != 0 korrigiert
+         Wenn ASC/ASQ und auch alle zusaetzlichen Bits/Key in Byte 2 0 sind, dann loeschen wir CHECK CONDITION wieder
+         weil das ein Linux USB Problem ist wo z.B. wegen einem DMA Underrun REQUEST SENSE geschickt wurde
+         und das Laufwerk erwartungemaesz mit NO SENSE geantwortet hat
+
+Sun Mar  7 23:43:08 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.279
+         Version -> 2.01a27
+
+Thu Mar  4 09:24:11 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.278
+         Bugfix: Nach Umstellung des Tests auf Schreibmodus Option ging nur noch TAO
+
+Wed Mar  3 01:27:14 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_dvd.c 1.115
+       * cue.c 1.20
+       * isosize.c 1.9
+       * drv_simul.c 1.47
+       * getnum.c 1.2
+       * movesect.c 1.3
+         Cstyle
+
+Tue Mar  2 21:02:42 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * misc.c 1.4
+       * cue.c 1.19
+         Copyright -> 2004
+
+Tue Mar  2 02:53:06 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * modes.c 1.25
+       * fifo.c 1.47
+       * drv_mmc.c 1.155
+       * drv_sony.c 1.70
+       * drv_dvdplus.c 1.13
+       * drv_7501.c 1.15
+       * diskid.c 1.37
+       * defaults.c 1.11
+       * crc16.c 1.6
+       * cdr_drv.c 1.36
+       * clone.c 1.7
+       * drv_philips.c 1.68
+       * readcd.c 1.64
+       * scsi_cdr.c 1.136
+       * scsi_scan.c 1.18
+       * iso9660.h 1.5
+       * xio.h 1.2
+       * cdtext.h 1.5
+         Cstyle
+
+Tue Mar  2 01:13:42 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * wm_track.c 1.4
+         Copyright -> 2004
+
+Mon Mar  1 11:08:40 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.159
+       * mmcvendor.h 1.3
+       * scsilog.h 1.4
+       * scsimmc.h 1.10
+       * drv_jvc.c 1.80
+       * scsi_mmc.c 1.8
+       * cdtext.c 1.10
+       * scsilog.c 1.16
+       * auinfo.c 1.23
+       * cdrecord.c 1.277
+       * audiosize.c 1.19
+       * sector.c 1.12
+       * subchan.c 1.17
+       * wm_packet.c 1.24
+       * xio.c 1.8
+         Cstyle
+
+Mon Mar  1 11:02:43 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsimmc.h 1.11
+       * subchan.c 1.18
+       * wm_packet.c 1.25
+       * xio.c 1.9
+       * sector.c 1.13
+         Copyright -> 2004
+
+Sun Feb 29 21:49:03 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.276
+         Cstyle
+
+Sun Feb 29 18:19:58 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.275
+         Version -> 2.01a26
+         -tao/-sao neu
+
+Sun Feb 29 18:13:20 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.92
+         -tao Option neu, -sao Option als Alias fuer -dao
+
+Sun Feb 22 16:41:57 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.91
+         Schreibfehler
+
+Sun Feb 22 15:53:51 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * readcd.c 1.63
+       * cdrecord.h 1.158
+       * defaults.c 1.10
+         cdr_defaults() Prototy -> neues defaults.h
+
+Sun Feb 22 15:53:00 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * defaults.h 1.1
+         date and time created 04/02/22 15:53:00 by joerg
+
+Sun Feb  1 21:32:58 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * adip.h 1.1
+         date and time created 04/02/01 21:32:58 by joerg
+
+Fri Jan 23 23:10:42 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-wnt.c 1.41
+         dev=ATAPI:1,0 geht nun wieder
+
+Mon Jan 19 21:29:24 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_dvd.c 1.113
+       * cdrecord.c 1.274
+       * drv_dvdplus.c 1.12
+       * wm_packet.c 1.23
+         trackp[i].padsecs * secsize -> (Llong)trackp[i].padsecs * secsize, damit kein Integeroverflow mehr stattfindet
+
+Thu Jan 15 22:24:39 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-wnt.c 1.40
+         w2k_or_newer() neu um bei NT-4.0 wegen DMA Problemen mit SPTI per Default mit ASPI zu betreiben
+         Debug prints fuer bessere Beurteilung der Funktionsweise
+
+Thu Jan 15 02:22:38 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-mac-iokit.c 1.9
+         memset sense 0 wieder eingebaut bis endgueltig geklaert ist wie es sein sollte
+
+Thu Jan 15 01:55:36 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-hpux.c 1.31
+       * scsi-linux-pg.c 1.43
+       * scsi-vms.c 1.33
+       * scsi-os2.c 1.25
+       * scsi-wnt.c 1.39
+       * scsi-remote.c 1.15
+       * scsi-unixware.c 1.36
+       * scsi-qnx.c 1.3
+       * scsi-osf.c 1.26
+       * scsi-sgi.c 1.36
+       * scsi-bsd.c 1.42
+       * scsi-bsd-os.c 1.28
+       * scsi-beos.c 1.22
+         Umbau fuer Cstyle
+
+Thu Jan 15 01:05:25 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-openserver.c 1.31
+         Aenderungen fuer Cstyle
+
+Thu Jan 15 00:50:11 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-next.c 1.32
+       * scsi-linux-ata.c 1.5
+         Umbau wegen Cstyle
+
+Wed Jan 14 20:05:52 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_dvd.c 1.112
+         Unbenutzte Variablen beseitigt
+
+Wed Jan 14 20:04:33 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-sun.c 1.82
+         Aumbau fuer Cstyle
+
+Wed Jan 14 19:57:28 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-sun.c 1.81
+         Ueberfluessige Variable sb beseitigt
+
+Wed Jan 14 18:54:48 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-apollo.c 1.5
+       * scsi-amigaos.c 1.6
+       * scsi-aix.c 1.36
+       * scsi-linux-sg.c 1.79
+       * scsiopen.c 1.95
+       * scsitransp.c 1.90
+       * scgsettarget.c 1.2
+       * scsihelp.c 1.4
+         Umbau fuer cstyle
+
+Wed Jan 14 15:37:47 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-linux-sg.c 1.78
+         LF_ATA Flag neu
+
+Wed Jan 14 01:14:27 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-mac-iokit.c 1.8
+         ux_errno wird nun korrekt gesetzt wenn ein Kommando schiefgeht
+         Die Sense Daten werden nicht mehr gelöscht
+         Author ist nun "schily", denn das Modul kommt nun teilweise dirch scgcheck
+
+Tue Jan 13 20:43:44 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-mac-iokit.c 1.7
+         Umbau fuer Cstyle
+
+Mon Jan 12 00:36:04 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.154
+         Besserer Kommentar bei den Profilen in identify
+
+Mon Jan 12 00:33:39 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdr_drv.c 1.35
+         dp bei error() ueberpruefen um coredumps bei cdrecord -xd zu verhindern
+
+Sun Jan 11 18:42:14 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-linux-sg.c 1.77
+         Versuch das /dev/hd* Interface von Linux-2.6 besser zu unterstützen.
+
+Sun Jan 11 16:18:48 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-linux-sg.c 1.76
+         Kommentar verbessert
+
+Sun Jan 11 14:39:45 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-wnt.c 1.38
+         w2kstyle_create() umgestellt und so repariert, dasy kein unzulaessiger Speicherzugriff mehr erfolgt
+
+Sun Jan 11 14:09:19 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-wnt.c 1.37
+         loas_aspi() neu
+
+Sun Jan 11 13:28:56 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-wnt.c 1.36
+         Aenderungen damit cdrecord -scanbus dev=ASPI geht
+
+Wed Jan  7 00:38:26 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.157
+       * scsi_scan.c 1.17
+       * scsi-mac-iokit.c 1.6
+       * scsi-sun.c 1.80
+       * scsi-wnt.c 1.34
+       * scsitransp.c 1.89
+       * cdrecord.c 1.273
+         Copyright -> 2004
+
+Wed Jan  7 00:20:32 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-wnt.c 1.35
+         Anderer Version String fuer SPTI
+
+Wed Jan  7 00:03:55 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.272
+         Version -> 2.01a24
+
+Tue Jan  6 23:58:43 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cue.c 1.18
+         Wenn FILE Anweisung im CUE Sheet keinen Slash (/) enthaelt, dann wird der Filename auch im Directory des CUE Sheets gesucht
+
+Tue Jan  6 23:52:52 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.c 1.88
+         Version -> 0.8
+
+Tue Jan  6 23:33:20 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-wnt.c 1.33
+         Cstyle
+
+Tue Jan  6 23:21:14 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-wnt.c 1.32
+         SPTI Unterdrueckung von nocht CD-ROM deaktiviert
+
+Tue Jan  6 23:10:18 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-wnt.c 1.31
+         Erste Version mit SPTI Support
+
+Tue Jan  6 17:58:47 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-mac-iokit.c 1.5
+         scgo_havebus() korrigiert (war immer FALSE) damit pxupgrade funktioniert
+
+Tue Jan  6 01:01:59 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.153
+         cmd_dummy statt init_mmc in den Treiberstrukturen fuer CD-ROM Leser
+
+Sun Jan  4 15:26:25 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-sun.c 1.79
+         Erste Version einer UID Verwaltung die fuer Solaris 9 USCSI gebraucht wird
+
+Fri Jan  2 16:05:57 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-sun.c 1.78
+         Erste Version die mit Volume Management arbeitet
+
+Fri Jan  2 16:05:21 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.271
+         Version -> 2.01a23
+
+Fri Jan  2 16:05:06 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_scan.c 1.16
+         Hack fuer fd == -1 -> Kein Zugriff auf LW -> '?' statt '*'
+
+Tue Dec 30 14:20:00 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.270
+         Schreibfehler will not not Korrigiert
+
+Mon Dec 29 15:25:05 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.90
+         Bessere Beschreibung und Beispiel fuer -setdropts driveropts=
+
+Wed Dec 24 11:51:56 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.152
+         Hinweis auf RAW bei nicht funktionierendem CUE Sheet
+
+Tue Dec 23 13:48:33 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.269
+         Version -> 2.01a21
+         Hack fuer POSIX_PRIORITY_SCHEDULING Bug (wir brauchen root Rechte um die Pri zu verringern)
+
+Sun Dec 21 14:29:21 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.89
+         Neuer Absatz ueber ATAPI auf erster Seite.
+
+Thu Dec 18 17:10:58 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.c 1.87
+         Aehnlicher Text wie in cdrecord.c wenn !defined(IS_SCHILY_XCONFIG)
+
+Thu Dec 18 17:10:26 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.268
+         Neuer Text fuer modifizierte Versionen ohne Support
+
+Thu Dec 18 17:09:41 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.88
+         .sp verschoben auf Wunsch von Eric Raymond
+
+Tue Dec 16 00:42:16 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.267
+         Security Test Ausgabe nun auch ohne Root Zugriff sichtbar
+
+Mon Dec 15 16:40:59 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.266
+         Ausgabe des Resultats des Security Checks
+
+Mon Dec 15 09:19:24 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.151
+         Copyright -> 2003
+
+Mon Dec 15 09:18:14 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.150
+         Ein DVD Brenner wird nun auch erkannt wenn er nur MMC-3 und nicht MMC-2 konform ist
+         Hinweis auf ftp://ftp.berlios.de/pub/cdrecord/ProDVD/
+
+Mon Dec 15 07:32:55 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.265
+         comexit(0); nach "erstem" -force blank unit entfernt damit auch mit dem Ricoh-5125 Medien erweckt werden koennen
+
+Thu Dec 11 12:59:54 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsireg.h 1.30
+         #ifdef __SCG_COMPAT_ zum enablen von info/ident/revision -> vendor_info/prod_ident/prod_revision
+
+Thu Dec 11 12:55:42 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_scan.c 1.15
+       * scsi_cdr.c 1.135
+         info -> vendor_info, ident -> prod_ident, revision -> prod_revision
+
+Wed Dec 10 00:42:39 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-dos.c 1.11
+         Hinweis auf http://bootcd.narod.ru/
+
+Wed Dec 10 00:40:49 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.264
+         Hinweis auf ftp://ftp.berlios.de/pub/cdrecord/ProDVD/
+
+Wed Dec 10 00:19:03 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.263
+         Version -> 2.01a20
+         FIFO Abschalten wenn fifosize < 2*bufsize
+
+Tue Dec  9 20:52:14 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.87
+         ..sp -> .sp Schreibfehler
+
+Sun Nov 30 13:50:31 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-dos.c 1.10
+         schcgeck funktioniert nun, kein DMAresid und max sense_count 18
+
+Sun Nov 30 00:00:01 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * xio.c 1.7
+       * readcd.c 1.62
+         #include <io.h> auch fuer DJGPP
+
+Sat Nov 29 23:36:39 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-dos.c 1.9
+         Srb.Type.ExecSCSICmd.SenseLen = DEF_SENSE_LEN; -> Srb.Type.ExecSCSICmd.SenseLen = (SENSE_LEN+2);
+
+Sat Nov 29 23:11:56 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * readcd.c 1.61
+         Version -> 2.01a20
+
+Sat Nov 29 23:10:16 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * xio.c 1.6
+         setmode(fileno, O_BINARY) auch fuer DJGPP
+
+Sat Nov 29 23:10:00 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * readcd.c 1.60
+         #include <io.h> fuer __CYGWIN32__/__EMX__
+         setmode(fileno, O_BINARY) auch fuer DJGPP
+
+Sat Nov 29 23:03:06 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-dos.c 1.8
+         Sense_len & sense_count korrekt beachten
+         SS_ERR -> vor die invalid Device & Cannot Select Bus cases im switch in send_cmd()
+
+Sat Nov 29 22:28:57 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-dos.c 1.7
+         Schreibfehler is statt if beseitigt
+
+Sat Nov 29 19:11:41 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-os2.c 1.24
+         Return (0) statt -1 bei FATAL Error in send_cmd() wenn kein gueltiges Target gesetzt ist
+
+Sat Nov 29 19:10:48 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-dos.c 1.6
+         Neuer AspiLoaded Counter fuer mehrfaches Oeffnen
+
+Sat Nov 29 19:06:55 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-wnt.c 1.30
+         Return (0) statt -1 bei FATAL Error in send_cmd() wenn kein gueltiges Target gesetzt ist
+         SS_ERR mit cp->SRB_TargStat != 0 ist nun SCG_NO_ERROR
+         AspiLoaded ist nun integer Counter damit mehrere open()s moeglich sind
+
+Sat Nov 29 19:04:36 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-dos.c 1.5
+         Return (0) statt -1 bei FATAL Error in send_cmd() wenn kein gueltiges Target gesetzt ist
+         SS_ERR mit Srb.Type.ExecSCSICmd.TargStat != 0 ist nun SCG_NO_ERROR
+
+Sat Nov 29 18:58:35 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-dos.c 1.4
+         Cstyle
+
+Sat Nov 29 18:30:44 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-dos.c 1.3
+         Umbau auf _go32_dpmi_allocate_real_mode_callback_retf()
+
+Fri Nov 28 10:25:15 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-dos.c 1.2
+         Callback Funktion neu
+
+Fri Nov 28 02:33:18 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsihack.c 1.43
+         scsi-dos.c neu
+
+Fri Nov 14 10:55:14 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-dos.c 1.1
+         date and time created 03/11/14 10:55:14 by joerg
+
+Sun Nov  2 23:50:22 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * fifo.c 1.46
+         fifo_percent() fragt nun (sp == NULL) ab um festzustellen of der FIFO aus ist
+
+Wed Oct 29 15:33:45 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-remote.c 1.14
+         strcatl()/concat()/*execl() casten nun NULL im letzten Arg nach (char *)NULL
+
+Wed Oct  1 00:39:23 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.156
+         Kommentar ueber minimale FIFO Groesse
+
+Sun Aug 24 13:15:10 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.86
+         driveropts in /Etc/default/cdrecord dokumentiert
+
+Tue Jul 22 21:43:08 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.262
+         Version -> 2.01a17
+
+Mon Jul 21 00:06:31 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.155
+       * cdrecord.1 1.85
+       * cdrecord.c 1.261
+         Neue Option ts=
+
+Fri Jul 18 10:04:20 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * readcd.c 1.59
+         Version -> 2.01a17
+         Teilweise #ifndef EXTVERS -> #ifdef CLONE_WRITE fuer genauere Beschreibung des Kodes
+
+Fri Jul 18 10:03:04 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.134
+         Kommentar Hinweis in cdr_underrun()
+
+Fri Jul 11 11:43:25 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.84
+         Schreibfehler
+
+Sun Jul  6 00:04:14 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-os2.c 1.23
+         EIO statt EINVAL damit Scan fuer Targets > 7 klappt
+
+Sat Jun 21 21:42:56 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-sun.c 1.77
+         Workaround fuer Solaris 8 x86 Bug: DKIOCINFO liefert 256 kB DMAsize aber nur 68 kB geht bei ATAPI & DMA
+
+Sat Jun 21 19:42:26 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * readcd.c 1.58
+         Neue Option -factor
+
+Fri Jun 20 22:47:08 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * readcd.c 1.57
+         Neue Option ts= fuer Transfer size
+
+Fri Jun 20 22:32:59 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * readcd.c 1.56
+         Residual count auswerten beim Lesen
+
+Fri Jun 20 22:21:33 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * readcd.c 1.55
+         prstats_silent() Prototyp neu
+         Versuch damit klarzukommen dasz einige BS (UnixWare) nicht mit odd byte DMA bei ATAPI klarkommen (READ FULL TOC)
+         Ausgabe aller Lead out startzeiten bei -clone (READ FULL TOC)
+         Geschwindigkeitsangaben beziehen sich auf 1000 Byte == 1 kb
+         Hack to write empty disks geht mit end == 1 statt end == 0
+
+Tue Jun 17 19:23:35 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.83
+         Schreibfehler
+
+Tue Jun 17 19:18:00 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * auinfo.c 1.22
+         samples -> nsamples wegen samples() Makro und K&R C
+
+Sat May 31 21:58:05 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-amigaos.c 1.5
+         Neue Version von Thomas Langer
+
+Sat May 31 19:41:16 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-amigaos.c 1.4
+         Eingerueckt nach cstyle
+
+Sat May 31 18:34:37 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.260
+         GPL Hinweise besser formuliert, Schreibfehler in usage() beseitigt
+
+Sat May 31 18:10:38 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.82
+         Schreibfehler berichtigt & -format dokumentiert
+
+Sat May 31 18:09:46 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * auinfo.c 1.21
+         Fix fuer fehlerhafte Erkennung von *.inf Dateien die Meldung 'WARNING: Stdin is connected to a terminal.' verursacht
+
+Fri May 16 13:02:58 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-remote.c 1.13
+         js_snprintf(devname, sizeof(devname), device);  -> js_snprintf(devname, sizeof(devname), "%s", device);
+
+Wed May 14 18:59:12 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.259
+         CD-Text -text Aktivierung durch trackp[MAX_TRACK+1].flags |= TI_TEXT
+         Kein CD-text mehr wenn track[0].flags & TI_TEXT schon gesetzt (durch textfile=)
+
+Wed May 14 18:57:53 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cue.c 1.17
+         CD-Text aus CDTEXTFILE nur noch wenn trackp[MAX_TRACK+1].flags & TI_TEXT
+
+Wed May 14 18:56:55 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.81
+         Neue erweiterte CD-Text Behandlung beschrieben
+
+Wed May 14 02:24:17 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.258
+         Version -> 2.01a15, Diverse Umstellungen damit tracks == 0 Abfragen bei cuefile=xxx korrekt behandelt werden
+
+Wed May 14 02:21:07 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * xio.c 1.5
+         while(pp) -> for (; pp; pp = pp->x_next) damit continue bei x_name == NULL nicht zur Endlosschleife wird
+
+Tue May 13 23:26:57 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.80
+         speed= Behandlung besser erklaert und Schreibfehler
+
+Tue May 13 23:26:14 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cue.c 1.16
+         TI_SWAB bei FILE ... WAVE setzen
+
+Tue May 13 13:07:03 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * xio.c 1.4
+         pp->x_name == NULL voer strcmp geaendert
+
+Tue May 13 13:05:00 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * xio.c 1.3
+         Neue Knoten korrekt in Liste ein und aushaengen
+
+Mon May 12 02:17:00 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.149
+         Support fuer TM_QUADRO/TM_ALLOW_COPY neu
+         Hack fuer CUE Sheet Handling mit MODE2/CDI  trackp[i].dbtype == DB_RAW
+         Fuer Lead-In/Lead-Out werden nun die Bits fuer Datengroesse wegmaskiert
+
+Mon May 12 01:39:30 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.257
+         setleadinout() setzt nun trackp[tracks+1].tracktype aus trackp[tracks].tracktype
+
+Mon May 12 01:38:03 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cue.c 1.15
+         Erste funktionierende Version
+
+Mon May 12 00:26:35 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_dvdplus.c 1.8
+         Canot -> Cannot Schreibfehler beseitigt
+
+Mon May 12 00:25:29 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.154
+         parsecue()/fparsecue() neu
+
+Mon May 12 00:22:57 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.256
+         Version -> 2.01a14, Neue Option cuefile=, Kein Aufruf von checkdsize() wenn tracks == 0 (tsize == -150)
+
+Mon May 12 00:20:55 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.79
+         einfache erste cuefile= Doku
+
+Sun May 11 21:47:29 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.153
+         TI_QUADRO & is_quadro() neu
+
+Sun May 11 21:46:53 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * xio.c 1.2
+         Schutz gegen Coredump wenn pp->x_name == NULL
+
+Sat May 10 16:15:14 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cue.c 1.14
+         Erster Ansatz fuer parse_file()
+
+Sat May 10 15:05:46 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cue.c 1.13
+         struct state neu
+         cueopen()/neednextitem()/needword()/needitem()/checkextra()/cueabort() neu
+
+Fri May  9 10:10:42 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cue.c 1.12
+         keyw_t Arrays -> LOCAL
+
+Fri May  9 10:08:10 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cue.c 1.11
+         Parser Funktionen -> LOCAL
+
+Fri May  9 10:00:21 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cue.c 1.10
+         Erster Ansatz zum weiteren parsieren der Keywort Zeilen mit den Funktionen parse_*()
+
+Fri May  9 09:58:25 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdtext.c 1.9
+         #include cdtext.h vor cdrecord.h wegen gettextptr() und den Typ textptr_t
+
+Fri May  9 09:57:08 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * auinfo.c 1.20
+       * cdrecord.h 1.152
+         gettextptr() ist nun nicht mehr LOCAL
+
+Fri May  9 09:56:24 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdtext.h 1.4
+         #define CDTEXT_H fuer Erkennung dasz cdtext.h includiert wurde
+
+Thu May  8 20:13:07 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cue.c 1.9
+         Umgestellt fuer mehr "Ordnung"
+
+Thu May  8 19:57:21 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cue.c 1.8
+         Definitionen fuer alle Schluesselworte
+
+Thu May  8 19:44:42 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cue.c 1.7
+         getlocal() beseitigt, parsecue()/fparsecue() neu
+
+Thu May  8 19:38:55 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsiopen.c 1.94
+         js_snprintf(errs, slen, scgp->errstr) -> js_snprintf(errs, slen, "%s", scgp->errstr)
+
+Thu May  8 19:38:14 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.148
+         get_speeds_plextor() geht nicht mit alten LW, daher Ausfuerung im silent Mode
+
+Thu May  8 00:45:07 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cue.c 1.6
+         Reihenfolge der Keyworte Kommentar
+
+Wed May  7 23:46:01 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.151
+       * wm_packet.c 1.22
+       * fifo.c 1.45
+       * cdrecord.c 1.255
+         Umbau auf 'xio'
+
+Wed May  7 20:31:31 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * xio.h 1.1
+       * xio.c 1.1
+         date and time created 03/05/07 19:31:31 by joerg
+
+Tue May  6 23:57:09 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.150
+       * cdrecord.1 1.78
+       * cdrecord.c 1.254
+         -abort Option neu
+
+Tue May  6 19:12:27 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cue.c 1.5
+         Kommentar verbessert, lookup() mit table Parameter
+
+Tue May  6 00:35:47 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cue.c 1.4
+         Kommentar verbessert
+
+Tue May  6 00:23:14 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cue.c 1.3
+         Umbau auf Makefilesystem, ungetline()/getlocal() neu
+
+Sun May  4 18:41:33 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.77
+         Beschreibung der Audio Kopie aus Pipe
+
+Sun May  4 18:36:46 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.253
+         Version -> 2.01a13
+
+Sun May  4 18:35:19 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.149
+       * cdrecord.c 1.252
+       * auinfo.c 1.19
+         Neue Funktion auinfosize() fuer AudioCDs aus Pipe Brennen
+
+Sun May  4 15:46:38 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.251
+         Neue Funktion opentracks() und Umstellung des Trackparsing
+
+Sun May  4 15:18:21 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * fifo.c 1.44
+         STDIN wird nicht mehr geschossen damit Audio "On the Fly" moeglich wird
+
+Sun May  4 15:16:43 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.148
+         Neues Track Flag TI_USEINFO, tracktype/dbtype nun Uchar
+
+Sun May  4 12:52:00 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.250
+         setuid(getuid()) nachdem alle root Dinge erledigt sind (hoffentlich)
+
+Sat May  3 20:09:17 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.h 1.54
+       * scsitransp.c 1.86
+         scg_fprascii()/scg_prascii()/scg_sprascii() neu
+
+Sat May  3 19:39:32 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.249
+         gracewait setzt nun didgrace auf TRUE um doppeltes Warten zu vermeiden
+
+Fri May  2 22:49:20 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-unixware.c 1.35
+         Debug error() beseitigt
+
+Fri May  2 22:46:35 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-unixware.c 1.34
+         xpopen() neu damit suid root Binaries gehen, denn /etc/scsi/pdiconfig geht nicht wenn euid != uid
+
+Tue Apr 29 22:59:14 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.248
+         Version -> 2.01a11
+
+Tue Apr 29 20:59:54 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.247
+       * cdrecord.1 1.76
+         Neue Optionen -xa/-xamix und -multi/-mode2/-xa1/-xa2/-cdi korrigiert
+
+Tue Apr 29 20:41:16 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.147
+         Support fuer TAO -mode2
+
+Tue Apr 29 20:40:26 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.147
+         Definitionen fuer Daten Sektor Typen
+
+Tue Apr 29 00:27:20 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.146
+         Bessere Ausgabe fuer formatierte RW Medien
+
+Tue Apr 29 00:26:27 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_mmc.c 1.7
+         Ausgave des Current Profile auf separater Zeile
+
+Wed Apr 23 23:25:27 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_dvdplus.c 1.5
+         Ungebrauchte Variablen beseitigt
+
+Wed Apr 23 23:20:27 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.133
+         read_track_info() Bug gefixt (type Bits waren in cmd_cdb[2] statt cmd_cdb[1])
+
+Wed Apr 23 23:19:24 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.246
+         gracewait() umstrukturiert
+
+Wed Apr 23 23:18:13 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_mmc.c 1.6
+       * drv_mmc.c 1.145
+       * cdrecord.h 1.146
+         print_profiles() neu
+
+Tue Apr 22 22:36:02 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.245
+         Return Code von (*dp->cdr_init)(scgp, dp) auswerten
+
+Tue Apr 22 19:08:58 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.244
+         raise_fdlim versucht nun nicht mehr z.B. ein Limit von 256 auf 109 zu "erhoehen".
+
+Tue Apr 22 17:47:29 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.144
+         Fehlendes " ergaenzt
+
+Tue Apr 22 17:46:28 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.143
+         Bessere Fehlermeldung fuer get next writable address auf formatierte CD-RW
+
+Tue Apr 22 17:42:06 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.243
+         Mehr Fehlermeldungen wenn in der Hauptschleife Fehler auftreten.
+
+Tue Apr 22 01:08:46 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.242
+         Version -> 2.01a11, gracewait() mit didgrace Parameter fuer Ausgabe ohne Warten
+
+Mon Apr 21 15:49:58 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.241
+         Format Code mit #ifdef DRV_DVD auskommentiert
+
+Mon Apr 21 15:40:04 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.142
+         CL_TYPE_* #defines neu fuer scsi_close_tr_session()
+
+Mon Apr 21 15:39:13 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.240
+         -format & BOOL gracedone neu
+
+Mon Apr 21 15:23:22 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.145
+       * scsi_cdr.c 1.132
+         request_sense_b()/reserve_tr_rzone() neu
+
+Mon Apr 21 14:22:51 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.239
+         Umbau auf gracewait()
+
+Sun Apr 20 16:26:57 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_mmc.c 1.5
+         get_format_capacities() neu
+
+Sun Apr 20 16:22:26 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.141
+         read_track_info() mit erweiterten Parametern (Type) -> TI_TYPE_TRACK
+
+Sun Apr 20 16:21:22 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.131
+         read_track_info() mit erweiterten Parametern (Type), read_rzone_info() aus drv_dvd.c durch read_track_info()
+
+Sun Apr 20 16:20:40 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.144
+         F_FORMAT neu, WM_FORMAT neu, DSF_DVD_PLUS_R/DSF_DVD_PLUS_RW/DSF_NEED_FORMAT neu
+         read_track_info() mit erweiterten Parametern (Type), read_rzone_info() aus drv_dvd.c durch read_track_info()
+         get_format_capacities()/read_format_capacities() neu
+
+Sun Apr 20 15:52:45 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsimmc.h 1.9
+         struct disk_info um dbit & bg_format_stat erweitert
+
+Sun Apr 20 15:13:25 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsireg.h 1.29
+         struct scsi_format_header um immed/tryout/ipattern Bits erweitert
+         struct scsi_format_cap_header neu
+         struct scsi_format_cap_desc neu
+         struct scsi_cap_data neu
+
+Sun Apr 20 15:04:56 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsicdb.h 2.18
+         NACA Bit im Control Byte neu
+
+Fri Apr 18 16:53:04 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_dvd.c 1.106
+       * drv_mmc.c 1.140
+       * cdrecord.h 1.143
+       * scsi_cdr.c 1.130
+         read_dvd_structure() nun mit addr und layer Parameter
+
+Fri Apr 18 16:51:11 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_mmc.c 1.4
+         Unbenutze & Uninitialisierte Variablen beseitigt
+
+Thu Apr 17 23:13:07 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdr_drv.c 1.34
+         DVD+ Treiber neu
+
+Thu Apr 17 23:09:29 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.139
+         Treibertexte besser eingerueckt
+         Umleitung auf DVD+ Treiber bei DVD+ Medium
+         Aufruf der dp->cdr_identify(scgp, dp, scgp->inq) Routine bei Weiterleitung auf DVD Treiber
+
+Thu Apr 17 09:45:56 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_sony.c 1.69
+       * drv_philips.c 1.67
+       * cdr_drv.c 1.33
+       * cdrecord.h 1.142
+       * drv_simul.c 1.46
+       * drv_dvd.c 1.105
+       * drv_jvc.c 1.79
+       * drv_7501.c 1.14
+       * drv_mmc.c 1.138
+         cdr_format() Funktion neu
+
+Thu Apr 17 02:32:05 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.137
+         load_media() fuer get_curprofile() im Silent Mode, wenn es ein CD Brenner ist dann wird nicht der CD-ROM Treiber returniert
+
+Thu Apr 17 01:10:51 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.136
+         SCSI-3/MMC-3 medien Tests neu um DVD+ zu erkennen
+
+Thu Apr 17 00:04:06 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_mmc.c 1.3
+         Vermeiden von pname(profile) ohne #defne DRV_DVD
+
+Wed Apr 16 23:40:46 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.135
+         mmc_getval() weiter nach hinten - nach Korrektur der Inquiry Daten fuer ATAPI
+
+Wed Apr 16 22:49:41 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.134
+         Treiber ID Text (Kommentar) verbessert
+
+Wed Apr 16 22:42:59 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_sony.c 1.68
+         Cue sheet Option auf 3 setzen
+
+Wed Apr 16 22:40:00 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.75
+         Hinweis auf mkisofs -print-size bei SAO/RAW
+
+Wed Apr 16 22:28:03 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdr_drv.c 1.32
+         SCSI-3/mmc-3 Support fuer DVD + DDCD Erkennung mit get_proflist()
+
+Wed Apr 16 22:25:56 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsimmc.h 1.8
+         struct rzone_info um lra_v erweitert
+         struct mmc_performance_header / struct mmc_performance / struct mmc_exceptions / struct mmc_write_speed / struct mmc_streaming neu
+
+Wed Apr 16 22:01:14 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.141
+         get_proflist()/get_wproflist() aus scsi_mmc.c neu
+
+Wed Apr 16 22:00:33 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_mmc.c 1.2
+         get_conflen()/get_profiles()/get_proflist()/get_wproflist() neu
+
+Wed Apr 16 00:49:27 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.133
+         get_speeds_plextor() komplett in die Statistik Funktion verlagert
+
+Wed Apr 16 00:28:09 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_mmc.c 1.1
+         date and time created 03/04/15 23:28:09 by joerg
+
+Wed Apr 16 00:28:00 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.140
+         scsi_mmc.c Definitionen neu
+
+Wed Apr 16 00:12:54 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.132
+         Trebertabellen aufgeraeumt
+
+Tue Apr 15 18:57:54 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.139
+         track_base(tp) Makro repariert (tp)->track statt (tp)->trackno
+
+Tue Apr 15 10:01:43 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_dvd.c 1.104
+         TAO Fake beseitigt
+
+Sun Apr 13 21:54:15 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_sony.c 1.67
+         #include timedefs.h fehlte
+
+Sun Apr 13 18:54:27 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_sony.c 1.66
+         Erste SAO Implementierung (ohne MCN/ISRC/multi-session)
+
+Sun Apr 13 17:15:15 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_dvd.c 1.103
+       * drv_simul.c 1.45
+       * drv_jvc.c 1.78
+       * drv_mmc.c 1.131
+       * drv_7501.c 1.13
+       * cdrecord.c 1.238
+       * cdrecord.h 1.138
+       * drv_philips.c 1.66
+         cdr_abort_session() neu
+
+Sun Apr 13 17:10:44 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.130
+         "Selected write speed:" -> "Last selected write speed:"
+
+Sun Apr 13 13:59:26 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.129
+         Intelligenteres scsi_load() kennt nun CDR_CADDYLOAD
+
+Sun Apr 13 13:54:27 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_philips.c 1.65
+         Yamaha CDR-100 nun mit scsi_load()
+
+Sun Apr 13 13:36:00 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.237
+         Version -> 2.01a10, Neue Funktion print_drflags()
+
+Sun Apr 13 13:35:26 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.137
+         Kommentar verbessert
+
+Sun Apr 13 12:28:01 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.236
+       * scsi_cdr.c 1.128
+         scsi_load()/scsi_unload() nun mit korrektem Return Wert (int statt BOOL) und Auswertung des Return Wertes in load_media()/unload_media()
+
+Fri Apr 11 15:31:30 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.129
+       * drv_7501.c 1.12
+         (*dp->cdr_gen_cue)() Aufruf nun ueber Pointer
+
+Fri Apr 11 15:27:44 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_dvd.c 1.102
+       * drv_simul.c 1.44
+       * drv_mmc.c 1.128
+       * cdr_drv.c 1.31
+       * cdrecord.h 1.136
+       * drv_7501.c 1.11
+         (*dp->cdr_send_cue)() nun mit cdr_t * Parameter
+
+Fri Apr 11 15:18:57 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_7501.c 1.10
+       * drv_simul.c 1.43
+       * drv_philips.c 1.64
+       * drv_dvd.c 1.101
+       * drv_mmc.c 1.127
+       * drv_sony.c 1.65
+       * drv_jvc.c 1.77
+       * cdrecord.h 1.135
+       * cdrecord.c 1.235
+         Neue Funktion (*cdr_gen_cue)()
+
+Fri Apr 11 01:25:58 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.126
+         get_speeds_plextor() nun mit 3 int * Parametern, Ausgabe der Maximalen Brenngeschwindigkeit in stats_mmc()
+
+Fri Apr 11 00:53:30 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.234
+       * cdrecord.h 1.134
+         is_sao() & TI_SAO neu, checktsize() ueberprueft nun ob ein Track mit unbekannter Laenge in SAO/RAW mode vorhanden ist und bricht ab
+
+Thu Apr 10 21:18:42 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_philips.c 1.63
+       * drv_simul.c 1.42
+       * drv_7501.c 1.9
+       * cdr_drv.c 1.30
+       * cdrecord.h 1.133
+       * drv_jvc.c 1.76
+       * drv_dvd.c 1.100
+       * drv_sony.c 1.64
+       * scsi_cdr.c 1.127
+       * drv_mmc.c 1.125
+       * cdrecord.c 1.233
+         cdr_check_recovery()/cdr_recover()/cdr_close_session() nun mit cdr_t * Parameter
+
+Thu Apr 10 19:19:22 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.132
+         Kommentar eingerueckt
+
+Thu Apr 10 19:15:16 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.232
+       * cdrecord.h 1.131
+       * drv_sony.c 1.63
+       * drv_simul.c 1.41
+       * drv_philips.c 1.62
+       * drv_mmc.c 1.124
+       * drv_7501.c 1.8
+       * drv_jvc.c 1.75
+       * drv_dvd.c 1.99
+         cdr_init() neu, cdr_speed_select() nun ohne "dummy" Parameter
+
+Thu Apr 10 15:32:14 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.123
+         get_speeds_plextor() neu
+
+Sun Apr  6 15:49:07 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.74
+         Neue driveropts= speedread/singlesession/hidecdr
+
+Sun Apr  6 15:48:07 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.231
+         (*dp->cdr_set_speed_dummy)() Aufruf bei -setdropts zwischen cdr_opt1() und cdr_opt2()
+
+Sun Apr  6 15:45:45 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.122
+         Support fuer Plextor PowerRec, SpeedReeed, SongleSession, HideCDR
+
+Sun Apr  6 02:19:35 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.230
+       * cdrecord.h 1.130
+         #defines und Auswertung fuer CDR_SINGLESESS/CDR_HIDE_CDR/CDR_SPEEDREAD neu
+
+Sat Apr  5 22:35:50 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.129
+       * cdrecord.c 1.229
+       * cdrecord.1 1.73
+         Neue Option -setdropts
+
+Sat Apr  5 20:51:06 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.121
+         mmc_load/mmc_unload() auskommentiert
+
+Sat Apr  5 20:46:51 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.120
+         opt2_mmc() neu und Kode aus open_session_mmc() dorthin bewegt
+
+Sat Apr  5 20:43:36 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.126
+       * cdrecord.c 1.228
+         Bessere Buffer underrun Erkennung und Beschreibung
+
+Sat Apr  5 15:49:22 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_sony.c 1.62
+       * drv_mmc.c 1.119
+       * drv_simul.c 1.40
+       * drv_7501.c 1.7
+       * cdrecord.c 1.227
+       * drv_philips.c 1.61
+       * drv_jvc.c 1.74
+       * cdrecord.h 1.128
+       * drv_dvd.c 1.97
+         (*dp->cdr_opt2)(scgp, dp) neu
+
+Sat Apr  5 15:37:12 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.226
+         Buffer Underrun Vorhersage verbessert (kein loeschen am Trackanfang & zusaetzlicher Test auf leres RAM)
+
+Sat Apr  5 01:42:33 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.118
+         Read Burn Proof Counter fuer Plextor
+
+Fri Apr  4 23:48:28 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-unixware.c 1.33
+         Reset Support neu
+
+Fri Apr  4 00:44:59 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.225
+         -packet impliziert nun nicht mehr TAO
+
+Fri Apr  4 00:35:13 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_7501.c 1.6
+         cw7501__do_cue() nun korrekt LOCAL
+
+Fri Apr  4 00:30:05 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * auinfo.c 1.18
+       * subchan.c 1.16
+         trackp->tracktype & TOC_MASK wegen TOCF_DUMMY/TOCF_MULTI
+
+Fri Apr  4 00:29:09 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_sony.c 1.61
+       * drv_simul.c 1.39
+       * drv_7501.c 1.5
+       * drv_philips.c 1.60
+       * cdrecord.h 1.127
+       * cdrecord.c 1.224
+       * drv_mmc.c 1.117
+       * drv_jvc.c 1.73
+       * drv_dvd.c 1.96
+         cdr_open_session()/cdr_fixate() ohne multi/dummy Parameter -> track[0].tracktype
+
+Thu Apr  3 22:49:10 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_jvc.c 1.72
+       * drv_dvd.c 1.95
+       * wm_packet.c 1.21
+       * cdrecord.c 1.223
+         Casting wegen Signed/Unsigned Arithmetik bei ANSI C
+
+Thu Apr  3 22:32:30 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_sony.c 1.60
+       * drv_7501.c 1.4
+       * drv_simul.c 1.38
+       * drv_dvd.c 1.94
+       * drv_philips.c 1.59
+       * drv_mmc.c 1.116
+       * drv_jvc.c 1.71
+       * cdrecord.c 1.222
+       * cdrecord.h 1.126
+         cdr_open_session()/cdr_fixate() Treiberinterface nun ohne toctype Parameter -> trackp[0]->tracktype
+
+Thu Apr  3 20:51:34 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * fifo.c 1.43
+         int -> Uint wegen Ansi C Vergleich
+
+Thu Apr  3 20:46:46 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * clone.c 1.6
+         first/last int -> Uint wegen Ansi C Vergleich
+
+Thu Apr  3 20:42:01 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * subchan.c 1.15
+         j int -> Uint wegen Ansi C Vergleich
+
+Thu Apr  3 18:16:00 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.221
+         Neue Option -lock
+         prtimediff() -> misc.c
+         Version -> 2.01a09
+
+Thu Apr  3 18:15:00 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.72
+         Neue Option -lock
+
+Thu Apr  3 18:14:43 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * misc.c 1.3
+         prtimediff() aus cdrecord.c neu
+
+Thu Apr  3 18:14:05 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.115
+         int/Uint Vergleiche gecastet
+         test auf tracksize < 0 vor do_cue()
+         Versuch zu erreichen dasz is_packet(trackp) nicht mehr is_tao(trackp) impliziert
+
+Thu Apr  3 18:11:45 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.125
+         F_DLCK & prtimediff() neu
+
+Thu Apr  3 18:11:22 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_7501.c 1.3
+         Support fuer SAO neu
+
+Sun Mar 30 22:16:25 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_7501.c 1.2
+         Schreibsupport fuer TAO
+
+Sun Mar 30 13:50:02 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.220
+       * drv_mmc.c 1.114
+         Eingerueckt nach cstyle
+
+Sat Mar 29 20:27:16 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-unixware.c 1.32
+         Auswertung von scbp->sc_comp_code und Setzten von sp->error
+
+Thu Mar 27 12:11:17 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * readcd.c 1.54
+         meshpoints=# Option neu
+
+Thu Mar 27 01:15:30 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.219
+         2002 -> 2003
+
+Thu Mar 27 01:03:48 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdr_drv.c 1.29
+         cw7501 neu
+
+Thu Mar 27 01:02:47 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_7501.c 1.1
+         date and time created 03/03/27 01:02:47 by joerg
+
+Thu Mar 27 00:53:40 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.218
+         Version -> 2.01a07, Unterdrueckung von "Warning: blockdesc secsize %d differs from cap secsize %d\n" wenn scgp->cap->c_bsize == 0
+
+Thu Mar 27 00:45:34 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.124
+         Eingerueckt nach cstyle
+
+Thu Mar 27 00:43:06 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.113
+         mmc_load()/mmc_unload() mit 2. Parameter cdr_t *
+
+Tue Mar 25 18:48:41 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-qnx.c 1.2
+         sccsid -> __sccsid
+
+Mon Mar 24 23:25:04 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.217
+         Version -> 2.01a06, Handler fuer SGIHUP/SIGTERM, cdr_underrun() neu
+
+Mon Mar 24 23:23:38 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.125
+       * cdrecord.h 1.123
+         cdr_underrun() neu
+
+Mon Mar 24 13:01:28 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-unixware.c 1.31
+         Beseitigung von fdesc[MAX_SCG][MAX_TGT][MAX_LUN] und Verkleinerung von sdidevs[scg][tgt][lun]
+         Nun kann wirklich scg_open() mehrmals aufgerufen werden.
+
+Sun Mar 23 21:10:45 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-unixware.c 1.30
+         valid/atapi/initiator -> flags mit SDI_* Bit #defines
+
+Sun Mar 23 17:33:07 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-unixware.c 1.29
+         Besseres Verhalten fuer scgcheck
+
+Sun Mar 23 15:14:23 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-unixware.c 1.28
+         Eingerueckt wegen cstyle(1)
+
+Sun Mar 23 14:12:01 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsihack.c 1.42
+         Support fuer QNX neu
+
+Sun Mar 23 14:11:14 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-qnx.c 1.1
+         date and time created 03/03/23 14:11:14 by joerg
+
+Thu Mar  6 16:39:42 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * fifo.c 1.42
+         faio_wait_on_buffer() mit Prototype implementierung wegen SCO cc
+
+Thu Mar  6 16:27:52 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.71
+         Beschreibung fuer -xa1 -xa2, ... berichtigt
+
+Fri Feb  7 12:34:37 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.70
+         Schreibfehler beseitigt
+
+Sun Feb  2 14:13:07 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-remote.c 1.12
+         Umgestellt, damit es auch ohne rcmd() geht
+
+Tue Jan 28 01:19:39 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.112
+         Workaround fuer LG TAO Audio Formware bug: audio_pause_len = 150
+
+Tue Jan  7 14:09:28 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.124
+         Ausgabe Save/Set Modepages auch auf stderr wie Rest der Zeile
+
+Tue Jan  7 14:08:43 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.111
+         set_mode_params() ist BOOL, daher ist Abfrage auf < 0 falsch
+
+Tue Dec 24 16:28:38 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.69
+         Version -> 2.0
+
+Tue Dec 24 14:16:34 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.216
+         Mail Adresse -> schilling@fokus.fhg.de
+         Vermeidung von "Cannot write CD's >= 100 minutes.\n" bei DVDs
+
+Mon Dec 16 22:26:39 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.68
+         Mailing Lists geupdated, Hinweis auf cddb= bei den cdda2wav Beispielen
+
+*************** Release 2.0 *******************
+
+Sat Nov 30 17:43:51 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * readcd.c 1.53
+       * cdrecord.c 1.215
+         Version -> 2.0
+
+Sat Nov 30 16:11:27 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.214
+         DVD-Pro Check for Tracksize-known only if ntracks > 0
+
+Sat Nov 30 13:01:27 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.110
+         Allow Medium removal after load Media for DVD/CD recognition as drecord -checkdrive would otherwise lock the tray if it has been open before
+
+Sat Nov 30 12:55:17 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-osf.c 1.25
+         Debug output with SCSI Status Byte
+
+Fri Nov 22 17:55:41 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.67
+         RSH= und RSCSI= documented for ssh(1) RSCSI
+
+Fri Nov 22 17:40:35 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-remote.c 1.11
+         Support for non-root rcmd() and ssh(2)
+
+Fri Nov 22 17:35:54 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * fifo.c 1.41
+         AmigaOS Support with ix_vfork()/ix_vfork_resume() and separate var buf_idx_reader for vfork()
+
+Thu Nov 21 22:28:57 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.213
+         New Option minbuf=
+
+Thu Nov 21 22:23:10 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.66
+         minbuf= Option new
+
+Tue Nov 19 19:13:34 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsiopen.c 1.93
+         Fix for Coredump with dev=/dev/rsr1c:@,0
+
+Sun Nov 10 19:18:04 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * diskid.c 1.36
+         Orange Forum Embargo Warning only if mp->msf_min == 97 for DVDs
+
+Mon Nov  4 18:12:16 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * fifo.c 1.40
+         close(f) /dev/zero oly if /dev/zero has been opened
+
+Sun Nov  3 16:32:52 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.123
+       * cdrecord.h 1.122
+         write_xscsi()/seek_scsi()/seek_g0()/seek_g1() new
+
+Sat Nov  2 22:11:55 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.212
+         Version -> 1.11a40, _POSIX_MEMLOCK/_POSIX_PRIORITY_SCHEDULING Test POSIX 2001 conformant
+
+Sun Oct 27 15:19:29 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.211
+         New Wait Feature free the IDE Busses if Source&Destination are on the same cable (use -immed)
+
+Sun Oct 27 14:57:11 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.65
+         New Wait (usleep) Feature for -immed documented
+
+Sun Oct 27 14:42:36 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.121
+         New Flag RF_WR_WAIT to actively free the IDE Busses via usleep()
+
+Sun Oct 27 02:26:26 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.210
+       * wm_packet.c 1.20
+       * drv_jvc.c 1.70
+         Change from trackp->padsize ->trackp->padsecs
+
+Sun Oct 27 02:02:38 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.120
+         Change from trackp->padsize ->trackp->padsecs
+         New Sektor based Makros Sminutes(s)/Sseconds(s)/Shseconds(s)/Sframes(s)
+
+Sun Oct 27 01:20:58 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.64
+         Better docukmentation for padsize=
+
+Sat Oct 26 23:13:47 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.122
+         Text Generic mmc2 DVD -> Generic mmc2 DVD-R/DVD-RW
+
+Sat Oct 26 20:21:15 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * wm_packet.c 1.19
+         Support printing the fill ratio of the drive buffer and the actual write speed
+
+Fri Oct 25 15:06:33 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.109
+         ATIP printinf for speed better -> %2d (reserved val %2d)
+
+Fri Oct 25 15:05:21 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.209
+         pad_track() now shows Drive buffer fill% and speed
+         Verbose prinrting for write_track_data() and pad_track() unified
+
+Fri Oct 25 00:49:04 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.208
+         Warning for cdrecord blank=fast if drive does not like -> Try cdrecord blank=all
+         write_track_data() now computes trackp->isecsize from trackp->isecsize to trackp->secsize
+
+Fri Oct 25 00:18:19 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.108
+         BURN-Free was not used -> BURN-Free was never needed
+
+Fri Oct 25 00:06:12 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.107
+         Test for 0xFF:0xFF/0xFF with dsp->ds_maxblocks == 716730 -> dsp->ds_maxblocks == 1166730 because we now use forceposivive in msf_to_lba()
+
+Thu Oct 24 23:47:23 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.106
+         di_to_dstat() now always sets dsp->ds_first_leadin to allow  2. setting for Yamaha AudioMaster
+
+Wed Oct 23 22:46:02 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.207
+         Version -> 1.11a39, Only cdrecord dev=help calls scg_help() no automatic printing if scg_open() fails
+
+Wed Oct 23 22:40:41 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.63
+         Many changes tp prepare for 2.0
+
+Wed Oct 23 22:21:46 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-linux-ata.c 1.4
+         Workaround for Linux Kernel design bug: CDROM_SEND_PACKET stes errno to EINVAL if Sense Key is "Invalid Command" 
+
+Mon Oct 21 19:20:33 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-linux-sg.c 1.75
+         /dev/sg* read loop again with 1000 loops but only if 'f' is a RAW device
+         Typo fixed
+
+Sun Oct 20 15:28:58 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-linux-sg.c 1.74
+         sg_clearnblock() new to alow to clear O_NONBLOCK directly after open(.., ...|O_NONBLOCK) 
+
+Sat Oct 19 22:04:23 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.206
+         Version -> 1.11a38, Support for libscg Help
+
+Sat Oct 19 21:28:22 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsiopen.c 1.92
+       * scsihack.c 1.41
+         scg_help() Funktion new
+
+Sat Oct 19 21:27:21 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.c 1.85
+         Version -> 0.7
+
+Sat Oct 19 21:26:25 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-wnt.c 1.29
+       * scsi-vms.c 1.32
+       * scsi-unixware.c 1.27
+       * scsi-sun.c 1.76
+       * scsi-sgi.c 1.35
+       * scsi-remote.c 1.10
+       * scsi-osf.c 1.24
+       * scsi-os2.c 1.22
+       * scsi-openserver.c 1.30
+       * scsi-next.c 1.31
+       * scsi-mac-iokit.c 1.4
+       * scsi-linux-sg.c 1.73
+       * scsi-linux-pg.c 1.42
+       * scsi-linux-ata.c 1.3
+       * scsi-hpux.c 1.30
+       * scsi-bsd.c 1.41
+       * scsi-bsd-os.c 1.27
+       * scsi-beos.c 1.21
+       * scsi-apollo.c 1.4
+       * scsi-amigaos.c 1.3
+       * scsi-aix.c 1.35
+         scgo_help() Funktion new
+
+Sat Oct 19 19:14:05 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.h 1.53
+         Parameter tcomment new in __scg_help()
+
+Sat Oct 19 14:02:47 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.h 1.52
+         Help functions new
+
+Fri Oct 18 17:25:31 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-linux-sg.c 1.72
+         Modified Cleanup read() loop in sg_initdev() by request from Linus Torvalds
+
+Fri Oct 18 17:20:00 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-sun.c 1.75
+         open Warnung von error() auf js_fprintf((FILE *)scgp->errfile umgestellt
+
+Fri Oct 18 17:16:48 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsiopen.c 1.91
+       * scsi-linux-ata.c 1.2
+       * scsi-sun.c 1.74
+         Allow unified dev=ATAPI, dev=ATAPI:, dev=USCSI, dev=USCSI: 
+
+Sun Oct 13 21:40:59 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-linux-sg.c 1.71
+         open(name, 2) -> O_RDWR....
+         sg_initdev() with better loop to read possible rests from driver (requested by Linus Torvalds)
+
+Sun Oct 13 21:23:54 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-sun.c 1.73
+       * scsi-linux-pg.c 1.41
+         open(name, 2) -> O_RDWR....
+
+Sat Oct 12 13:53:52 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * sector.c 1.11
+         Initialize Testsector in encspeed() to make resulting speed independent from junk on the stack
+
+Thu Oct 10 23:43:33 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.205
+         Change wording from DAO -> SAO
+
+Wed Oct  9 19:36:09 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsireg.h 1.28
+         New device types for Inquiry 
+
+Wed Oct  9 19:35:44 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.c 1.84
+         scg_fprintdev() New device types for Inquiry
+
+Tue Oct  8 00:57:50 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-unixware.c 1.26
+         Handle EBUSY for multiple opens
+
+Mon Oct  7 22:19:15 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * sector.c 1.10
+       * cdrecord.h 1.119
+       * cdrecord.c 1.204
+         Verbose printing of the LEC encoding speed -> encspeed()
+
+Sat Oct  5 22:07:27 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.203
+         call cdr_buffer_cap() in Silent mode to make sure buggy drives (CW-7585) will not print constantly error messages
+
+Sat Oct  5 18:07:46 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-linux-ata.c 1.1
+         date and time created 02/10/05 17:07:46 by joerg
+
+Sat Oct  5 17:48:27 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-linux-sg.c 1.70
+         Support for CDROM_SEND_PACKET in scsi-linux-ata.c new
+         SCSI Timeout now may be distinguished from SCSI selection Timeout by implementing a workarounf for a Linux kernel bug
+
+Sat Oct  5 00:02:52 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-sun.c 1.72
+         Do not open all /dev/scg* devices if not in SCAN mode
+         ENXIO for USCSI means selection Timeout
+
+Fri Oct  4 23:59:05 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-vms.c 1.31
+         Warn for missing Scanbus, up to 26 IDE Controller from Chip.Dancy@hp.com
+
+Wed Oct  2 21:44:22 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.202
+         Version -> 1.11a36, #ifdef HAVE_LIB_EDC_ECC to allow compilation without libedc
+
+Wed Oct  2 02:22:32 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * fifo.c 1.39
+         Allow again compilation with #undef FIFO 
+
+Wed Oct  2 00:54:52 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsiopen.c 1.90
+         replace comma by semikolon 
+
+Wed Oct  2 00:48:49 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-vms.c 1.30
+         gk_chan is Unsigned but there was a comparison <= 0
+         scsi status scsi_sts now correct for ATAPI
+
+Sat Sep 28 20:36:58 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.105
+         deflt_writemodes_mmc() now with fallback to SAO if TAO is not supported
+
+Sat Sep 28 14:53:33 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.201
+         -force Wirkung auf RAW Speed nur noch bis maximal das was eine CPU kann
+         Neue environment Variable "CDR_FORCERAWSPEED"
+
+Sat Sep 28 14:46:54 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * sector.c 1.9
+         EDC_SCRAMBLE_NOSWAP #define in old libedc new
+
+Fri Sep 27 17:39:00 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.200
+         Limit gracetime to 999, Do not use \b with wait time because seconds may use more than one column
+
+Fri Sep 27 16:40:46 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_simul.c 1.37
+         DVD max speed -> 1000
+
+Fri Sep 27 14:33:00 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.199
+         Drive current speed/Drive default speed/Drive max speed printing now with lverbose > 1
+         Hint to Heiko with Encoding speed printing
+
+Fri Sep 27 14:30:18 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.104
+         Max Speed in struct from 370 -> 372,
+         mmc_opthelp()/hasdrvopt()/get_justlink_ricoh() now with EXPORT
+         Bug with dp->cdr_dstat->ds_dr_cur_wspeed fixed,
+         set dp->cdr_speeddef/dp->cdr_speedmax from drive values
+
+Fri Sep 27 14:28:27 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_dvd.c 1.89
+         Change to use new driveropts= method from drv_mmc.c
+
+Fri Sep 27 14:25:18 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_simul.c 1.36
+         Max Speed for CD from 370 -> 372
+
+Thu Sep 26 03:06:39 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.121
+         scsi_load()scsi_unload() now may be called with cdr_t * 0
+
+Wed Sep 25 18:05:41 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.103
+         scsi_blank()/scsi_close_tr_session()/scsi_flush_cache() with immed Flag
+
+Wed Sep 25 16:12:10 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.117
+       * cdrecord.c 1.198
+       * drv_simul.c 1.35
+       * drv_philips.c 1.58
+       * scsi_cdr.c 1.120
+       * drv_dvd.c 1.88
+         start/stop, load/unload, flush_cache with immed Parameter
+
+Wed Sep 25 14:22:26 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_jvc.c 1.69
+       * drv_dvd.c 1.87
+       * drv_mmc.c 1.102
+       * cdr_drv.c 1.28
+       * cdrecord.c 1.197
+       * cdrecord.h 1.116
+         blank() driver function now weith cdr_t * parameter for F_IMMED
+
+Wed Sep 25 13:52:12 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.196
+         -immed new
+
+Wed Sep 25 13:51:28 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.195
+         F_DVD -> TI_DVD (was wrong)
+
+Wed Sep 25 13:13:11 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.115
+         F_DVD -> TI_DVD (was wrong), F_IMMED new
+
+Wed Sep 25 00:38:52 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.194
+       * cdrecord.h 1.114
+       * drv_sony.c 1.59
+       * drv_simul.c 1.34
+       * drv_philips.c 1.57
+       * drv_mmc.c 1.101
+       * drv_jvc.c 1.68
+       * drv_dvd.c 1.86
+         close_track()/fixate() enhanced by cdr_t * Parameter 
+
+Tue Sep 24 21:28:33 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.100
+         mmc_set_speed() new to allow drives that don't like speed=1
+
+Tue Sep 24 18:40:42 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.193
+         Version -> 1.11a35, Do not print Zeit/speed Statistics if writing did not yet start
+
+Tue Sep 24 18:36:56 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.119
+         Modify speed printing to include CD/DVD Speed 
+
+Mon Sep 23 15:42:22 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_simul.c 1.33
+         Simulate Next Writable Address (for TAO)
+
+Mon Sep 23 15:39:22 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.192
+         Move Comment out of #ifdef DRV_DVD
+
+Mon Sep 23 15:17:56 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.191
+         Fix Pregap handling for DVD (no 150 Sektors per Track)
+
+Sun Sep 22 01:35:18 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.113
+         F_DVD new
+
+Sun Sep 22 00:11:57 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_dvd.c 1.85
+         Set DVD Flag in driverstructure because it is now used
+
+Sat Sep 21 23:59:25 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_simul.c 1.32
+         Set DVD Flags, calculate DVD speed correctly,
+         correct real time spend in usleep()
+
+Sat Sep 21 01:33:16 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.190
+         Version -> 1.11a34, Late check for tracks == 0 only if -fix was not used
+
+Fri Sep 20 01:58:54 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * auinfo.c 1.17
+         -auinfo should be superceede -scms / -copy
+
+Thu Sep 12 17:16:35 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.189
+         Statistics order new and better, 
+         Print new statistics even on abort
+
+Thu Sep 12 17:03:42 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.112
+         New Flags RF_DID_STAT/RF_DID_CDRSTAT
+
+Thu Sep 12 16:42:57 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_philips.c 1.56
+         Modified -> reload_media()
+
+Thu Sep 12 15:52:20 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.99
+         cdr_dstat->ds_dr_max_rspeed/cdr_dstat->ds_dr_cur_rspeed neu
+         cdr_dstat->ds_dr_max_speed/cdr_dstat->ds_dr_cur_speed -> cdr_dstat->ds_dr_max_wspeed/cdr_dstat->ds_dr_cur_wspeed
+         scsi_set_speed() with MMC-3 rotctl Parameter
+
+Thu Sep 12 15:47:01 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.188
+         Version -> 1.11a33, ds_dr_max_speed -> ds_dr_max_wspeed
+
+Thu Sep 12 15:43:36 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_dvd.c 1.84
+       * scsi_cdr.c 1.118
+       * cdrecord.h 1.111
+         scsi_set_speed() mit MMC-3 rotctl Parameter
+
+Thu Sep 12 14:37:26 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.98
+         dsp->ds_flags with DSF_HIGHSP_ERA / DSF_ULTRASP_ERA 
+         New Speed Tabels for HS and UHS RW media
+         atip_printspeed() new
+         Print A1 ATIP Werte also in hex
+         Modify ATIP printout for UHS CD-RW
+
+Thu Sep 12 13:34:49 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.187
+         Driveropts print MMC,MMC-2,MMC-3
+         -force now allows to write faster data in -raw Data
+         Checks for Ultra High speed CD-RW for old writers
+         Do not print average write speed if data size is unknown
+
+Thu Sep 12 13:27:10 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.117
+         Enhancements for MMC-2 & MMC-3 in -prcap (mode Page 2A)
+
+Wed Sep 11 21:23:48 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsireg.h 1.27
+         MMC-2 & MMC-3 enhancements for Mode Page 2A
+
+Wed Sep 11 20:47:35 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.110
+         CDR_MMC/CDR_MMC2/CDR_MMC3 new
+
+Wed Sep 11 15:13:20 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * subchan.c 1.14
+         end = 0 for useless GCC Warning 'end' might be uninitialized
+
+Wed Sep 11 15:01:55 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.109
+         trackp->dataoff/tracks/track/trackno -> Uchar
+         DSF_HIGHSP_ERA & DSF_ULTRASP_ERA new
+         CDR_ALLOC without top Bit for GCC Warning
+
+Wed Sep 11 14:59:46 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_dvd.c 1.83
+       * auinfo.c 1.16
+         Cast for trackp->track*  -> Uchar
+
+Wed Sep 11 14:59:07 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_sony.c 1.58
+         Constant 0xFFFFFFFF with #ifdef for K&R/ANSI
+
+Sun Sep  1 23:43:15 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.186
+         Print minimal Drive Buffer fill ratio
+
+Sun Sep  1 23:42:39 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.97
+         DiskT@2 Support new
+
+Sun Sep  1 23:33:34 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.108
+         Several new ds_* Vars for better Statistics
+
+Sun Sep  1 21:27:35 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.185
+         cdrstats() now guesses Buffer underruns and prints average write speed
+
+Sun Sep  1 17:42:59 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.96
+         cdr_stats() Function new
+         speed_select_mmc() with 2nd Parameter dp for FORCESPEED
+         driveropts=foesecpeed new
+         driveropts=tattooinfo new
+         driveropts=tattoofile=name new
+         hasdrvopt() fixed: missing break nach past recognised Option
+
+Sun Sep  1 16:50:22 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.184
+         Buffer Cap print every 1 MB
+
+Fri Aug 30 13:57:26 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.183
+         Version -> 1.11a32, CDR_DISKTATTOO new, (*dp->cdr_stats)(scgp, dp); for Burn-Free Statistics
+
+Fri Aug 30 13:42:33 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.107
+         New driverinterfacefunction cdr_stats()
+         CDR_DISKTATTOO new
+
+Fri Aug 30 13:41:21 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_sony.c 1.57
+       * drv_simul.c 1.31
+       * drv_philips.c 1.55
+       * drv_jvc.c 1.67
+       * drv_dvd.c 1.82
+         New driverinterfacefunction cdr_stats()
+
+Thu Aug 29 21:40:34 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_sony.c 1.56
+       * drv_simul.c 1.30
+       * drv_philips.c 1.54
+       * drv_jvc.c 1.66
+       * drv_dvd.c 1.81
+       * cdrecord.h 1.106
+       * cdrecord.c 1.182
+         New Parameter cdr_t *dp for cdr_set_speed_dummy() for "forcespeed"
+
+Thu Aug 29 17:12:40 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mmcvendor.h 1.2
+         link_counter is [2].
+
+Mon Aug 26 17:47:17 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.95
+         Turning... messages -> stdout
+
+Mon Aug 26 01:56:39 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.94
+         JustLink Support new
+
+Mon Aug 26 01:22:08 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mmcvendor.h 1.1
+         date and time created 02/08/26 00:22:08 by joerg
+
+Tue Aug 20 01:11:19 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.93
+         mmc_opt1() new
+         Yamaha Audio Master Support new
+         Be more careful with test_write (-dummy) in deflt_writemodes_mmc()
+         Check driveropts= already in attach_mmc() and turn into flags
+
+Tue Aug 20 00:06:22 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.181
+         Call dp->cdr_opt1() _before_ set speed/dummy and before the first Size Check
+
+Mon Aug 19 02:30:52 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.180
+         Do not clear ds_cdrflags after attach()
+
+Mon Aug 19 01:12:18 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.179
+         driveropts=help new in short usage()
+
+Mon Aug 19 00:45:49 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.105
+       * drv_dvd.c 1.80
+       * drv_simul.c 1.29
+       * drv_jvc.c 1.65
+       * drv_sony.c 1.55
+       * drv_philips.c 1.53
+         cdr_t->cdr_opt1() new
+
+Mon Aug 19 00:40:47 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.178
+         dataoff = 16 as Default in autoaudio to allow cdrecord -raw to work without -data 
+
+Mon Aug 19 00:34:46 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.177
+         Call (*dp->cdr_opt1)(scgp, dp) for Yamaha Audio Master, then 2. Check for size
+
+Sat Aug 17 01:13:39 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.92
+         Yamaha Audio Master recognition, Varirec in driveropts=help, Varirec recognition
+
+Sat Aug 17 00:52:44 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.104
+         Calling sequence comment new
+
+Sat Aug 17 00:04:28 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * sector.c 1.8
+         Max RAW speed in metering raised from 100x -> 1000x 
+
+Fri Aug 16 02:39:01 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.176
+       * cdrecord.h 1.103
+         CDR_VARIREC / CDR_AUDIOMASTER / CDR_FORCESPEED new
+
+Wed Aug 14 23:43:34 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.175
+         Version -> 1.11a30, Speed test for RAW data sectors
+
+Wed Aug 14 20:50:55 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * defaults.c 1.9
+         Allow Space as separator in /etc/default/cdrecord 
+
+Wed Aug 14 01:04:46 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.102
+       * sector.c 1.7
+         encspeed() new
+
+Tue Aug 13 23:45:22 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * sector.c 1.6
+         HAVE_LIB_EDC_ECC/HAVE_NEW_LIB_EDC/CLONE_WRITE new
+
+Tue Jul 30 00:22:27 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.174
+         Version ->1.11a28, tracksize/secsize ->itracksize/isecsize for debug printf
+
+Mon Jul 29 22:22:12 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.101
+         track_base() Macro new, typedef struct ofile ofile_t new
+
+Mon Jul 29 21:58:12 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * subchan.c 1.13
+         Shift ISRC & MCN by one to the end if the are on an index change
+
+Sun Jul 28 23:19:55 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_simul.c 1.28
+         Flags with allen possible write modi and with CDR_TRAYLOAD to avoid 
+
+Sun Jul 28 13:54:08 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * subchan.c 1.12
+         better comment
+
+Thu Jul 25 03:25:39 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * subchan.c 1.11
+         Support for ISRC/MCN in RAW Mode new (but witout index shift)
+
+Tue Jul 23 23:47:58 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * subchan.c 1.10
+         First loop in fillsubch() removed because it is identical to second loop
+
+Tue Jul 23 23:32:31 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * subchan.c 1.9
+         fillsubch() now coeerect for audio Pregap between Tracks korrekt with relative time counting downwards
+
+Sun Jul 21 18:21:24 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.91
+         set dsp->{ds_disktype!ds_trfirst!ds_trlast!ds_trfirst_ls} from dip->* 
+         Do not cast malloc() anymore
+         Check write_cdtext() Returncode
+         Prepare for just Link
+
+Sun Jul 21 18:13:25 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_dvd.c 1.79
+         set CDR_BURNFREE Flag,
+         set dsp->{ds_disktype!ds_trfirst!ds_trlast!ds_trfirst_ls} from dip->* 
+
+Sun Jul 21 18:07:21 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.173
+         Version -> 1.11a27,
+         Define Warning that needs to be printed if Source has been changed,
+         Better messages for wrong DVD-RW write speed, reload_media() at end Ende of RAW Write
+
+Sun Jul 21 17:52:54 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.116
+       * auinfo.c 1.15
+         malloc() Cast removed
+
+Sun Jul 21 17:51:44 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_sony.c 1.54
+         dsp->ds_diskid now is UInt32_t
+
+Sun Jul 21 17:44:11 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.100
+         struct disk_status with Typen from utypes.h
+
+Mon Jul  8 00:31:04 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * wm_session.c 1.4
+       * wm_packet.c 1.18
+       * subchan.c 1.8
+       * fifo.c 1.38
+       * drv_mmc.c 1.90
+       * drv_jvc.c 1.64
+       * clone.c 1.5
+       * cdrecord.h 1.99
+       * cdrecord.c 1.172
+         'tracks' outside driver interface removed and replaced by trackp->tracks
+
+Sun Jul  7 22:30:24 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_jvc.c 1.63
+         Better rebuild old driver interface in next_wr_address_jvc()
+
+Sun Jul  7 22:28:35 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * wm_packet.c 1.17
+       * drv_mmc.c 1.89
+       * cdr_drv.c 1.27
+       * cdrecord.h 1.98
+       * cdrecord.c 1.171
+       * drv_sony.c 1.53
+       * drv_simul.c 1.27
+       * drv_philips.c 1.52
+       * drv_jvc.c 1.62
+       * drv_dvd.c 1.77
+         trackno/tracks Parameter in driverinterface removed for new Struct Member
+
+Sat Jul  6 21:19:22 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.170
+       * cdrecord.h 1.97
+         track_t now with tracks and track for simplified driverinterface
+
+Sat Jul  6 18:20:27 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.96
+       * cdrecord.c 1.169
+       * drv_sony.c 1.52
+       * drv_simul.c 1.26
+       * drv_philips.c 1.51
+       * drv_mmc.c 1.88
+       * drv_jvc.c 1.61
+       * drv_dvd.c 1.76
+         cdr_speeddef/cdr_speedmax new and do not default to speed= 1 but to cdr_speeddef
+
+Fri Jul  5 23:11:39 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.168
+         Version -> 1.11a26
+         wm2name[] with better systematics
+         Bugfix for High Speed CD-RW that could not be written anymore at 10x speed
+         New test for too slow writing of a CD-RW
+         Modename for blank only now is "BLANK"
+         Text: write XXX mode -> real XXX mode
+         SAO & RAW start (leadin) Code -> drv_mmc.c
+         Correctly print the current DVD writespeed
+
+Fri Jul  5 21:36:25 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.95
+         New driverfunction write_leadin, WM_ \b* Macros with better system,
+         new Macro wm_base(),
+         RF_LEADIN new
+
+Fri Jul  5 21:31:48 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.87
+         New driverfunction write_leadin_mmc() with Code from cdrecord main function
+
+Fri Jul  5 21:26:04 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_sony.c 1.51
+       * drv_simul.c 1.25
+       * drv_philips.c 1.50
+       * drv_jvc.c 1.60
+       * drv_dvd.c 1.75
+         New driverfunction write_leadin as dummy
+
+Thu Jul  4 13:01:36 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.167
+         Version -> 1.11a25
+         Print Writemodes (new)
+         set_wrmode() new
+         restructuring: cdr_t->cdr_dstat is now used
+         dp->cdr_dstat->ds_cdrflags |= RF_PRATIP new
+         Check for ultra low speed media in High Speed writer
+         Check for high speed media in Low Speed writer
+         Avoid that cdrecord -- speed=8 causes speed=8 to be ignored as file type arg
+
+Thu Jul  4 12:55:52 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.94
+         restructuring: cdr_t->cdr_dstat is now used
+         New Write Mode WM_* definitions
+
+Thu Jul  4 12:53:14 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_dvd.c 1.74
+       * drv_mmc.c 1.86
+       * drv_philips.c 1.49
+       * drv_sony.c 1.50
+         Check for dp->cdr_dstat->ds_cdrflags & RF_PRATIP
+         Fill dsp->ds_flags |= DSF_ERA and dsp->ds_at_*_speed
+
+Tue Jul  2 19:55:47 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_sony.c 1.49
+       * drv_simul.c 1.24
+       * drv_philips.c 1.48
+       * drv_jvc.c 1.59
+       * cdr_drv.c 1.26
+       * drv_mmc.c 1.85
+       * drv_dvd.c 1.73
+         dstat_t * now is a Member of cdr_t -> better handling of special funcs
+
+Tue Jul  2 15:18:31 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.84
+         get_atip() now is always usable (not only if PRINT_ATIP has been defined)
+
+Sun Jun 16 15:58:37 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.115
+         Comment -> mmc-2
+
+Fri May 31 22:09:39 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.114
+         wait_unit_ready() fast Abort even if k == SC_MEDIUM_ERROR
+
+Wed May 29 01:43:13 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-wnt.c 1.28
+         Better printf() format strings for DWORD
+
+Wed May 29 01:02:28 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdtext.h 1.3
+         List of language codes enhanced
+
+Wed May 29 00:55:22 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * fifo.c 1.37
+         palign() Macro with (UIntptr_t) Cast
+
+Wed May 29 00:54:26 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.166
+         Version -> 1.11a24, gracetime= in usage(), printf() Format correkt for bmtime()
+
+Wed May 29 00:51:56 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.62
+         gracetime= new
+
+Wed May 29 00:50:03 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdtext.c 1.8
+         Avoid Coredump if a single .inf File is missing and trackp[i].text is NULL -> ->textcodes does not work
+
+Mon May 20 17:08:41 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-aix.c 1.34
+         palign() -> with UIntptr_t cast
+
+Mon May 20 16:38:23 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-remote.c 1.9
+         avoid Integeroverflow with %.*s and 64 bit
+
+Mon May 20 14:28:12 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-sun.c 1.71
+         Cast (int)req.uscsi_buflen/(int)req.uscsi_resid forr 64 bit
+
+Mon May 13 02:02:09 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.165
+         Version -> 1.11a23,
+         Flush Cache with exit() in Silent Mode to avoid problem with cdrecord -toc and CD-ROMs
+
+Mon May 13 02:00:49 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * fifo.c 1.36
+       * drv_mmc.c 1.83
+       * drv_jvc.c 1.58
+       * drv_dvd.c 1.71
+       * cdrecord.h 1.93
+         New Typ tsize_t instead of off_t for Track size Vars > sizeof(long) on non-largefile OS
+
+Sat May  4 21:55:38 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.164
+         Avoid that abort via ^C kills a running SCSI Command
+
+Sat May  4 21:42:56 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.c 1.83
+       * scsitransp.h 1.51
+         Callback Function at Ende of SCSI Command
+
+Sat May  4 18:10:05 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.163
+         Version -> 1.11a22
+         gracetime= Option new
+         Now use geterrno()/seterrno()
+         reload_media() reads from stdder if input is from stdin
+
+Sat May  4 16:00:13 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.162
+         printf() Formats enhanced to get non jumping output with DVDs
+
+Sat May  4 15:36:45 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_dvd.c 1.70
+         always set CDR_TAO|CDR_SAO in cdr_flags to allow speudo-DAO Mode
+
+Sat May  4 15:34:41 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.92
+         MIN_GRACE_TIME new
+
+Sat Apr 20 22:29:26 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * fifo.c 1.35
+         Now use geterrno()/seterrno()
+
+Tue Apr 16 19:20:40 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsierrs.c 2.28
+         New Errorstrings from 29.5.2001
+
+Tue Apr  9 22:48:58 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * diskid.c 1.35
+         Embargo Message now better
+
+Tue Apr  9 22:41:41 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.91
+         F_STDIN Flag new
+
+Sat Mar 30 12:26:12 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_dvd.c 1.69
+         Make drecord -atip print useful things
+
+Wed Mar 27 23:36:26 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_dvd.c 1.68
+         maxblocks computing corrected (now even works with Panasonic)
+
+Tue Mar 26 19:18:31 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * subchan.c 1.7
+         create SCMS Bit
+         set COPY Bit in TOC and sub channels
+
+Tue Mar 26 19:10:32 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.161
+         Version -> 1.11a19
+
+Tue Mar 26 19:07:15 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * auinfo.c 1.14
+         Albumperformer= new
+
+Tue Mar 26 19:02:58 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdtext.c 1.7
+         textfile= not-existent caused a Coredump
+
+Sun Mar 24 23:39:28 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.160
+         SCMS and Copy permitted printing new, Version -> 1.11a18
+
+Sun Mar 24 23:38:11 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * auinfo.c 1.13
+         SCMS as new value for Copy_permitted=
+
+Sun Mar 10 00:24:19 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.159
+         Print real write speed
+
+Sat Mar  9 23:21:05 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.82
+         remiove typo in hasdrvopt()
+
+Sat Mar  9 23:03:00 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.81
+         first VariRec Support
+
+Sat Mar  9 21:15:48 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_dvd.c 1.65
+         Burn-PROOF Support new, try tp make Panasonic DVD-R working
+
+Sat Mar  9 20:20:16 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.158
+         IS_SCHILY_XCONFIG new, Short Usage with susage() new
+
+Fri Mar  8 16:48:58 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.157
+         Version print Lizens better, -cdi sets toctype
+
+Fri Mar  8 16:46:54 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.c 1.82
+         Version -> 0.6
+
+Tue Mar  5 23:34:46 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * defaults.c 1.8
+         NULL Pointer for args is now OK to allow to be used with readcd
+
+Tue Mar  5 23:32:00 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.90
+         getnum()/getllnum() from cdrecord.c -> getnum.c
+
+Tue Mar  5 23:26:31 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.156
+         Version -> 1.11a17
+         getnum()/getllnum() -> getnum.c
+         cdr_defaults() changed to allow to be used with readcd.c
+
+Tue Mar  5 23:20:48 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * getnum.c 1.1
+         date and time created 02/03/05 23:20:48 by joerg
+
+Mon Mar  4 23:42:43 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * diskid.c 1.34
+       * drv_mmc.c 1.80
+       * drv_dvd.c 1.64
+       * scsi_cdr.c 1.113
+       * drv_simul.c 1.23
+       * fifo.c 1.34
+       * crc16.c 1.5
+       * crc16.h 1.3
+       * cdrecord.h 1.89
+         Copyright -> 2002
+
+Mon Mar  4 23:32:08 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdtext.h 1.2
+         Comment for Text Language code now better
+
+Mon Mar  4 23:21:31 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.155
+         better comment for Version printing for not working Branches
+
+Mon Mar  4 22:43:47 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.154
+         Comments for Sector size
+
+Mon Mar  4 22:42:12 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * defaults.c 1.7
+         Copyright -> 2002
+         new Function open_cdrdefaults(),
+         Comment that states that "/etc/default/cdrecord" may not be changed
+
+Fri Mar  1 22:37:21 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * diskid.c 1.33
+         Better Text for unknown ID Codes
+
+Thu Feb 28 23:04:45 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * auinfo.c 1.12
+         readtstr() now looks for rightmost ' from right to left,
+         readtag("CDINDEX_DISCID=") -> readtstr("CDINDEX_DISCID=")
+
+Sun Feb 24 15:44:34 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.153
+         Copyright -> 2002
+
+Sat Feb 23 22:00:51 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdtext.c 1.6
+         First Support for CD-Text Synthesis with new functions text_txt()/packtext()/anytext()/fillup_pack()/fillpack()
+
+Sat Feb 23 21:44:33 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdtext.h 1.1
+         date and time created 02/02/23 21:44:33 by joerg
+
+Sat Feb 23 21:21:10 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.61
+         -text/textfile= Options documented
+
+Sat Feb 23 21:17:42 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.152
+         Version -> 1.11a15, Option -text new, char * textfile not global anymore
+
+Sat Feb 23 21:10:53 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * auinfo.c 1.11
+         First CD-Text Support
+
+Sat Feb 23 17:24:48 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.88
+         void *text new in struct track, packtext() Prototype new
+
+Sat Feb 23 16:01:50 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.79
+         CD-Text Cue sheet for Lead-in does not depend anymore from char *textfile but from trackp[0].flags & TI_TEXT
+
+Wed Feb 20 19:39:39 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.112
+       * drv_dvd.c 1.63
+       * drv_simul.c 1.22
+       * fifo.c 1.33
+         #ifndef DEBUG around #define DEBUG
+
+Tue Feb 19 22:10:23 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdtext.c 1.5
+         setuptextdata() new
+
+Fri Feb 15 00:46:56 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * crc16.h 1.2
+       * crc16.c 1.4
+         flip_crc_error_cor() with bsize Parameter and EXPORT instead of LOCAL
+         cdtext_crc_ok() removed -> cdtext.c
+
+Fri Feb 15 00:42:47 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdtext.c 1.4
+         Flip error correction for Text CRC correction
+         Automatic Text Size Header recognition
+
+Sun Feb 10 12:43:07 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-openserver.c 1.29
+         MAX-DMA -> 63kB, -scanbus contolled by env Vars
+
+Sat Feb  9 17:29:02 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * diskid.c 1.32
+         Warning for guessed IDs
+
+Tue Jan 29 20:46:42 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * diskid.c 1.31
+         Removed wrong (now superfluous) IDs
+
+Thu Jan 24 00:03:25 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * diskid.c 1.30
+         "Advanced Digital Media", "Moser Baer India Limited", "NAN-YA Plastics Corporation", "SHENZEN SG&GAST DIGITAL OPTICAL DISCS" new from Plextools binary
+         m_grandadvance[] was superfluous (m_grandadv[])
+         "WEALTH FAIR INVESTMENT LIMITE" typo fixed (D missing).
+
+Fri Jan 18 12:43:58 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-linux-sg.c 1.69
+         do not try to use the PG driver if open(device) fails
+
+Fri Dec  7 22:40:31 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.111
+         scsi_in_progress() with additional sense qualifier 0x04 for CyberDrive
+
+Sun Dec  2 15:42:53 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-beos.c 1.20
+         Typo removed, Support for BeOS 5
+
+Sun Dec  2 15:37:36 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-amigaos.c 1.2
+         Reworked the error handling code
+
+Sun Dec  2 13:44:43 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-amigaos.c 1.1
+         date and time created 01/12/02 13:44:43 by joerg
+
+Tue Nov 27 20:25:39 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsihack.c 1.40
+         Copyright + 2001
+
+Tue Nov 27 20:24:18 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsihack.c 1.39
+         scsi-amigaos.c new
+
+Tue Nov 27 02:10:34 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.151
+         NEED_SYS_SOCKET_H for BeOS new
+         Version -> 1.11a13
+         cdr_buffer_cap() environment for Plasmon RF41xx better
+
+Tue Nov 27 02:08:47 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_philips.c 1.47
+         Comment for buffer_cap dummy function for the Plasmon RF41xx better
+
+Tue Nov 13 16:17:05 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.87
+       * drv_dvd.c 1.62
+       * cdrecord.c 1.150
+         New Flag DSF_DVD, better overcapacity output for DVD
+
+Sun Nov 11 18:30:47 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_dvd.c 1.61
+         Comment for ACARD TECH AEC-7720 ATAPI<->SCSI adaptor better
+
+Sun Nov 11 17:53:42 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-remote.c 1.8
+         Test HAVE_RCMD new
+
+Thu Nov  1 19:15:46 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_simul.c 1.21
+         Now using timedefs.h
+
+Wed Oct 31 19:29:35 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.110
+         For ACARD TECH AEC-7720 ATAPI<->SCSI adaptor read Mode Page list only in debug mode
+
+Wed Oct 31 00:24:58 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.109
+         sense_secsize() now calles mode_sense() first with 12 Bytes and again with 0xFE Bytes for Moge Page List
+
+Wed Oct 31 00:17:27 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.78
+         check_writemodes_mmc() -> EXPORT, read_dvd_structure() now with mit 32 byte instead of 15 bytes len Parameter
+
+Wed Oct 31 00:06:47 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.86
+         Prototyp for check_writemodes_mmc()
+
+Tue Oct 30 23:12:03 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsireg.h 1.26
+         cd_mode_page_05 intel byteorder link_size was wrong
+
+Tue Oct 30 21:36:53 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.147
+         DVD Check code did code exit() for non MMC CD writers
+         version -> 1.11a10
+
+Mon Oct 29 19:12:29 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-mac-iokit.c 1.3
+         Include Liste reworked
+
+Mon Oct 29 18:57:46 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cd_misc.c 1.10
+       * misc.c 1.2
+       * modes.c 1.24
+       * diskid.c 1.29
+       * drv_simul.c 1.20
+       * fifo.c 1.32
+       * wm_track.c 1.3
+       * wm_session.c 1.3
+       * wm_packet.c 1.16
+         avoid sys/types.h 
+
+Sat Oct 27 02:56:16 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-remote.c 1.7
+         Test for HAVE_NETDB_H for rcmd()
+
+Sat Oct 27 02:55:30 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsierrs.c 2.27
+         #include <unixstd.h> for size_t for snprintf()
+
+Sat Oct 27 02:53:49 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * fifo.c 1.31
+         Test for HAVE_FORK new
+
+Sat Oct 27 02:53:18 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdtext.c 1.3
+         casts because sizeof() on MacOS X is long 
+
+Thu Oct 25 16:19:08 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-mac-iokit.c 1.2
+         Unitnitialised Var dict, plugInResult format string ... GCC error removed
+
+Thu Oct 25 02:03:56 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsihack.c 1.38
+         Support for MaxOS X (Darwin-1.4)
+
+Thu Oct 25 02:03:11 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-mac-iokit.c 1.1
+         date and time created 01/10/25 01:03:11 by joerg
+
+Wed Oct 17 19:40:22 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.146
+         initialize scgp with NUL
+         brackets around if (p = senv_field(6))
+
+Tue Oct 16 17:03:53 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_dvd.c 1.57
+       * cdrecord.c 1.144
+       * cdrecord.h 1.85
+       * drv_simul.c 1.19
+       * drv_sony.c 1.48
+       * drv_philips.c 1.46
+       * drv_mmc.c 1.77
+       * drv_jvc.c 1.57
+         New Structuremember cdr_cmdflags in cdr_t
+
+Tue Oct 16 15:57:05 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.143
+         Better error messages for DVD Demo Mode > 1 GB
+
+Wed Oct 10 23:04:03 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.139
+         number() corrected - had wrong if/then/else Structure for T/P/G Multiplyer
+
+Tue Oct  9 02:19:36 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.138
+         sys/types.h & sys/stat.h -> statdefs.h, -> 1.11a09
+
+Tue Oct  9 01:42:05 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * audiosize.c 1.18
+       * isosize.c 1.8
+         sys/types.h & sys/stat.h -> statdefs.h
+
+Sun Oct  7 21:27:14 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-linux-pg.c 1.40
+       * scsi-linux-sg.c 1.68
+         Better error messages for Scanbus if /dev/sg* or /dev/pg* cannot be opened
+
+Sun Oct  7 21:03:23 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.76
+         Modifications to allow recognition of CD/DVD writer
+
+Sun Oct  7 20:41:51 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdr_drv.c 1.25
+         xdebug for DVD/CD writer recognition
+
+Sun Oct  7 19:01:25 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_dvd.c 1.55
+         read_dvd_structure() from drv_dvd.c -> scsi_cdr.c for Pioneer A03 DVD-R/CD-R
+         reload_media() only if writing later
+
+Sun Oct  7 13:35:21 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.108
+       * cdrecord.h 1.84
+         read_dvd_structure() from drv_dvd.c -> scsi_cdr.c for Pioneer A03 DVD-R/CD-R
+
+Thu Sep 27 19:01:30 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsidefs.h 1.27
+         #undef DEV_UNKNOWN for True64
+
+Thu Sep 13 19:10:03 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.107
+       * cdr_drv.c 1.24
+       * drv_dvd.c 1.54
+       * cdrecord.h 1.83
+         Modifications to allow recognition of CD/DVD writer
+
+Thu Sep 13 19:01:46 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.137
+         cdrecord -version now may print cdrecord-Clone,
+         Modifications to allow recognition of CD/DVD writer
+
+Thu Sep 13 15:36:21 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsidefs.h 1.26
+         DEV_MMC_DVD_WR new
+
+Thu Sep 13 14:31:05 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-sun.c 1.70
+         maxdma for USCSI to default if == -1 (e.g. for TAPE), Debug print the RQ Buffer.
+
+Tue Sep 11 14:04:03 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.106
+         Open CD-Text File in Binary
+
+Tue Sep 11 03:06:31 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-linux-sg.c 1.67
+         Timeout Workaround for ioctl()
+
+Tue Sep  4 14:04:25 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.136
+         DEMO_SPEED new
+
+Thu Aug  9 16:38:21 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.82
+       * cdrecord.c 1.135
+         #define GRACE_TIME 9 new
+
+Fri Jul 20 13:17:21 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.75
+       * cdrecord.c 1.134
+       * cdrecord.h 1.81
+         RF_BLANK new to avoid opening the tray before blanking
+         Version -> 1.11a07
+
+Thu Jul 19 00:28:36 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-remote.c 1.6
+         Now using _niread()/_nixwrite()
+
+Thu Jul 12 23:40:28 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsidefs.h 1.25
+         Taiyo Yuden EW-50 new
+
+Thu Jul 12 23:35:08 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.105
+       * cdr_drv.c 1.23
+       * drv_philips.c 1.45
+         New driver for Taiyo Yuden EW-50 because it swabs audio bytes compared to Philips CDD-521
+
+Thu Jul 12 23:33:28 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * fifo.c 1.30
+         Better Debug messages for FIFO adresse/size
+
+Thu Jul  5 00:08:38 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * sector.c 1.5
+         Match new libedc
+
+Thu Jun 28 13:19:02 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.74
+         Use -DSAO_RAW -DSAO_RAW_TEST for SAO RAW tests only
+
+Wed Jun 27 10:04:03 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * clone.c 1.4
+         clone_cue() for Test
+
+Wed Jun 27 09:51:19 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.133
+         CDR_SRAW16 removed
+
+Wed Jun 27 09:47:10 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsimmc.h 1.6
+       * scsi_cdr.c 1.104
+         struct ftrackdesc -> scsimmc.h
+
+Wed Jun 27 09:35:13 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.103
+         struct tocheader definition removed because it is in scsimmc.h
+
+Sun Jun 24 22:35:23 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.73
+         check_writemodes_mmc() now resety silent correctly, deflt_writemodes_mmc() new
+
+Sun Jun 24 19:55:02 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.80
+         CDR_SRAW16 disabled, because SAO supports only RAW96x
+
+Fri Jun 22 08:42:55 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsimmc.h 1.5
+         struct tocheader now with Uchar
+
+Wed Jun 20 21:53:55 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * subchan.c 1.6
+         min Struktur member -> pmin
+
+Wed Jun 20 21:53:34 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdr_drv.c 1.22
+         #include <stdio.h> for printf()
+
+Wed Jun 20 21:53:03 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.132
+         Changes for GCC-3.0 & Linux include file bugs for printf() (is a #define), 1.11a04 -> 1.11a05
+
+Tue Jun 19 12:26:49 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.131
+         Usage() with textfile=, 1.11a03 -> 1.11a04
+
+Tue Jun 19 12:22:30 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdtext.c 1.2
+         Modifications for RAW CD-Text
+
+Tue Jun 19 11:39:08 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.79
+       * subchan.c 1.5
+         addrw() new for CD-Text Support in RAW mode
+
+Tue Jun 19 02:10:37 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.78
+       * cdrecord.c 1.130
+         BUF_SIZE -> CDR_BUF_SIZE & from cdrecord.c -> cdrecord.h
+
+Tue Jun 19 01:04:54 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.129
+         Do not call exit() if interrupting during wait time via ^C
+
+Mon Jun 18 09:29:52 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdtext.c 1.1
+         date and time created 01/06/18 08:29:52 by joerg
+
+Mon Jun 18 08:55:07 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.72
+       * cdrecord.c 1.128
+       * cdrecord.h 1.77
+         First CD-Text Support
+
+Sat Jun 16 19:20:36 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.127
+         trackp->dataoff new, call on_comerr() earlier
+
+Sat Jun 16 18:16:51 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.76
+         Dataoffset in struct track new, is_text() new
+
+Sat Jun 16 18:15:05 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.71
+         Forgotten if (xdebug)
+
+Tue Jun 12 22:57:03 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.126
+         -clone new, write mode for -xa1 -xa2, RAW data bug removed
+
+Tue Jun 12 22:42:25 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * sector.c 1.4
+         recodesectors() -> subrecodesecs()/sunchan.c, scrsectors() without return for AUDIO
+
+Tue Jun 12 22:41:37 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * subchan.c 1.4
+         subrecodesecs() from sector.c & scrsectors() dummy
+
+Tue Jun 12 22:40:59 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.75
+         recodesectors() -> subrecodesecs()
+
+Tue Jun 12 01:51:49 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.74
+         Modifications for clone.c
+
+Tue Jun 12 01:50:53 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * clone.c 1.1
+         date and time created 01/06/12 00:50:53 by joerg
+
+Tue Jun 12 01:07:06 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * subchan.c 1.3
+         subq/nsubh -> _subq/_nsubh
+
+Tue Jun 12 01:05:54 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * subchan.c 1.2
+         Changes for clone writing, qwto16() new for clone 16/96 Writing
+
+Tue Jun 12 00:12:42 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * sector.c 1.3
+         removed unused Vars
+
+Mon Jun 11 23:31:00 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.73
+         Enhancements for clone writing
+
+Mon Jun 11 23:29:50 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * sector.c 1.2
+         scrsectors()/recodesectors() fuer clone writing neu
+
+Mon Jun 11 23:12:41 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.70
+         Checking write modes Message only with xdebug
+
+Mon Jun 11 23:11:55 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * movesect.c 1.2
+         Make it more general to allow compress and expand
+
+Mon Jun 11 23:09:58 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * auinfo.c 1.10
+         Comment for ISRC
+
+Sat Jun  9 20:13:35 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.125
+         -copy/-nocopy new, Prevent data sectors only in RAW Mode (without libedc_ecc)
+
+Sat Jun  9 20:05:59 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.60
+         New Options -raw, -raw96r, -raw96p, -raw16, -copy, -nocopy
+
+Wed Jun  6 00:09:58 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.124
+         Any positive startsector for RAW is wriong -> Philips Firmware bug fixed
+
+Mon Jun  4 19:28:17 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.123
+         Modifications for RAW Mode
+         cdr_t *dp now allocated
+         BURNFREE printput with Driver Flags
+         OPC also for -blank
+         write_secs() new for all writes on ATAPI
+         print_wrmodes()/check_wrmode() new
+         reload_media() new
+
+Mon Jun  4 17:45:49 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.72
+       * drv_dvd.c 1.53
+       * drv_mmc.c 1.69
+         New Function reload_media()
+
+Mon Jun  4 17:08:05 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.71
+       * wm_packet.c 1.15
+         Modifications for RAW Mode
+
+Mon Jun  4 17:06:21 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * subchan.c 1.1
+         date and time created 01/06/04 16:06:21 by joerg
+
+Mon Jun  4 16:52:34 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * crc16.c 1.3
+         Now correct Code with Inverted CRC Bits
+
+Mon Jun  4 16:49:47 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * auinfo.c 1.9
+         SECT_AUDIO_NPRE -> SECT_AUDIO_NOPRE
+
+Mon Jun  4 16:06:15 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * crc16.c 1.2
+         Now using Uint*_t
+
+Mon Jun  4 16:02:17 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * crc16.h 1.1
+         date and time created 01/06/04 15:02:17 by joerg
+
+Mon Jun  4 13:33:19 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.68
+         Now using CDR_SRAW*, botchexit Abort removed
+
+Mon Jun  4 12:53:18 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * sector.c 1.1
+         date and time created 01/06/04 11:53:18 by joerg
+
+Sun Jun  3 20:51:22 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * auinfo.c 1.8
+         Modifications for RAW Mode
+
+Sun Jun  3 14:48:57 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.122
+         Use comexit()/comerr() instead of exscsi()
+         New Function do_opc() now also called before blank, -force avoids this
+
+Sat Jun  2 21:24:52 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * movesect.h 1.1
+       * movesect.c 1.1
+         date and time created 01/06/02 20:24:52 by joerg
+
+Fri Jun  1 07:54:04 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.59
+         burnproof -> burnfree
+
+Fri Jun  1 07:46:01 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.102
+         BURN-Proof (Sanyo) -> Buffer-Underrun-Free recording
+
+Fri Jun  1 07:44:39 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * fifo.c 1.29
+         call fill_buf() instead of read_buf() and trackp/secno Parameter for Subcode Generator
+
+Fri Jun  1 02:08:55 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.67
+         BURN-Proof -> BURN-Free
+
+Thu May 31 23:31:44 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsireg.h 1.25
+         BURN Free & link size new
+
+Thu May 31 03:21:47 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.66
+         check_writemodes_mmc() new, is_raw() set write modes
+
+Mon May 28 00:51:36 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cd_misc.c 1.9
+         sec_to_msf() new
+
+Sun May 27 14:01:28 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * audiosize.c 1.17
+         Better comment
+
+Thu May 24 19:10:28 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * auinfo.c 1.7
+         No exit() if -debug & nindex > 1
+
+Thu May 24 19:09:39 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * modes.c 1.23
+         Warning using default data only if not in Silent mode
+
+Thu May 24 19:07:13 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_dvd.c 1.52
+       * drv_jvc.c 1.56
+       * drv_simul.c 1.18
+       * drv_philips.c 1.44
+       * drv_sony.c 1.47
+         CDR_DAO -> CDR_SAO, SAO no more predefined - it either does not work or is tested automatically (MMC)
+
+Sun May 20 21:23:53 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_sony.c 1.46
+       * drv_philips.c 1.43
+         mask sectype with ST_MASK because of new mode bits
+
+Sun May 20 18:51:41 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_simul.c 1.17
+         CDR_SIMUL Flag new
+
+Fri May 18 21:07:58 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.70
+         F_OVERBURN new, F_RAW / is_raw() new, CDR_SIMUL new
+
+Fri May 18 19:30:02 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.121
+         trackp[0].dbtype is set with Data type from Track 1 
+
+Fri May 18 19:22:50 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.65
+         In open_session() wird nun schon der Datenblocktyp fuer den ersten track eingestellt
+
+Mon May 14 23:36:07 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.120
+         -overburn new
+         Bracket bug with > 90 min Warning removed
+         > 90 Min Warning only if offizial capacity is exceeded (for DVD-R)
+         -pad implied for next Track with -isosize
+         Win32 Priorities are non contiguous (fix in rt_raisepri())
+
+Mon May 14 22:54:17 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.69
+         F_OVERBURN (-overburn) new
+
+Mon May 14 22:53:33 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.58
+         -overburn new, -isosize better documented
+
+Sat Apr 28 23:34:12 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-remote.c 1.5
+         Read char with buffer for cygwin
+
+Fri Apr 20 11:38:03 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.c 1.81
+         scg_svhead() is silent if non verbose
+
+Fri Apr 20 11:34:41 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-linux-sg.c 1.66
+         Hack for ide-scsi bug, although there is sense data, SCSI Status is 0 
+
+Thu Apr 19 21:52:41 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.64
+         removed superfluous scgp->silent--; in fixate_mmx(). silent did become negative
+
+Thu Apr 19 21:51:26 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.119
+         Enhance wait time in wait_unit_ready() after blank to 240 s for Mitsumi
+
+Tue Apr 17 00:58:57 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.57
+         Hint for mailman interface
+
+*************** Release 1.10 *******************
+
+Fri Apr 13 20:41:36 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.118
+         Version -> 1.10 final
+
+Fri Apr 13 20:40:58 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.117
+         Backwardcounter corrected
+
+Fri Apr 13 20:39:09 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.56
+         New Support mail Adresses
+
+Wed Apr 11 01:22:18 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.101
+       * cdrecord.h 1.68
+         print_capacity() new with FILE * Parameter
+
+Sun Apr  8 02:03:49 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * modes.c 1.22
+         scgp->silent--; was oat wrong place
+
+Sun Apr  1 14:39:01 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.55
+         Typo
+
+Sat Mar 31 23:02:28 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * modes.c 1.21
+         unit_ready() before each mode_sense()/mode_select()
+
+Sat Mar 31 22:46:28 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.63
+         Comment for IOMEGA DMA overrun modified (Philips removed)
+
+Sun Mar 18 19:39:48 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.54
+         REMOTE SCSI description and new unified SCSI Options
+
+Sun Mar 18 19:31:31 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.116
+         Unified SCSI Options
+
+Sun Mar 18 19:27:02 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.c 1.80
+         Fixed bug that printed SCSI timing without verbose
+
+Sun Mar 18 18:37:45 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.c 1.79
+         New Functions: scg_svhead()/scg_svtail()/scg__sprinterr()
+         Comments for Functions
+         Print SCSI timing for earch failed SCSI Command
+
+Sun Mar 18 18:28:17 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.h 1.50
+         New Funstions: scg_svhead()/scg_svtail()/scg__sprinterr()
+
+Sun Mar 18 15:37:09 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.c 1.78
+         Print Timing without Verbose
+
+Sun Mar 18 15:10:18 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-wnt.c 1.27
+       * scsi-vms.c 1.29
+       * scsi-unixware.c 1.25
+       * scsi-sgi.c 1.34
+       * scsi-osf.c 1.23
+       * scsi-next.c 1.30
+       * scsi-linux-sg.c 1.65
+       * scsi-hpux.c 1.29
+       * scsi-linux-pg.c 1.39
+       * scsi-bsd.c 1.40
+       * scsi-bsd-os.c 1.26
+       * scsi-beos.c 1.19
+       * scsi-aix.c 1.33
+         if (scgp->debug) -> if (scgp->debug > 0)
+
+Wed Mar 14 00:42:40 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.h 1.49
+       * scsitransp.c 1.77
+         scg_verbose() -> scg_vsetup()
+
+Mon Mar 12 23:09:38 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.115
+         Version -> 1.10a17, select_target() uses FILE *
+
+Mon Mar 12 23:08:46 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_scan.h 1.3
+       * scsi_scan.c 1.14
+         comerrno() removed
+         select_target() with FILE *
+         select_target() returns number of Targets
+
+Mon Mar 12 23:06:50 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.67
+       * scsi_cdr.c 1.100
+         printinq() new
+
+Mon Mar 12 22:06:05 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-linux-sg.c 1.64
+         Better differentiation SCG_RETRYABLE/SCG_NO_ERROR
+         Set ux_errno if Sense Data present
+
+Sun Mar 11 17:10:12 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-linux-pg.c 1.38
+         SCG_RETRYABLE for DMA overrun
+         CHECK CONDITION == SCG_NO_ERROR
+
+Sun Mar 11 17:07:48 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.c 1.76
+         Remove unused Variables
+
+Sun Mar 11 16:56:24 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.h 1.48
+         scg_vhead()/scg_vtail()/scg_verbose() & scg_errfflush() new
+
+Sun Mar 11 16:55:55 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.c 1.75
+         scg_vhead()/scg_vtail()/scg_verbose() & scg_errfflush() new
+         Version -> 0.5
+
+Sat Mar 10 17:53:45 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.h 1.47
+         scgp->bufptr new
+         SCG_KVERSION new
+
+Sat Mar 10 17:52:53 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.c 1.74
+         scgp->bufptr new
+         scgp->scmd->resid < 0 == DMA overrun
+
+Sat Mar 10 16:24:00 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-linux-sg.c 1.63
+         SCG_KVERSION new
+
+Mon Feb 26 22:20:32 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-unixware.c 1.24
+         New formatting
+
+Mon Feb 26 22:18:39 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-unixware.c 1.23
+         Environment "LIBSCG_SCAN_ALL" controls scanning of Harddisks because of system crash
+
+Mon Feb 26 16:05:41 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.114
+         Warning if DVD-R code is missing and we found a DVD-R drive
+
+Sun Feb 25 13:02:42 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * fifo.c 1.27
+         Now using mmapdefs.h
+
+Fri Feb 23 17:32:38 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsidefs.h 1.24
+         ccs() Makro -> is_ccs()
+
+Fri Feb 23 00:24:02 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * fifo.c 1.26
+         Support for mmap() on Apollo Domain/OS with mmap(0, &size, ...)
+
+Thu Feb 22 16:13:27 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * audiosize.c 1.16
+         Fixed bug in Prototyp (result from long -> off_t)
+
+Thu Feb 22 16:11:07 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.66
+       * wm_packet.c 1.14
+       * cdrecord.c 1.113
+       * drv_mmc.c 1.62
+       * drv_jvc.c 1.54
+       * drv_dvd.c 1.51
+         Large File support
+
+Thu Feb 22 16:10:53 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_jvc.c 1.55
+         padsize Parameter for pad_track() casted to Llong 
+
+Thu Feb 22 00:57:53 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdr_drv.c 1.21
+         mconfig.h/unixstd.h for Large Files
+
+Thu Feb 22 00:55:35 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_scan.c 1.13
+         #include <mconfig.h> for Large Files
+
+Thu Feb 22 00:54:26 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * fifo.c 1.25
+         Large File support
+         Casts for sizeof() [long] on MaxOS X
+
+Wed Feb 21 23:32:51 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * defaults.c 1.6
+         #include unixstd.h for Large Files
+
+Wed Feb 21 23:27:48 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * auinfo.c 1.6
+       * isosize.c 1.7
+       * audiosize.c 1.15
+         Large File support
+
+Tue Feb 20 23:56:44 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_sony.c 1.45
+       * drv_philips.c 1.42
+         unixstd.h for sys/types.h for off_t in cdrecord.h
+
+Thu Feb 15 23:09:12 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsihack.c 1.37
+         Test for HAVE_BSD_DEV_SCSIREG_H for new MacOSX
+
+Fri Feb  9 00:35:50 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_philips.c 1.41
+         Fixes for Plasmon RF 4100
+
+Tue Jan 23 12:20:32 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * modes.c 1.20
+         Cast for singed/unsigned cmparison
+
+Mon Jan 15 01:09:05 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * fifo.c 1.24
+         %x -> %p Format
+
+Sun Jan  7 19:46:42 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsihack.c 1.36
+         scsi-apollo.c new
+
+Sun Jan  7 19:39:40 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.c 1.73
+       * scsi-vms.c 1.28
+       * scsi-unixware.c 1.22
+       * scsi-linux-pg.c 1.37
+       * scsi-aix.c 1.32
+         sense_len check -> scsitransp.c
+
+Tue Jan  2 00:09:45 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.c 1.72
+         sccsid[] is always used -> without #ifdef lint
+
+Fri Dec 29 00:06:35 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.112
+         Lint, 1.10a10, rlimit cast to Llong for SGI
+
+Thu Dec 28 23:19:23 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.99
+         Modified for Lint
+
+Wed Dec 20 18:26:01 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-sgi.c 1.33
+         Cast to caddr_t for SENSEBUF(dsp)
+
+Wed Dec 13 20:22:52 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-linux-pg.c 1.36
+         Cast s_cmd.addr = (caddr_t)sp->u_sense.cmd_sense;
+
+Tue Dec 12 15:20:46 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.h 1.46
+         struct scsi -> struct scg_scsi for AIX
+
+Sat Dec  9 22:52:01 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-linux-sg.c 1.62
+         Recognise ENOTTY as errno for failed ioctl()
+
+Sat Dec  9 18:20:25 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * modes.c 1.19
+       * scsilog.c 1.13
+       * drv_sony.c 1.44
+       * drv_philips.c 1.40
+       * drv_mmc.c 1.61
+       * drv_jvc.c 1.53
+       * drv_dvd.c 1.50
+         u_char -> Uchar
+
+Wed Dec  6 12:43:51 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.111
+         atoll() -> libschily
+
+Wed Nov 29 17:22:15 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-vms.c 1.27
+         Indented
+
+Wed Nov 29 17:18:51 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-vms.c 1.26
+         ATAPI Support and changed for new libscg Interface
+
+Fri Nov 24 11:00:58 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.110
+         Workaround for ACER drive that does not return from -dummy
+         Typo in  online Help
+
+Wed Nov  8 00:06:05 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.h 1.45
+       * scsireg.h 1.24
+       * scsidefs.h 1.23
+       * scgio.h 2.16
+         #ifdef __cplusplus extern "C" {
+
+Sat Nov  4 15:00:50 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * fifo.c 1.23
+       * cdrecord.c 1.109
+         Printf-like Formats cleaned up
+
+Sat Nov  4 14:56:09 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.98
+         PIONEER CD-WO DR-R504X -> DEV_PIONEER_DW_S114X
+
+Sat Nov  4 14:52:43 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.65
+         DEFAULT_FIFOSIZE -> Long Constant
+
+Tue Oct 31 15:58:54 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.108
+         Cygwin-1.x Compatibility
+
+Sun Oct 22 13:37:15 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-aix.c 1.31
+         Type in sizeof(devname removed
+
+Tue Oct 17 10:35:34 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.53
+         SEE ALSO enhanced
+
+Fri Oct 13 11:28:51 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-linux-sg.c 1.61
+         use pg_version() only for PP
+
+Wed Sep 20 00:59:38 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * modes.c 1.18
+         Code reordered so DMA overrun messages only appears once
+
+Sun Sep 17 17:15:06 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.64
+         #define sample -> #define msample for Win32
+
+Fri Sep  8 03:04:50 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * modes.c 1.17
+         Warning for Philips DMA overrun
+
+Wed Sep  6 23:41:34 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.97
+         unit_ready() made better
+
+Wed Sep  6 09:59:05 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.c 1.71
+       * scsitransp.h 1.44
+         scg_cmderr() -> scg_cmd_err(), scg_cmd_status() new
+
+Tue Sep  5 03:32:34 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.c 1.70
+         Default printing to stderr
+
+Tue Sep  5 03:06:01 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.c 1.69
+         scg__open() returns -1 when SCGO_OPEN fails, to avoid calling scg_fileno()
+
+Tue Sep  5 02:30:41 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.96
+         allow_atapi() calls unit_ready() before mode_sense() to make it work past a reset
+
+Tue Sep  5 02:28:03 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * modes.c 1.16
+         Minimal transfer sizeof(struct scsi_mode_header) after DMA overrun
+
+Tue Sep  5 02:22:48 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.60
+         read_toc()/read_disk_info() reads minimal 4 bytes for Philips ATAPI drives
+
+Mon Sep  4 20:24:52 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.52
+         Typo removed
+
+Sat Sep  2 21:16:00 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.h 1.43
+         Drive flags new in SCSI *
+
+Sat Sep  2 21:03:48 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-wnt.c 1.26
+       * scsi-vms.c 1.25
+       * scsi-unixware.c 1.21
+       * scsi-sgi.c 1.32
+       * scsi-osf.c 1.22
+       * scsi-os2.c 1.21
+       * scsi-next.c 1.29
+       * scsi-linux-sg.c 1.60
+       * scsi-linux-pg.c 1.35
+       * scsi-hpux.c 1.28
+       * scsi-bsd.c 1.39
+       * scsi-bsd-os.c 1.25
+       * scsi-aix.c 1.30
+       * scsi-beos.c 1.18
+         All debug printing to stderr (scgp->errfile)
+
+Tue Aug 29 23:44:31 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-next.c 1.28
+       * scsi-bsd-os.c 1.24
+         error codes & return harmonised
+
+Tue Aug 29 02:36:09 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.59
+         set curspeed only if > 0 (SCSI-3 floating point exception in waitfix)
+
+Tue Aug 29 02:35:04 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_scan.c 1.12
+         call scg_settarget() in scanbus, to make sure SCSI address for scg_initator_id() is OK
+
+Sat Aug 26 10:20:43 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.58
+         OPC Hack for strange drive that returns from OPC with "UNIT ATTENTION/operator selected write permit"
+
+Sat Aug 26 10:15:03 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.107
+         Enhancements for remote SCSI, scg_reset() with what Parameter
+
+Sat Aug 26 00:53:10 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsihack.c 1.35
+       * scsitransp.c 1.68
+         scsibus/target/lun acess now only with scg_scsibus()/scsi_target()/scg_lun() and scg_settarget()
+         do not initialize target in struct scg_cmd because this is now done in SCG lowlevel code
+         scg__open() from scsihack.c -> scsitransp.c, scg_settarget() -> scgsettarget.c
+         dummy code it now always present
+
+Sat Aug 26 00:22:51 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.h 1.42
+         scg_settarget() -> scgsettarget.c
+
+Fri Aug 25 23:17:25 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-wnt.c 1.25
+       * scsi-vms.c 1.24
+       * scsi-unixware.c 1.20
+       * scsi-sgi.c 1.31
+       * scsi-osf.c 1.21
+       * scsi-os2.c 1.20
+       * scsi-next.c 1.27
+       * scsi-linux-sg.c 1.59
+       * scsi-linux-pg.c 1.34
+       * scsi-hpux.c 1.27
+       * scsi-bsd.c 1.38
+       * scsi-bsd-os.c 1.23
+       * scsi-beos.c 1.17
+       * scsi-aix.c 1.29
+         scsibus/target/lun acess now only with scg_scsibus()/scsi_target()/scg_lun() and scg_settarget()
+         do not initialize target in struct scg_cmd because this is now done in SCG lowlevel code
+
+Thu Aug 24 00:52:32 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.h 1.41
+         scg Address Stucture new
+         scg__open() without bus/target/lun Parameter
+         scg_remote() new
+
+Wed Aug 23 22:44:26 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_scan.c 1.11
+       * scsilog.c 1.12
+       * drv_dvd.c 1.49
+       * drv_jvc.c 1.52
+       * drv_philips.c 1.39
+       * drv_sony.c 1.43
+       * scsi_cdr.c 1.95
+         scsibus/target/lun acess now only with scg_scsibus()/scsi_target()/scg_lun() and scg_settarget()
+         do not initialize target in struct scg_cmd because this is now done in SCG lowlevel code
+
+Sun Aug 20 20:57:32 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.h 1.40
+       * scsitransp.c 1.67
+       * scsihack.c 1.34
+       * scsi-linux-sg.c 1.58
+       * scsi-linux-pg.c 1.33
+       * scsi-sgi.c 1.30
+       * scsi-next.c 1.26
+       * scsi-hpux.c 1.26
+       * scsi-bsd.c 1.37
+       * scsi-aix.c 1.28
+       * scsi_scan.c 1.10
+         Now using scg_settarget()
+
+Sat Aug 19 23:24:03 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.c 1.66
+       * scsihack.c 1.33
+       * scsi-wnt.c 1.24
+       * scsi-vms.c 1.23
+       * scsi-unixware.c 1.19
+       * scsi-sgi.c 1.29
+       * scsi-osf.c 1.20
+       * scsi-os2.c 1.19
+       * scsi-next.c 1.25
+       * scsi-linux-sg.c 1.57
+       * scsi-linux-pg.c 1.32
+       * scsi-hpux.c 1.25
+       * scsi-bsd.c 1.36
+       * scsi-beos.c 1.16
+       * scsi-bsd-os.c 1.22
+       * scsi-aix.c 1.27
+       * scsitransp.h 1.38
+         scg_reset() with Function code Parameter
+
+Sat Aug 19 22:37:30 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.63
+       * scsitransp.h 1.39
+         #ifdef's modified for new #define _SCG_*_H
+
+Sat Aug 19 21:57:31 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsireg.h 1.23
+       * scsidefs.h 1.22
+       * scgio.h 2.15
+         Correctly made multi include safe with #ifdef _SCG_*
+
+Sat Aug 19 21:05:25 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.c 1.65
+         sys/param.h removed
+
+Sat Aug 19 20:52:31 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.h 1.37
+         Now using scg_ops
+         Remote Version #defines, scg__version() removed
+
+Sat Aug 19 20:23:20 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-sgi.c 1.28
+       * scsi-osf.c 1.19
+       * scsierrs.c 2.26
+       * scsitransp.c 1.64
+       * scsireg.h 1.22
+         u_char -> Uchar
+
+Sat Aug 19 19:13:16 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.c 1.63
+       * scsihack.c 1.32
+         scsitransp.c and scsihack.c separated
+
+Sat Aug 19 17:30:28 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsireg.h 1.21
+         Status & Sense Definitions from scsireg.h
+
+Fri Aug 18 10:40:48 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-vms.c 1.22
+       * scsi-wnt.c 1.23
+       * scsi-unixware.c 1.18
+       * scsi-sgi.c 1.27
+       * scsi-osf.c 1.18
+       * scsi-os2.c 1.18
+       * scsi-next.c 1.24
+       * scsi-linux-sg.c 1.56
+       * scsi-linux-pg.c 1.31
+       * scsi-hpux.c 1.24
+       * scsi-bsd.c 1.35
+       * scsi-bsd-os.c 1.21
+       * scsi-beos.c 1.15
+       * scsihack.c 1.31
+       * scsi-aix.c 1.26
+       * scsitransp.c 1.62
+         Now uses scg_ops Structure and calling via pointers
+
+Thu Aug 17 22:50:53 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.c 1.61
+         Bracketing typo in scg_sprintresult() removed (printed junk)
+
+Wed Aug 16 10:11:08 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-wnt.c 1.22
+       * scsi-vms.c 1.21
+       * scsi-unixware.c 1.17
+       * scsi-sgi.c 1.26
+       * scsi-os2.c 1.17
+       * scsi-osf.c 1.17
+       * scsi-next.c 1.23
+       * scsi-linux-sg.c 1.55
+       * scsi-hpux.c 1.23
+       * scsi-linux-pg.c 1.30
+       * scsi-bsd.c 1.34
+       * scsi-beos.c 1.14
+       * scsi-bsd-os.c 1.20
+       * scsi-aix.c 1.25
+       * scsihack.c 1.30
+       * scsitransp.c 1.60
+         scg_send() now only with scgp* Parameter
+
+Sun Aug 13 23:31:37 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.c 1.59
+         Buggy braketing corrected (printed 4-5 null Bytes to error output even in silent mode)
+
+Fri Aug  4 01:26:24 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.h 1.36
+       * scsitransp.c 1.58
+         Komplett umgebaut damit die Fehlerausgabe in einen String erfolgt
+
+Tue Aug  1 00:03:45 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.h 1.35
+       * scsitransp.c 1.57
+       * scsierrs.c 2.25
+       * scsi-wnt.c 1.21
+       * scsi-vms.c 1.20
+       * scsi-unixware.c 1.16
+       * scsi-sgi.c 1.25
+       * scsi-osf.c 1.16
+       * scsi-os2.c 1.16
+       * scsi-next.c 1.22
+       * scsi-linux-sg.c 1.54
+       * scsi-linux-pg.c 1.29
+       * scsi-hpux.c 1.22
+       * scsi-bsd.c 1.33
+       * scsi-bsd-os.c 1.19
+       * scsi-beos.c 1.13
+       * scsi-aix.c 1.24
+         All printf()'s -> js_printf(), sprintf() -> snprintf()
+
+Sun Jul 30 15:15:34 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.c 1.56
+       * scsitransp.h 1.34
+         scg_prbytes()/scg_prsense() & scg_printdev() INterface restructured
+
+Sun Jul 30 13:52:05 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * wm_packet.c 1.13
+       * scsi_scan.c 1.9
+       * scsilog.c 1.11
+       * cdrecord.c 1.106
+       * scsi_cdr.c 1.94
+       * modes.c 1.15
+       * drv_sony.c 1.42
+       * drv_simul.c 1.16
+       * drv_philips.c 1.38
+       * drv_mmc.c 1.57
+       * drv_jvc.c 1.51
+       * drv_dvd.c 1.48
+         Restructured for new libscg with scg_*()
+
+Thu Jul 27 01:17:47 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.c 1.55
+         scg_prbytes()/scg_printdev() now using FILE * Parameter
+         scg__errmsg() restructured to be similar to snprintf()
+
+Thu Jul 27 01:15:54 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsierrs.c 2.24
+         Made similar to snprintf()
+
+Thu Jul 27 01:15:02 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.h 1.33
+         scg_prbytes()/scg_printdev() now using FILE * Parameter
+         scg__errmsg() restructured to be similar to snprintf()
+
+Sun Jul 23 18:01:12 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsierrs.c 2.23
+       * scsihack.c 1.29
+       * scsitransp.c 1.54
+       * scsi-wnt.c 1.20
+       * scsi-vms.c 1.19
+       * scsi-unixware.c 1.15
+       * scsi-osf.c 1.15
+       * scsi-sgi.c 1.24
+       * scsi-os2.c 1.15
+       * scsi-next.c 1.21
+       * scsi-linux-sg.c 1.53
+       * scsi-linux-pg.c 1.28
+       * scsi-hpux.c 1.21
+       * scsi-bsd.c 1.32
+       * scsi-beos.c 1.12
+       * scsi-bsd-os.c 1.18
+       * scsi-aix.c 1.23
+       * scsitransp.h 1.32
+         restructured to use scg_ basieed Function names
+
+Sun Jul 23 00:28:09 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.h 1.31
+         open_scsi()/close_scsi()/... -> scg_open()/scg_close/...
+
+Thu Jul 20 20:12:42 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.51
+         Note for Volmgt & Solaris/USCSI
+
+*************** Release 1.9 *******************
+
+Thu Jul 20 19:49:20 2000 joerg
+       * diskid.c 1.28
+         New Manufacturer: "Grand Advance Technology LTD."
+
+Thu Jul 20 19:12:01 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.105
+         Version -> 1.9
+         99 Minute check better
+
+Mon Jul  3 01:19:21 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-linux-sg.c 1.52
+         Type fixed in !scglocal(scgp)->drvers < 0 
+
+Mon Jul  3 00:11:20 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.93
+       * drv_sony.c 1.41
+       * drv_dvd.c 1.47
+       * drv_mmc.c 1.56
+       * cdrecord.h 1.62
+       * cd_misc.c 1.8
+         msf_to_lba() with force_positive Flag for 99 Minute CD's
+
+Sun Jul  2 23:22:00 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-linux-sg.c 1.51
+         scsi_raisedma() only for Kernel-2.2.10 and newer
+
+Sat Jul  1 13:40:49 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-linux-sg.c 1.50
+         New allocated copy buffer in SCSI * -> local for raisedma
+
+Sat Jul  1 13:22:49 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.c 1.53
+       * scsi-wnt.c 1.19
+       * scsi-vms.c 1.18
+       * scsi-unixware.c 1.14
+       * scsi-sgi.c 1.23
+       * scsi-osf.c 1.14
+       * scsi-os2.c 1.14
+       * scsi-next.c 1.20
+       * scsi-linux-sg.c 1.49
+       * scsi-linux-pg.c 1.27
+       * scsi-hpux.c 1.20
+       * scsi-bsd.c 1.31
+       * scsi-bsd-os.c 1.17
+       * scsi-beos.c 1.11
+       * scsi-aix.c 1.22
+         maxdma/maxbuf new in SCSI *
+         scsi_getbuf() now calls scsi_bufsize() to init new members
+
+Sat Jul  1 13:09:43 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.h 1.30
+         maxdma/maxbuf new in SCSI *
+
+Fri Jun 30 18:43:43 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-linux-sg.c 1.48
+         scsi_raisedma() now called with correct DMA Buffersize
+
+Fri Jun 30 18:38:48 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.c 1.52
+       * scsihack.c 1.28
+       * scsi-wnt.c 1.18
+       * scsi-vms.c 1.17
+       * scsi-unixware.c 1.13
+       * scsi-sgi.c 1.22
+       * scsi-sco.c 1.14
+       * scsi-osf.c 1.13
+       * scsi-os2.c 1.13
+       * scsi-next.c 1.19
+       * scsi-linux-sg.c 1.47
+       * scsi-hpux.c 1.19
+       * scsi-linux-pg.c 1.26
+       * scsi-bsd.c 1.30
+       * scsi-beos.c 1.10
+       * scsi-bsd-os.c 1.16
+       * scsi-aix.c 1.21
+         scsi_maxdma() now with 2nd Parameter "amt" for Linux sg driver
+
+Tue Jun 27 19:29:05 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.55
+         Disk Subtype decoder for High Speed RW
+
+Tue Jun 27 19:19:51 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.104
+         Support for 99 Minute CD's
+
+Tue Jun 27 19:17:16 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * diskid.c 1.27
+         99 Minute media in table
+
+Mon Jun 26 22:40:39 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * diskid.c 1.26
+         Bestdisc Technology Corporation new
+
+Mon Jun 26 22:29:17 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-bsd.c 1.29
+       * scsi-bsd-os.c 1.15
+       * scsi-sgi.c 1.21
+       * scsi-linux-sg.c 1.46
+       * scsi-linux-pg.c 1.25
+       * scsi-next.c 1.18
+         better error messages into scgp->errstr
+
+Fri Jun 23 23:52:39 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-linux-sg.c 1.45
+         pvers && isold -> scglocal
+
+Fri Jun 23 23:23:33 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-linux-sg.c 1.44
+         Variable pvers only conditional for unused... warning
+
+Fri Jun 23 23:19:00 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-linux-sg.c 1.43
+         Support for SG_IO ioctl()
+
+Fri Jun 23 21:40:38 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.h 1.29
+         overbose new
+
+Thu Jun 22 15:20:18 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-linux-sg.c 1.42
+         SG_SCSI_RESET & SG_SET_RESERVED_SIZE new
+
+Wed Jun 21 10:34:52 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-linux-pg.c 1.24
+         Test with ATAPI SCSI status code
+
+Wed Jun 21 10:33:31 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.c 1.51
+         scsitransp.c split into scsitransp.c & scsi-sun.c
+
+Wed Jun 21 10:27:11 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsihack.c 1.27
+         scsi-sun.c new
+
+Tue Jun 20 07:20:40 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.h 1.28
+         secured _SCGIO_H -> _SCG_SCSISENSE_H
+
+Tue Jun 20 06:09:57 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-bsd.c 1.28
+         ATAPI Support for OpenBSD
+
+Sun Jun  4 00:55:02 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.103
+         #include <sys/select.h> for select() (autoconf Test for AIX), version -> 1.9a02
+
+Sat Jun  3 17:31:06 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.102
+         New Option -shorttrack/-noshorttrack
+
+Fri Jun  2 22:37:51 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.61
+         New Flag TI_SHORT_TRACK & is_shorttrk() macro
+
+Fri Jun  2 22:32:59 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.50
+         New Optionen -shorttrack & -noshorttrack
+
+Fri Jun  2 21:44:43 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * defaults.c 1.5
+         Prevent a buffer overrrun with dev= option
+
+Fri Jun  2 21:43:16 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * auinfo.c 1.5
+         Check for buffer ovverun
+
+Fri Jun  2 00:03:13 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.54
+         Set Pregapsize to 1 if the drive does not support 0
+         free(cue) if cuep == NULL
+
+Tue May 30 02:46:22 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * diskid.c 1.25
+         Restructured
+
+Tue May 30 01:06:32 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * diskid.c 1.24
+         New manufacturers: "WEALTH FAIR INVESTMENT LIMITE", "General Magnetics Ld", "MPO"
+
+Tue May 30 00:59:12 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.h 1.27
+         debug Parameter -> odebug
+
+Mon May 29 19:07:56 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-next.c 1.17
+         Typo corrected max_scsibus -> scglocal(scgp)->max_scsibus
+
+Mon May 29 00:31:18 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsireg.h 1.20
+         Mode page 2A pw_in_lead_in & side_change new
+
+Mon May 29 00:13:25 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.92
+         More Page 2A bits for cdrecord -prcap
+
+Sun May 28 18:52:11 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-vms.c 1.16
+         scsi_close() now works
+
+Sun May 28 18:40:55 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.49
+         -fix hint for CDR-50 & CDR-55 specified
+
+Sun May  7 16:52:20 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.91
+       * scsilog.c 1.10
+       * scsi_scan.c 1.8
+       * auinfo.c 1.4
+       * cd_misc.c 1.7
+       * audiosize.c 1.14
+       * cdr_drv.c 1.20
+       * fifo.c 1.22
+       * defaults.c 1.4
+       * wm_packet.c 1.12
+       * modes.c 1.14
+       * cdrecord.c 1.101
+       * drv_sony.c 1.40
+       * drv_simul.c 1.15
+       * drv_philips.c 1.37
+       * drv_mmc.c 1.53
+       * drv_jvc.c 1.50
+       * drv_dvd.c 1.46
+       * scsierrs.c 2.22
+       * scsitransp.c 1.50
+         #include <schily.h>
+
+Sun May  7 16:46:39 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.90
+         New DVD recognition, to allow Ricoh 9060
+
+Sun May  7 16:11:09 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsihack.c 1.26
+         Support for new Mac OS X
+
+Mon May  1 20:06:37 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.c 1.49
+         scsi_maxmdma() cleaned up
+
+Thu Apr 27 15:06:42 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.48
+         Examples for cdda2wav
+
+Thu Apr 27 14:22:19 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.52
+         No more error message forSony & long write in progress when Fixating
+
+Thu Apr 27 14:17:01 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * diskid.c 1.23
+         Better message for illegal ID (CD-RW)
+        all old CD-R's now print ILLEGAL OLD CODE
+
+Wed Apr 26 11:50:19 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.100
+       * cdrecord.h 1.60
+       * scsi_cdr.c 1.89
+       * drv_jvc.c 1.49
+       * drv_dvd.c 1.45
+         scsi_close_tr_session()/scsi_blank() with immed Parameter
+
+*************** Release 1.8.1 *******************
+
+Thu Apr 27 14:22:19 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.52
+         No error message for Sony & long write in progress while fixating
+
+Thu Apr 27 14:17:01 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * diskid.c 1.23
+         Better printout with illegal ID for CD-RW, all old CD-R's now give ILLEGAL OLD CODE
+
+Wed Apr 26 11:50:19 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.100
+       * cdrecord.h 1.60
+       * scsi_cdr.c 1.89
+       * drv_jvc.c 1.49
+       * drv_dvd.c 1.45
+         scsi_close_tr_session()/scsi_blank() with immed Parameter
+
+Mon Apr 24 12:32:14 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.99
+         Version -> 1.8.1 final, exitcode == 0 only if fixating in Dummy Mode fails
+
+Sat Apr 22 15:37:05 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * diskid.c 1.22
+         New manufacturer "VICTOR COMPANY OF JAPAN, LIMITED", "VIVASTAR AG"
+
+Sun Apr 16 17:07:55 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.47
+         BURN-Proof Option for Sanyo
+
+Sun Apr 16 17:07:11 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.51
+         BURN-Proof Support for Sanyo
+
+Sun Apr 16 17:06:30 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.98
+         New Option driveropts=
+         better -dao usage
+
+Sun Apr 16 03:11:26 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.88
+         display BURN-Proof for cdrecord -prcap
+
+Sun Apr 16 03:08:58 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * defaults.c 1.3
+       * cdrecord.dfl 1.2
+         driveropts new
+
+Sun Apr 16 02:16:29 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_sony.c 1.39
+       * cdrecord.h 1.59
+       * drv_simul.c 1.14
+       * drv_philips.c 1.36
+       * drv_jvc.c 1.48
+       * drv_dvd.c 1.44
+         open_session() now with cdr_t * Parameter for BURN-Proof
+
+Mon Apr  3 21:05:37 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-linux-pg.c 1.23
+         #include <string.h> for strlen()
+
+Sat Apr  1 21:59:19 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * diskid.c 1.21
+         New manufaturer: "TAROKO INTERNATIONAL CO.,LTD.", "UNIDISC TECHNOLOGY CO.,LTD", "Hong Kong Digital Technology Co., Ltd.", "VIVA MAGNETICS LIMITED"
+
+Sat Mar 11 12:31:09 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.87
+         Sanyo CRD-R24S -> Philips CDD 521
+
+Sat Mar 11 12:30:06 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.50
+         send_opc_mmc() now calls send_opc() and suppresses ILLEGAL_REQUEST
+
+Sat Mar 11 12:26:37 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.46
+         WeB address changed
+
+Sun Feb 20 21:54:33 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.58
+       * cdrecord.c 1.97
+       * cdrecord.1 1.45
+         New Option -waiti for multi session from Pipe from mkisofs
+
+Sun Feb 20 20:56:09 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.96
+         scsi_in_progress() Test and usleep(100000) if Long Write in Progress
+
+Sun Feb 20 20:54:06 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.49
+         scsi_in_progress() test for scsi_flush_cache() in fixate, send_cue() -> LOCAL
+
+Sun Feb 20 20:52:49 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.57
+         scsi_in_progress() new, send_cue() removed
+
+Sun Feb 20 20:52:15 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.86
+         scsi_in_progress() new
+
+Sat Feb 19 00:38:35 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.95
+         read Sectorsize from read_capacity too, for drivs without Blockdescriptor, dp->cdr_opc() new
+
+Sat Feb 19 00:33:54 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.85
+         send_opc() new
+
+Sat Feb 19 00:24:37 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.56
+       * drv_sony.c 1.38
+       * drv_simul.c 1.13
+       * drv_philips.c 1.35
+       * drv_mmc.c 1.48
+       * drv_jvc.c 1.47
+       * drv_dvd.c 1.43
+         Separate OPC code in driver interface
+
+Sun Feb  6 08:27:21 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-sgi.c 1.20
+       * scsi-openserver.c 1.17
+       * scsi-linux-sg.c 1.41
+       * scsi-aix.c 1.20
+       * scsi-bsd-os.c 1.14
+       * scsi-hpux.c 1.18
+       * scsi-linux-pg.c 1.22
+       * scsi-bsd.c 1.27
+         added missing brackets in scsi_close() to make sure that scsi_close() really closes files
+
+Sun Feb  6 08:25:14 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-linux-sg.c 1.40
+         Maxdma now is correcteven if only a prallel port is present
+
+*************** Release 1.8 *******************
+
+Fri Jan 28 10:01:48 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.47
+       * drv_dvd.c 1.42
+         load_media() with new doexit Parameter
+         Reload now does not make problems with notebook type drives
+
+Fri Jan 28 09:51:26 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_philips.c 1.34
+       * cdrecord.h 1.55
+       * cdrecord.c 1.94
+         load_media() with new doexit Parameter
+
+Fri Jan 28 09:50:51 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.84
+         wait_unit_ready() does not print error message if scgp->silent >= 1 
+
+Wed Jan 26 11:48:08 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_scan.c 1.7
+         Initiator-ID test past havebus()
+
+Sun Jan 23 16:39:01 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.93
+         Better error message for open_scsi()
+
+Sun Jan 23 16:07:46 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-unixware.c 1.9
+         New code from SCO, -scanbus now works
+
+Sun Jan 23 00:44:28 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsihack.c 1.25
+         scsi-sco.c -> scsi-openserver.c
+
+Tue Jan 18 00:02:33 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.92
+         Version -> 1.8, mlockall()/setpri() problems do not cause abort
+         Note to -pad option for audio Files with wrong length
+         #include <sys/procset.h> for SCO Openserver
+
+Thu Jan 13 01:32:35 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * diskid.c 1.20
+         Problems with m_digitalstor (97:27/01) in table docuented
+
+Thu Jan 13 01:11:45 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * defaults.c 1.2
+         CDR_DEVICE now superseedes /etc/default/cdrecord
+
+Tue Jan 11 01:46:47 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-hpux.c 1.17
+         sprintf(.../dev/rscsi...) now uses hex digits for tgt 0..15
+
+Sat Jan  8 23:42:25 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.83
+         scsi_read() now looks for is_atapi to allow mkisofs & ATAPI to do multi-session 
+
+Fri Jan  7 02:24:28 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsihack.c 1.24
+         Dummyfunctions fuor new Interface
+
+Fri Jan  7 02:22:36 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdr_drv.c 1.19
+         set_cdrcmds() now calls return() past exit() for lint's sake
+
+Wed Dec 29 14:01:03 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.91
+         exargs Strukt new
+         Setting to 2048 bytes/sector earlier for -msinfo
+         new function exscsi()
+         exfifo() -> excdr()
+
+Wed Dec 29 02:14:11 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.54
+       * fifo.c 1.21
+         wait_faio() new
+
+Wed Dec 29 00:38:52 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * diskid.c 1.19
+         New manufacturer: "Hile Optical Disc Technology Corp."
+                         "Friendly CD-Tek Co."
+                         "Sound Sound Multi-Media Development Limited"
+                         "kdg mediatech AG"
+
+Wed Dec 29 00:34:39 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.44
+         better dociumentation for SUID Installation 
+
+Fri Dec 24 01:59:35 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * fifo.c 1.20
+         sp null pointer Problem in fifo_stats() fixed
+         input-buffer -> input buffer
+
+Tue Dec  7 01:07:24 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.43
+         added missing .TP 
+
+Sun Dec  5 13:37:16 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * fifo.c 1.19
+         kill_fifo() now kil only if faio_pid > 0
+
+Sat Dec  4 21:36:38 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * diskid.c 1.18
+         New manufacturer: EXIMPO & Seantram Technology Inc.
+         Seantram has been guessed before
+
+Sat Dec  4 14:15:16 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.90
+         intfifo()/exfifo() new
+         kill FIFO on comerr() and signals
+
+Sat Dec  4 14:12:41 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_dvd.c 1.41
+         isgui as with drv_mmc.c added
+
+Tue Nov 30 14:48:12 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsihack.c 1.23
+       * scsi-linux-pg.c 1.21
+         pg.h now locally available
+
+Sat Nov 27 21:38:54 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-os2.c 1.12
+         SRB in scsi_send() and scsi_reset() -> static to prevent core dump
+
+Sat Nov 20 17:49:38 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-os2.c 1.11
+         scgfiles array removed
+         set_error() new
+         added some ux_errno = EIO
+         wait_post() now calls DosResetEventSem() in any case
+
+Sat Nov 20 14:21:09 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-os2.c 1.10
+         DEBUG2/SCANDEBUG code removed
+
+Sat Nov 20 07:23:59 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * diskid.c 1.17
+         New manufacturer: Customer Pressing Oosterhout
+                         Harmonic Hall Optical Disc Ltd.
+                         DELPHI TECHNOLOGY INC.
+
+Sat Nov 20 06:45:18 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.89
+         Version -> 1.8a32
+         5 missing set_secsize(.. oldsize) added
+
+Sat Nov 20 06:44:02 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdr_drv.c 1.18
+         Kodak PDC-600 in driver recognition
+
+Sat Nov 20 06:43:12 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.46
+         next_wr_addr() in driver struct for CD-ROM -> cmd_ill() 
+
+Sat Nov 20 06:41:39 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * fifo.c 1.18
+         fixed typo for HAVE_DOSALLOCSHAREDMEM
+
+Fri Nov 12 10:00:19 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.c 1.48
+         scsi_yes() now global
+
+Fri Nov 12 09:59:49 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.h 1.26
+         scsi_yes() new
+
+Mon Oct 18 02:38:11 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.88
+         always set TAO mode on startup to make checkdsize() working
+
+Mon Oct 18 01:34:34 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsilog.c 1.9
+       * scsi_cdr.c 1.82
+         i_to_short() -> i_to_2_byte()
+
+Mon Oct 18 01:15:21 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsilog.c 1.8
+       * scsi_cdr.c 1.81
+       * drv_dvd.c 1.40
+       * drv_mmc.c 1.45
+       * drv_philips.c 1.33
+       * iso9660.h 1.4
+         a_to_u_short() -> a_to_u_2_byte()
+
+Mon Oct 18 01:04:17 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * isosize.c 1.6
+         utypes.h wegen intcvt.h
+
+Mon Oct 18 00:38:01 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.80
+       * drv_sony.c 1.37
+       * drv_jvc.c 1.46
+       * drv_dvd.c 1.39
+         a_to_3_byte() -> a_to_u_3_byte()
+
+Mon Oct 18 00:10:18 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_dvd.c 1.38
+       * drv_sony.c 1.36
+       * drv_jvc.c 1.45
+       * drv_philips.c 1.32
+         i_to_long() -> i_to_4_byte()
+
+Mon Oct 18 00:04:43 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.79
+       * isosize.c 1.5
+       * drv_dvd.c 1.37
+       * drv_mmc.c 1.44
+       * drv_jvc.c 1.44
+       * drv_sony.c 1.35
+       * drv_philips.c 1.31
+       * audiosize.c 1.13
+       * cdrecord.c 1.87
+         modified to use intcvt.h and a_to_4_byte()
+
+Sun Oct 17 23:21:40 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * iso9660.h 1.3
+         removed i_to_* and a_to_* macros -> intcvt.h
+
+Sun Oct 17 22:51:51 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsireg.h 1.19
+         struct scsi_capacity modified to use Int32_t 
+
+Sat Oct 16 13:52:29 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.78
+       * drv_mmc.c 1.43
+       * auinfo.c 1.3
+       * drv_sony.c 1.34
+         malloc() casts for K&R C
+
+Fri Oct 15 20:28:25 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.53
+       * cdr_drv.c 1.17
+       * cdrecord.c 1.86
+         set_cdrmds() if 2. Parameter is NULL returns BOOL
+         for cdrecord to check for dvd driver or not
+
+Fri Oct 15 20:19:36 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.77
+         Optima Dis Covery 650 CD-R Inquiry recognition new
+
+Fri Oct 15 20:17:17 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-beos.c 1.9
+       * scsi-osf.c 1.12
+         typos removed
+
+Thu Oct  7 15:33:17 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-bsd-os.c 1.13
+       * scsi-aix.c 1.19
+         mising bracket  in scsi_open() fixed
+
+Fri Sep 17 17:59:18 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.85
+         Version -> 1.8a29
+         libscg version check
+         #incude <vadefs.h> for win32 realtime pri Code
+
+Fri Sep 17 17:56:57 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.76
+         endless lookp in mmc_cap() removed: no medium (wait_unit_ready())
+
+Fri Sep 17 15:48:09 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.c 1.47
+         HAVE_SCG #define earlier
+
+Fri Sep 17 15:42:39 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-linux-pg.c 1.20
+         duplicates with scsi-linux-sg.c fuer scg__version() removed
+
+Fri Sep 17 15:36:55 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.c 1.46
+         #ifdef HAVE_SCG for _scg_trans_version[]
+
+Fri Sep 17 15:09:54 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-wnt.c 1.17
+       * scsi-vms.c 1.15
+       * scsi-unixware.c 1.8
+       * scsi-sgi.c 1.19
+       * scsi-osf.c 1.11
+       * scsi-sco.c 1.13
+       * scsi-os2.c 1.9
+       * scsi-next.c 1.16
+       * scsi-linux-sg.c 1.39
+       * scsi-linux-pg.c 1.19
+       * scsi-hpux.c 1.16
+       * scsi-bsd.c 1.26
+       * scsi-bsd-os.c 1.12
+       * scsi-beos.c 1.8
+       * scsi-aix.c 1.18
+       * scsitransp.c 1.45
+       * scsitransp.h 1.25
+         scg_version() new
+
+Fri Sep 17 14:55:17 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsihack.c 1.22
+         Comment changed
+
+Tue Sep 14 10:57:29 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-linux-sg.c 1.38
+         scgfile variable in max_dma corrected from scgfile -> scglocal(scgp)->scgfile
+
+Fri Sep 10 14:06:19 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * diskid.c 1.16
+         Better text for Disk Typ (e.g. Long strategy type)
+
+Thu Sep  9 12:30:38 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * auinfo.c 1.2
+         isrc_illchar() Prorotype new
+
+Wed Sep  8 17:57:45 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * diskid.c 1.15
+         New manufacturer: Guann Yinn Co. Ltd.
+                         Opti.Me.S. S.p.A.
+                 Nacar Media srl
+
+Wed Sep  8 12:45:37 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-wnt.c 1.16
+         missing bracket at malloc(amt)
+
+Tue Sep  7 17:13:09 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-wnt.c 1.15
+       * scsi-unixware.c 1.7
+       * scsi-vms.c 1.14
+       * scsi-sgi.c 1.18
+       * scsi-sco.c 1.12
+       * scsi-osf.c 1.10
+       * scsi-next.c 1.15
+       * scsi-os2.c 1.8
+       * scsi-linux-sg.c 1.37
+       * scsi-linux-pg.c 1.18
+       * scsi-hpux.c 1.15
+       * scsi-bsd.c 1.25
+       * scsi-beos.c 1.7
+       * scsi-bsd-os.c 1.11
+       * scsi-aix.c 1.17
+       * scsitransp.c 1.44
+         First error messages past scgp->errstr
+         less calls to comerr()
+
+Tue Sep  7 17:07:55 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.h 1.24
+         errstr & errptr new in SCSI *
+         open_scsi() with errs Parameter
+
+Tue Sep  7 16:47:21 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.84
+         Now using new open_scsi()
+         added some calls to flush()
+
+Tue Sep  7 16:46:04 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.42
+         1.6 -> 1.8
+
+Tue Sep  7 00:21:08 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.42
+       * drv_jvc.c 1.43
+       * drv_dvd.c 1.36
+         flush() for Blanking new
+
+Fri Sep  3 11:57:35 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-linux-sg.c 1.36
+       * scsi-linux-pg.c 1.17
+         scsi_initiator_id() in scsi-linux-pg.c -> pg_initiator_id()
+
+Thu Sep  2 18:57:59 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.83
+         1.8a24 -> 1.8a26
+         Ricoh DAO Bug (fwa != -150) workaround
+         Realtimepri for Win32
+
+Thu Sep  2 14:42:14 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_scan.c 1.6
+         scsi_initiator_id() new
+         Now prints bus,tgt,lun before selektor
+
+Thu Sep  2 13:32:57 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.h 1.23
+       * scsi-wnt.c 1.14
+       * scsi-vms.c 1.13
+       * scsi-unixware.c 1.6
+       * scsi-sco.c 1.11
+       * scsi-sgi.c 1.17
+       * scsi-osf.c 1.9
+       * scsi-os2.c 1.7
+       * scsi-next.c 1.14
+       * scsi-linux-sg.c 1.35
+       * scsi-hpux.c 1.14
+       * scsi-linux-pg.c 1.16
+       * scsi-bsd.c 1.24
+       * scsi-bsd-os.c 1.10
+       * scsi-aix.c 1.16
+       * scsi-beos.c 1.6
+       * scsitransp.c 1.43
+         scsi_initiator_id() new
+
+Mon Aug 30 13:36:17 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.c 1.42
+       * drv_simul.c 1.12
+       * fifo.c 1.17
+         #include libport.h new
+
+Sun Aug 29 01:42:10 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * fifo.c 1.16
+         shared memory for OS/2
+
+Sun Aug 29 00:52:56 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * fifo.c 1.15
+         Typo fixed (\f instead of \n)
+
+Tue Aug 10 21:34:03 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.c 1.41
+       * scsi-wnt.c 1.13
+       * scsi-vms.c 1.12
+       * scsi-unixware.c 1.5
+       * scsi-sco.c 1.10
+       * scsi-sgi.c 1.16
+       * scsi-osf.c 1.8
+       * scsi-os2.c 1.6
+       * scsi-next.c 1.13
+       * scsi-linux-sg.c 1.34
+       * scsi-linux-pg.c 1.15
+       * scsi-hpux.c 1.13
+       * scsi-bsd.c 1.23
+       * scsi-bsd-os.c 1.9
+       * scsi-beos.c 1.5
+       * scsi-aix.c 1.15
+         Static locale variable removed
+         Test for openbydev
+         scsi_freebuf() new
+
+Mon Aug  9 00:39:37 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.h 1.22
+         SCSI *->bufbase & scsi_freebuf() new
+
+Sat Aug  7 22:24:46 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.h 1.21
+         running/curcmdname/local new in SCSI *
+
+Sat Aug  7 22:22:36 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.c 1.40
+       * scsi-wnt.c 1.12
+       * scsi-vms.c 1.11
+       * scsi-unixware.c 1.4
+       * scsi-sgi.c 1.15
+       * scsi-sco.c 1.9
+       * scsi-osf.c 1.7
+       * scsi-os2.c 1.5
+       * scsi-next.c 1.12
+       * scsi-linux-sg.c 1.33
+       * scsi-linux-pg.c 1.14
+       * scsi-hpux.c 1.12
+       * scsi-bsd.c 1.22
+       * scsi-bsd-os.c 1.8
+       * scsi-beos.c 1.4
+       * scsi-aix.c 1.14
+         scg_maxdma removed
+         scsi_running/scsi_command -> SCSI * struct
+
+Sat Aug  7 21:05:51 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-vms.c 1.10
+         scsi_close() new
+
+Sun Aug  1 22:08:46 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * fifo.c 1.14
+         WRITER_MAXWAIT & READER_MAXWAIT -> 240s for SAO SCSI Timeout
+         usleep() debug code
+
+Sun Aug  1 17:14:54 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.41
+         Better documentation for -multi Option (DAO mode)
+
+Sun Aug  1 17:05:30 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.82
+         -msinfo now works even if drive is in DAO mode
+         Now corrects trackstart values for second session in DAO Mode
+
+Sun Aug  1 16:51:35 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_sony.c 1.33
+       * drv_simul.c 1.11
+       * drv_philips.c 1.30
+       * drv_mmc.c 1.41
+       * drv_jvc.c 1.42
+       * drv_dvd.c 1.35
+         speedp == 0 allowed if speed should remain as is
+
+Sun Aug  1 16:10:40 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_sony.c 1.32
+       * drv_simul.c 1.10
+       * drv_mmc.c 1.40
+       * drv_jvc.c 1.41
+       * drv_dvd.c 1.34
+         recovery_needed()/recover()/reserve_track() References to Philips driver removed
+
+Sun Aug  1 16:02:03 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_philips.c 1.29
+       * scsi_cdr.c 1.75
+       * cdr_drv.c 1.16
+       * cdrecord.h 1.52
+         Several functions scsi_cdr.c -> drv_philips.c
+         new function cmd_ill() 
+
+Sun Aug  1 13:25:42 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_dvd.c 1.33
+         phys_end in dvd_structure_00 may be 0 for empty session
+
+Sun Jul 25 13:52:02 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.c 1.39
+         scsi_close() new
+         __scgp removed
+
+Sun Jul 25 13:36:47 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-wnt.c 1.11
+       * scsi-unixware.c 1.3
+       * scsi-sgi.c 1.14
+       * scsi-osf.c 1.6
+       * scsi-sco.c 1.8
+       * scsi-os2.c 1.4
+       * scsi-next.c 1.11
+       * scsi-linux-sg.c 1.32
+       * scsi-linux-pg.c 1.13
+       * scsi-hpux.c 1.11
+       * scsi-bsd.c 1.21
+       * scsi-bsd-os.c 1.7
+       * scsi-beos.c 1.3
+       * scsi-aix.c 1.13
+         scsi_close() new
+
+Sun Jul 25 00:50:18 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.h 1.20
+         close_scsi() and scsi_smalloc()/scsi_sfree() new
+
+Sat Jul 24 22:26:22 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.h 1.19
+         scsi_close() new
+
+Sat Jul 24 22:25:39 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-vms.c 1.9
+         last changes fro Mr. Heuser
+         Max Timeout corrected
+
+Sat Jul 24 22:22:44 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-next.c 1.10
+         Kernel Driver is in undefined state if SCSI Bus is not valid -> bugfix & debug prints
+
+Sat Jul 24 20:43:47 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.39
+         from BCD converson (debug) for Ricoh test
+         Trying to suppress error messages for newer MITSUMI ATAPI drives
+
+Sat Jul 24 19:27:06 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.40
+          Better documentation for -pad/padsize=
+
+Sat Jul 24 19:25:34 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * diskid.c 1.14
+         New manufacturer: OPTROM
+                         AUDIO DISTRIBUTORS
+                         Acer Media Technology 
+
+Sat Jul 24 19:23:49 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.81
+         -> 1.8a24 & write_buf() Test Code
+
+Sat Jul 24 19:19:22 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.80
+         Check HAVE_SETPRIORITY and HAVE_NICE
+
+Sat Jul 24 19:17:30 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.79
+         Version -> 1.8a23
+         Signalhandler for wait time before burning
+         O_BINARY define for win32
+         setmode(TDIN, O_BINARY) for win32
+         track[] Array now MAX_TRACKS+2
+         Print Drive Buffer size and FIFO size
+         -force Flag to blank problematic CD-RW's
+         set sector size to 2k before burning for Plextor
+         set_speed...() now with speedp Parameter to allow MMC to send back actual values
+         DAO for MMC
+         new Options -atip/-useinfo/-force/-dao/mcn=text/isrc=text/index=list
+         first Test for continuous Drive buffer cap printouts
+         set_secsize() new (for Plextor & DAO)
+         EMX Wildcard expansion for OS/2
+         Timeout for DAO -> minimal 200s
+         print_toc() \ removed for K&R C
+         print_toc() with CD-Text
+         DosSetPriority() now korrectly doing delta
+         setpregaps() sets values for lead-in/out
+         checktsize() checks for DAO
+
+Sun Jul 18 14:39:31 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.51
+       * scsi_cdr.c 1.74
+         open_scsi() -> libscg
+
+Sat Jul 17 15:54:11 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.c 1.38
+          MAX DMA for Solaris x86 from 32k -> 56k
+         scsierr() checks for sense[0] != 0
+         scsi_sense_{key!code!qual} return 0 if scsierr() == FALSE
+
+Sat Jul 17 15:37:00 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.h 1.18
+         open_scsi() for scsiopen.c new
+
+Mon Jun 28 01:11:18 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-linux-pg.c 1.12
+         set CDB to 0 past cdb_len
+
+Sun Jun  6 19:41:11 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_philips.c 1.28
+         CDR_SWABAUDIO for pioneer_dws114x
+
+Sun Jun  6 19:40:29 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * modes.c 1.13
+         get_mode_params() now return FALSE if has_mode_page() returns FALSE
+
+Sun Jun  6 19:39:02 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.73
+         Hack for NT-4.0 ASPI ISE inquiry fake (bug in add_len)
+         workaround for Ricoh NOT_READY key in get Mode page 2A
+
+Thu May 13 16:55:13 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-wnt.c 1.10
+         #define for format to avoid hiding messages
+         Now uses dlopen()
+         ha_inquiry() new
+         better paraeters in scsi_open() 
+         SRB_HaID/SRB_HaId unified
+
+Thu May 13 15:07:36 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.72
+         check scsi_open() return code for < 0
+
+Thu May 13 15:00:48 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * modes.c 1.12
+         Cast for ANSI C comparison
+
+Thu May 13 15:00:07 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_sony.c 1.31
+         Cast for ANSI C
+         fixed typo in error texts
+
+Thu May 13 14:31:50 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_jvc.c 1.40
+         mods for ANSI C comparison
+
+Thu May 13 14:31:12 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.39
+         New Options -atip and index= 
+
+Thu May 13 12:00:58 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsierrs.c 2.21
+         field_ptr now correctly used for progress printing on NOT_READY
+
+Wed May 12 01:42:18 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-os2.c 1.3
+         -scanbus support
+
+Wed May 12 01:01:54 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_philips.c 1.27
+       * scsi_cdr.c 1.71
+       * cdr_drv.c 1.15
+       * scsidefs.h 1.21
+         DEV_RICOH_RO_1060C new (preliminary)
+
+Mon May  3 01:30:22 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-wnt.c 1.9
+         changed names and indented
+         WBOOL definition to distinguish BOOL from Windows.h and BOOL from standard.h
+         busses new
+         compare busno with busses
+         Debug File removed
+         EventStatus as result of WaitForSingleObject()
+         set_error() new for correct error codes
+         scsiabort() new
+
+Tue Apr 27 23:11:59 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-wnt.c 1.8
+         Debug File removed
+
+Tue Apr 27 21:06:48 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-wnt.c 1.7
+         -scanbus now works
+         file matrix removed
+         check for nuber of SCSI Busses
+
+Mon Apr 26 22:37:40 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-wnt.c 1.6
+         Try to implement -scanbus 
+
+Mon Apr 26 22:36:00 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-wnt.c 1.5
+         sp->u_scb.cmd_scb[0] = s.SRB_Status -> sp->u_scb.cmd_scb[0] = s.SRB_TargStat
+         error code SCG_FATAL -> SCG_RETRYABLE
+
+Mon Apr 26 22:35:00 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-wnt.c 1.4
+         Indented II
+
+Mon Apr 26 22:34:15 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-wnt.c 1.3
+         Indented
+
+Mon Apr 26 22:33:41 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-wnt.c 1.2
+         Better comment
+
+Mon Apr 26 22:32:32 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-wnt.c 1.1
+         date and time created 99/04/26 21:32:32 by joerg
+
+Sun Apr 25 09:48:05 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.50
+         is_copy()/is_scms() new
+         TI_COPY/TI_SCMS new
+         read_subchannel() new
+         pr_manufacturer()/disk_rcap() with rw/audio Parameters
+
+Sun Apr 25 09:46:03 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.38
+         clear -dummy status by clearin -dummy state
+         COPY & SCMS handling
+
+Sat Apr 24 14:10:19 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * diskid.c 1.13
+       * drv_mmc.c 1.37
+         pr_manufacturer()/disk_rcap() now using rw and audio Parameter
+
+Sat Apr 24 14:05:48 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_philips.c 1.26
+         pr_manufacturer()/disk_rcap() now using rw and audio Parameter
+         Printing of ATIP "restricted"
+
+Sat Apr 24 14:04:38 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_sony.c 1.30
+         pr_manufacturer()/disk_rcap() now using rw and audio Parameter
+         printf() Format (%l..)
+
+Sat Apr 24 14:02:11 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.70
+         read_subchannel() new
+
+Sat Apr 24 13:03:56 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsihack.c 1.21
+         scsi-wnt.c new
+
+Sun Apr 18 21:04:15 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * defaults.c 1.1
+         date and time created 99/04/18 20:04:15 by joerg
+
+Sun Apr 18 19:56:45 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_sony.c 1.29
+       * drv_simul.c 1.9
+       * drv_philips.c 1.25
+       * drv_mmc.c 1.36
+       * drv_jvc.c 1.39
+       * cdr_drv.c 1.14
+       * drv_dvd.c 1.32
+       * cdrecord.h 1.49
+         New driver function cdr_send_cue
+
+Sun Apr 18 19:28:03 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_jvc.c 1.38
+         g6 & g7 test functions
+
+Sun Apr 18 18:40:56 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.48
+         index= Option new
+
+Sun Apr 18 18:40:54 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.35
+         index= Option new
+
+Sun Apr 18 00:42:59 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.47
+         New Flags F_SAO/F_WRITE/F_PREGAP/F_FORCE
+         isrc in struct track
+         is_tao()/is_pregap() new
+         ds_cdrflags in struct disk_status
+         cdr_buffer_cap in struct cdr_cmd
+         cdr_set_speed_dummy with *speedp - to allow mmc to return value
+         Functions for auinfo.c
+
+Sun Apr 18 00:18:30 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-linux-sg.c 1.31
+         MAX_SCG & MAX_TGT -> 16
+         Debug function for printing buscookies[] and scgfiles[][][]
+         sg_mapbus() now with Bus Parameter and spcial handling for holes in buscookies[]
+         sg_setup() doing range check
+         better handling of Status byte in extended Code for mk2 Interface
+
+Sun Apr 18 00:09:52 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-linux-pg.c 1.11
+         Search slot for PP Bus backwards, as buscookies[] may have holes
+
+Sat Apr 17 22:12:22 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_jvc.c 1.37
+         New Function in Driver table to read Buffer capacity
+          buf_cap_teac(), read_peak_buffer_cap_teac (), buffer_inquiry_teac(), check_buffer_teac() new
+
+Sat Apr 17 19:32:41 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_scan.c 1.5
+         Enhancements for 16 SCSI busses and 17 Targets/Bus
+
+Sat Apr 17 19:29:25 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdr_drv.c 1.13
+         buf_dummy() new
+         New Function in Driver table to read Buffer capacity
+
+Sat Apr 17 19:28:27 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_sony.c 1.28
+       * drv_mmc.c 1.34
+       * drv_philips.c 1.24
+       * drv_simul.c 1.8
+       * drv_dvd.c 1.31
+         New Function in Driver table to read Buffer capacity
+
+Sat Apr 17 19:25:47 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_sony.c 1.27
+         Workaround for CDU 620 (can not read lead-in Start time)
+
+Sat Apr 17 18:57:36 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.c 1.37
+         MAX_SCG & MAX_TGT -> 16
+         Workaround for /dev/scg if Target > 7
+
+Sat Apr 17 18:55:26 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-bsd-os.c 1.6
+       * scsi-vms.c 1.8
+       * scsi-unixware.c 1.2
+       * scsi-sgi.c 1.13
+       * scsi-sco.c 1.7
+       * scsi-osf.c 1.5
+       * scsi-os2.c 1.2
+       * scsi-next.c 1.9
+       * scsi-hpux.c 1.10
+       * scsi-bsd.c 1.20
+       * scsi-aix.c 1.12
+         MAX_SCG & MAX_TGT -> 16
+
+Sat Apr 17 18:47:39 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-next.c 1.8
+         scsi_setup() & scsi_havebus() with scgp Pointer (bug)
+
+Sat Apr 17 17:09:00 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.c 1.36
+         limit SunOS 4.x maxdma to 64k-1
+
+Sat Apr 17 13:14:24 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.38
+         -force flag and -useinfo new
+
+Tue Apr 13 01:29:14 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * diskid.c 1.12
+         m_seantram Index 28 (typo) -> 83
+
+Tue Apr 13 01:06:45 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * modes.c 1.11
+         Test in has_mode_page() if desired page is really available for JVC 2080 FW Bug
+
+Fri Apr  9 20:49:08 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_jvc.c 1.36
+         speed -> *speedp Parameter in speed_select()
+
+Fri Apr  9 01:03:54 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.69
+       * drv_dvd.c 1.30
+       * audiosize.c 1.12
+         Signed/unsiged comparisons with cast
+
+Fri Apr  9 00:46:07 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsilog.c 1.7
+         cast for comparing unsigned > int
+
+Fri Apr  9 00:33:17 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.68
+         read_buff_cap() Ulong -> int
+
+Fri Apr  9 00:32:35 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * diskid.c 1.11
+         New manufacturer: "Woongjin Media corp"
+                        "INFODISC Technology Co., Ltd."
+                        "UNITECH JAPAN INC."
+                        "AMS Technology Inc."
+
+Tue Apr  6 22:08:31 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.33
+         speed -> *speedp Parameter in speed_select()
+         Read write speed Auslesen and set *speedp
+         Test for dsp->ds_cdrflags & RF_WRITE
+         first DAO enhancements
+
+Tue Apr  6 22:05:25 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.67
+         speed -> *speedp Parameter IN speed_select()
+         read_buffer() WITH mode Parameter
+         scsi_get_speed() new
+         read_buff_cap() prints Data if sp && fp == NULL and avoids division by 0
+         read_cdtext() new
+         Workaround for Philips CDD-522 cannot do read TOC MSN
+
+Tue Apr  6 01:15:52 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_philips.c 1.23
+         speed -> *speedp Parameter in speed_select()
+         Test for dsp->ds_cdrflags & RF_WRITE
+
+Tue Apr  6 01:13:14 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_sony.c 1.26
+         ATIP Support
+
+Fri Apr  2 16:06:31 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * diskid.c 1.10
+         "Seantram Technology Inc." new (guess)
+
+Fri Apr  2 15:50:28 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_sony.c 1.25
+       * drv_simul.c 1.7
+       * drv_dvd.c 1.29
+         speed -> *speedp Parameter in speed_select()
+
+Sun Mar 28 15:31:56 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsimmc.h 1.4
+         struct mmc_cue new
+
+Sun Mar 28 15:29:43 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.37
+         -dao and -audio default for .au & .wav
+
+Fri Mar 12 02:05:58 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * auinfo.c 1.1
+         date and time created 99/03/12 02:05:58 by joerg
+
+Sun Mar  7 22:30:42 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * fifo.c 1.13
+         roundup(bufsize, pagesize) to make each Segment page aligned
+
+Wed Mar  3 23:45:20 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * diskid.c 1.9
+         New manufacturers: vanguard, grandadv, taeil, kingpro, digitalstor
+
+Wed Mar  3 22:58:38 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * diskid.c 1.8
+         New RCAP Liste
+
+Sat Feb 20 00:00:44 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.66
+         read_buffer() new
+         timeout for read_toc_philips() -> 240s for TEAC
+         read_master_cue() new
+         send_cue_sheet() new
+         read_buff_cap() new
+
+Sun Jan 31 22:37:38 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * wm_packet.c 1.11
+       * cdrecord.c 1.78
+         carriage Return to beginning of Track... Strings to make error message not overwrite position
+
+Sun Jan 31 19:50:01 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.77
+         ignore dev= values from /etc/default/cdrecord for -scanbus
+
+Sun Jan 31 19:23:53 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.65
+         Suport for ACER CR-4020C
+
+Sun Jan 31 19:23:05 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_philips.c 1.22
+         scgp->inq->ansi_version = 1; -> scgp->inq->data_format = 1; to make Plasmon RF-4100 work again
+
+Sun Jan 31 18:55:45 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.36
+         Hint for SVr4 and POSIX Realtime scheduler
+
+Sun Jan 31 18:49:06 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-bsd.c 1.19
+         scsi_maxdma() from MAXPHYS -> DFLTPHYS
+
+Sat Dec 12 12:36:09 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-beos.c 1.2
+         sccsid[] -> __sccsid[]
+
+Sun Dec  6 13:16:25 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-beos.c 1.1
+         date and time created 98/12/06 13:16:25 by joerg
+
+Sun Dec  6 12:41:50 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsihack.c 1.20
+         BeOS new
+
+Sun Dec  6 12:41:30 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-vms.c 1.7
+         New Version past phone call with vaxinf@CHCLU.CHEMIE.UNI-KONSTANZ.DE
+
+Sun Dec  6 12:10:54 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.35
+         FreeBSD device name bug
+         New address for Mailing List
+         Documentation of /etc/default/cdrecord
+
+Sat Dec  5 13:46:27 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.76
+         HAVE_SYS_RESOURCE_H new (BeOS)
+         1.8a13 -> 1.8a14
+         cdr_defaults() new
+
+Sat Dec  5 13:38:16 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.46
+         default.c/cdr_defaults() new
+
+Sun Nov 29 19:40:50 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-sco.c 1.6
+         cleaned up and permission to use /dev/xxx:target,lun 
+
+Sun Nov 29 19:27:55 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsidefs.h 1.20
+         fused
+
+Sun Nov 29 19:25:54 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scgio.h 2.14
+         Splitted into scgcmd.h and scgio.h
+
+Sun Nov 29 19:23:33 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-unixware.c 1.1
+         date and time created 98/11/29 19:23:33 by joerg
+
+Sun Nov 29 19:22:45 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsihack.c 1.19
+         UNIXWARE new
+
+Sun Nov 29 19:15:04 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.75
+         scgio.h -> scgcmd.h/scgio.h, scgio.h scgcmd.h scsidefs.h scsireg.h scsitransp.h -> include/scg, 1.8a11 -> 1.8a13
+
+Sun Nov 29 19:14:20 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsierrs.c 2.20
+       * scsitransp.c 1.35
+       * cdr_drv.c 1.12
+       * modes.c 1.10
+       * scsilog.c 1.6
+       * wm_packet.c 1.10
+       * scsi_scan.c 1.4
+       * scsi_cdr.c 1.64
+       * audiosize.c 1.11
+       * drv_sony.c 1.24
+       * drv_simul.c 1.6
+       * drv_philips.c 1.21
+       * drv_mmc.c 1.32
+       * drv_jvc.c 1.35
+       * drv_dvd.c 1.28
+         scgio.h -> scgcmd.h/scgio.h, scgio.h scgcmd.h scsidefs.h scsireg.h scsitransp.h -> include/scg
+
+Sun Nov 29 00:39:42 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-sco.c 1.5
+         Correctly return Sense Data, EIO if errno == 0
+
+Sat Nov 28 12:32:00 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsierrs.c 2.19
+         asc <= 80 -> asc < 80 for invalid sense code
+
+Sat Nov 28 00:49:19 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsierrs.c 2.18
+         Missing NULL as terminator for sd_ccs_error_str[] added
+
+Wed Nov 25 22:23:07 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-linux-pg.c 1.10
+         pg_send() Prototyp new
+
+Wed Nov 25 22:22:46 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.c 1.34
+         HAVE_PARAM_H -> HAVE_SYS_PARAM_H (Typo)
+
+Sun Nov 22 15:50:37 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.74
+         1.8a9 -> 1.8a11, DosSetPriority() new
+
+Sun Nov 22 15:26:16 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * isosize.c 1.4
+       * audiosize.c 1.10
+         Now using statdefs.h
+
+Sat Nov 21 23:41:31 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.c 1.33
+         #ifdef  HAVE_PARAM_H for VMS
+
+Sat Nov 21 21:38:31 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.63
+         unsigned int cast for char Parameter in i_to_short()
+
+Sat Nov  7 22:21:28 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.73
+         1.8a8 -> 1.8a9
+
+Fri Nov  6 23:49:59 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-linux-sg.c 1.30
+         Typo in scsi_send() header
+
+Mon Nov  2 22:22:23 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-bsd.c 1.18
+         Typ bus -> busno for CAM removed
+
+Mon Nov  2 14:55:22 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-os2.c 1.1
+         date and time created 98/11/02 14:55:22 by joerg
+
+Mon Nov  2 13:24:30 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsihack.c 1.18
+         Now completely using SCSI *scgp as Function parameter
+         scsi-os2.c new
+
+Mon Nov  2 14:27:10 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-vms.c 1.6
+       * scsi-sgi.c 1.12
+       * scsi-sco.c 1.4
+       * scsi-osf.c 1.4
+       * scsi-next.c 1.7
+       * scsi-linux-sg.c 1.29
+       * scsi-linux-pg.c 1.9
+       * scsi-hpux.c 1.9
+       * scsi-bsd.c 1.17
+       * scsi-bsd-os.c 1.5
+       * scsi-aix.c 1.11
+       * scsierrs.c 2.17
+       * scsitransp.c 1.32
+       * scsitransp.h 1.17
+       * cdrecord.c 1.72
+       * cdrecord.h 1.45
+       * cdr_drv.c 1.11
+       * drv_mmc.c 1.31
+       * drv_philips.c 1.20
+       * drv_jvc.c 1.34
+       * drv_dvd.c 1.27
+       * drv_simul.c 1.5
+       * drv_sony.c 1.23
+       * scsi_cdr.c 1.62
+       * modes.c 1.9
+       * scsi_scan.h 1.2
+       * scsi_scan.c 1.3
+       * scsilog.c 1.5
+       * wm_packet.c 1.9
+         Now completely using SCSI *scgp as Function parameter
+
+Thu Oct 29 15:59:52 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsihack.c 1.17
+       * scsitransp.h 1.16
+       * scsitransp.c 1.31
+       * scsi-sgi.c 1.11
+       * scsi-vms.c 1.5
+       * scsi-sco.c 1.3
+       * scsi-osf.c 1.3
+       * scsi-next.c 1.6
+       * scsi-linux-pg.c 1.8
+       * scsi-linux-sg.c 1.28
+       * scsi-hpux.c 1.8
+       * scsi-bsd.c 1.16
+       * scsi-bsd-os.c 1.4
+       * scsi-aix.c 1.10
+         Globale Variables removed and replaced by SCSI *scgp
+
+Thu Oct 29 15:45:38 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-sco.c 1.2
+         Indented and scsi_isatapi() new
+
+Thu Oct 29 15:30:53 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-sco.c 1.1
+         date and time created 98/10/29 15:30:53 by joerg
+
+Thu Oct 29 15:21:52 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.70
+         Lowlevel SCSI transport Routines now have scgp Parameter, 1.8a6 -> 1.8a7
+
+Thu Oct 29 15:21:09 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.61
+       * drv_sony.c 1.22
+       * modes.c 1.8
+       * scsilog.c 1.4
+       * drv_philips.c 1.19
+       * drv_mmc.c 1.30
+       * drv_jvc.c 1.33
+       * drv_dvd.c 1.26
+         Lowlevel SCSI transport Routines now have scgp Parameter
+
+Wed Oct 28 22:20:25 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-aix.c 1.9
+         dev=device:b,t,l Syntax new
+
+Mon Oct 26 03:18:37 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * diskid.c 1.7
+         manufacturer_id() new
+         mi_num new in struct disk_man
+
+Mon Oct 26 03:17:34 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.44
+         manufacturer_id() new
+
+Mon Oct 26 00:27:22 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * diskid.c 1.6
+         New manufacturer: Xcitec Inc.
+                       Doremi Media Co., Ltd.
+                       Matsushita Electric Industrial Co.,Ltd.
+                       CDA Datenträger Albrechts GmbH.
+
+Sun Oct 25 13:00:22 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.71
+         #ifdef HAVE_SYS_MMAN_H new
+
+Sat Oct 24 01:41:22 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-vms.c 1.4
+       * scsi-osf.c 1.2
+       * scsi-sgi.c 1.10
+       * scsi-next.c 1.5
+       * scsi-hpux.c 1.7
+       * scsi-bsd.c 1.15
+       * scsi-bsd-os.c 1.3
+       * scsi-aix.c 1.8
+         Blind changes for 1st stage of SCSI lib: Globale Variables removed and replaced by SCSI *scgp
+
+Sat Oct 24 00:22:01 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.69
+       * scsi_cdr.c 1.60
+         open_scsi(dev, timeout, verboseopen) -> open_scsi(dev, debug, verboseopen)
+
+Fri Oct 23 23:46:23 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * wm_packet.c 1.8
+       * scsi_cdr.c 1.59
+         scsi_settimeout() -> do not divide by 100
+
+Fri Oct 23 15:53:37 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.68
+         XXX scgp->cap->c_bsize = 2048; XXX Hack init !!!
+
+Fri Oct 23 03:14:46 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsihack.c 1.16
+         scsi-sco.c new
+
+Fri Oct 23 16:01:44 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-linux-sg.c 1.27
+       * scsi-linux-pg.c 1.7
+       * scsitransp.c 1.30
+       * scsitransp.h 1.15
+       * scsierrs.c 2.16
+       * scsi_cdr.c 1.58
+       * scsidefs.h 1.19
+       * cdrecord.c 1.67
+       * drv_dvd.c 1.25
+       * drv_philips.c 1.18
+       * drv_sony.c 1.21
+       * drv_jvc.c 1.32
+       * cdr_drv.c 1.10
+       * drv_mmc.c 1.29
+       * modes.c 1.7
+       * scsi_scan.c 1.2
+       * scsilog.c 1.3
+         Globale Variables removed and replaced by SCSI *scgp
+
+Thu Oct 22 18:49:06 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-next.c 1.4
+         Now using scsi_open(device, busno, tgt, tlun) Interface
+
+Tue Oct 20 18:31:25 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.57
+         CDD521/02 (Kodak PCD-200)
+
+Sun Oct 18 14:54:35 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.66
+         1.6.1 -> 1.7.1
+
+*************** Release 1.6.1 *******************
+
+Sun Oct 18 14:47:55 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.65
+         O_BINARY for Tracks
+         Restore old sector size on exit()
+         Better handling for lba (512/2048) in read_toc()
+
+Sun Oct 18 14:40:35 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.56
+       * cdrecord.h 1.43
+         sense_secsize() new
+
+Sat Oct 17 16:39:41 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * fifo.c 1.12
+         #ifdef SHM_LOCK to allow compilation of SysV shm on AIX
+
+Fri Oct  9 14:21:38 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-bsd.c 1.14
+         sp->ux_errno = EIO; for old Transport Interface
+
+Fri Oct  9 22:19:30 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * modes.c 1.24
+       * cd_misc.c 1.6
+       * fifo.c 1.11
+       * diskid.c 1.5
+       * port.c 1.8
+         #include <utypes.h> new
+
+Fri Oct  9 14:21:38 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cd_misc.c 1.5
+       * wm_packet.c 1.7
+       * wm_session.c 1.2
+       * wm_track.c 1.2
+         #include <sys/types.h> & #include <utypes.h> new
+
+Thu Oct  8 15:43:50 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.42
+         u_char -> Uchar
+
+Wed Oct  7 18:08:46 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.64
+         1.7a2 -> 1.7, -fix -eject corrected
+         wait_unit_ready(120); after a load
+
+Wed Oct  7 18:07:41 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.55
+         IMMED hack in close track/session added
+
+Wed Oct  7 18:06:02 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.28
+         new function waitfix_mmc()
+         -dummy error hiding better
+
+Wed Oct  7 17:54:02 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-linux-pg.c 1.6
+         EIO on SCG_RETRYABLE
+
+Tue Oct  6 12:53:11 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-vms.c 1.3
+         next version from vaxinf@CHCLU.CHEMIE.UNI-KONSTANZ.DE and my remarks
+
+Tue Oct  6 12:21:50 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-vms.c 1.2
+         next version from vaxinf@CHCLU.CHEMIE.UNI-KONSTANZ.DE
+
+Tue Oct  6 02:09:14 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-linux-pg.c 1.5
+       * scsi-linux-sg.c 1.26
+       * scsi-bsd-os.c 1.2
+         New device:@ Syntax
+
+Tue Oct  6 02:04:46 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.54
+         New device:@ Syntax
+         sscanf() -> scsi_scandev()
+
+Tue Oct  6 01:50:13 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.34
+         new dev= Syntax (dev=device:@ / dev=device:@,lun) inserted
+
+Tue Oct  6 01:05:29 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-bsd.c 1.13
+         modified to use -lcam & cam_open_btl(busno, tgt, tlun, O_RDWR, NULL);
+
+Thu Oct  1 01:15:57 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-bsd.c 1.12
+         Mods for dev=devname:@,l
+
+Mon Sep 21 01:24:45 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-linux-sg.c 1.25
+         scsi_settimeout() -> sg_settimeout()
+
+Sat Sep 19 21:49:11 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-osf.c 1.1
+         date and time created 98/09/19 20:49:11 by joerg
+
+Tue Sep 15 02:55:28 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_philips.c 1.17
+         capacity_philips() with Philips CDD-2600 Support new
+         *_attach() now uses cdr_t * Parameter
+         cdr_kodak_pcd600 new
+         Pioneer DW-S114X from open_track_yamaha -> open_track_oldphilips
+
+Tue Sep 15 02:39:44 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-bsd.c 1.11
+         #ifndef BSD_CAM -> #ifndef HAVE_CAMLIB_H
+
+Tue Sep 15 02:37:58 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.63
+         Now uses: fctldefs.h, strdefs.h
+         SECURITY new
+         1.7a1 -> 1.7a2
+         open_scsi() check return value and print error message
+         Blanking time print
+         #ifdef  _SC_PRIORITY_SCHEDULING around sysconf()
+         #ifdef  PRIO_PROCESS around setpriority() for WNT 
+
+Tue Sep 15 02:31:16 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_jvc.c 1.31
+         Now uses: fctldefs.h, strdefs.h
+         blank_jvc() new
+
+Tue Sep 15 02:30:11 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_sony.c 1.20
+         Now uses: fctldefs.h, strdefs.h
+
+Tue Sep 15 02:22:12 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.41
+         struct index -> struct tindex to allow #define index strchr
+
+Tue Sep 15 02:21:24 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.27
+         Now uses: fctldefs.h, strdefs.h, timdefs.h
+         Sony 928 Support new
+         For drives that don't support read ATIP use data from read_diskinfo
+         Try to handle "early Return" fixating syndrom from Mitsumi drives
+         no error messages when fixating using -dummy
+
+Tue Sep 15 02:13:49 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.53
+         Now uses: fctldefs.h, strdefs.h
+
+Tue Sep  8 01:32:08 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsihack.c 1.15
+         Conditional compilation for Linux pg driver to support old Linux releases
+
+Mon Sep  7 02:30:15 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-bsd.c 1.10
+         Typo in scsi_fileno() fixed
+
+Sun Sep  6 18:47:16 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-bsd.c 1.9
+         first FreeBSD CAM Support
+
+Sun Sep  6 18:22:13 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-bsd.c 1.8
+         Enhancements for NetBSD & ATAPI
+
+Sun Sep  6 01:39:22 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdr_drv.c 1.9
+         cdr_mmc_sony new
+
+Sun Sep  6 00:43:43 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_simul.c 1.4
+       * drv_dvd.c 1.24
+         Now uses: strdefs.h
+
+Sat Sep  5 23:23:31 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.c 1.29
+         Now uses: timedefs.h fctldefs.h
+
+Mon Aug 31 01:50:12 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-linux-pg.c 1.4
+         pgbus init from -1 -> -2
+
+Mon Aug 31 01:39:52 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-linux-sg.c 1.24
+         /dev/sga... to /dev/sgz instead of /dev/sgy now checked
+         return nopen to allow recognition of bad dev= parameters
+
+Mon Aug 31 01:38:08 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-linux-pg.c 1.3
+         Debug print for pgbus
+         if scsibus >= 0 ist do nothing if busno is wrong
+
+Mon Aug 31 01:03:17 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.52
+         write_xg5() new
+
+Mon Aug 31 01:02:00 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.51
+         open_scsi() now checks dev=devicename:b,t,l
+        read_trackinfo() now don't prints Cannot read TOC Meldung in silent mode
+
+Mon Aug 31 00:43:31 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.c 1.28
+         scsiprintresult() new
+
+Mon Aug 31 00:40:32 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.h 1.14
+         scsiprintcdb()/scsiprintwdata()/scsiprintrdata()/scsiprintresult() new
+
+Sun Aug 30 12:55:35 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_dvd.c 1.23
+         g5_cdbaddr()/g5_cdblen() -> scgio.h
+
+Sun Aug 30 12:54:37 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsihack.c 1.14
+         USE_PG -> USE_PG_ONLY
+
+Sun Aug 30 12:54:02 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scgio.h 2.13
+         g0_cdblen()/g5_cdblen() & g5_cdbaddr() new
+
+Sun Aug 30 12:53:06 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.40
+         write_xg5() new
+
+Sat Aug 29 22:15:37 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cd_misc.c 1.4
+         pr_manufacturer() reference removed from print_min_atip()
+
+Sat Aug 29 21:57:01 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.33
+         PP tranport documented, -scanbus doc corrected
+
+Sat Aug 29 21:01:59 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-linux-pg.c 1.2
+         #include <linux/pg.h> statt "pg.h"
+         support for integrated parallel Port Adapter & SCSI
+         timeout code corrected
+         DMA overrun now recognized
+
+Sat Aug 29 20:48:28 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-linux-sg.c 1.23
+         Support for integrated parallel Port Adapter & SCSI
+
+Sat Aug 29 20:22:10 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cd_misc.c 1.3
+       * cdrecord.h 1.39
+         print_min_atip() new in cd_misc.c
+
+Tue Aug 25 20:23:20 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsihack.c 1.13
+         scsi_isatapi() defined, for default SCSI code
+
+Sun Aug 23 13:42:44 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-linux-sg.c 1.22
+         Fix for misaligned integer access in sg_header for Linux/sparc if valloc() DMA Buffer is used
+
+Thu Aug 20 10:05:14 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-aix.c 1.7
+         errno == Reference removed
+
+Thu Aug 20 01:24:33 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.32
+         dev=devicename:target,lun documented
+
+Tue Aug 18 04:41:56 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsihack.c 1.12
+         scsi-next.c & scsi-vms.c new
+
+Mon Aug 17 23:08:36 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-vms.c 1.1
+         date and time created 98/08/17 22:08:36 by joerg
+
+Mon Aug 17 22:35:19 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsihack.c 1.11
+         scsi-linux-pg.c new use with  USE_PG
+
+Mon Aug 17 22:34:55 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-linux-pg.c 1.1
+       * scsi-bsd-os.c 1.1
+         date and time created 98/08/17 21:24:24 by joerg
+
+Mon Aug 17 22:22:04 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-linux-sg.c 1.21
+         MAX_SCG -> 8
+         search /dev/sg0... before /dev/sfg...
+
+Mon Aug 17 21:47:35 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-linux-sg.c 1.20
+         Support new sg driverinterface
+         scgfile new to use with global ioctl's
+         MAX_DMA_LINUX -> 4k if SG_BIG_BUFF undefined
+         SG_MAX_SENSE -> 16 if not declared
+         SG_GET_BUFSIZE ioctl new
+         scsi_isatapi() new
+
+Sun Aug 16 23:47:48 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * misc.c 1.1
+         date and time created 98/08/16 22:47:48 by joerg
+
+Sun Aug 16 23:47:06 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.38
+         misc.c: timevaldiff() new
+
+Sun Aug 16 23:34:35 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-bsd.c 1.7
+         scsi_isatapi() new
+         /dev/scgx may be replaced by dev=/dev/xxx:0,0
+
+Sun Aug 16 23:32:42 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.h 1.13
+       * scsitransp.c 1.27
+       * scsi-sgi.c 1.9
+       * scsi-aix.c 1.6
+       * scsi-hpux.c 1.6
+         scsi_isatapi() new
+
+Fri Jul 17 03:44:13 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsihack.c 1.10
+         BSDI new -> scsi-bsd-os.c
+
+Fri Jun 19 19:59:07 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.h 1.12
+       * scsitransp.c 1.26
+       * scsihack.c 1.9
+       * scsi-sgi.c 1.8
+       * scsi-hpux.c 1.5
+       * scsi-bsd.c 1.6
+       * scsi-aix.c 1.5
+       * scsi-linux-sg.c 1.19
+         Use scsi_open(device, busno, tgt, tlun) with parameters
+
+Tue Jun  9 01:44:46 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_dvd.c 1.22
+         korrekte Indizierung bei tracksize virtual tracklist
+
+Sat Jun  6 00:16:40 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * port.c 1.7
+         #include <time.h> -> #include <timedefs.h> wegen sys/time.h
+
+Wed Jun  3 02:20:27 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.31
+         bytes= Option removed
+         Introduced Mailing List
+
+Wed Jun  3 02:18:47 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_dvd.c 1.21
+         Treshold for printing the Virtual Trackliste corrected
+         Abort if first virt Track is not a multiple of the sectorsize
+
+Wed Jun  3 01:35:24 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * diskid.c 1.4
+         disk_rcap List new
+
+Wed Jun  3 01:04:49 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.62
+         CD -> CD/DVD
+
+Wed Jun  3 01:01:53 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.61
+         #if defined(_POSIX_PRIORITY_SCHEDULING) -> #if defined(_POSIX_PRIORITY_SCHEDULING) && !defined(HAVE_SYS_PRIOCNTL_H) bei LOCAL declaration
+
+Tue Jun  2 00:41:37 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_dvd.c 1.20
+         attach_???() new now implementing the side effects from identify_???()
+
+Tue Jun  2 00:41:36 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.26
+         attach_???() neu mit den Nebeneffekten aus identify_???()
+
+Mon Jun  1 23:34:26 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.50
+         Cast for malloc(): not every malloc() is void *
+
+Mon Jun  1 23:33:21 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_sony.c 1.19
+       * drv_jvc.c 1.30
+       * cdr_drv.c 1.8
+       * cdrecord.h 1.37
+       * cdrecord.c 1.60
+         attach Routine now uses cdr_t * Parameter
+
+Mon Jun  1 22:24:42 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_dvd.c 1.19
+       * scsilog.c 1.2
+         Superfluous & in a_to_u_short() removed
+
+Sun May 31 21:38:00 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsihack.c 1.8
+         OSF1 new
+
+Sun May 31 01:45:04 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.c 1.25
+         void * cast for valloc() return
+
+Sun May 31 00:39:54 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.59
+         Casts for tracksize & padsize
+
+Sat May 30 23:12:56 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_simul.c 1.3
+         Verbose Message for islast
+
+Sat May 30 00:35:26 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.58
+         tracksize & padsize -> LLong
+
+Fri May 29 00:32:30 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.57
+         astoll() & getllnum() new
+         number() -> LLong
+
+Fri May 29 00:05:29 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.30
+         waw in .wav Typo
+
+Fri May 29 00:03:32 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_dvd.c 1.18
+         Better comment and housekeeping
+
+Thu May 28 01:08:06 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_dvd.c 1.17
+         next_wr_addr_dvd() now correct with read_rzone_info()
+
+Thu May 28 00:02:01 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_dvd.c 1.16
+         Verbose level documented
+         set ds_maxblocks from rzone_info
+         rzone_size() new
+         phys size computation corrected
+
+Tue May 26 04:16:55 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_dvd.c 1.15
+         Speed code removed
+
+Tue May 26 04:03:55 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_dvd.c 1.14
+         Removed lines that have been commented out
+
+Tue May 26 04:01:03 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_dvd.c 1.13
+         dvd check in identify_dvd() later
+
+Tue May 26 03:58:57 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_dvd.c 1.12
+         fcntl.h
+         errno.h
+         sys/file.h removed
+
+Tue May 26 03:56:48 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_dvd.c 1.11
+         scsiprbytes() with lverbose > 1
+         multi Track Hack indented
+
+Tue May 26 03:49:19 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_dvd.c 1.10
+         Superfluous Debugs in SCSI routines removed
+
+Tue May 26 00:02:51 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.56
+         checktsize() with Llong for total Tracksize in Bytes
+         checkdsize() now computed the remaining rest capacity
+
+Mon May 25 04:40:51 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_dvd.c 1.9
+         Computations of the track split code -> long long
+         MAX tracks -> 99
+
+Mon May 25 04:35:54 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_dvd.c 1.8
+         close_Xtrack_dvd() code -> fixate_dvd()
+
+Mon May 25 04:30:05 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_dvd.c 1.7
+         send_dvd_structure() & send_dvd0F() new
+
+Mon May 25 03:46:30 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_dvd.c 1.6
+         print_laserlog() new
+         print_logpages() new
+
+Mon May 25 03:42:16 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_dvd.c 1.5
+         przone() new
+         print_dvd00()/print_dvd01()print_dvd04()/print_dvd05()/print_dvd0D()/print_dvd0E()print_dvd0F() new
+         now reads 4096 Bytes DVD structure
+
+Mon May 25 03:17:14 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_dvd.c 1.4
+         print_dvd_info() new
+
+Mon May 25 02:31:56 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsilog.c 1.1
+         date and time created 98/05/25 01:31:56 by joerg
+
+Mon May 25 02:05:22 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsimmc.h 1.3
+         rzone_info new
+         dvd_structure_XX new
+
+Sat May 23 22:41:54 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_simul.c 1.2
+         #include unixstd.h new
+
+Sat May 23 21:32:13 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.49
+         New Mode Page 2A Heuristic (min length 0x14 -> 0x10): ATAPI LITEON only gives 0x12: No Write Speed.
+
+Wed May 20 23:49:35 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.55
+         islast bug (|| instead of &&) fixed
+         bytes= Option removed
+
+Tue May 19 04:11:02 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_dvd.c 1.3
+         struct disk_info & struct track_info -> scsimmc.h
+         scsilog.h new
+
+Sat May 16 13:15:21 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsimmc.h 1.2
+         u_char -> Uchar
+
+Sun May 10 00:12:04 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsimmc.h 1.1
+         date and time created 98/05/09 23:12:04 by joerg
+
+Sun May 10 00:04:17 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * auheader.h 1.2
+         generic Copyright comment
+
+Sun May 10 00:02:27 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.25
+         Strukturdefinitionen -> scsimmc.h
+
+Thu May  7 22:43:07 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.48
+         strindex() -> strbeg()
+         vendor_info / prod_ident / prod_revision new because of array index problems
+         Kodak PCD-600 new
+
+Thu May  7 21:38:58 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.36
+         getnum() now extern
+         is_mmc() with DVD recognition
+         disk_rcap() new
+
+Thu May  7 21:38:13 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdr_drv.c 1.7
+         DRV_DVD new
+         cdr_kodak_pcd600 / cdr_cdr_simul / cdr_dvd_simul new
+         DEV_PIONEER_DVDR_S101 new
+         DVD recognition in is_mmc() nee
+
+Thu May  7 21:15:19 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.54
+         1.6 -> 1.7a1
+         getnum() LOCAL -> EXPORT
+         test_unit_ready() before load Medium
+         Allow Medium removal if not ready on load_media()
+
+Thu May  7 10:43:00 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * diskid.c 1.3
+         Vendor list actualalized
+
+Wed May  6 02:52:16 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.29
+         simulation driver documented
+
+Wed May  6 02:41:33 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * audiosize.c 1.9
+         .wav files that are smaller than expected are handled correctly
+
+Mon May  4 02:09:55 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_dvd.c 1.2
+         Function names *_mmc -> *_dvd
+         ds_maxblock -> ds_maxblocks
+         getdisktype_dvd() now includes more tests
+         write_type -> WT_SAO
+         Hack for virtual track list
+
+Sun May  3 19:37:17 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.47
+         mode_select_sg0()/mode_sense_sg0() cnt usage corrected
+         mode_sense_sg0() movebytes() count corrected
+
+Sat May  2 00:46:07 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_simul.c 1.1
+         date and time created 98/05/01 23:46:07 by joerg
+
+Fri May  1 19:26:22 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.46
+         DEV_PCD_600 new
+         is_mmc() now uses dvdp Arg
+
+Fri May  1 19:08:34 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsidefs.h 1.18
+         PCD_600 new
+
+*************** Release 1.6 *******************
+
+Fri Apr 17 12:53:59 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.45
+         & before ibuf removed because it is an array
+
+Fri Apr 17 12:45:38 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.44
+         min/sec/frame -> amin/asec/aframe because of min() Macro
+
+Thu Apr 16 01:43:26 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.26
+         -ignsize new
+         web page for cdrecord added
+
+Thu Apr 16 00:55:39 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * diskid.c 1.2
+         Print if Manufacturer is in none of the tables
+
+Thu Apr 16 00:52:13 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.24
+         ds_maxblock -> ds_maxblocks
+         do get_atip() always, but print if lverbose is set
+
+Thu Apr 16 00:32:50 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.35
+       * cdrecord.c 1.53
+         ds_maxblock -> ds_maxblocks
+         new Option -ignsize
+
+Thu Apr 16 00:31:32 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_jvc.c 1.29
+       * drv_philips.c 1.16
+         ds_maxblock -> ds_maxblocks
+
+Sun Apr 12 16:14:07 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.43
+         Smart & Friendly CD-R4012 (TEAC CDR-55S) new
+
+Sun Apr 12 02:15:15 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.c 1.24
+         scsiprintcdb()/scsiprintwdata()/scsiprintrdata() new
+         print scsiprintcdb() on errors
+
+Sun Apr 12 01:58:26 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.34
+       * cdrecord.c 1.52
+         Real Blocks new
+         1.6a14 -> 1.6
+
+Wed Apr  1 03:28:36 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.51
+         checkgui() now has verbose print
+
+Wed Apr  1 01:36:59 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_jvc.c 1.28
+         lberbose > 1 for all subcode Messages
+         teac_wr_pma()/teac_rd_pma() new
+         JVC Errorcodes new
+         check for cdrecord -fix without Parameter
+         hide Illegal Command errorcode for next_wr_addr_teac()
+
+Wed Apr  1 01:29:49 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.c 1.23
+       * scsi_cdr.c 1.42
+       * drv_mmc.c 1.23
+         GCC Warnings removed: printf format errors
+
+Tue Mar 31 20:58:07 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.50
+         ->1.6a14, LOAD & EJECT works for CD-ROM too
+         GUI test on STDERR
+         first Trackno -> track[0] as Hack
+
+Tue Mar 31 20:56:43 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.25
+         CREDITS
+         better Documentation for tsize= & TEAC
+
+Sun Mar 29 15:31:08 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.24
+         -vv/-VV mods
+         -fix: not for TEAC
+         -load new
+         timeout= Option
+         tsize= description because of tracksize and TEAC
+         nice/SunOS -> nice/others
+
+Sun Mar 29 15:26:19 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_philips.c 1.15
+         open_session() with tracks & trackp Parameters
+         Philips CDD-521 old/dumb new
+         Pioneer DW-S114X new
+
+Sun Mar 29 15:22:29 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.22
+         open_session() with tracks & trackp Parameters
+         Check for zeroed ATIP Info
+         wait_unit_ready() for ATAPI - sorry not working
+
+Sat Mar 28 23:43:07 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.49
+         check_recovery() now uses flags for unload_media()
+         call unload_media() on input buffer, wait error, and for blank media error
+         open_session() now usees tracks & trackp Parameters for Sizecheck
+         Printing of is_swab() with audio fixed
+
+Sat Mar 28 23:22:30 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_jvc.c 1.27
+         teac_open_session() checks tracksize ( <= 0 is not possible)
+
+Sat Mar 28 23:21:08 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.41
+         wait_unit_ready() now handles BUSY
+         mode_sense_sg0() movebytes() count handling corrected (amt-4)
+         better (komplete) Inquiry printing with -V
+         JVC XR-W2001 / Plilips CDD521/00 / Traxdata CDR4120 / Pioneer CD-WO DW-S114X / Pinnacle RCD-1000 new
+
+Sat Mar 28 23:06:05 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsireg.h 1.18
+         SCSI Status codes
+
+Fri Mar 27 01:04:50 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_sony.c 1.18
+       * cdrecord.h 1.33
+         open_session() with tracks & trackp parameters
+
+Thu Mar 26 22:42:29 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdr_drv.c 1.6
+         Pioneer DW-S 114, old Philips, dumb Philips new
+
+Tue Mar 24 21:30:08 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.32
+         is_*() Macros now clearer: != 0
+
+Tue Mar 24 21:29:18 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsidefs.h 1.17
+         DEV_CDD_521_OLD new
+
+Mon Mar 16 00:48:34 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_dvd.c 1.1
+         date and time created 98/04/20 00:48:34 by joerg
+
+Sat Mar 14 17:49:09 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-bsd.c 1.5
+         MAX_DMA_BSD 64k -> 60k
+
+Thu Mar 12 23:48:19 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_jvc.c 1.26
+         set ds_maxblock
+         next_wr_addr_jvc() uses read_B0() if track == 0
+         use trackp[i].trackno for TOC
+         Lead-out Start time now uses frames
+         teac_calibrate() inits lba_addr from read_B0()
+         next_wr_addr_teac() with Parameters
+
+Thu Mar 12 23:42:09 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.48
+         use real Track nubmers
+         -v/-V now Inc type Flag
+         print remaining capacity
+         Pregapsize || bug fixed
+         Trackno in struct track
+         wait_unit_ready() new
+
+Thu Mar 12 23:35:26 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_philips.c 1.14
+         Print computed ATIP only for empty Disk
+         ATIP printout now prints Lead-out start time too
+         compute Disk capacity
+
+Thu Mar 12 22:33:50 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_sony.c 1.17
+         close_track_sony() -> track = 0 !
+         mode_sense() -> get_mode_params()
+
+Thu Mar 12 22:24:10 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.31
+         Strukt track now includes trackno
+         CDR_DVD new
+         from_bcd()/to_bcd() new
+         wait_unit_ready() new
+         read_B0() new
+
+Thu Mar 12 22:20:40 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.40
+         unit_ready() now checks for UNIT_ATTENTION
+         wait_unit_ready() new
+         toc struktures char -> Uchar
+         read_tochdr()/read_trackinfo() may have NULL Pointer Args
+         read_B0() new
+
+Thu Mar 12 22:12:16 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.c 1.22
+         Print data if verbose > 1
+
+Thu Mar 12 01:21:58 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cd_misc.c 1.2
+         from_bcd()/to_bcd() new
+
+Tue Mar 10 00:07:50 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.47
+       * drv_mmc.c 1.21
+         checkgui() & isgui new
+
+Mon Mar  9 23:29:02 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.20
+         Read ATIP non-fatal
+         warnung in fixation with correct lverbose flag
+
+Sun Mar  8 15:02:13 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.39
+         SAF CD-R2006PRO CD-R2006, JVC R2626 new
+
+Sun Mar  8 14:59:31 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.46
+         Default Timeout -> 40s
+         flags int -> long
+         new Option -load
+         Print Lead-out start
+         90 Min value corrected
+
+Sun Mar  8 14:56:53 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.30
+         fsamples()/frames() new
+
+Fri Mar  6 01:11:56 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.c 1.21
+         print SCSI command names before ABORT
+
+Thu Mar  5 01:15:26 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsierrs.c 2.15
+         referres -> refers
+
+Thu Mar  5 01:15:02 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.h 1.11
+       * scsitransp.c 1.20
+         scsi_sense_qual() new
+
+Mon Mar  2 22:50:12 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.19
+         msf_to_lba()/lba_to_msf() -> cd_misc.c
+         len += 2 to correct length for TOC & disk Info
+         failed read ATIP is no fatal error
+         better print_atip()
+
+Mon Mar  2 22:45:53 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cd_misc.c 1.1
+         date and time created 98/03/02 22:45:53 by joerg
+
+Mon Mar  2 22:39:02 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.29
+         F_LOAD new
+         All Flags sorted
+         msf_to_lba()/lba_to_msf() new
+
+Mon Mar  2 22:36:10 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_philips.c 1.13
+         philips_getlilo() new
+         print disk manufacturer new
+
+Mon Mar  2 21:56:53 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.38
+         Pinnacle RCD 4X4, SAF CD-RW226 new
+
+Mon Feb 23 22:32:27 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.37
+         read_toc_philips() same parameters as read_toc() (ses -> fmt)
+
+Mon Feb 23 22:30:57 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.18
+         msf_to_lba() corrected (+-150 bug)
+         lba_to_msf() new
+         Check for Complete Disk: 0xFF:0xFF/0xFF
+         pr_manufacturer() new with lverbose
+         different Formatting
+
+Mon Feb 23 21:54:28 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.45
+         80 Minute limit -> 90 Minutes
+
+Mon Feb 23 21:51:56 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * diskid.c 1.1
+         date and time created 98/02/23 21:51:56 by joerg
+
+Sun Feb 22 23:23:22 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * fifo.c 1.10
+         fifo_percent() with Parameter
+         FIFO Bug (duoubling of a segment at end of writing) fixed
+
+Sun Feb 22 22:54:46 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.44
+         fifo_percent() with Parameter
+         unit_ready() for UNLOAD removed
+         print Disk capacity
+
+Sun Feb 22 22:52:53 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * wm_packet.c 1.6
+         fifo_percent() with Parameter
+
+Sun Feb 22 22:47:51 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.28
+         fifo_percent() with Parameter
+         msf_t typedef
+         pr_manufacturer() new
+
+Sun Feb 15 21:01:03 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * audiosize.c 1.8
+         getWavShort() & getWavLong() Definitions removed
+
+Tue Feb 10 01:00:48 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.43
+         New option timeout=#
+
+Mon Feb  9 12:44:40 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-linux-sg.c 1.18
+         timeout from 1/100 sec -> 1/HZ sec
+
+Sun Feb  8 21:56:01 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-linux-sg.c 1.17
+         Missing bracket at read() inserted
+
+Sun Feb  8 18:45:19 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.36
+         Tayo Yuden CD-WO EW-50 better Inquiry
+
+Sun Feb  8 15:52:15 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * fifo.c 1.9
+         fifo_percent() returns -1 if buflen == 0
+         dummy fifo_percent() always -1
+
+Sun Feb  8 15:50:43 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * wm_packet.c 1.5
+       * cdrecord.c 1.42
+         Copyright -> 1998
+         fs Reference in fifo_percent() removed
+         fifo_percent() in wm_packet new
+
+Sun Feb  8 13:54:25 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.23
+         fs= - administrative part
+         .au & .wav description
+         better -swab description
+
+Sun Feb  8 13:30:33 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-linux-sg.c 1.16
+         Fix for sendcommand() befor scsi_getbuf() call
+         read() < 0 now handled
+
+Sun Feb  8 13:28:38 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * audiosize.c 1.7
+         Definitions for WAVE better
+         better WAV recognition from Dave
+
+Sat Feb  7 23:20:14 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_jvc.c 1.25
+         close_track_teac() fixed only audio uses no run-out blocks
+
+Sat Feb  7 23:18:43 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.41
+         rezero_unit() now silent not supported by all drives
+
+Sat Feb  7 23:14:03 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.35
+         Kodak CDR-240 new
+
+Sun Feb  1 23:17:33 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * fifo.c 1.8
+         HAVE_SHM -> HAVE_USGSHM was a typo
+
+Sun Feb  1 21:20:48 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.34
+         DVD enhancements in mmv_getval() & print_capabilities()
+
+Sun Feb  1 20:35:06 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsireg.h 1.17
+         DVD Definitions in Mode Page 2A
+
+Sun Feb  1 19:56:10 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-linux-sg.c 1.15
+         scsi_getbuf() hat nun char *ret wegen pointer Aritmetik
+         sizeof() cast comparison to int
+         scsi_send(): superfluous ; before scsi_settimeout() removed
+
+Sun Feb  1 19:45:21 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.40
+         filename new in struct track
+         Errorcode and exit() in audio*size()
+
+Sun Feb  1 19:44:08 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * auheader.h 1.1
+         date and time created 98/02/01 19:44:08 by joerg
+
+Sun Feb  1 19:44:00 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * audiosize.c 1.6
+         auheader.h new
+         Errorcodes
+
+Sun Feb  1 19:43:26 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.27
+         filename new in struct track
+         cd_mode_page_2A *cdr_cdcap new in struct cdr_cmd
+
+Sun Feb  1 19:42:28 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_philips.c 1.12
+       * drv_sony.c 1.16
+       * drv_mmc.c 1.17
+       * drv_jvc.c 1.24
+         cd_mode_page_2A *cdr_cdcap new in struct cdr_cmd
+
+Sun Feb  1 16:03:29 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.16
+         ATIP Enhanced
+
+Sun Feb  1 15:56:31 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.15
+         mmv_check() -> mmc_cap()/mmc_getval()
+         Handle non-trayload drives
+         warning for dummy/verbose while fixating
+
+Sun Feb  1 15:49:17 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsidefs.h 1.16
+         DEV_MMC_DVD, DEV_PIONEER_DVDR_S101 new
+
+Sun Feb  1 15:46:50 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.33
+         mmc_getval() & mmv_check() with dvdp
+         DEV_MMC_DVD new
+         Pioneer DVD-R S101, TEAC CD-R55S new
+         allow_atapi() in print_capabilities()
+         heuristic with speed >= 176 according to mmc2
+
+Sun Feb  1 15:46:17 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.39
+         better CD-Recorder warning
+
+Sun Feb  1 14:53:02 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.38
+         Honour file sizes
+         better usage() Output
+         .au & .wav Filesize recognition
+         early recognition of "incompatible medium"
+         sched_setscheduler() error code (< 0) is correct
+
+Sun Feb  1 14:39:27 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.26
+         mmc_getval() & mmv_check() with dvdp
+         TI_WAV & is_wav() removed
+
+Sun Feb  1 14:33:39 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * audiosize.c 1.5
+         Complete recognition of a Wavheader (with Hilfe from Heiko)
+
+Mon Jan 26 01:56:21 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-aix.c 1.4
+         valloc() re-implemented (not available in AIX libc)
+         scsi sense handling ready
+
+Mon Jan 26 01:51:58 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.32
+         mmc_cap(), mmc_getval() new
+         Strings for printcap() static for K&R
+
+Mon Jan 26 01:07:27 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * audiosize.c 1.4
+         Filesize - header for Sun .au Files, data_size is not always correct
+
+Sun Jan 25 23:08:00 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * audiosize.c 1.3
+         Sun .au Header new
+
+Sun Jan 25 22:58:58 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.25
+         TI_NOWAV -> TI_NOAUHDR, is_auname() & ausize() new
+
+Sun Jan 25 18:10:47 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.24
+         TI_NOWAV, mmc_cap() & mmg_getval(), is_wavname() new
+
+Sun Jan 25 16:16:23 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * audiosize.c 1.2
+         is_wavname() new
+
+Sun Jan 25 16:02:26 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * audiosize.c 1.1
+         date and time created 98/01/25 16:02:26 by joerg
+
+Sun Jan 25 13:38:40 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_jvc.c 1.23
+         Errortexts for CD-R55S
+
+Sat Jan 24 17:52:52 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * wm_packet.c 1.4
+       * fifo.c 1.7
+         Honour file sizes
+
+Fri Jan 23 02:08:22 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-linux-sg.c 1.14
+         scsi_initdev() new to allow concurrent cdrecord's
+
+Fri Jan 23 02:04:01 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_jvc.c 1.22
+       * drv_mmc.c 1.14
+       * drv_sony.c 1.15
+       * scsireg.h 1.16
+       * scgio.h 2.12
+         Uint for Bitfields -> Ucbit
+
+Sun Jan 18 14:25:01 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.c 1.19
+         flush() calls to correctly mix stderr/stdout
+
+Sun Jan 18 14:23:33 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.23
+         TI_WAV, is_wav(), wavsize() nee
+
+Sat Jan 17 22:07:03 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.22
+       * cdrecord.c 1.37
+         -reset Option new
+
+Sat Jan 17 21:53:58 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.22
+         F_RESET, F_PRATIP, F_PRDINFO, SES_UNDEF new
+         Definitios for disk status and session status
+         dstat_t enhanced
+         CDR_NOLOLIMIT & CDR_ALLOC new
+         fifo_percent(), allow_atapi(),  mode_sense_??()/mode_select_??() new
+
+Sat Jan 17 21:35:54 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * fifo.c 1.6
+         undef FIFO if no shared mamory
+         SHM_LOCK for Linux
+         Stat buffer for fifosize
+         removed sp->cont because it is not secure  (use diff)
+         fifo_percent() new
+
+Sat Jan 17 21:20:57 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.36
+         -reset new
+         fifo_percent() printing for -v
+
+Sat Jan 17 21:09:24 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.21
+         Better description of dev= and -scanbus
+
+Tue Dec 23 01:26:35 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.31
+         Plextor PX-R24CS
+         S&F CD-R2006PLUS
+         Wearns CDR-632P new
+
+Tue Dec 23 01:23:34 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.30
+         Uint in Bitfields -> Ucbit
+
+Thu Dec 11 19:30:31 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.c 1.18
+         Print command execution time for each failed (non-silent) command
+
+Sun Nov  9 18:33:48 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.13
+         Remove get Page 0x2A for Matsushita CW-7502
+         has_mode_page() checks "current" instead of "default"
+
+Sat Nov  8 16:11:51 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.35
+         Disk size check -> checkdsize() : new
+
+Fri Nov  7 00:02:20 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-aix.c 1.3
+         timeout counts in seconds
+
+Fri Nov  7 00:04:11 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsireg.h 1.15
+       * scgio.h 2.11
+       * scsi_cdr.c 1.29
+       * drv_sony.c 1.14
+       * drv_mmc.c 1.12
+       * drv_jvc.c 1.21
+         u_char in Bitfields -> Uint
+
+Thu Nov  6 20:27:08 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsihack.c 1.7
+         Typo __AIX -> defined(_IBMR2) || defined(_AIX)
+
+Thu Nov  6 20:26:23 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-aix.c 1.2
+         sccsid[] -> __sccsid[], fd -> f Typo, #include <malloc.h>
+
+Thu Nov  6 20:22:14 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.20
+         Typo corrected
+
+Thu Nov  6 20:19:26 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.c 1.17
+       * scsierrs.c 2.14
+       * scsi_cdr.c 1.28
+       * scsi.c 1.4
+       * drv_sony.c 1.13
+       * drv_philips.c 1.11
+       * drv_mmc.c 1.11
+       * drv_jvc.c 1.20
+         #include <mconfig.h> for AIX
+
+Thu Nov  6 20:18:25 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.34
+          #ifdef RLIMIT_NOFILE fuer AIX
+
+Wed Nov  5 18:01:32 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.19
+         Better doc for fs=
+
+Wed Nov  5 17:57:50 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.10
+         msf_to_lba() new, get_diskinfo() new, di_to_dstat() new, getdisktype_mmc() new, additions for Matsushita CW-7502
+
+Wed Nov  5 17:43:41 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * fifo.c 1.5
+         switch -> if then else
+
+Wed Nov  5 17:15:45 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.33
+         init struct disk_status, better aritmetic for disk size
+
+Wed Nov  5 17:14:29 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * fifo.c 1.4
+         print FIFO min fill in percent
+
+Tue Nov  4 11:20:22 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.26
+         return (mode_select_g0(dp, cnt, smp, pf)) was missing in mode_select()
+
+Tue Nov  4 10:35:02 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-linux-sg.c 1.13
+         Check for NULL at return of valloc()
+
+Tue Nov  4 00:13:35 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_jvc.c 1.19
+         New flag CDR_NO_LOLIMIT
+
+Sun Nov  2 16:17:10 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.25
+         SCSI mode(6/10) conversion for ATAPI, distinguish between S&F 2006PLUS / S&F 2006PLUS
+
+Sun Nov  2 14:57:57 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.c 1.16
+         Print finish time
+
+Sun Nov  2 14:54:50 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scgio.h 2.10
+         i_to_4_byte new
+
+Thu Oct 23 19:21:19 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsihack.c 1.6
+         AIX Support
+
+Thu Oct 23 19:20:25 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-aix.c 1.1
+         date and time created 97/10/23 18:20:25 by joerg
+
+Thu Oct 23 19:12:02 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.9
+         Enhancements for packet writing
+
+Thu Oct 23 01:35:02 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.18
+         New options -prcap, -packet, pktsize =#, -noclose
+
+Wed Oct 22 23:50:44 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_jvc.c 1.18
+       * wm_packet.c 1.3
+       * cdrecord.c 1.32
+         fflush(stdout) -> flush(), flush() after Fixating...
+
+Wed Oct 22 23:49:12 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.24
+         scsi_close-session() -> scsi_close_tr_session()
+
+Wed Oct 22 23:49:11 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.21
+         scsi_close-session() -> scsi_close_tr_session()
+
+Sun Oct 19 15:41:35 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.23
+       * cdrecord.c 1.31
+         Prevent medium removal problems fixed (read TOC) & Matsushita CD-750?
+
+Sun Oct 19 15:40:32 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsidefs.h 1.15
+         Matsushita CW-7501 & CW-7502
+
+Sun Oct 19 02:08:53 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_sony.c 1.12
+       * drv_philips.c 1.10
+       * drv_jvc.c 1.17
+       * wm_packet.c 1.2
+       * cdrecord.h 1.20
+       * cdrecord.c 1.30
+         next_wr_address() has track_t * added
+
+Sun Oct 19 01:37:02 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_jvc.c 1.16
+         read_disk_info() -> read_disk_info_teac(), zero pre-gap audio support, opt_power_judge() timeout -> 60 sec
+
+Sun Oct 19 01:33:21 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.22
+         read_disk_info() new, print_capabilities() new
+
+Sun Oct 19 00:40:36 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.29
+       * cdrecord.h 1.19
+         get_buf() new, -prcap & print_capabilities() new, -packet new, pktsize=# new
+
+Sun Oct 19 00:36:32 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * wm_track.c 1.1
+       * wm_session.c 1.1
+       * wm_packet.c 1.1
+         date and time created 97/10/18 23:36:31 by joerg
+
+Sat Oct 18 19:14:05 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi.c 1.3
+         stdlib.h -> stdxlib.h, unistd.h -> unixstd.h
+
+Sat Oct 18 01:34:19 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * modes.c 1.3
+         Ausgabe der Mode Parameter wenn mode_select() nicht klappt & return FALSE
+
+****   1.6a3 ***
+
+Sun Oct 12 20:00:21 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.17
+       * cdrecord.c 1.28
+         New options pregap= defpregap=
+
+Sun Oct 12 19:30:45 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.18
+         is_first() & is_last() new
+
+Sat Oct 11 18:01:28 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.27
+         islast debug printf deleted
+
+Sat Oct 11 17:57:43 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.21
+       * drv_sony.c 1.11
+       * drv_philips.c 1.9
+       * drv_mmc.c 1.8
+       * drv_jvc.c 1.15
+       * cdrecord.h 1.17
+       * cdrecord.c 1.26
+         islast for TEAC & no run-out blocks for disksize computing
+
+Sat Oct 11 14:54:03 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_jvc.c 1.14
+         OLD_CLOSE_TRACK re-aktiviert, clear_subcode() in open_track(), set_limits() in open_track() for audio without run-out, dummy sector -> static to be zeroed
+
+Thu Oct  9 14:14:24 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_jvc.c 1.13
+         Audio Tracks have no link&run-in
+
+Thu Oct  9 02:01:23 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_jvc.c 1.12
+         SWABAUDIO Flag new
+
+Wed Oct  8 17:24:40 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.20
+       * drv_sony.c 1.10
+       * drv_philips.c 1.8
+       * drv_mmc.c 1.7
+       * cdrecord.h 1.16
+       * cdrecord.c 1.25
+         Modification of data structures for JVC/TEAC
+
+Wed Oct  8 17:23:41 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * fifo.c 1.3
+         WRITER_MAXWAIT 20 -> 120 s
+
+Wed Oct  8 17:14:04 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_jvc.c 1.11
+         Enhancements for audio and multi track disks
+
+Wed Oct  8 14:48:06 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.16
+         Better doc for padsize & fs=
+
+Mon Oct  6 20:37:39 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_jvc.c 1.10
+         Modified to use pad_track()
+
+Mon Oct  6 20:32:11 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.24
+         In pad_track(): if (bytesp != 0) check was missing ->coredump
+
+Mon Oct  6 20:29:22 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.19
+         SMART&FRIENDLY CD-R2006
+
+Sun Oct  5 16:53:45 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.6
+         verbose printing modified
+
+Sun Oct  5 16:53:09 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.23
+         Check for bytesp != 0 in pad_track()
+
+Sat Oct  4 01:09:56 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.22
+         realtime raisepri Problem for HP-UX fixed (function present bot not working)
+
+Fri Oct  3 21:33:13 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.18
+       * drv_sony.c 1.9
+       * drv_philips.c 1.7
+       * drv_mmc.c 1.5
+       * drv_jvc.c 1.9
+       * cdrecord.h 1.15
+       * cdrecord.c 1.21
+       * cdrecord.1 1.15
+       * cdr_drv.c 1.5
+         new option blank=type for CD-RW
+
+Fri Oct  3 16:23:00 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.20
+         pad_track() new, await_faio() new & init_faio() befor wait loop, always pad to 300 sectors , padsize= option new, DEFAULT_FIFOSIZE new
+
+Thu Oct  2 02:02:10 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * fifo.c 1.2
+         MIN_BUFFERS -> 3, await_faio() new, kill_faio() new, stdin EOF check, Messages only for debug
+
+Thu Oct  2 01:38:39 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.14
+         padsize Option new, nice --18 bug, 's' & 'f' mult for getnum()
+
+Thu Oct  2 01:31:28 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_jvc.c 1.8
+         sleep()'s added to cure fixating problems ???
+
+Thu Oct  2 01:19:46 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.14
+         DEFAULT_FIFOSIZE, roundup(), tracksize & padsize -> long, pad_track() new, await_fifo() & kill_fifo() new, minutes() cast to int
+
+Wed Sep 24 00:02:39 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.19
+         Fifo & tracksize Option
+
+Tue Sep 23 23:46:27 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-sgi.c 1.7
+         Bug with resid != 0 fixed
+
+Sun Sep 21 23:20:15 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.13
+         fs= Option, tsize= Option, mkisofs | cdrecord with fs= EXAMPLE
+
+Sun Sep 21 22:58:34 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * fifo.c 1.1
+         date and time created 97/09/21 21:58:34 by joerg
+
+Sun Sep 21 22:45:08 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.13
+         faio_get_buf() & fifo_stats()
+
+Sun Sep 21 01:12:43 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.12
+         fifo code
+
+Wed Sep 17 13:55:57 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_jvc.c 1.7
+         Typo in cdr_write_teac() EXPORT -> LOCAL
+
+Wed Sep 17 13:55:06 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.18
+         raisepri() has Parameter (n below Max), _POSIX_PRIORITY_SCHEDULING, _POSIX_MEMLOCK
+
+*************** Release 1.5 *******************
+
+Mon Sep 15 16:46:16 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * README 1.9
+         Anpassungen fuer release 1.5
+
+Wed Sep 10 18:40:49 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.17
+         Print always Copyright except for -msinfo
+
+Wed Sep 10 18:12:59 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.17
+         Inquiry debug data indented
+         Mode Parameters only for verbose
+
+Wed Sep 10 17:57:32 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.16
+         Flags defs von cdrecord.c -> cdrecord.h
+         load_media() new
+         load/unload_madia() global
+         Track verbose output after inquiry
+         Test errorcodes while burning
+         Dummy blocks added for close_track() is not an error
+         -nofix Flag activated
+         Exit code for burning errors: -2
+         Swabaudio automatic
+
+Wed Sep 10 17:43:12 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.11
+         Flag defs from cdrecord.c
+         getdisktype() with cdr_t *
+         load_media() new
+         load/unload_madia() global
+
+Wed Sep 10 17:42:13 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdr_drv.c 1.4
+       * drv_jvc.c 1.6
+         getdisktype() with cdr_t *
+
+Wed Sep 10 17:41:02 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_philips.c 1.6
+         philips_getdisktype() new for automatic eject on "Command Sequence Error"
+
+Wed Sep 10 16:50:56 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.12
+         Scsibus , typo removed
+
+Wed Sep 10 15:10:03 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.11
+         1.4 -> 1.5
+
+Wed Sep 10 15:04:26 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_sony.c 1.8
+         new_track_sony() return valoe corrected
+
+Wed Sep 10 15:03:36 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.10
+         Changes for cdrecord-1.5
+
+Thu Sep  4 19:26:00 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-linux-sg.c 1.12
+         Use channel on multi channel controlers
+
+Thu Sep  4 19:09:10 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_jvc.c 1.5
+       * drv_sony.c 1.7
+       * scsi_cdr.c 1.16
+         inq.ansi_version -> inq.data_format for all mode_select() calls
+         for Philips CDD-522 (version == 1 , format == 2)
+
+Wed Sep  3 02:00:33 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-linux-sg.c 1.11
+         scsi_mapbus() new
+         better timeout handling
+         copy Struct now automatic Variable
+         Sense Data error = SCG_RETRYABLE
+
+Mon Sep  1 01:25:16 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-sgi.c 1.6
+       * scsi-linux-sg.c 1.10
+       * scsi-hpux.c 1.4
+       * scsi-bsd.c 1.4
+         Last tuning make all implementations equal
+         Open only one file if possible.
+         Better bound checking
+
+Sun Aug 31 23:21:06 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-hpux.c 1.3
+         Array again has 8 Luns
+         havebus tests bounds
+
+Sun Aug 31 23:18:35 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-sgi.c 1.5
+         MAX_* introduced, open max 1 lun (for now)
+
+Sun Aug 31 20:14:02 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-hpux.c 1.2
+         MAX_LUN now 1
+
+Sun Aug 31 20:10:25 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-hpux.c 1.1
+         date and time created 97/08/31 19:10:25 by joerg
+
+Sun Aug 31 18:00:16 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsihack.c 1.5
+         HP-UX added
+
+Tue Aug 26 19:37:15 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.15
+         init dp in main now correctly
+
+Tue Aug 26 17:50:20 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-sgi.c 1.4
+         Support complete without using -lds
+
+Tue Aug 26 17:47:35 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.15
+         scsibus/target/lun now now -1 if bus is scanned
+         to make sure that not ony one target can be opened.
+
+Tue Aug 26 17:46:22 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.14
+         test_unit_ready() after select_target() (SCANBUS)
+
+Tue Aug 26 01:47:41 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-sgi.c 1.3
+         unused includes removed
+
+Mon Aug 25 22:02:35 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scgio.h 2.9
+       * scsitransp.c 1.15
+       * scsi-sgi.c 1.2
+       * scsi-linux-sg.c 1.9
+       * scsi-bsd.c 1.3
+         errno -> ux_errno in scg_cmd for POSIX multithread
+
+Mon Aug 25 21:27:55 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-sgi.c 1.1
+         date and time created 97/08/25 20:27:55 by joerg
+
+Mon Aug 25 18:10:12 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.13
+         raisepri() not always done
+
+Sun Aug 24 22:58:37 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_jvc.c 1.4
+         First pre-aplha makes one data track only
+
+Sun Aug 24 17:03:05 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.12
+         New options: driver=name -checkdrive -inq -scanbus -nofix
+         set_trsizes() later
+         get_cdr_cmds() new
+         first simple sizecheck
+         "swap" output from print_data_track() removed
+
+Sun Aug 24 16:54:31 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.10
+         struct disk_status new
+         is_unknown_dev() new
+         is_mmc() new
+         mmc_check() new
+         set_cdrcmds() new
+
+Sun Aug 24 16:53:09 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.14
+         is_unknown_dev() new
+         is_mmc() new
+         mmc_check() new
+         open_scsi() modified for scsi_scan()
+         Device recognition new for CD-R
+         scsi_load() now correct
+
+Sun Aug 24 16:22:22 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.9
+         -nofix new
+         driver=name new
+         -checkdrive new
+         -inq new
+         -scanbus new
+         Sense Output uses new form
+
+Sun Aug 24 16:19:42 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.4
+         CDR_SWABAUDIO new
+         cd_mode* pages -> scsireg.h
+         identify_mmc() uses mmc_check()
+
+Sun Aug 24 16:18:00 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdr_drv.c 1.3
+         set_cdrcmds() new
+         get_cdrcmds() enhanced
+
+Sun Aug 24 15:47:30 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_sony.c 1.6
+       * drv_philips.c 1.5
+         CDR_SWABAUDIO Flag new
+
+Sun Aug 24 14:51:43 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsidefs.h 1.14
+         CDD-2000 & CDD-2600 new
+         MMC Definitionen new
+
+Sun Aug 24 14:18:47 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsireg.h 1.14
+         CD mode pages 05 & 2A
+
+Sun Aug 10 19:29:38 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_philips.c 1.4
+       * drv_sony.c 1.5
+       * drv_mmc.c 1.3
+       * cdrecord.h 1.9
+       * cdrecord.c 1.11
+         cdr_driver -> cdr_drname + cdr_drtext
+         open_track() with track_info * instead of many arguments
+
+Sun Aug 10 18:10:14 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.13
+         LOAD (A6) command now uses correct SCSI definition
+
+Sun Aug 10 17:43:35 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-linux-sg.c 1.8
+         Buffer overflow in sg_rq corrected
+         timeout corrected (semicolon past if)
+         12 Byte Hack now OK
+
+Sun Aug 10 17:42:06 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scgio.h 2.8
+         SCSI g5 command struct now ansi compliant
+
+Sun Aug 10 17:40:30 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsihack.c 1.4
+         SGI include
+
+Fri Jul 18 13:41:46 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.12
+         read_capacity() new
+         scsi_load_unload() new
+         scsi_set_sped() new
+         write_xg1() new
+         read_toc() for SCSI-3 new
+         read_toc_philips() from old name
+         read_track_info() -> read_track_info_philips()
+         read_track_info() new
+         scsi_close_session() new
+         first_writable_address() with address Pointer
+         read_tochdr() with cdr_t * ????
+         read_session_offset() with offset Pointer + Version for SCSI-3
+         is_cdrecorder() removed, Taiyo Yuden new
+
+Fri Jul 18 12:35:02 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-linux-sg.c 1.7
+         with new ioctl() SCSI_IOCTL_GET_BUS_NUMBER more SCSI busses
+
+Fri Jul 18 02:49:46 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.8
+         -version
+         better -isosize Doku
+         -multi warning removed
+
+Fri Jul 18 02:44:11 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.10
+         fix_it now past open_session()
+         next_writable_address() and read_session_offset() now with adress Pointer
+         -version usage()
+         superfluous argument removed with lout
+
+Fri Jul 18 02:31:23 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.8
+       * drv_mmc.c 1.2
+         SCSI-3/mmc first implementation
+
+Fri Jul 18 02:25:10 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_jvc.c 1.3
+       * drv_philips.c 1.3
+       * drv_sony.c 1.4
+         next_writable_address now has adress pointer
+         read_session_offset_philips() extracted
+
+Thu Jul 17 18:12:43 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-bsd.c 1.2
+         ifdef for BSD SENSE bug
+
+Thu Jul 17 17:43:10 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * isosize.c 1.3
+         filedescriptor sense (seek) test.
+
+Tue Jul 15 21:27:29 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * isosize.c 1.2
+         & before vd.vd_type deleted
+
+Tue Jul 15 21:26:57 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_sony.c 1.3
+         & before mode deleted
+
+Tue Jul 15 21:16:46 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.9
+         version string
+         write_track_data() with startsec parameter
+         cd_recorder/drive recognition now uses cdr_t
+         print_toc() with cdr_t parameter
+         open_session() with multi parameter
+         Progress printing in write_track_data() now uses correct rounding
+         dbtype with -multi corrected
+         read_session_offset() with cdr_t parameter
+         print_toc() prints sector numbers correctly and 'lout' for 0xAA
+
+Tue Jul 15 13:34:04 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdr_drv.c 1.2
+         drive_identify may modify cdr_t struct pointer
+         Yamaha CDR-400 correct with cdr_mmc
+
+Tue Jul 15 13:24:49 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_philips.c 1.2
+       * drv_jvc.c 1.2
+       * drv_sony.c 1.2
+         open_track() with dbtyp arg
+         open_session() with multi arg
+         struct cdr_t driver flags filled in
+         driver type string
+
+Tue Jul  8 19:42:42 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-linux-sg.c 1.6
+         /dev/sg0 ... tested too
+
+Tue Jul  8 18:00:39 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-bsd.c 1.1
+         date and time created 97/07/08 17:00:39 by joerg
+
+Tue Jul  8 17:59:20 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsihack.c 1.3
+         New Implementation for *BSD
+
+Sun Jun 22 19:58:40 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.11
+         Smart & Friendly Support
+
+*************** Release 1.4 *******************
+
+Sat Mai 21 19:58:42 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.7
+         Updates for release 1.4
+
+Sat Mai 21 18:11:25 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi.c 1.2
+         scsireg.h Include
+
+Sat Mai 21 00:52:33 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_sony.c 1.1
+         date and time created 97/05/20 23:52:33 by joerg
+
+Sat Mai 21 00:27:56 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_philips.c 1.1
+         date and time created 97/05/20 23:27:56 by joerg
+
+Sat Mai 21 00:27:50 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_mmc.c 1.1
+         date and time created 97/05/20 23:27:50 by joerg
+
+Sat Mai 21 00:27:43 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * drv_jvc.c 1.1
+         date and time created 97/05/20 23:27:43 by joerg
+
+Sat Mai 21 00:27:14 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.10
+         mode_select() uses inq.ansi_version >= 2
+
+Sat Mai 21 00:26:42 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.7
+         attach_unknown() new
+
+Sat Mai 21 00:26:05 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdr_drv.c 1.1
+         date and time created 97/05/20 23:26:05 by joerg
+
+Thu Mai 19 23:46:54 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.8
+         Struct track -> cdrecord.h
+         DB_XXX Data block types
+         cdr_cmd Struct as Drive Abstraction Layer
+         -eject Flag
+         checktsize() new
+         CDR_SPEED & CDR_DEVICE
+
+Thu Mai 19 16:59:44 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.6
+         struct track from cdrecord.c
+         DB_XXX Data block types
+         cdr_cmd Struct as Drive Abstraction Layer
+
+Thu Mai 19 15:42:53 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.9
+         Prototypes lokal too
+         scsi_load_unload() -> load_unload_philips()
+         start_stop_unit() now with eject
+         close_track_philips() new
+         recover with track parameter
+         mode_sense() new
+         speed_select splitted
+         inquiry news new drives
+         scsi_cdr_write()
+
+Mon Mai 16 15:46:48 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * config.h 1.1
+         date and time created 97/05/16 14:46:48 by joerg
+
+Mon Mai 16 15:46:48 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi.c 1.1
+         date and time created 97/05/16 14:46:48 by joerg
+
+Fri May 23 22:09:21 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.c 1.14
+         bad 2. Parameter in gettimeofday -> struct timezone *
+
+Fri Apr 23 22:08:16 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsierrs.c 2.13
+         missing %s in Formatstring added
+
+Wed Apr 14 00:54:03 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsireg.h 1.13
+         new scsi device types
+
+Wed Apr 14 00:53:28 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.c 1.13
+         scsireset() into hack part
+         scsi_setnonstderrs() new, scsierrmsg() chganges
+         new scsi devicetype codes, Solaris x86 dmasize without gethostid()
+
+Wed Apr 14 00:46:27 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.h 1.10
+         Changes for scsierrs.c enhancements
+
+Wed Apr 14 00:45:26 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsierrs.c 2.12
+         Enhancements for SCSI-2 & SCSI-3
+
+Tue Apr  6 17:15:43 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsidefs.h 1.13
+         Different order & Yamaha CDR-400, Sony CDU-924, Ricoh RO-1420, Teac CD-R50 new
+
+Tue Apr  6 16:36:38 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scgio.h 2.7
+         Enhancements for SCSI-2 & SCSI-3
+
+Tue Apr  6 14:10:35 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-linux-sg.c 1.5
+         CCD-> CCS Typo
+
+Tue Apr  6 13:59:16 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsihack.c 1.2
+         scsireset() -> transport specific part
+
+Tue Apr  6 13:59:16 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-linux-sg.c 1.4
+         scsireset() -> transport specific part
+
+*************** Release 1.3 *******************
+
+Fri Mar  4 19:48:35 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * README 1.6
+         Changes for Release 1.3
+
+Fri Mar  4 18:57:02 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.6
+         release 1.3
+
+Fri Mar  4 18:46:37 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.5
+         Changes for Release 1.3
+
+Fri Mar  4 11:55:28 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-linux-sg.c 1.3
+         scsihack.c & scsi-linux-sg.c splitted
+
+Fri Mar  4 11:53:59 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsihack.c 1.1
+         date and time created 97/03/04 10:53:59 by joerg
+
+Fri Mar  4 11:52:42 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * iso9660.h 1.2
+         Quick hack for ANSI C
+
+Wed Mar  2 17:16:35 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.8
+         open_scsi() with verbose arg
+         write_track() & write_track_info() isaudio/preemp -> sectype
+         read_toc() new, read_header() new, read_track_info() new
+         first_writable_addr() now working
+         read_tochdr() new, read_trackinfo() new, read_session_offset() new
+         is_cddrive() new read_scsi() now korrekt with G0_MAXADDR & cnt < 256
+         HACK XXX scsi_capacity to 2048 bytes Sectorsize initialized for mkisofs-1.10
+
+Wed Mar  2 16:51:24 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.c 1.12
+         BAD -> EX_BAD, BOOL scsi_havebus() new
+         scsi_fileno(bus, tgt, lun) new with 3 Parameters, MAX_DMA_SUN386 new
+
+Wed Mar  2 16:46:44 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-linux-sg.c 1.2
+         better Kommentar
+
+Wed Mar  2 16:35:04 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.h 1.9
+         BOOL scsi_havebus() new, scsi_fileno(bus, tgt, lun) new with 3 Parameters
+
+Wed Mar  2 16:33:18 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scgio.h 2.6
+         intriduced _SCGIO_H & bei __STDC__ 0xFF000000UL
+
+Wed Mar  2 16:14:35 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsidefs.h 1.12
+         BAD -> EX_BAD
+
+Wed Mar  2 16:14:04 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * port.c 1.6
+         include fmt.h only if #ifdef FMT
+
+Wed Mar  2 16:07:53 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi-linux-sg.c 1.1
+         date and time created 97/03/02 15:07:53 by joerg
+
+Wed Mar  2 15:49:56 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * iso9660.h 1.1
+         date and time created 97/03/02 14:49:56 by joerg
+
+Wed Mar  2 15:48:55 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * isosize.c 1.1
+         date and time created 97/03/02 14:48:55 by joerg
+
+Wed Mar  2 15:40:32 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.7
+         toctname[] * sectname[] new
+         ldebug -> debug, HAVE_MLOCKALL, -msinfo new, -toc new
+         -audio/-mode2/-xa1/-xa2/-cdi new, -isosize new
+         better Check for options, print_msinfo() new, print_toc() new
+         HAVE_SYS_PRIOCNTL_H new
+
+Wed Mar  2 15:30:26 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.h 1.5
+         BAD -> EX_BAD in standard.h, TOC_* defines, ST_* defines, struct msf
+         several Interface changes for Prototypes
+
+Wed Jan 19 00:23:11 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.6
+         Changed to use scsi_buf_size() & scsi_getbuf(), better gcc Kompat.
+
+Wed Jan 12 23:11:18 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.c 1.11
+         Sbufsize -> long, scsi_maxdma() new
+
+Wed Jan 12 22:10:33 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.h 1.8
+         Sbufsize -> long
+
+Fri Jan  7 21:10:26 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * port.c 1.5
+         ANSI C & printf %ld
+
+Thu Jan  6 22:45:03 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.h 1.7
+         scsi_sense_key() & scsi_sense_code() from fmt.c
+
+Thu Jan  6 22:45:02 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.c 1.10
+         scsi_sense_key() & scsi_sense_code() from fmt.c
+
+Mon Jan  3 14:47:53 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.h 1.6
+         scsi_bufsize() & scsi_getbuf() new
+
+Mon Jan  3 14:47:52 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.c 1.9
+         scsi_bufsize() & scsi_getbuf() new
+
+Fri Dec 31 17:16:13 1996 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsireg.h 1.12
+         Defekt List: length & list_block -> char[] for Byteorder
+
+Tue Dec 28 20:51:42 1996 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scgio.h 2.5
+         #error beseitigt for SunOS cc
+
+Tue Dec 28 14:28:01 1996 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsitransp.c 1.8
+         debug -> kdebug
+
+Tue Dec 28 14:19:16 1996 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scgio.h 2.4
+         debug -> kdebug
+
+Sun Dec 19 16:18:18 1996 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.7
+         Mitsumi
+
+Sun Dec 19 16:14:12 1996 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * README 1.5
+         Performance X86 & Mitsumi
+
+Sat Dec 18 12:37:38 1996 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsierrs.c 2.11
+         param.h, sys/buf.h, sun/dklabel.h, sun/dkio.h eliminated
+
+Sat Dec 18 03:26:04 1996 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * README 1.4
+         Changes for Release 1.2
+
+Sat Dec 18 03:24:14 1996 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.1 1.4
+         Changes for Release 1.2
+
+Sat Dec 18 03:13:41 1996 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * cdrecord.c 1.5
+         -swab new
+         LOCAL functions
+         timings, new timeout for fixating
+         countdown timer before Start
+         write_track_info() disabled
+         -pad for audio, pad to 2352 bytes.
+
+Sun Dec 12 21:09:24 1996 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi_cdr.c 1.6
+         Flush cache & Fixation with big Timeout.
+
+Thu Nov 26 10:54:18 1996 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsierrs.c 2.10
+         New Codes for CDD-2000 & Support for Yamaha CDR-100
+
+Mon Dec 16 16:19:54 1996  J. Schilling  <joerg@schily.isdn.cs.tu-berlin.de>
+
+       * Added -swab option to support Yamaha audio
+         Thanks to (Fred) vecoven@montefiore.ulg.ac.be
+         for the hint.
+       * Added counter for quit time (9 seconds)
+
+Wed Dec 12 21:09:24 1996  J. Schilling  <joerg@schily.isdn.cs.tu-berlin.de>
+
+       * Flush cache & Fixation with separate bigger timeout,
+          other timeout reduced to 20sec.
+
+Mo Dec 3 13:03:30 1996  J. Schilling  <joerg@schily.isdn.cs.tu-berlin.de>
+
+       * Set sector size on all drive types before writing,
+       * Omwith the write_track_info Mode Select before write_track
+         even for Philips drives (this is currently not needed because
+         we don't support ISRC codes at this time).
+
+Tue Nov 26 10:54:18 1996  J. Schilling  <joerg@schily.isdn.cs.tu-berlin.de>
+
+       * New error codes for CDD-2000 & error code support for Yamaha CDR-100
+
+Sun Nov 3 22:58:21 1996  J. Schilling  <joerg@schily.isdn.cs.tu-berlin.de>
+
+       * scsireset() aded to scsitransport.[hc]
+       * Timings for Track and Fixation
+
+Fri Oct 4 11:45:13 1996  J. Schilling  <joerg@schily.isdn.cs.tu-berlin.de>
+
+       * Version 1.1 released.
+
+Mon Aug 19 22:25:18 1996  J. Schilling  <joerg@schily.isdn.cs.tu-berlin.de>
+
+       * Read access test to allow cdrecord to run savely suid root
+
+Sun Aug 18 12:11:20 1996  J. Schilling  <joerg@schily.isdn.cs.tu-berlin.de>
+
+       * bit ordering problems solved
+         Thanks to Gert Poletiek <gert@fwi.uva.nl> for testing
+
+Tue Jun 18 21:38:51 1996  J. Schilling  <joerg@schily.isdn.cs.tu-berlin.de>
+
+       * several changes in scgio.h
+
+Sun Jun 16 15:56:35 1996  J. Schilling  <joerg@schily.isdn.cs.tu-berlin.de>
+
+       * Ansi C Protytypes
+       * priocntl added for Solaris
+         Thanks to Anders Lundgren <al@irfu.se>
+
+Sun Feb 4 19:14:46 1996  J. Schilling  <joerg@schily.isdn.cs.tu-berlin.de>
+
+       * Initial release 1.0
diff --git a/FAQ b/FAQ
new file mode 100644 (file)
index 0000000..cc31a21
--- /dev/null
+++ b/FAQ
@@ -0,0 +1,33 @@
+Frequently Asked Questions about cdrkit
+=======================================
+
+Q: What does "wodim" stand for?
+A: It is not a forest troll and not a winner of the inpronounceability
+   contest. It was simply the next alternative to wom (Writes Optical Media)
+   which was unfortunately already used by other software products.
+
+Q: What this name of ... mean?
+A: Terminology: some names are based on pure imagination, some on
+   abbreviations, some on permutations of chars in descriptions.
+
+      genisoimage: Generate ISO IMAGEs
+      icedax: InCrEdible Audio eXtractor
+      librols: LIB Remains Of LibSchily
+      libusal: LIB Unified/Universal Scsi Access Layer
+      netscsid: NET SCSI Daemon
+      readom: READ Optical Media (see also wodim)
+      wodim: see above
+
+Q: Are there additional depedencies, compared to cdrtools?
+A: Yes. Libcap is required on Linux plattform. Libmagic is needed to support
+   content-based creator/type tables with HFS (optional). Libiconv is needed to
+   support iconv-based filename converstion, eg. from UTF-8 ins Joliet's UCS-2
+   unicode (optional, on plattform where iconv is not already included in the libc
+   system library).
+
+Q: Burning dies with (logical unit communication crc error (ultra-dma/32)).
+   Reason? Solutions?
+A: Try enabling DMA for your device. Some CDROM readers/writters seem to send
+   non-critical UDMA control/error codes without beeing in DMA mode and so
+   those messages are not interpreted by the kernel but delivered to the
+   applications instead.
diff --git a/FORK b/FORK
new file mode 100644 (file)
index 0000000..b2bcb30
--- /dev/null
+++ b/FORK
@@ -0,0 +1,63 @@
+Forking cdrtools as cdrkit
+--------------------------
+
+
+So, why the fork? CD/DVD burning is a complicated business that needs a
+lot of knowledge, so forking such a big collection isn't a step to be
+taken lightly. It requires a lot of development effort that could be put to
+better use elsewhere.
+
+In the past, we, the Debian maintainers of cdrtools, had a good and
+mutually cooperative relationship with Jörg Schilling.  He even
+commented on Debian bug reports, which is one of the best things an
+upstream maintainer can do.  Naturally, there were occasionally
+disagreements, but this is normal.
+
+
+Unfortunately Sun then developed the CDDL[1] and Jörg Schilling
+released parts of recent versions of cdrtools under this license.
+The CDDL is incompatible with the GPL.  The FSF itself says that this
+is the case as do people who helped draft the CDDL. One current and
+one former Sun employee visited the annual Debian conference in Mexico
+in 2006. Danese Cooper clearly stated there that the CDDL was
+intentionally modelled on the MPL in order to make it GPL-
+incompatible. For everyone who wants to hear this first-hand, we have
+video from that talk available at [2].
+
+You can read the FSF position about the CDDL at [3]. The thread behind
+[4] contains statements on the issue made by Debian people; for more
+context also see the other mails in that thread.
+In short -  the CDDL has extra restrictions, which the GPL does not
+allow.  Jörg has a different opinion about this and has repeatedly
+stated that the CDDL is not incompatible, interpreting a facial
+expression in the above-mentioned video, calling us liars and generally
+appearing unwilling to consider our concerns (he never replied to the
+parts where we explained why it is incompatible). As he has basically
+ignored what we have said, we have no choice but to fork. While the CDDL
+*may* be a free license, we never questioned if it is free or not, as it
+is not our place to decide this as the Debian cdrtools
+maintainers. However, having been approved by OSI doesn't mean it's ok
+for any usage, as Jörg unfortunately seems to assume. There are several
+OSI-approved licenses that are GPL-incompatible and CDDL is one of
+them. That is and always was our point.
+
+
+For our fork we used the last GPL-licensed version of the program code
+from Cdrtools [5] and killed the incompatibly licensed build system. It
+is now replaced by a cmake system, and the whole source we distribute
+should be free of other incompatibilities, as to the best of our current
+knowledge.
+
+
+Anyone who wants to help with this fork, particularly developers of
+other distributions, is welcome to join our efforts. You can contact us
+on IRC, server irc.oftc.net, channel #debburn, or via mail at
+debburn-devel@lists.alioth.debian.org. Our svn repository is
+http://svn.debian.org/wsvn/debburn.
+
+
+[1] http://www.opensource.org/licenses/cddl1.php
+[2] http://meetings-archive.debian.net/pub/debian-meetings/2006/debconf6/theora-small/2006-05-14/tower/OpenSolaris_Java_and_Debian-Simon_Phipps__Alvaro_Lopez_Ortega.ogg
+[3] http://www.gnu.org/licenses/license-list.html
+[4] http://lists.debian.org/debian-devel/2006/08/msg00552.html
+[5] Cdrtools 2.01.01a08 from May 2006, http://cdrecord.berlios.de
diff --git a/INSTALL b/INSTALL
new file mode 100644 (file)
index 0000000..1e30812
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,66 @@
+
+Short overview for those who don't read manuals:
+
+This software is compiled to binary form using a build system based on the
+CMake framework. Therefore, the requirements to build this package are:
+
+ - cmake 2.4.3 or newer (available from http://www.cmake.org or maybe as a
+   package in your Linux distribution)
+ - GNU make
+ - working GCC compiler environment
+ - maybe additional requirements for your operating system, see
+   doc/platforms/... and FAQ.
+   Recommended: glibc (Linux standard) or GNU libiconv
+
+COMPILATION:
+
+Run: make
+
+INSTALLATION:
+
+Run: make install
+
+To customize the target paths, some variables can be appended to this line:
+PREFIX=/opt/cdrkit/latest (default: CMake preset, e.g. /usr/local)
+MANSUBDIR=man (default: share/man)
+
+TROUBLESHOOTING:
+
+Problem: Linking error.
+Solution: Look for missing dependencies. If you installed additional libraries
+in non-system paths, they may have a conflict with the system libraries which
+are already installed. Make sure that the linker gets the right ones, those
+that belong to the headers. For example, if you installed libmagic and libiconv
+into /usr/local/{include,lib} and your compiler or linker have different
+defaults (eg. they use /usr/lib, /usr/include or intermix them), then you can
+set CFLAGS and LDFLAGS vars to override the system defaults, assumed by cmake.
+Example: 
+(AIX5l, /usr/lib is default lib dir but /usr/local/include is preferred by gcc
+for headers), command:
+    make clean
+    make CFLAGS=-I/usr/local/include LDFLAGS=-L/usr/local/lib
+(cleaning is important to rerun tests. Alternatively, remove build/CMakeCache*)
+
+Problem: Library not found
+Solution: Install the library and its development files. Depending on the
+system distribution they can be shipped in different packages. Install them
+all and make sure that the development files match the version of the main
+library package.
+
+Problem: Library not found during configuration though it's installed
+Solution: Install the development files, see above for details.
+
+Problem: Library not found though it's installed with dev files
+Solution: Install the development files, see above for details. If you use
+non-standard paths not known/searched by Cmake and/or your compiler, pass the
+location of the headers in CFLAGS and the libraries via LDFLAGS. See examples
+above.
+
+Problem: None of those hints helps
+Solution: Examine the following files:
+    build/CMakeFiles/CMakeFiles/CMakeOutput.log
+    build/CMakeFiles/CMakeOutput.log
+and look for failed commands. Some checks are expected to fail if the platform
+does not provide a certain feature, others must not fail. Look the failing
+check and use THE FORCE to find related problems and solutions.
+
diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..6b24226
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,72 @@
+ifneq ($(CFLAGS),)
+CMAKETWEAKS += ( cd build ; cmake .. -DCMAKE_C_FLAGS="$(CFLAGS)" ) || exit 1; 
+endif
+
+ifneq ($(LDFLAGS),)
+CMAKETWEAKS += (cd build ; cmake .. -DCMAKE_EXE_LINKER_FLAGS:STRING="$(LDFLAGS)" -DCMAKE_MODULE_LINKER_FLAGS:STRING="$(LDFLAGS)" -DCMAKE_SHARED_LINKER_FLAGS:STRING="$(LDFLAGS)" ) || exit 1; 
+endif
+
+ifneq ($(PREFIX),)
+CMAKETWEAKS += ( cd build ;  cmake .. -DCMAKE_INSTALL_PREFIX="$(PREFIX)") || exit 1; 
+endif
+
+ifneq ($(MANSUBDIR),)
+CMAKETWEAKS += ( cd build ;  cmake .. -DMANSUBDIR="$(MANSUBDIR)" ) || exit 1; 
+endif
+
+default_target: all
+
+DISTNAME=cdrkit-$(shell cat VERSION)
+DEBSRCNAME=cdrkit_$(shell cat VERSION | sed -e "s,pre,~pre,").orig.tar.gz
+
+build/Makefile:
+       @-mkdir build 2>/dev/null
+       cd build && cmake ..
+
+cmakepurge:
+       rm -rf install_manifest.txt progress.make CMakeFiles CMakeCache.txt cmake_install.cmake 
+       rm -rf */install_manifest.txt */progress.make */CMakeFiles */CMakeCache.txt */cmake_install.cmake 
+       rm -rf */*/install_manifest.txt */*/progress.make */*/CMakeFiles */*/CMakeCache.txt */*/cmake_install.cmake 
+       rm */Makefile */*/Makefile
+
+clean:
+       rm -rf build
+
+tarball:
+#      if test "$(shell svn status | grep -v -i make)" ; then echo Uncommited files found. Run \"svn status\" to display them. ; exit 1 ; fi
+       @if test -f ../$(DISTNAME).tar.gz ; then echo ../$(DISTNAME).tar.gz exists, not overwritting ; exit 1; fi
+       -svn up
+       rm -rf tmp
+       mkdir tmp
+       svn export . tmp/$(DISTNAME)
+       rm -rf tmp/$(DISTNAME)/debian
+       tar -f - -c -C tmp $(DISTNAME) | gzip -9 > ../$(DISTNAME).tar.gz
+       rm -rf tmp
+       test -e /etc/debian_version && ln -f ../$(DISTNAME).tar.gz ../$(DEBSRCNAME) || true
+       test -e ../tarballs && ln -f ../$(DISTNAME).tar.gz ../tarballs/$(DEBSRCNAME) || true
+
+tarball-remove:
+       rm -f ../$(DISTNAME).tar.gz ../tarballs/$(DEBSRCNAME) ../$(DEBSRCNAME)
+
+SVNBASE=$(shell svn info | grep URL: | cut -f2 -d' ' | xargs dirname)
+release: tarball
+       svn ci
+       svn cp $(SVNBASE)/trunk $(SVNBASE)/tags/release_$(shell cat VERSION)
+
+#%::
+#      $(MAKE) $(MAKE_FLAGS) build/Makefile
+#      $(CMAKETWEAKS)
+#      $(MAKE) -C build $(MAKE_FLAGS) $@
+
+# needs to be explicite, for PHONY and install (AKA INSTALL) file on cygwin
+install: build/Makefile
+       $(CMAKETWEAKS)
+       $(MAKE) -C build $(MAKE_FLAGS) $@
+
+all: build/Makefile
+       $(CMAKETWEAKS)
+       $(MAKE) -C build $(MAKE_FLAGS) $@
+
+.PHONY: install all
+
+
diff --git a/START b/START
new file mode 100644 (file)
index 0000000..647b5da
--- /dev/null
+++ b/START
@@ -0,0 +1,2 @@
+build/mkisofs/mkisofs -r -J -o /tmp/cd.iso . 
+build/wodim/wodim -dummy -v speed=24 dev=/dev/cdrw /tmp/cd.iso
diff --git a/TODO b/TODO
new file mode 100644 (file)
index 0000000..48acd53
--- /dev/null
+++ b/TODO
@@ -0,0 +1,50 @@
+
+ - on various places in drv_dvd.c, check for the correct answer ("long write in
+   progress" and friends) instead of using the dumb wait_unit_ready method.
+
+ - (for consideration) similar got natname management in libusal, add a method
+   to check whether the device can be opened without side effects (for safety)
+   and then get the device capabilities to select the best drive for the input
+   size. Kind of generic implementation of the Linux specific guessing code.
+
+ - look for alternative ways to find the maximum DMA transfer size, Schilling
+   wrote something about SKGETSIZE ioctl being fixed in recent Linux kernel
+   versions
+
+ - wrong buffer size displayed with MMC5 DVD recorders, works with -prcap
+   though. Find a way to get the real one when printing status.
+ - check OpenBSD issues with OSS libs
+
+ - fix the multi-file in cuefile support at all. First idea:
+   import libcuefile from on cuetools-1.3.1/src/lib (after generating the
+   parser with its build system), add CMakeLists.txt, drop cue.c and make wodim
+   make use of the parsed CUE data if available.
+   But be warned, JS said something about bugs in cuetools code, a proper test
+   suite is required. I doubt he will share his test cases.
+
+   Maybe even do it properly and create a track writting strategy preprocessor
+   module which could be feeded from cue/toc or from CLI options.
+   But OTOH this is similar to what libburnia is going to make real, spare time
+   is better invested there.
+
+ - Scale the command timeout with the recommended WRITE command minimum wait
+   time? See Pioneer specs from DVR-111 for details.
+
+ - check the REMOTE method, especially with real device names and ssh.
+   Something is going wrong.
+   OR
+   Stop supporting it, add a warning to libusal (scsi-remote.c or so) to not
+   use it, add an appropriate comment to a BUGS file
+ - check libparanoia, we may link dynamicaly with it. Quality? Portability?
+ - check notes in help output, drop advisories, notes about future plans...
+ - find out why spawn.c breaks in WAIT_H while the WAIT_UNION check works quite
+   well on sys/wait.h. See include/CMakeLists.txt comments.
+ - wodim -audio wavefile thesamewavefile thesamewavefile fails with obscure
+   symptoms. Why? See .cue file problems above for that topic.
+ - make some deflt.h functions inline, use a define wrapper INLINE which is set
+   empty if the compiler does not support it
+ - review the sort/uniq code in dvd_file.c, see comments there
+ - implement -stream-file-name properly. Then close #157962
+
+
diff --git a/VERSION b/VERSION
new file mode 100644 (file)
index 0000000..9ee1f78
--- /dev/null
+++ b/VERSION
@@ -0,0 +1 @@
+1.1.11
diff --git a/doc/ANNOUNCEMENTs/AN-2.0 b/doc/ANNOUNCEMENTs/AN-2.0
new file mode 100644 (file)
index 0000000..c504298
--- /dev/null
@@ -0,0 +1,1607 @@
+NEW features of cdrtools-2.0:
+
+Please have a look at the German open Source Center BerliOS at www.berlios.de
+BerliOS will continue to support free hosting of cryptography projects even
+when US laws change and don't allow to host cryptography projects in the USA.
+Also look at sourcewell.berlios.de, the first Open Source announcement service
+that itself is implemented as Open Source project.
+
+***************** Important news ****************************
+
+For the 'Slottable Source Plugin Module' SSPM Features read README.SSPM
+
+***************** Please Test *********************************
+
+All:
+
+-      Now using the "Slottable Source" feature of the makefile system.
+       This is the fist modular reusable portable makefile standard
+       in the open source world.
+
+       To see a new feature call: "make tinfo"
+
+-      config.sub now recognises "parisc-unknown-linux-gnu"
+
+-      Circumvent some problems with GCC-3.0 on Linux
+
+-      Removed printf() definitions from schily.h to avoid type clashes
+
+-      Support for SCO (Caldera) OpenUNIX (aka. UnixWare 8)
+
+-      Better support for Darwin-1.3 and 1.4
+
+       This is:
+
+       -       enhanced makefile system
+
+       -       type casts needed for unusual types used on Darwin
+               (e.g. sizeof() returns long!)
+
+-      Schily support includefiles rearranged to make portability even 
+       easier.
+
+-      mconfig.h now defines IS_SCHILY to signal users of the
+       Schily makefilesystem, that the Schily portability environment
+       is being used.
+
+-      now includes the forgotten mkdep-sco.sh that helps to better
+       work around the SCO C-compiler.
+       
+-      timedefs.h modified. Now the last schily portability support include
+       file hast been reworked to make portability even much easier.
+
+-      schily.h & standard.h have been modified to hopefully finally solve
+       all type clash problems with size_t & spawn*()
+
+-      Compile support for QNX Neutrino
+
+-      Now we hopefully have floating point support for _all_ platforms
+       even those without *cvt() and without __dtoa(). Thanks to a hint
+       from Thomas Langer <Langer.Thomas@gmx.net> we now use strtod.c
+       to gert a fallback __dtoa()
+
+-      Added an autoconf test for rcmd() so cdrtools now should compile 
+       again on BeOS and AmigaOS where no rcmd() is present.
+
+-      fixed fexec.c to make it compile ion QNX
+
+-      Now the complete libschily is included although it it not needed
+       for cdrtools. There are two reasons for doing this:
+
+       -       Cdrtools is _the_ program that is heavily tested on
+               many different platforms, so I will get reports for
+               compile problems this way.
+
+       -       cdrtools becomes a base docking platform for the SSPM
+               system this way. Now any of the Schily tools may be included
+               and compiled inside the base portability platform 'cdrtools'.
+
+-      New supported architctures:
+               s390-linux-cc.rul parisc-linux-cc.rul parisc64-linux-cc.rul
+
+-      Large File support for IRIX-6.2 (added autoconf test for -n32 cc option)
+
+-      Large File support for IRIX-6.5 now everything works correctly if the
+       OS supports Large Files by default in 32 bit mode (uses fseeko()/ftello()
+       if present. This could only be done by massively changing the autoconf code
+       stolen from GNUtar.
+
+-      Support for SGI IRIX platform ip17-irix
+
+-      Support for SGI IRIX-6.5
+
+-      Try to support recent BeOS (again)
+
+       -       Workaround in libschily/comerr.c for the nonstandard 
+               big negative errno values on BeOS
+
+-      libschily now includes floating point printf() for BeOS 
+
+-      fileluopen.c from libschily now compiles on BeOS (without O_NDELAY)
+
+-      workaround for the nonstandard negative errno values on BeOS
+
+-      Schily makefile RULES for AmigaOS added
+
+-      getpagesize() emulation for BeOS to make cdda2wav compile on BeOS
+
+-      New rule allows automatic fallback to GCC if the configured
+       default compiler could not be found.
+
+-      statdefs.h enhanced
+
+-      Many corrections to give less warnings on SCO Openserver
+
+-      Support for NT-5.1 (WIN XP) added os-cygwin_nt-5.1.id
+
+-      VMS script build_all.com now includes astoll.c so compilation
+       on VMS should work again.
+
+-      New macros for max/min values of int*_t in utypes.h
+
+-      Limit the different handling of packed bitfields for AIX to AIX CC.
+
+-      Unfortunately fragementation of cdrecord has begun.
+       I noticed this fact recently when people started to ask me
+       senseless things which turned out to be a result of
+       a modified cdrtools source that I have not ben aware of.
+
+       One main goal of cdrtools is to provide a platform indepenant
+       user interface which cannot be achieved if people change important
+       parts os the user interface. 
+       For this reason, I changed the license in hope that this will
+       help at least to keep the user interface the same on all
+       platforms and on all distributions.
+
+       Please keep in mind that fragmentation in many cases increases
+       my workload. There is no real reason for a modification,
+       and (even worse) the people who create modifications do not help
+       to keep my workload low in order to help me (and Heiko and James)
+       with the cdrtools project. People should rather contribute to
+       the project. Cdrtools should be free and actively mantained
+       in future. With increasing workload, I don't know how to do this.
+
+
+-      Add hints that compiling on unknown platforms wil only work if
+       "smake" is used.
+
+-      Autoconf code for Large file support now handles Linux system include
+       file bugs that prevented correct behavior on 64 Bit Linux systems.
+
+
+-      Better autoconf code for the problems with mlock() & HP-UX-10.20 
+
+-      Better autocheck code for available C-compilers on HP-UX
+       Now even a fallback from GCC to CC works.
+
+-      Some changes to make compilation on 64 bit systems more correct
+
+-      Added support for GNU Hurd to the Schily Makefilesystem
+
+-      Cast pointerdiffs to int for printf() %.*s format and/or include
+       workarounds for 64 bit problems in this area.
+       
+-      Several modifications to make OS/2 work again
+       (e.g. -lsocket added)
+
+-      fexec.c now uses a configurable PATH environment separator
+       to allow PATH lookup on OS/2
+
+-      A 20 year old extension has been removed from format.c
+       This caused printf() to interpret %X as %lX. This caused noticable
+       problems on IA-64. It should have created problems on True64
+       and on 64 bit Sparc programs too but was not directly visible
+       due to a different stack content.
+       
+-      remove #elif to avoid a GCC-3.x warning
+
+-      config.sub now knows about IA64 architecture
+
+-      Makefilesystem now spports compiler specific optimization flags
+
+-      Align_test.c now creates a better include file (using more () to
+       make sure the compiler created correct code).
+
+-      Makefilesystem changed $(MAKE) to "$(MAKE)" to allow spaces
+       in pathnames
+
+-      Correct autoconf test for broken OS like MAC OS X that do not
+       allow local malloc() implementations due to linker bugs.
+
+-      Add autoconf test for strange clock_t definition method on Linux
+
+-      README.ATAPI enhanced for all platforms
+
+-      README.ATAPI now contains a hint on how to use ATAPI drives on HP-UX-11.x
+
+-      Support for FreeBSD on Ultrasparc added to the makefile system
+
+-      *roff'd man pages in .../doc dir re-created
+
+-      Try to work around a bug in OpenBSD.
+       OpenBSD defines EOF in ctype.h but POSIX only mentions an EOF definition
+       for stdio.h. If we include ctype.h bfore schily.h on OpenBSD while
+       stdio.h has not been included, this will fail.
+
+/*--------------------------------------------------------------------------*/
+
+Libparanoia (Ported by Jörg Schilling, originated by Monty xiphmont@mit.edu):
+
+-      The paranoia code from cdparanoia (written by Monty xiphmont@mit.edu)
+       has been converted into a portable library.
+
+/*--------------------------------------------------------------------------*/
+
+Libedc (Optimized by Jörg Schilling, originated by Heiko Eißfeldt heiko@hexco.de):
+
+-      Changed to allow compilation on K&R compilers too
+
+-      Speedup by 300%
+       The speedup is nearly processor independant.
+
+       Pentium-233             2443 sectors/s   32x
+       333Mhz-UltraSparc-IIi   6402 sectors/s   85x
+       900Mhz-UltraSparc-III+  22813 sectors/s 304x
+       Athlon-1000             24378 sectors/s 325x
+       Athlon-1700             40168 sectors/s 535x
+
+       Depending on the speed of gettimeofday(), these numbers may be up to 5%
+       too low.
+
+-      Code is now put under GPL.
+
+/*--------------------------------------------------------------------------*/
+
+Libscg:
+
+-      Trying to add a workaround for just another bug in the
+       sg driver in the Linux kernel. If a TIMEOUT occurs, 
+       the error code does not indicate a TIMEOUT.
+
+-      Better scg_open() error messages when trying to do scanbus on Linux
+       and no /dev/sg* or /dev/pg* could be opened.
+
+-      Output Request Sense buffer with -debug when the USCSI interface is
+       used on Solaris.
+
+-      First attempt for support for the new IOKit SCSI interface on MaxOS X
+       Darwin-1.4 and newer with much much help from
+       Constantine Sapuntzakis  <csapuntz@Stanford.EDU>
+
+       Unfortunately there is not yet support for SCSI devices nor
+       is there support for standard Bus,Target,Lun device namings.
+       I hope that bot may be added in the future.
+
+       Volunteers who like to help with the libscg interface stuff
+       for Darwin-1.4 are welcome.
+
+-      Try to make scsi-beos.c compile on new BeOS version 5
+
+-      First attempt to integrate the AmigaOS SCSI transport interface code
+       from Thomas Langer <Langer.Thomas@gmx.net>
+
+-      Massive modicifation of the support code for SCO OpenServer 5.x
+
+       As the kernel implementation contains several bugs, 
+       the new code will by default not check for hard disks in scan mode.
+       
+       The code checks the following environment variables:
+
+       "LIBSCG_SCAN_ALL"       To force scanning for all SCSI targets.
+       "LIBSCG_SCSIUSERCMD"    use old SCSIUSERCMD ioctl()
+       "LIBSCG_MAX_DMA"        override MAX_DMA value, value must be number in kB
+       "LIBSCG_ENABLE_USB"     enable access of USB devices
+
+-      Version -> 0.6
+
+-      Adding support for the CDROM_SEND_PACKET ioctl() from cdrom.c
+
+       Thanks to Alexander Kern <alex.kern@gmx.de> for the idea and first 
+       code fragments for supporting the CDROM_SEND_PACKET ioctl() from 
+       the cdrom.c kernel driver. Please note that this interface in principle 
+       is completely unneeded but the Linux kernel is just a cluster of 
+       code and does not support planned orthogonal interface systems. 
+       For this reason we need CDROM_SEND_PACKET in order to work around a 
+       bug in the linux kernel that prevents to use PCATA drives because 
+       the kernel panics if you try to put ide-scsi on top of the PCATA 
+       driver. 
+
+       The code is currently in "status nascendi" but usable with some trade offs.
+
+       To use: call e.g.
+
+               cdrecord -scanbus dev=ATAPI:
+
+               cdrecord -dao -v speed=24 dev=ATAPI:0,0 ....
+
+       Be careful! This code is only needed in order to be able to use
+       PCATA CD-writers on notebooks because there is a severe kernel bug.
+       Unfortunately, this bug causes the kernel to hang (and force you
+       to reboot) if you try to call:
+
+               cdrecord -scanbus
+
+       without the dev=ATAPI: option. 
+
+       In this case cdrecord will hang infintely and unkillable 
+       in open("/dev/sg1", 2) => you need to reboot :-(
+
+       Repeat by: Insert a PCATA CD-Writer in a Sony VAIO notebook and run
+                       cdrecord -scanbus. 
+
+-      Enhanced list of SCSI Error texts from SCSI standard from 29.5.2001
+
+-      New callback function to allow execption handling to be done after
+       the current SCSI command did finish.
+
+-      scsi-aix.c now uses UIntptr_t in alignement macro.
+
+-      Some 64 bit casts in the USCSI code from scsi-sun.c
+
+       For hints on the Linux Packet code in ide-cdrom.c read README.ATAPI
+
+-      Introduce a workaround for a conceptional Bug in the Linux kernel 
+       SCSI implementation.
+
+       Linux is unable to distinct between a target selection timeut (e.g. switched
+       off target) and a command timeout (e.g. command needs more time than expected).
+
+       If the detected command time is < 1 second, libscg will now assume a dead target.
+
+-      Fix a bug with ATAPI in scsi-vms.c - now the SCSI status byte is OK
+       Thanks To Eberhard Heuser
+
+-      Allow up to 26 IDE controlers in scsi-vms.c - Thanks to Chip Dancy
+
+-      Do not open all /dev/scg* devices on Solaris if not in Scanbus mode
+
+-      Handle ENXIO in Solaris USCSI interface code as indicator for a 
+       switched off device.
+
+-      Max DMA size for Linux ATAPI Packet interface code corrected.
+       Max DMA is 128k-1 and not 128k.
+
+-      Support for recently defined new SCSI target types found in SCSI
+       standard.
+
+-      New help system that lists all SCSI low level transports for a specific
+       platform together with their properties.
+
+-      Allow consistent usage of alternate SCSI transport layers.
+
+       Now the Solaris USCSI implementation and the (SuSE) Linux ATA implementation
+       behave similar and both allow dev=<Transport> as well as dev=<Transport>:
+       for -scanbus, e.g.
+
+       cdrecord dev=USCSI -scanbus
+       cdrecord dev=USCSI: -scanbus
+       cdrecord dev=ATAPI -scanbus
+       cdrecord dev=ATAPI: -scanbus
+
+       all work the same way.
+
+-      Small change for Linux device initialization by request of Linus Torvalds
+
+       The purpose of this change is to support a new SCSI transport interface
+       for ATAPI in Linux that came up with the latest developer Linux kernels
+       (e.g. Linux-2.5.43). This interface allows to send SCSI commands directly
+       to ATAPI drives without using ide-scsi and sg, but it has several pitfalls.
+
+       While Linux allows to use DMA when using ide-scsi and sg if the
+       sector size is 2048 and the transfer buffer starts page aligned, the new
+       direct interface never uses DMA (acording to Linus Torvalds). So if you 
+       write audio CDs or data CDs in RAW mode, there is no difference. If you
+       write data CDs in TAO or DAO mode, using ide-scsi and sg allows much
+       higher write speed. Note that this may change in future....
+
+       Notes for use:
+
+       -       You need to specify something like dev=/dev/hdc
+               Note that this is unsupported by libscg.
+
+       -       As long as there is no safe way for libscg to find out early that
+               this new interface is used, libscg may hang a bit on open.
+               This is caused by the fact that libscg is forced to read 
+               from the open filedscriptor to clean up old Linux sg driver
+               interfaces. This was never a problem with /dev/sg*, but 
+               when doing the same thing, this causes libscg to read content
+               from /dev/hd*
+
+       -       There is (currently) no way for cdrecord to scan for ATAPI
+               devices when using this interface.
+
+               As long as this is true, you may want to prefer to use
+
+               cdrecord dev=ATAPI: -scanbus
+               and
+               cdrecord dev=ATAPI:0,0 ...
+               instead.
+
+-      Fix scsi-unixware.c to allow multiple opens.
+
+-      Fixed several typo's.
+
+-      Avoid to read from the media (when using the new experimental
+       Linux ATAPI transport) while trying to clear old sg driver status.
+
+-      Woraround for Linux kernel design bug: CDROM_SEND_PACKET sets errno 
+       to EINVAL in case SCSI sense key is "Invalid command".
+
+/*--------------------------------------------------------------------------*/
+
+Rscsi:
+
+-      RSCSI now works if the target is a Win32 system.
+       This is not done by changing rscsi.c but by fixing a bug
+       in Cygwin!
+
+       The fix to Cygwin's rshd is posted in
+
+               http://sources.redhat.com/ml/cygwin-apps/2001-05/msg00000.html 
+
+       Thanks to  egor duda <deo@logos-m.ru>
+
+       NOTE that in a few weeks this patch will be integrated into Cygwin
+       and cdrecord/RSCSI will work out of the box on a recent Cygwin release.
+
+-      Now prints user ID & user Name into DEBUG file
+
+-      Now using signal safe read/write functions.
+
+-      Code now checks for HAVE_NETDB_H (added by request of
+       "Thomas" <Langer.Thomas@gmx.de> to help with AmigaOS port)
+       This should indicate whether there is support for rcmd()
+       in the OS.
+
+-      Make it compile on BeOS
+
+-      changed because GNU Hurd has no MAXHOSTNAMELEN
+
+-      Return "PIPE" for hostname comparison if called from e.g. 'sshd'.
+
+/*--------------------------------------------------------------------------*/
+
+Cdrecord:
+
+-      New option -overburn
+
+       This option has been added as many people seem to be unabe to understand
+       that they are going to write more than the official disk capacity from
+       reading cdrecord's output. Oveburnung now is no more done by default!
+
+       NOTE that there even are some drives that prevent you from writing
+       exactly the official size and stop several hundreds of sectors before.
+
+-      Do not print a warning for writing more than 90 minutes if the media is
+       a DVD
+
+-      Fix for a problem with setting high priority on Win32 systems.
+       Thanks to  egor duda <deo@logos-m.ru>
+
+-      Sony MMC drives now work in -multi session mode.
+       There was a bug in cdrecord that was accepted by all other drives.
+       The bug did cause a temporary bad setup to the drive.
+
+-      I hope that the 90 minute CD capacity warning now will finally
+       disappear for DVD writers.
+
+-      Old test code removed that prevented cdrecord from being able
+       to write manually configured indices. Note that the index lists
+       from the *.inf files with using the -useinfo option alway worked.
+
+-      -force will force cdrecord to ingnore any failed forced OPC.
+       currently this is only done if the drive does not support 
+       forced OPC.
+
+-      Do forced OPC before blanking a CD-RW
+
+-      Driveropts "burnproof" renamed to "burnfree".
+       This  has been done as this technology now appears in the MMC standard.
+
+-      Cdrecord now shows whether BURN-Free is active. This makes
+       sense as Ricoh's "Just-Link" is enabled by default.
+       Unfortunately, the way "Just-link" is implemented is not compliant
+       with the MMC standard. We will have to wait until I get the needed
+       information from Ricoh.
+
+-      Support for MMC RAW mode writing.
+
+       This allows to do disk at once recording on Philips drives that
+       do not support SAO.
+
+       You may write audio tracks in RAW mode. There are some new
+       and most likely transient options:
+
+       -raw16          Write 2352 Bytes sectors + P+Q Subchannel
+
+       -raw96r         Write 2352 Bytes sectors + P+W Subchannel (R-W in raw mode)
+
+       -raw96p         Write 2352 Bytes sectors + P+W Subchannel (R-W in packed mode)
+
+       Indices are fully supported in RAW mode.
+
+       MCN & ISRC are not yet suported in RAW mode, they are silently discarded.
+
+       I know that cdrecord currently does not work in RAW/R96P mode.
+       It is not clear whether this is a bug in cdrecord or in the Plextor
+       firmware as I did not yet found another drive that claimes to support
+       RAW7R96P.
+
+       If you find other problems in RAW mode or if you find
+       new bugs introduced in old write modes, please send a bug report.
+
+-      Cdrecord now checks the properties of the writer. If a specific write
+       mode is not supported by the writer, cdrecord warns you and makes
+       a suggestion for a similar alternate write mode.
+
+       With the curent structure of cdrecord, it is not possible to silently
+       e.g. change the write mode from -dao to -raw96r
+
+-      MMC compliant drives are automatically scanned for supported write modes.
+       This should help to make cdrecord work without manual static configuration.
+       My hope is still to have no need to know all drive properties in 
+       advance, so new drives will continue to work as long as they
+       are standard comliant enough for cdrecord.
+
+       NOTE for GUI implementors:
+
+       the line starting with the text:
+
+               "Checking possible write modes:"
+
+       will go away in the near future.
+
+       The line starting with:
+
+               "Supported modes:"
+
+       will remain and should be checked for possible write modes.
+       
+-      Fixed a bug in the option checking that prevented to write
+       data CD's at all.
+
+       Now only "RAW data" CD's are flagged as expected.
+
+-      Fixed a bug in the Firmware bug recognition system.
+       This bug did prevent cdrecord to work with Philips drives
+       when writing in RAW mode.
+
+-      New options -copy & -nocopy to allow to modify the 'copy' bit
+       in audio subchannel data.
+
+-      -scms option added to the man page and online help.
+
+-      New model to compute SCSI transfersizes
+
+-      -xa1 -xa2 sector typedefinitions changed.
+
+-      Debug messages while checking possible write modes of MMC
+       compliant made optional.
+
+-      RAW writing scatter sector function made more general
+
+-      New functions to convert between 2448 and 2368 byte sectors
+
+       NOTE: Read README.raw
+
+-      add a forgotten if (xdebug) in drv_mmc.c.
+       This caused a superfluous write mode debug message to be printed
+
+-      do installation of exit handlers (to reset SCSI state) earlier
+
+-      Cdrecord now does not exit with 0 anymore when interrupted with ^C
+       during the waittime before starting to write.
+
+-      First CD-Text support (can only copy CD-Text information from master
+       disk)
+
+       Writing of CD-Text is supported for all drives that support
+       CD-Text in SAO write mode and for all drives that support
+       to write in RAW/RAW96R mode (use -raw96r in this case).
+
+       NOTE: Read README.cdtext
+
+-      Circumvent a bug in the system include files from Linux that
+       makes printf() a macro and prevented compilation with GCC-3.0
+
+-      Added some #include <stdio.h> to substitute missing printf() definitions
+
+-      SAO/R16 mode removed from tests, it may never occur.
+
+-      Changed some .min defines in structs to .pmin to avoid K&R complier
+       problems
+
+-      better FIFO debug messages
+
+-      New driver config table for Taiyo Yuden EW-50.
+       This dive is like a Philips CDD-521 but has been reported to
+       swab audio data.
+
+-      rscsi client code now uses buffered read to speed up on Cygwin
+
+-      rscsi client code now uses signal safe read/write functions
+
+-      Cdrecod now does not open/close the tray anymore if the disk
+       is going to be erased.
+
+-      modify -version output if Clone writing support is present
+
+-      A new driver has been added that first checks the media if the drive
+       supports to write CD & DVD.
+
+-      Behaviour of the function that reads fs= tsize= and similar
+       corrected.
+
+-      Modified driver interface for better DVD support
+
+-      FIFO Code now checks for HAVE_FORK (added by request of
+       "Thomas" <Langer.Thomas@gmx.de> to help with AmigaOS port)
+
+-      Better messages when trying to write more than the amount of data
+       that fits on a DVD.
+
+-      The DVD driver now reports a DVD media back to the high level code.
+
+-      correctly use the buffer capacity code from the driver instead
+       of the MMC-2 read buffer cap code directly
+
+-      Support for the unusual not ready error code of the CyberDrive CW038D
+
+-      CD-Text Code now also accepts Text File without 4 byte Size header
+
+-      CD-Text file read code now is able to do CRC error correction
+       Note that only songle bit errors per 18 byte pack.
+
+-      CD-text Autoring support:
+
+       CD-text may now be based on fields found in the *.inf files
+       created by cdda2wav.
+
+       To create a CD with CD-Text based on information from freedb.org
+       call:
+
+       1)      cdda2wav -B -v255 -L
+       2)      cdrecord {-dao!-raw96r} -v -useinfo -text *.wav
+
+       CD-text TODO:
+
+       -       Check whether the *.inf files are all from the same CD
+               and clear some CD-text fields that are only valid if
+               they relate to one CD only.
+
+       -       Add some more fields (mainly a dficiency of cdda2wav)
+
+       -       Support multi language text
+
+       -       Support character coding other than ISO-9959-1
+
+       CD-text may be based on fields found in the *.inf files
+       created by cdda2wav.
+
+       NOTE: Read README.cdtext
+
+-      better messages for CD manufacturer codes that are not in the
+       latest free Orange forum table.
+
+-      Default usage code is now only 6 lines so the error message
+       does no longer scroll out the screen. If yu like to get the old
+       long usage information, call cdrecord -help
+
+-      move 'dd' like number conversion stuff into getnum.c
+
+-      Allow the /etc/default/cdrecord parsing code to be used by
+       readcd too (as documented in the man page)
+
+-      First support for Plextor's VariRec feature in the PX-W4012
+       I am not sure about the final user interface.
+       For now, call e.g. cdrecord speed=4 driveropts=varirec=-1
+       for all audio CDs. Allowed varirec parameters are -2, -1, 0, 1, 2
+       VariRec only works at write speed 4.
+
+-      Print the actual current write speed in verbose mode.
+
+-      DVD-R code (undisclosed) now supports:
+               Vendor_info    : 'MATSHITA' 
+               Identifikation : 'DVD-RAM LF-D310 ' 
+               Revision       : 'A116' 
+
+-      Support for SCMS from *.inf files
+       Note that you need to use cdda2wav/cdrecord that have fitting versions
+       because of this change. Otherwise cdrecord may add SCMS copy 
+       protection.
+
+-      RAW mode now honors COPY bit and SCMS coding.
+
+-      Avoid coredump with "cdrecord textfile= non/existant ..."
+
+-      Corrected printf() formats for verbose printing to hold enough
+       space for media > 1 GB (DVD)
+
+-      Corrected printf() formats to make the write speed non-jumping.
+
+-      If called from a GUI, cdrecord now reads from "stderr" if
+       the CD-input-data is from "stdin".
+       If it turns out that stderr is not open for reading, cdrecord
+       waits to receive a SIGUSR1
+
+-      Better printouts for the DISC-ids covered by the orange forum embargo.
+
+-      DVD structure structure definition enhanced to reflect
+       current standard.
+
+-      new option gracetime=
+
+-      Try to abort DAO recording with a flush_buffer() if ^C is hit.
+
+-      Try to make cdrecord behave more polite for platforms (like Cygwin)
+       that don't support large files when the DVD data to be written
+       is read from stdin.
+
+       mkisofs ... | cdrecord ... - 
+
+       will now work for DVDs on non large file OS
+
+-      Call flush buffer in silent mode to avoid error messages with
+       cdrecord -toc called on a CD-ROM drive.
+
+-      Avoid core dump is a single .inf file is missing and -text
+       option is used.
+
+-      Data structures modified to allow new features in the future.
+
+-      Fixed a bug that caused cdrecord to ignore escaped file type
+       args if they looked like a valid option (e.g.):
+
+               cdrecord dev=0,0 -dao -v -- speed=8
+
+       "speed=8" should be handled as if it was a filename but was
+       skipped.
+
+-      Print write mode when starting to write.
+       I hope that this helps me to understand incorrect "bug reports"
+       from lazy people who do not include their cdrecord command line.
+
+-      Printing ATIP information is now caused by a separate (internal) flag
+       and not ny a hack.
+
+-      Do not allow to write to ultra low speed RW media if the drive
+       is not able to write at 2x or 1x. This may be circumvented
+       with -force.
+
+-      Do not allow to write to high speed RW media if the drive is not
+       a high speed RW drive. This may be circumvented with -force.
+
+-      Data structures modified to allow new features in the future.
+
+       Trying to make driver interface simpler and cleaner. This resulted
+       in a major rewrite of the driver interface.
+
+       -       please test if multi session with TEAC CDR-50/CDR-55
+               still works.
+
+       As a lot has been changed in the driver interface, please test
+       if bugs have been introduced!
+
+-      New test that prevents to write CD-RW media too slow
+
+-      Display of current DVD write speed now correct and no more based on
+       single speed CD but on single speed DVD.
+
+-      Moving SAO/RAW start code from cdrecord.c into drv_mmc.c
+       allows clean DVD-R/RW driver interface code.
+       Now cdrecord -dao will work correctly (as expected) even for DVDs
+
+-      speed= option no longer defaults to speed=1
+       Each driver now includes a default speed and a maximum speed.
+       If the maximum speed in the driver is wrong, use -force to overwrite.
+
+       Please send feedback if my assumptions on write speed are wrong:
+
+       -       No drive using the Philips CDD-521 command set is faster
+               or slower than 2x
+
+       -       No drive using the Yamaha CDR-100 driver is faster than 4x
+               No drive using the Yamaha CDR-100 driver is slower than 2x
+
+       -       The Tayo Yuden CW-50 is 2x
+
+       -       The Kodak PCD-600 is 6x
+
+-      Abort when the last track # of a multi session disk would be > 99
+
+-      Data structures modified to allow new features in the future.
+
+-      Better bessages for CD-RW where the speed ofthe media does not match
+       the properties of the writer.
+
+-      Avoid to reload media in -dummy RAW mode.
+
+-      Correctly abort if there was a problem when writing CD-Text in the LEAD-IN.
+
+-      Again: Data structures modified to allow new features in the future.
+
+       This release uses the new data structurec to allow to write ISRC/MCN
+       in RAW mode.
+
+-      Fixed a bug that caused cdrecord to write a wrong relative time
+       into the subchannel data when writing audio CDs in RAW mode.
+       This affected the pregap sectors if pregap size was != 0.
+
+-      Allow cdrecord to write ISRC & MCN even in RAW mode.
+
+-      Allow Simulation driver cdr_simul and dvd_simul to simulate any write
+       mode.
+
+-      Simulation driver cdr_simul and dvd_simul changed so no reload on the
+       real background drive occurs.
+
+-      Since last release , the new data structures allow to write
+       ISRC/MCN in RAW mode. This now makes RAW mode fully usable for
+       audio CDs. NOTE: if you find any problems with CDs written in SAO
+       mode, first try to write the same CD in RAW mode if your
+       drive supports to write in RAW mode. Tere are a lot of drives
+       that have rotten firmware and create broken CDs in DAO mode.
+
+-      Support for Yahama Audio Master Quality Recording.
+
+       This support is switched on via driveropts=audiomaster
+
+       I am sorry, but I had to do major changes in the MMC
+       driver in order to be able to support Audio Master.
+       This may have affected all other driveropts= 
+       too. Please test and keep in mind that I like to have 
+       the mext major release in a few weeks.
+
+       When audiomaster has been specified, BURN-Free recording
+       is disabled and - as the visible size of the medium 
+       decreases - a second disk size check is done after 
+       Audio Master has been turned on.
+
+-      man page enhanced according to new features
+
+-      Short Usage funtion now includes a hint on how to
+       obtain the list of possible driveropts= parameters
+
+-      Include the tags 
+
+               "VARIREC ", "AUDIOMASTER ", "FORCESPEED "
+
+       In the "Driver flags" line that is visible with
+
+               cdrecord -checkdrive.
+
+-      cdrecord driveropts=help now includes 
+
+       "varirec=" and "audiomaster"
+
+
+-      Support for writing data sectors in RAW mode has been added
+       to the GPL#ed version of cdrecord.
+       Note that writing data sectors in RAW mode is a highly CPU
+       intense task. For this reason, cdrecord first checks whether
+       it would be possible to do the requested job reliably.
+       If it is questionable whether the job could be done in the
+       desired speed, cdrecord aborts with a related message.
+
+       The max theoretical speed (not including the writing load)
+       is printed in a new line starting with: "Encoding speed :".
+       Cdrecord allows half of this speed.
+
+-      Allow RAW writing of data sectors to work correctly without
+       the need of specifying -data
+
+-      Allow spaces as delimiters between different tags in a single
+       line in the file /etc/default/cdrecord
+
+-      Support for Ricoh (and others) Just Link
+
+       This support is switched on via driveropts=burnfree
+
+       Note that Just Link is by default swichted on in the drive
+       but as Just Link may create CDs that are no 100% OK,
+       cdrecord now by default switches it off. Now you definitely
+       need to specify driveropts=burnfree to switch Just Link on
+       again.
+
+       If you call cdrecord dev=... -checkdrive you will see
+       the TAG "BURNFREE" as a hint that either Burn-Proof or
+       Just Link is supported.
+
+-      "Turning .... " messages for drive special functiions are
+       now printed to stdout
+
+-      Limited display (once every 1 MB) of the drives internal buffer
+       RAM fill ratio.
+
+-      Display the minimal drive buffer fill ratio a the end of the write
+       process.
+
+-      Display number of predicted drive buffer underruns based on the
+       fill ratio of the drive buffer (incremented if fill ratio is < 5%).
+
+-      Display average write speed at the end of the write process.
+       In dao mode, this includes the time needed to write the lead in and
+       thus is not 100& correct (value is too low).
+
+-      Display of the number of times the Buffer underrun protection
+       has been active for drives where the manufacturer send me the needed
+       information (Ricoh, Yamaha, Aopen). It may work for other drives too
+       but there is no guarantee.
+
+-      Fixed a bug in the driveropts= parsing routine.
+
+-      New driveropts= option "forcespeed". Use with extreme care as this
+       will force several drives ((Ricoh, Yamaha, Aopen, ...) to write with
+       the selected high speed although the mediaum is too bad for this
+       operation.
+
+-      New driveropts= option "tattooinfo". Use together with -checkrive 
+       to retrieve the information about the picture size that will fit.
+
+       The result will be someting like:
+
+       DiskT@2 inner r: 265
+       DiskT@2 outer r: 583
+       DiskT@2 image size: 3744 x 318 pixel.
+
+-      New driveropts= option "tattoofile=". Use together with -checkrive 
+       to write an image of the right size to disk.
+
+       Read README.DiskT@2
+
+-      Rearrange the order of the new statistics printing
+
+-      Allow several of the new statistics to be printed even if cdrecord
+       aborts due to an error.
+
+-      Let the old Philips drive use the common CD media 'reload' function.
+
+-      Try to find out if a drive is MMC, MMC-2 or MMC-3 compliant.
+       - see cdrecord -checkdrive
+
+-      Suppress printing oof the average write speed if the size of the
+       tracks is not known prior to start CD writing
+
+-      ATIP printing (cdrecord -atip) enhanced to support Ultra high speed
+       CD-RW media.
+
+-      Check whether somebody likes to write a Ultra high speed CD-RW on
+       an improper writer
+
+-      Print MMC conformance level of the drive based on content of
+       SCSI mode page 2A.
+
+-      Print more information for MMC-2 & MMC-3 drives with cdrecord -prcap
+
+-      The new true CAV Plexwriter 482448 is now supported.
+
+       Please note that it is not easy to write at 48x. You definitely need 
+       a correct DMA setup to optimal values.
+
+       Also note switching on Burn-Proof will reduce the max speed to 40x
+       so it may be that you don't need Burn-Proof if you simply reduce speed
+       to 40x manually
+
+-      make sure that using both -copy and -useinfo will not result in unclear state
+       Instead the content of the *.inf files will be used
+
+-      Simulation driver (cdr_simul / dvd_simul) now uses correct speed ratio
+       for DVDs
+
+-      Simulation driver now supports fake "Next writable address" function.
+
+-      On Linux usleep() is very unacurate, meter the real sleep time
+       and cumulate a correction value. This allows the simulation driver
+       to simulate the correct write speed.
+
+-      Added a note to Heiko Eißfeldt's libedc when printing RAW encoding speed
+
+-      Limit gracetime to 999 seconds and make output correct even for
+       times > 9 seconds.
+
+-      Corrected a bug in the MMC driver that caused cdrecord to use the 
+       wrong place for current speed when doing MMC/MMC-3 dependant stuff
+
+-      cdrecord -prcap will now use the same format for MMC & MMC-3 drives
+       rsulting in a better readability.
+
+-      Don't print write time statistics if writing did not yet start
+
+-      Try to handle drives that don't support to write at speed 1 but
+       will fail if you try to call cdrecord speed=1 ...
+
+-      New option -immed tells cdrecord to set the SCSI "IMMED" flag in certain
+       commands.
+
+       This option is not needed if your PC has been configured correctly.
+       However, ATAPI drives usually cannnot do disconnect/reconnect.
+       As a result, the PC may hang with long lasting commands if the CD-writer
+       has been connected to the same IDE cable as the harddisk. A correct
+       solution would be to set up a correct cabling but there seem to be 
+       notebooks around that have been set up the wrong way by the manufacturer.
+       As it is impossible to fix this problem in notebooks, -immed has been
+       added. Use this option with care and do not expect cdrecord to work
+       correctly if it has been called with -immed.
+
+-      -force will not completely removeany speed restrictions for writing in RAW
+       mode. Instead, only the speed that a single CPU allows will be permitted
+       by cdrecord. This still has a high potential for a buffer underrun.
+       By default cdrecord still is limited to half the encoding speed that
+       a single CPU allows. Even this may result in a buffer underrun on Linux
+       as Linux does not use DMA for IDE when the sector size is != 2048 bytes
+       which is true in RAW write mode.
+
+-      If the environment variable "CDR_FORCERAWSPEED" is set, this will have
+       the same results for RAW speed as using -force. However, -force has more
+       general effects and should be avoided.
+
+-      Fixed a bug in fifo.c introduced with the driver interface change.
+       Now cdrecord compiles again on VMS (without FIFO).
+       Thanks to Eberhard Heuser.
+
+-      Allow cdrecord to compile without libedc
+       Thanks to Eberhard Heuser.
+
+-      Run read buffer capacity in silent mode.
+       This is needed because drives with buggy firmware like the CW-7585
+       did cause hundreds of "command sequence erorrs" to be emmited when 
+       trying to read the current drive buffer fill ratio.
+       
+-      Fixed man page to correctly call SAO mode SAO and not DAO.
+
+-      Encoding speed is contend dependant. Initalize test buffer
+       before doing a libedc speed test to make the result independant
+       from grabage on the stack.
+
+-      Support for libscg help system
+
+-      Warn to use cdrecord blank=all if a drive rejects cdrecord blank=fast
+
+-      Fixed a bug that became obvious with Yamaha AudioMaster mode and CD-Text
+       The problem was caused by the fact that cdrecord did not allow to overwrite
+       the lead in start time in cdrecord's internal data structures.
+
+-      Fixed a bug with recognition of complete disks that came up after cdrecord
+       did allow to deal with >= 90 minute CD's.
+
+-      Changed Text "BURN-Free was not used" to "BURN-Free was never needed" because
+       people did believe that the old text means that Burn-Proof has been disabled.
+
+-      Man page now includes a hint that padsize is always using 2048 as sector size.
+
+-      Fixed a bug with padsize=xxx if sector size was not 2048 bytes.
+       Cdrecord in this case did just divide the number of pad bytes by the
+       number of bytes in an output sized sector (e.g. 2448 or 2352 bytes).
+       This did result in a too low number of padding sectors.
+       The fix caused a complete rewrite of the pad size handling.
+
+-      Treat packet mode similar to normal writing: Print Drive buffer fill ratio 
+       and current write speed.
+
+-      Treat padding similar to normal writing: Print Drive buffer fill ratio and 
+       current write speed.
+
+-      Make verbose printing consistent and non-jumping
+
+-      A new experimental feature of the -immed flag is  to
+       tell  cdrecord  to try to wait short times wile writing
+       to the media. This is expected to free the IDE  bus  if
+       the  CD/DVD writer and the data source are connected to
+       the same IDE cable. In this  case,  the  CD/DVD  writer
+       would  otherwise  usually  block the IDE bus for nearly
+       all the time making it impossible to  fetch  data  from
+       the source drive.
+
+       As this is an experimental feature, I would like to get feedback.
+
+
+-      #ifdef _POSIX_MEMLOCK/_POSIX_PRIORITY_SCHEDULING Tests now 
+       POSIX 2001 compliant
+
+-      Do not try to close fd if running on an OS that does not use an fd
+       to mmap() chared memory from anonymous pages.
+
+-      Print Orange Forum embargo warning only if ATIP minutes == 97
+       because some DVD writer return junk with read ATIP
+
+-      New option minbuf= to choose the mininum drive buffer fill ratio
+       for the ATAPI wait option that is intended to forcibly free the
+       IDE bus to avoid buffer underruns with bad HW configurations.
+       The permitted range is 25..95 for 25%..95% buffer fill ratio.
+
+-      minbuf= may switch on the ATAPI wait option without enabling
+       the SCSI Immed option.
+
+-      Forcibly switch on -v for now if the ATAPI wait option has been
+       selected. This is needed because due to a bug, this option will
+       not work without -v
+
+-      Make FIFO code work on AmigaOS
+
+
+For Yamaha Disk Tatoo features read README.DiskT@2
+
+/*--------------------------------------------------------------------------*/
+
+Cdda2wav (By Heiko Eißfeldt heiko@hexco.de):
+
+-      Changes to make cdda2wav compile better on Alpha/True64
+
+-      Restructured to better use the schily makefile portability structures.
+
+-      Changed handling of Table of contents. Now the more informative
+       methods of Read full toc are being used in favor to the old SCSI readtoc
+       command. For Sony methods, the fallback is the old method.
+       The new methods are available on MMC drives and modern drives with
+       Sony command sets. It should enhance access to very weird multi session
+       cds.
+
+       **************
+       NOTE: If your drive still has problems to copy such non-CD's, there
+       is a simple hack to allow the disk to be copied on all drives:
+
+       Use a (black) whiteboard pen (non-permanent) and paint on the
+       space directly outside the visible ring that is in the middle 
+       of the non-CD. This is the space where the broken TOC from the
+       second session is located.
+
+       After doing the copy please return the disk to the dealer and
+       tell the dealer that this is broken goods. This is the only way
+       to stop the big groups to defraud the customers.
+       *************
+
+-      Temporary hack to fix a bug in the ISRC code that caused the ISRC
+       string to be shortened by one character.
+
+-      fixed ioctl handling of toc entries
+
+-      checked ISRC retrieval (MMC + Plextor)
+
+-      more checking for weird CDs with wrong track types
+
+-      bugfix in setuid.c
+
+-      read full toc method extended to a data track in the second
+       session for cd-extra/enhanced cd recognition
+
+-      if the tracks in the TOC are labelled as data, this is checked
+       and corrected if untrue
+
+-      show cd text disc identification, if one exist
+
+-      a new perl script to generate a binary cdtext file for use with
+       cdrecord. This is currently very simple, but it enables you to
+       create cd-text enriched copies from non cd-text originals.
+       For a hint how to use the new perl script see the CD-text usage 
+       notes above.
+
+
+-      New option -L to ask freedb.freedb.org for CDDB information.
+       This alllows to automatically create CD-Text CDs.
+
+-      correct TOC endianess for FreeBSD ioctl interface.
+
+-      Fixed a bug that caused cdda2wav to dump core with certain
+       CD-Text data.
+
+-      new option -L changed. Now a numerical parameter (0 or 1)
+       defines the handling of multiple cddbp entries.
+       0 enters user interactive mode.
+       1 take the first entry unconditionally.
+       I still need a reasonable way for gui interaction in this case!
+       Proposals are welcome.
+
+-      made cddbp handling for mixed mode cds more robust.
+       It is unclear yet, if data tracks have to be included in the
+       query. Anybody knows the definitive answer?
+
+-      Better TOC ADDR/CRTL (red book) handling
+
+-      Better method to scan for indices.
+
+-      Support for SCMS in *.inf files
+
+-      Better SUID/SGID handling
+
+-      new script cddda2ogg
+
+-      bugfix deemphasizing (thanks to Klaus Wolterec)
+
+-      bugfix rounding error (creation of info files)
+
+-      added AlbumPerformer entry in info files
+
+-      integration of Monty's libparanoia
+
+-      switch to Jörgs getargs option handling
+
+-      Fix some bugs with option parsing introduced with the new option
+       parsing using getargs()
+
+-      New option -version to make cdrtools behave similar
+
+-      New option paraopts=opts for paranoia options.
+
+-      Print Paranoia statistics result at end of every track.
+
+-      prepare for better recording of discs with illegal TOCs
+
+-      prepare for non-english cd_text languages
+
+-      rewrite of the TOC handling code (now multisession capable
+       and much more robust)
+
+-      add a fallback method (shmat()) for failed mmap()
+
+-      linux bug workaround: open() sound device does block when device is busy.
+
+-      several code cleanups, some 64-bit portability bugfixes
+
+-      Fixed shell script 'cdda2mp3.new' to correctly use "#!/bin/sh"
+
+-      Fixed a bug (introduced while converting to getargs()) that caused
+       cdda2wav to dump core on OS that implement read only text
+       correctly like Solaris does) if compled with gcc or Sun CC COPTX=-xstrconst
+
+-      Remove old unused getopt() code.
+
+-      Check DMA residual count
+
+-      FreeBSD cooked ioctl() Byte swapping now finally OK?
+
+-      Fixed a bug that caused cdda2wav to return wrong byteorder
+       on Big endian machines if -paranoia has been specified
+
+-      fix several CDDB query bugs
+-      support CDDBP protocol 5
+
+-      customizable CDDBP server and port settings.
+
+-      Fixed a bug in the paranoia calling code that caused
+       cdda2wav to try to access one sector too far on the media
+       if in paranoia mode.
+
+-      Allow again compilation on FreeBSD
+
+-      bugfix for CD Extra, when copyright messages were present
+
+-      patch from Kyle to make CD extra handling more robust
+
+-      bugfix for wrong warning message 'no generation of info files'
+       due to incomplete length
+
+-      new verbose suboptions. Strings will finally replace the
+       tedious binary masks. For script compatibility the special
+       form of -v255 will be recognized for some releases.
+       -vhelp will show the new strings.
+-      reworked the toc display code to make it more orthogonal.
+
+-       changed option 'speed-select' to 'speed' for better interoperability
+
+-      Temporary added -v<number> for compatibility with old GUI programs.
+       Note: -v<number> is outdated and will be removed soon.
+
+-      Implement a temporary compatibility bug for the -v option.
+
+-      Support for libscg help system
+
+-      Man page fixed
+
+-      Fix for an uninitialized variable
+
+-      New exit codes for xcdroast
+
+-      Fix for a CDDB bug: need to use lead out start for play time
+
+-      Fix for a CDDB bug: Allow whitepsace in Genre
+
+-      Fix for a CDDB bug: need to count data tracks too
+
+/*--------------------------------------------------------------------------*/
+
+Readcd:
+
+-      better error recovery with -noerror
+
+-      error handling increased
+
+-      Handle signals and other aborts by restoring old drive state
+
+-      Set PF bit with mode select.
+
+-      New option -quiet to suppress primary SCSI error messages
+       in read CD error handling
+       This are the messages that are printed before entering the
+       retry mode.
+
+-      Secondary SCSI error messages are now suppressed by default,
+       they may be turned on again with -verbose 
+       This are the messages that are printed in -noerror
+       retry mode.
+
+-      Better handling of C2 scans on unreadable data disks.
+
+-      use comerrno() instead of comerr() if the drive is not ready
+       as errno is not valid after that test.
+
+-      Enhanced output for C2 error scan.
+
+-      Now use /etc/default/cdrecord as documented in the man page.
+
+-      Better behavior with extreme badly readable media.
+
+-      List number of completely unreadable sectors in addition to
+       the C2 error count.
+
+-      Man page updated to contain all options
+
+-      New option speed= to allow reading at slower speed and avoid read error
+       caused by vibrations of the media.
+
+-      added new option -overhead to meter SCSI command execution overhead.
+
+/*--------------------------------------------------------------------------*/
+
+Scgcheck:
+
+-      Fixed Makefile so scgcheck now compiles on FreeBSD
+
+/*--------------------------------------------------------------------------*/
+
+Mkisofs (By Jörg Schilling and James Pearson j.pearson@ge.ucl.ac.uk):
+
+-      Man page updated and corrected.
+
+-      Try to avoid the C-compiler warnings for getopt.c that are caused
+       by the non-confirming way of hacking used by FSF people
+
+-      isoinfo now corectly displays file with filesize > 1 GB
+
+-      isoinfo now implements a new option -s that displays the size
+       of the files in multiples of the sector size (2048 Bytes)
+
+-      libhfs_iso reworked to use timedefs.h from schily portability support.
+
+-      Better error messages for ISO and Rock Ridge directory sort problems
+
+-      Preserves HFS file dates for AppleDouble, AppleSingle and NetaTalk files
+
+-      Fixed a problem from an uninitialized variable in desktop.c
+       that caused random effects in Apple CD's
+
+-      better documentation for README.sort/README.hide from James Pearson
+
+-      Fixed a bug in sort code that caused the compare function to behave
+       symmetric when called c(a,b) vs. c(b,a)
+
+-      First UDF support via -udf option - thanks to Ben Rudiak-Gould.
+
+       Note that the UDF support is not what you might indend. It is currently
+       wired to the Joliet tree which is a bad idea. It also does not yet
+       support Symbolic Links, user ID's and similar.
+
+-      Write messages with more correct size names for the floppy eltorito 
+       boot images
+
+-      Added a missing prototype in getopt.c
+
+-      isodump.c isoinfo.c isovfy.c:
+       Correctly handle symlinks
+       use offsetof(struct iso_directory_record, name[0]) instead of
+       sizeof(struct iso_directory_record) - sizeof(idr->name)
+
+-      Fixed a check in the Apple HFS code that used strcmp for
+       data that could contain null bytes.
+
+-      Introduced many casts to enhance portability.
+       This was needed for GNU fnmatch.c and the HFS support lib libhfs_iso
+
+-      Use Protoyped function definitions for hash.c to allow old UNIX variants
+       where sizeof(dev_t) is < sizeof(int)
+
+-      Fixed a check in the Apple HFS code that used strcmp for
+       data that could contain null bytes.
+
+-      Introduced many casts to enhance portability.
+       This was needed for GNU fnmatch.c and the HFS support lib libhfs_iso
+
+-      Use Protoyped function definitions for hash.c to allow old UNIX variants
+       where sizeof(dev_t) is < sizeof(int)
+
+-      Support generic boot code if session does not start at sector 0.
+
+-      Fixed a minor bug with HFS labels & multi-session
+       Thanks to James Pearson
+
+-      Only print a short Usage if mkisofs detected a usage error.
+
+-      -z option now working to create CDs in a format with Linux proprietary
+       Rock Ridge extensions for transparent compression.
+
+       This is a patch from H.P. Anvin. It makes only sense with Linux-2.4.14
+       or later.
+
+-      New option -debug
+
+-      Correctly use stat()/lstat() with graft points
+
+-      Fixed a bug with escape character handling in graft point handling.
+
+-      Make the graft point a directory if the file it should point to
+       is a directory.
+
+-      Correctly handle non-canonical filenames with graft points.
+
+       .////././///test=OBJ/sparc-sunos5-cc/ will now work correctly
+       and not result in a corrupted ISO-Filesystem.
+
+-      Canonicalize graft points so commands like:
+
+               mkisofs -graft-points /a/b/././//=some_dir
+       and
+               mkisofs -graft-points /a/b/../c/=some_dir
+
+       will not cause broken ISO images anymore.
+
+-      Avoid unwanted information in debug information on disk.
+
+-      Allow the -sort option to work with the Eltorito Boot Catalogue
+
+-      Allow '-' to be part of the ISO-9660 filename if -no-iso-translate
+       has been specified. 
+       Thanks for this hint from Georgy Salnikov (sge@nmr.nioch.nsc.ru)
+       from Novosibirsk, Russia.
+
+-      Try to avoid an integer overflow with the -C option and DVDs
+
+-      Try to fix (very old) rotten code in various files that did cause
+       integer overflows for files > 2 GB - 2kB.
+
+       Inconsistent use of (always diferent) hand crufted code using
+       2048, 2047, ... instead of SECTOR_SIZE, ISO_ROUND_UP(), ...
+
+       Note that this is not only of interest for DVDs as mkisofs could
+       believe that > 2 GB of data would fit on a CD.
+
+-      New code to print file type names.
+
+-      Some more changes to reduce the probability of integer overflows
+       in size computations.
+
+-      Fixed a bug in the code that removes sensitive information from
+       the command line.
+
+-      Add text strings with descritpive text to the output_fragment structures
+
+-      verbose > 1 (use -v) writes debug info for output fragments.
+       This uses the new strings introduced with the last version.
+
+-      isoinfo now uses getargs() and includes -version and -help
+       options.
+
+-      isoinfo now is able to find out that Joliet information is
+       present if the disk contains illegal Joliet UNICODE escape code.
+       This seem to happen with disks written with Adaptecs programs.
+
+-      isoinfo has new option -debug that prints more information
+       from the Primary volume descriptor.
+
+-      Support for Apple HFS on Mac OS X Thanks to James Pearson.
+
+-      Support for more then 65535 directories as only the parent entries
+       need to fit into the path tables.
+
+-      Full DVD-Video support thanks to Olaf Beck - olaf_sc@yahoo.com
+
+-      Avoid a C-compler warning caused by mkisofs.h
+
+-      Fixed a bug in the DEBUG code from the DVD-Video enhancements
+
+-      Allow symlink targets to be up to 1024 bytes
+
+-      devdump/isodump/isovfy now use getallargs() and implement -help/-version
+
+-      If UDF but no Joliet is used, UDF filenames may be 255 chars long.
+       Note that this is still hack.
+
+-      From James: New option -joliet-long to allow 103 UNICODE characters with
+       Joliet. This is not Joliet compliant but several other programs
+       also create long Joliet names.
+
+-      Fixed a minor C non-compliance in ifo_read.c
+
+-      Allow symlink targets to be up to 1024 bytes
+
+-      devdump/isodump/isovfy now use getallargs() and implement -help/-version
+
+-      If UDF but no Joliet is used, UDF filenames may be 255 chars long.
+       Note that this is still hack.
+
+-      From James: New option -joliet-long to allow 103 UNICODE characters with
+       Joliet. This is not Joliet compliant but several other programs
+       also create long Joliet names.
+
+-      Correct a minor problem with K&R compilers for the programs
+       in mkisofs/diag/
+
+-      Make fire PATH_MAX is defined in isoinfo.c too.
+
+-      Make sure UDF directory permissions include 'execute permission'.
+
+-      A patch from James that make mkisofs able to create a HFS volume < 4 GB.
+
+-      Support for MS code page 1250 (Slavic/Central Europe) added.
+       Thanks to Petr Balas petr@balas.cz
+
+-      A patch from James that make mkisofs able to create a HFS volume > 4 GB.
+
+-      A new option -hfs-parms for better HFS support for HFS volumes > 4 GB
+       from James Pearson
+
+-      Fixed several typos in the man page and the source
+
+-      Belly based speudo fix for a problem with mkisofs -f (follow)
+       and symlinks to directories where directory content was 
+       missing with the old version. The new version is most likely better
+       and we (James and I) could not find problems with the new version.
+
+-      Make "HFS_TYPE" and "HFS_CREATOR" work as documented in ~/.mkisofsrc
+
+-      Fixed a small typo in isofinfo.c
+
+-      As mkisofs -f has bugs that cannot be fixed for this release, I decided
+       to mark the '-f' Option as non-functional. People who use it will be warned
+       that it does not work correctly.
+
+-      Sort VIDEO_TS.IFO to be the first entry in VIDEO_TS/ woth -dvd-video
+
+-      Disable Joliet if -dvd-video has been specified. This needs to be done to
+       allow the change above.
+
+-      Correctly handle files > 1GB on the UDF filesystem.
+       Thanks to Wei DING <ding@memory-tech.co.jp> for the patch.
+
+-      Add support for Code Page 1251
+
+-      Koi8-u added to libunls
+
+-      Fix a nasty bug in the UDF handling part that caused mkisofs to
+       create completely broken filesystem images if directories have been
+       nested deeper than 8 and -D has not been specified.
+
+-      Include a new piece of code that causes mkisofs to abort with an
+       error message if it turns out that the block numbers estimated
+       during the sizing phase do not match the block numbers in the
+       write phase.
+
+-      Enabled a piece of code that has been introduced 2 years ago and that
+       causes mkisofs to prevent deep directory relocation if Rock Ridge
+       has not been spacified.
+
+       If you like mkisofs not to omit the part of the directory tree that
+       is nested too deep, specify either -R, -r or -D.
+
+
+TODO:
+       -       read Joliet filenames with multi-session if no TRANS.TBL
+               or RR is present. I am looking for a volouteer for this task:
+               Peter Berendi <berendi2@webdesign.hu> announced that he likes
+               to be the volounteer for this task.
+
+               Unfortunately, I did no hear again from him, but I got
+               a proposal from
+               "Krisztian Gede" <nameless@mail.datanet.hu>
+               who also likes to do the job.
+
+               Note that this can never be 100% correct as there is no relation
+               between the names on the master (UNIX) filesystem, the ISO-9660
+               names and the Joliet names. Only the Rock Ridge names are
+               untranslated with respect to the original files on the
+               master (UNIX) filesystem.
+
+       -       implement Yellow book compliant XA extended dir attributes
+
+       -       add libecc/edc for CDI and similar.
+               This may not be needed if we ise VCDimager and recent
+               cdrecord versions.
+
+
+CYGWIN NT-4.0 NOTES:
+
+To compile on Cygwin32, get Cygwin and install it.
+For more information read README.win32
+
+The files are located on:
+
+ftp://ftp.berlios.de/pub/cdrecord/alpha ...
+
+NOTE:  These tar archives are 100% ansi compatible. Solaris 2.x tar and GNU
+       tar may get some minor trouble.
+
+WARNING: Do not use 'mc' to extract the tar file!
+       All mc versions before 4.0.14 cannot extract symbolic links correctly.
+
+WARNING: Do not use 'winzip' to extract the tar file!
+       Winzip cannot extract symbolic links correctly.
+
+Joerg
diff --git a/doc/ANNOUNCEMENTs/AN-2.01 b/doc/ANNOUNCEMENTs/AN-2.01
new file mode 100644 (file)
index 0000000..3268bbb
--- /dev/null
@@ -0,0 +1,1496 @@
+Please have a look at the German open Source Center BerliOS at www.berlios.de
+BerliOS will continue to support free hosting of cryptography projects even
+when US laws change and don't allow to host cryptography projects in the USA.
+Also look at sourcewell.berlios.de, the first Open Source announcement service
+that itself is implemented as Open Source project.
+
+***************** Important news ****************************
+
+For the 'Slottable Source Plugin Module' SSPM Features read README.SSPM
+
+***************** Please Test *********************************
+
+NEW features of cdrtools-2.01:
+
+
+All:
+
+-      Support for the ELF format in BSDi 4.x
+
+-      Allow floating point printing on OS/2. This has been possible
+       since 11/2001 but OS/2 has been forgotten.
+
+-      Correct OS/2 ranlib handling
+
+-      New architecture 9000-831-hp
+
+-      Include +DAportable in HP-UX cc options
+
+-      README.hpux enhanced to include hints on how to compile 64 bit
+       binaries.
+
+-      Support for NetBSD on PPC (macppc-netbsd-cc)
+
+-      portable getdomainname() replacement now supports to get the domainname
+       from /etc/resolv.conf. This allows usage even on OS/2
+
+-      Typo in DEFAULTS files fixed
+
+-      New generic target for symlinks
+
+-      New file rename.c for portability part of libschily
+
+-      Better Next STep support:
+
+       -       Some workarounds for broken unistd.h
+
+       -       -lkvm removed from Next Step config.
+
+       -       waitdefs.h fixed for very old BSD based systems (~ 1980)
+               like Next STep
+
+       -       strdup() moved into portability part of libschily
+
+       -       fixed typo in fctldefs.h R_RDONLY -> O_RDONLY
+
+       -       New file ttydefs.h includes portability phrases from ved and bsh.
+
+       -       Added an autoconf test for buggy termios.h in Next Step.
+               Next STep provides fully functional termios.h but tcgetattt(), ...
+               is missing in libc.
+
+       -       Test for clock_t changed to deal with a bug in Next STep.
+               Next Step illegally needs sys/time.h for clock_t
+
+
+-      Make recently introduced symlink install use relative symlinks instead
+       of absolute symlinks.
+
+-      Change autoconf/statdefs.h to support nanosecond support for SCO
+       UnixWare and FreeBSD
+
+-      Call conf/mkdep-sco.sh via sh to be independent from 'x' bit.
+
+-      libschily/rename.c fixed for SCO Openserver fo avoid warning
+       for redefinition of MAXPATHNAME
+
+-      libschily/usleep.c fixed to avoid SCO Openserver warning about
+       non matchin prototype in system include files
+
+-      Better Portability for SCO UnixWare
+
+       -       New platforms i486, i586, Pentium III, Pentium Pro
+
+       -       Let strdefs.h also include strings.h for strcasecmp()
+
+       -       Support for missing struct sockaddr_storage
+
+       -       Support for broken wait3() (returns wrong timings)
+
+       -       Changed broken portability Prototype support in libfile
+               to use 'makefiles / prototype.h' based system
+
+       -       Changed fileopen() and filereopen() to avoid fdopen()
+               provlems (does not accept mode string that does not
+               match fd flags)
+
+-      Catch the case where somebody tries to compile on Solaris with
+       /usr/ucb in PATH before /opt/SUNWspro/bin and when calling 'cc'
+       results in:
+               /usr/ucb/cc:  language optional software package not installed
+
+-      Trying to make the source get accepted by 'cstyle'.
+
+-      Changes in the general topic 'Stack Scanning' and the software signal
+       system handlecond()/raisecond() that make the software signal system
+       now usable on all platforms.
+
+-      Trying to support DOS with the DJGPP compilation environment
+       Thanks to Alex Kopylov <reanimatolog@yandex.ru> for the first version
+       of the port and further helping.
+
+       Note that in order to compile cdrtools on DOS/DJGPP you need smake-1.2a20 or newer.
+       GNU make does not seem to work for a DOS compilation.
+
+-      New File README.msdos
+
+-      New RULES for DOS/DJGPP
+
+-      Make some vars in align_test.c static because Mac OS X creates unneeded
+       name space pollution.
+
+-      DJGPP has no SIGBUS, use #ifdef in avoffset.c and align_test.c
+
+-      Several changes with casting Null pointer constants to Null Pointers
+       if they are used as parameters in var arg lists (see below).
+
+-      New gethostname() fallback emulation using uname(2).
+
+-      Better rename(2) emulation for Platforms that don't have rename().
+
+-      niread()/niwrite()/nixread()/nixwrite() in libschily now resets errno
+       to the old value in case EINTR did occur.
+
+-      README.msdos has been corrected according to a hint from Alex Kopylov
+
+-      New macros to platform independently set up integers in little endian
+       format. This is needed to e.g. write PC disk labels from big endian
+       platforms.
+
+-      Rules extended to support volume management libs
+
+-      The install-sh script not takes care about UNIX variants like SCO UnixWare
+       and SCO OpenServer that allow to give away files via chown.
+
+       If this works and /tmp has the sticky bit set, the root test was unable
+       to remove the test files later. For this reason, now a subdirectory
+       in /tmp is used.
+
+
+-      Support for the special .PHONY: target ---> needs smake-1.2a21 or newer
+
+       This helps to deal with files like INSTALL operating systems
+       like Win32 and Mac OS that don't honor file name case and prevents
+       the file named INSTALL to get into trouble with 'make install'
+
+
+-      'make install' now works on operating systems that require a '.exe'
+       suffix for executable binaries
+
+-      Updated the file README.ATAPI
+
+       Updated information for Linux, SCO-OpenServer, SCO-UnixWare, Win32
+       and DOS
+
+-      mconfig.h now supports make COPTX=-DNO_FORK & COPTX=-DNO_VFORK
+
+-      snprintf() from libschily now correctly follows POSIX.1-2001 for maxlength == 0
+
+-      Workaround for a bug in the C-compiler from SCO-OpenServer. It
+       is not very probable that this causes problems with cdrecord. The 
+       function getfp() did not return the correct Frame Pointer when called
+       as first function in another function as the compiler sdoes set up the
+       new stack frame after getfp() has been called.
+
+-      New function filemopen(char *name, char *omode, mode_t mode) with additional
+       mode_t parameter.
+
+-      update recent getargs() version from repository. This has been forgotten.
+       
+-      Add a workaround for a SCO OpenServer C-compiler bug.
+       The bug causes the first function in a function to be called
+       before the new stack frame has been established and did cause
+       scanning the stack frame to fail.
+
+-      Make snprintf() POSIX compliant.
+
+-      Many typos in the READMEs fixed, thanks to a hint from Stefano Allrath
+
+-      New global method to handle PATH environment delimiters (":" on
+       POSIX systems and ";" on DOS).
+
+-      New README.msdos reflecting new features of smake-1.2a23 on DOS/DJGPP
+
+-      Some minor enhancements to the makefilesystem
+
+-      Some minor changes for better compilation in SGI IRIX
+
+-      Trying to start adding support for Win32/Mingw32
+
+-      New global #define NEED_O_BINARY to make using setmode() easier
+
+-      New autoconf test for struct stat.st_fstype
+
+-      New autoconf test for fnmatch()
+
+-      New autoconf test for blksize_t/blkcnt_t
+
+-      libscgily/stdio/io.h renamed to schilyio.h to avoid conflicts with
+       DOS.
+
+-      Added a Note to README.linux:
+
+       NOTE for all Linux 2.5.x versions and all Linux versions before 2.6.8:
+               Linux did ship with defective kernel include files starting
+               with 2.5.x. These defective kernel include files did prevent
+               compilation. If you have problems compiling software and see
+               error messages related to include/scsi/scsi.h & include/scsi/sg.h
+               either upgrade to Linux-2.6.8 or newer or remove /usr/src/linux
+
+-      Support added to the makefile system that allows compilation on
+       AMD x86_64 using non automake aware make programs like GNU make.
+       Note that smake ftp://ftp.berlios.de/pub/smake/alpha/ is able to compile
+       things even on unknown platforms as it includes auto make features.
+
+
+Libparanoia (Ported by Jörg Schilling, originated by Monty xiphmont@mit.edu):
+
+-      Included a bug fix from the libparanoia Author.
+       Correctly allocate some arrays. Note: on 32 Bit machines, this patch does
+       not result in a different binary but the code is now really correct.
+
+-      New indentation is better conforming to 'cstyle'
+
+-      Fixed a bug in libparanoia that prevented the statistics to show up
+       the number of 'skips' (the number of exhausted read retries) when
+       SKIP verification has been turned off.
+
+-      modified to avoid GCCs shadowed variable warnings.
+
+-      Try to use page aligned transfer buffers if possible.
+
+-      Avoid buffer size problems wit non page aligned transfers on FreeBSD.
+
+-      Avoid freeing pointers that are not from malloc() by copying the data
+       to a second allocated chunk of free()able space. This has been a bug
+       introduced while trying to handle buffer size problems with non page aligned
+       transfers on FreeBSD.
+
+
+Libedc (Optimized by Jörg Schilling, originated by Heiko Eißfeldt heiko@hexco.de):
+
+
+Libscg:
+
+-      Reordered and restructured scsi-remote.c code to allow compilation on OS/2
+       and hopefully other OS like BeOS
+
+-      First attempt to support QNX.
+       Note that the sourcecode comes from QNX and it looks as if it 
+       is buggy for commands that cause SCSI commands that result in 
+       a Check Condition status. From looking at the source, the stack
+       gets overwritten in this case.
+
+-      SCSI adaptation layer for SCO UnixWare rewritten to support
+       multiple opens and to better follow the libscg interface standard.
+
+-      Second attempt to support QNX.
+       Make it compile
+
+-      Check kernel level error return codes on SCO-UnixWare
+
+-      Starting to support SCSI reset on SCO-UnixWare
+
+-      Extensions to libscg related include files to support DVD+RW formatting
+
+-      Make libscg work on SCO UnixWare if an application like cdrecord
+       has been installed suid root.
+
+       Before, the called administration programs did not work if euid!=uid
+
+-      Fixed a problem with possible garbage in the SCSI error string.
+       Thanks to Stefano Di Paola <stefano.dipaola1@tin.it> for reporting.
+
+-      Fixed another printf buffer vulnerability in scsi-remote.c
+
+-      New version of scsi-amigaos.c from Thomas Langer
+
+-      Added a work around for a Solaris 9 x86 bug:
+       DKIOCINFO returns a max DMA size of 256 kB but only 68 kB will work.
+       Check max DMA size for a IDE disk to get a correct value....
+
+       For more information read the updated file README.solaris and the
+       new files README.solaris-x86-ata-DMA and README.solaris-x86-ATAPI-DMA
+
+-      Changed scsi-os2.c to allow 'cdrecord -scanbus' to find targets with
+       target ids > 7.
+
+-      Librscg now uses correct casting to a Null Pointer for execlp() as
+       NULL is a Null Pointer Constant but no Null Pointer. This could
+       make problems with some 64 bit architectures.
+
+-      New driver scsi-dos.c acting as 16 bit DOS ASPI interface
+       Thanks to Alex Kopylov <reanimatolog@yandex.ru> for the first version
+       of the driver.
+
+       Check his Web Page: http://bootcd.narod.ru/index_e.htm
+       it contains precompiled DOS binaries.
+
+-      The driver scsi-dos.c has already been verified with 'scgcheck'.
+
+-      scsi-os2.c and scsi-wnt.c now correctly return 0 from scg_send() if
+       the target is not valid.
+
+-      scsi-wnt.c does now support multiple SCSI opens.
+
+-      scsi-wnt.c does now correctly return SCG_NO_ERROR in case a SCSI command
+       returned CHECK CONDITION.
+
+-      scg__open() now prints a warning if it has not compiled with the results
+       from a certified autoconf environment.
+
+-      Introduced a fix to avoid the need for a #define ident prod_ident
+       for SCSI Inquiry data. This #define did cause problems with the
+       latest Sun Studio 8, C compilers
+
+-      First attempt to support running cdrecord while the volume management is
+       active.
+
+-      Increased version number to 0.8
+
+-      First attempt to work around the problems for suid programs introduced by
+       Sun with Solaris 9. Programs that like to issue a USCSI ioctl() need to be
+       root or get EPERM. Cdrecord did does up root privilleges eraly to avoid
+       security problems.
+
+       libscg now selectively runs the USCSI ioctl() as root if the program is installed
+       suid root.
+
+-      Fixed a bug in scsi-mac-iokit.c in scgo_havebus() that caused pxupgrade not
+       to work on MacOS X.
+
+-      First attempt to support the SPTI Ioctl interface on Windows NT.
+       see also http://www.ste-home.de/cdrtools-spti/
+       Thanks to Richard Stemmer, Jay A. Key and thomas podkanski
+
+       This allows to use cdrtools on NT without the need to install ASPI in case
+       you are administrator when yu run a program.
+
+       Please note that the use of SPTI is default. If you like to force using
+       ASPI, use dev=ASPI:b,t,l or dev=ASPI (in the -scanbus case).
+       If you like to force STPI, use dev=SPTI:b,t,l or dev=SPTI.
+
+       Currently, the interface does not yet fully matches the scg interface standard.
+
+-      Try to support the half hearted and badly designed /dev/hd* interface
+       from Linux-2.6 in a more usable way.
+
+       The only reason for adding this kind of support is that the Linux kernel
+       hackers reject to fix the known DMA bugs in the already existing SCSI
+       transport interfaces in the Linux kernel. Using /dev/hd* is unfortunately
+       the only way to get DMA with sector size being 2352, 2448 or similar.
+
+       Use cdrecord -scanbus dev=ATA and
+       cdrecord dev=ATA:1,0,0
+
+       Note: The Bus mapping function inside the kernel for this interface is
+       a dummy. For this reason, we need to do the mapping ourselves.
+       Busnumber is ("/dev/hd*"[7] - 'a') / 2
+       Target    is ("/dev/hd*"[7] - 'a') % 2
+
+       Also note that creating this interface in the Linux kernel was a waste of
+       time. It did need a lot of effort to be created. Instead of first adding
+       a new interface with a new broken DMA implementation and later fixing
+       the DMA bugs, it would have been better to just fix the DMA bugs
+       in ide-scsi.c
+
+       Adding SCSI transport to something like /dev/hd* on an OS that includes
+       a generic SCSI transport driver is disregarding SCSI protocol layering.
+       A clean way to implement ATAPI on Linux would be to rather introduce a
+       SCSI hostadaptor driver that sends the SCSI commands via the
+       ATA hardware.
+
+       Linux users should think about buying a CD writer for Linus Torvalds.
+       Maybe this could help to get better SCSI support in the Linux. Currently
+       Linus doesn't know anything about the CD-writing problems on Linux and
+       his contributions to CD-writing related issues in discussions are just
+       guesses that are not related to own experiences and understanding for
+       the matter :-(
+
+       It seems that the Linux way of dealing with bugs is to implement a new
+       incompatible interface instead of fixing the known bugs from 
+       old interfaces :-(
+
+-      Allow cdrecord -scanbus dev=ASPI and cdrecord -scanbus dev=SPTI to work
+       on win32.
+
+-      Correct a bug in the Win32 version analyze function that is needed to
+       use the correct SPTI interface. Unfortunately, the interface did
+       change with a NT-4.0 service pack. It is unclear whether the currently
+       used interface type is correct for all possible NT-4.0 variants.
+
+-      For Win32, default to STPI only if on NT-5.x as there is a bug in some
+       UDMA implementations that causes blue screens.
+
+-      The Mac OS X SCSI low level transport now roughly meets the interface standard.
+       For this reason, the file scsi-mac-iokit.c now is marked with Author "schily"
+
+-      Indented according to the cstyle standard.
+
+-      For win32, dev=ASPI:1,0 and dev=SPTI:1,0 work again
+
+-      Trying to add a workaround for the Linux problem with USB where the
+       kernel issues a request sense even when there was only a DMA underrun
+       and the drive replies as expected with no-sense. Our problem in this
+       case is that we needed to ad another workaround because sometimes
+       Linux clears the status byte and we did assume a CHECK CONDITION in case
+       sense[0] was != 0.
+
+-      Enhanced max # of SCSI busses to 256 for the Linux sg driver.
+       This was needed because of the (compared to Solaris) suboptimal
+       way of dealing with instance numbers on Linuux.
+
+       While Solaris keeps a data base with instance numbers, disconnecting and
+       reconnecting a USB drive results in the USB device getting the same 
+       SCSI address as before.
+
+       As Linux does not have such a data base, disconnecting/reconnecting
+       a USB device has the unfortunate side effect of assigning a new and
+       different SCSI address with every USB connect. This also creates problems
+       when software likes to manage access rights to devices for non-root
+       users.
+
+-      Win32 SPTI interface now also supports controllers with more than one
+       SCSI Bus. Thanks to Richard Stemmer
+
+-      Fixed a bug in the Win32 SPTI/ASPI interface introduced with 2.01a28
+       that caused core dumps because it did try to access data behind the end of the
+       sense data array in the ASPI cmd structure.
+
+-      Scan /dev/hda../dev/hdz instead of /dev/hda../dev/hdt for dev=ATAPI on Linux.
+
+-      Trying to write a better warning message for the dev=ATAPI: interface
+       on Linux (the related kernel interface is unmaintained and does
+       not support DMA at all).
+
+-      Fixed a bug in Win-NT Version string handling in scsi-wnt.c
+       Thanks to Alex Kopylov <reanimatolog@yandex.ru>
+       This caused that libscg did not properly recognize NT-4.x with service pack 4
+       to be equivalent to NT-5.0 (Win2k).
+
+-      Trying to avoid using the WinNT-SPTI interface for NT-4.0
+
+-      Fixed a security bug in scsi-remote.c (the RSCSI client).
+
+
+Rscsi:
+
+-      Support for IPv6
+
+-      Workaround for missing struct sockaddr_storage on SCO UnixWare
+
+-      Security update. Forbid to write arbitrary debug files, only allow
+       a debug file name that has been configured in /etc/rscsi.conf.
+       Writing arbitrary files with a siud root program could be used to become
+       root on a local machine if you are already logged into that local machine.
+
+-      README.rscsi typo's corrected.
+
+
+Cdrecord:
+
+-      Use correct set_mode_params() return value in deflt_writemodes_mmc()
+
+-      Correct a debug printing to go to stderr instead of stdout.
+
+-      Workaround for broken Firmware for LG (Lucky Goldstar) drives.
+       These drives have been unable to write Audio in TAO mode because
+       they have an illegal audio pause length default.
+
+       Thanks to a hint from: Mark Vytlacil <markvyt@comcast.net>
+
+-      Man page now correctly describes the data formats used with -xa1 & -xa2
+
+-      Use Prototypes for functions with enum parameter in fifo.c to avoid
+       warnings on SCO UnixWare
+
+-      Trying to catch SIGHUP to avoid hung recorders after people
+       close X windows by accident (This in most cases happens because
+       some newer GUIs try try copy bad ideas from Microsoft like the 'x'
+       button on the top bar in the window.
+
+-      Trying to print hints if the SCSI error core looks like a buffer
+       underrun occurred.
+
+-      First (still mostly empty) driver for the Matsushita CW-7501
+
+-      First TAO writing support for the Matsushita CW-7501
+
+-      New option -setdropts to allow cdrecord to set driver specific
+       parameters and exit.
+
+-      Added support to disable/enable the Plextor PowerRec feature.
+       Use driveropts=forcespeed
+       Be very careful as this will cause in badly readable disks.
+       The only senseful reason to use this feature is to run tests in
+       -dummy mode to check whether the system would be able to record
+       fast enough and to later buy High-Speed Media.
+       Note that documentation for the related SCSI command is not
+       oficially available and thus the information has been "guessed".
+
+-      Added support to enable/disable the Plextor SpeedRead feature.
+       Use driveropts=speedread
+       to allow the drive to read CDs faster than 40x.
+       Be very careful as this may cause the media to break in the drive
+       while reading, resulting in a destroyed media and drive!
+       Note that documentation for the related SCSI command is not
+       oficially available and thus the information has been "guessed".
+
+-      Added support to enable/disable the Plextor SingleSession feature.
+       Use driveropts=singlesession
+       This allows to read defective (illegal) media with extremely
+       non-standard additional TOC entries. You need to enable Single Session
+       mode before you insert the defective disk!
+       Note that documentation for the related SCSI command is not
+       oficially available and thus the information has been "guessed".
+
+-      Added support to enable/disable the Plextor Hide CD-R feature.
+       Use driveropts=hidecdr
+       This allows to make CD-Rs look like CD-ROMs and applications believe
+       that the media in the drive is not a CD-R.
+       Note that documentation for the related SCSI command is not
+       oficially available and thus the information has been "guessed".
+
+-      Added reading out "real" Burn-Proof counter for Plextor drives.
+       Note that documentation for the related SCSI command is not
+       oficially available and thus the information has been "guessed".
+
+-      Try to do a more correct job when doing Buffer Underrun estimation
+       counts.
+
+-      Make the explicit Buffer underrun error checking work for
+       Plextor drives too.
+
+-      Fixed the command line parser for driveropts= parameters.
+       Before the fix, driveropts=noburnfree,hidecdr would result
+       in assuming: driveropts=noburnfree,nohidecdr
+
+-      Now also supporting SAO/DAO write mode for the CW-7501
+
+-      New option -lock (similar to -load) that loads the media but leaves
+       the drive in locked status.
+
+-      New driver interface to allow SAO recording for the CW-7501
+       Simplified: "dummy" and "multi" Parameter information has been
+       moved into the track structure.
+
+-      Removed the internal implication that -packet is a TAO write mode.
+       Please test! It may be that this did introduce bugs.
+
+-      Try to avoid ANSI C arithmetic conformance change warnings from 
+       SCO C-compiler by introducing proper casting.
+
+-      Driver interface restructured to support aborting SAO recording
+       with the Sony CDU-948
+
+-      "Driver flags" printing corrected
+
+-      Better behavior with CADDY drives and -load option
+
+-      Fixed a bug that caused cdrecord not to abort if Tracks with unknown
+       length are present in RAW write mode.
+
+-      Print extended Power Rec Speed information for Plextor drives.
+
+-      CUE Sheet handling generalized to allow to implement SAO writing
+       for more drives.
+
+-      Start supporting the Sony CDU-948 in SAO mode. Currently not yet working:
+
+       -       Multi-session
+
+       -       MCN/ISRC
+
+-      Grace time handling restructured. The grate time waiting is now done 
+       even before the forced blanking and it is made sure that the waiting
+       is done only once.
+
+-      Several changes in the open source part are visible as a result of the
+       new DVD+RW / DVD+R support.
+
+-      cdrecord-ProDVD now includes first DVD+RW and DVD+R support.
+       Check ftp://ftp.berlios.de/pub/cdrecord/ProDVD/ 
+       on Thursday 24.4.2002 for the first binaries
+
+-      Do not try to lower the possible number of open files in raise_fdlim()
+       anymore.
+
+-      Check return code of driver's init function.
+
+-      Better error messages from main write loop.
+
+-      Write a hint that a user may have used a "preformatted" CD-RW if 
+       read_next_writable_address fails for the "invisible" track
+       and tell him to run cdrecord blank=....
+
+-      Fixed a bug that caused cdrecord to prevent a 3rd session on a
+       multi session disk. This bug was introduced with the driver
+       restructuring a few releases before.
+
+-      Better driver text strings for the driver IDs in the CD MMC drivers.
+
+-      Move Plextor PowerRec speed info completely to the statistics _past_
+       the recording activities.
+
+-      Allow more nonstandard Cue sheets to be accepted by the Sony CDU-924
+       and CDU-948.
+
+-      Implement MMC-3 DVD+ Drive/Media recognition to avoid that cdrecord starts
+       to treat a DVD+ as a CD-R because the DVD+ drive identifies as CD-R/RW + DVD-ROM
+       with "no DVD media installed" from a MMC-2 viewpoint.
+
+-      Added a note to the cdrecord man page how to use mkisofs
+       to allow cdrecord to knoe about track sizes in SAO or RAW mode.
+
+-      Fixed a multi session bug that has been introduced with the DVD+R/RW 
+       restructuring with cdrecord-2.01a11. This bug caused cdrecord to be unable
+       to start a track from a sector number != 0 in TAO mode.
+
+-      Fixed a problem with cdrecord -msinfo introduced with the the DVD+R/RW
+       restructuring with cdrecord-2.01a11. The unwanted verbose printing has been
+       removed with this version.
+
+-      New option -xa to create CD-ROM XA mode 2 form 1 sectors with 2048 bytes
+       of user data
+
+-      New option -xamix to create mixed CD-ROM XA mode 2 form 1/2 sectors 
+       with 2332 bytes of user supplied data.
+
+-      Restructured sector types to make them usable:
+
+       -mode2         CD-ROM data mode 2        - 2336 bytes
+       -xa            CD-ROM XA mode 2 form 1   - 2048 bytes
+       -xa1           CD-ROM XA mode 2 form 1   - 2056 bytes
+       -xa2           CD-ROM XA mode 2 form 2   - 2324 bytes
+       -xamix         CD-ROM XA mode 2 form 1/2 - 2332 bytes
+
+       To write conforming CD-ROM XA multisession disks use cdrecord -multi -xa1
+       together with mkisofs -XA -sectype xa1
+
+-      -cdi is now implemented how it should be: as a flat to change
+       the TOC type of a CD and not as a sector mode.
+
+-      Track parsing completely restructured to allow new features.
+       One of the features is to write audio CDs from a pipe,
+       other features will follow.
+
+-      Cdrecord now resets euid to the uid of the caller (if called suid root)
+       before it opens data files.
+
+-      Fixed a bug that caused cdrecord to insert two grace wait periods
+       if a disk was blanked and rewritten in one call.
+
+-      Allow cdrecord to copy audio CDs from a pipe from cdda2wav
+       without using an intermediate file on disk.
+
+       To copy an audio CD  from  a  pipe  (without  intermediate
+       files), first run
+
+           cdda2wav dev=1,0 -vall cddb=0 -info-only
+
+       and then run
+
+           cdda2wav dev=1,0 -no-infofile -B -Oraw - | \
+           cdrecord dev=2,0 -v -dao -audio -useinfo -text *.inf
+
+       This  will get all information (including track size info)
+       from the *.inf files and then read  the  audio  data  from
+       stdin.
+
+       If  you  like to write from stdin, make sure that cdrecord
+       is called with a large enough fifo size  (e.g.   fs=128m),
+       reduce  the write speed to a value below the read speed of
+       the source drive (e.g.  speed=12), and  switch  the  burn-
+       free   option   for  the  recording  drive  on  by  adding
+       driveropts=burnfree.
+
+-      New option -abort allows you to send a write abort sequence to a drive.
+       This may help if other software did leave the drive in an unusable
+       condition.
+
+-      New 'xio' module allows to open a file virtually more than once to
+       support CDRWIN CUE sheets in cdrecord.
+
+-      Run Plextor Speedinfo SCSI command in silent mode as old Plextor drives
+       do not support this command.
+
+-      Workaround for a Plextor (Premium only???) firmware bug that may result
+       in a B0 pointer A5:A5:A5 instead of FF:FF:FF.
+
+       This made it impossible to blank a freshly written CD-RW witout reloading
+       the media. Now cdrecord does not check the disk size anymore if the number
+       of tracks to be written is 0.
+
+-      First CDRWIN CUE sheet support.
+
+       Cdrecord currently supports what is in the CUE sheet description in
+       the CDRWIN documentation (with a few exceptions). Note that the
+       examples in the rest of the CDRWIN man page are mostly illegal 
+       if you compare them against the CDRWIN CUE sheet syntax documentation.
+
+       These exceptions are currently in effect:
+
+       -       Only one FILE Line per CUE sheet file (This is compliant to the
+               CUE shet format documentation although the examples show CUE
+               files with more than one FILE line). NOTE that the CUE syntax has
+               been ill defined so that it would not make sense to e.g. use
+               more than one FILE line for audio CDs.
+
+       -       The AIFF File type is not implemented (because I have no documentation
+               for this audio file format).
+
+       -       The MP3 File type is not yet implemented.
+
+       -       The CDG data type keyword will not yet work
+
+       -       The CDI data type keyword will not yet work
+
+       -       Only a sector size of 2048 will work with MODE1
+
+       -       Sectors with sector size 2336 will not yet work
+
+       -       POSTGAP will not yet work.
+
+       Note that the CDRWIN CUE documentation is bad and it is unclear how
+       formless (non XA) MODE 2 sectors should be made.
+       
+       CDI is not a sector/track property but a disk property.
+
+       The File type BINARY vs. MOTOROLA is unclear.
+
+       To use the cue sheet feature call:
+
+               cdrecord dev=.... -v -dao cuefile=xx.cue
+
+       The main reason for implementing CUE sheet support was to allow to
+       write VCD/SVCD with cdrecord. It has currently tested with the
+       test SVCD from ftp://ftp.vcdimager.org/pub/vcdimager/examples/test_svcd/
+
+       Cdrecord should allow to write audio type CUE sheet based CDs also.
+
+
+-      Modified the notes close to the Copyright printing code in cdrecord.c
+       to make clear that this note is not a deviation from the GPL but just
+       a memorandum on how to understand the GPL.
+
+-      Fixed a bug in file descriptor handling that caused cdrecord not
+       to continue at offset xxx in the file after a new track did start.
+
+-      Added a forgotten feature in the CUE Sheet parser so it will now know that
+       WAVE files use swapped (intel) byte order.
+
+-      Restructured the main program of cdrecord so that cdrecord overall
+       behaves similar to before when cue sheets are used.
+       e.g. cdrecord -eject cuefile=xxx did only eject the disk instead of
+       first writing and then ejecting.
+
+-      Added some hints to the man page to make speed= handling clearer
+
+-      Fixed some typos in the man page
+
+-      Added the -format option to the man page
+
+-      CD-Text handling reworked:
+
+       CD-Text from textfile= or from CUE CDTEXTFILE wins over CD-Text
+       from *.inf files and over CUE SONGRITER.
+
+-      CD-Text from CUE file (either CDTEXTFILE or SONGRITER) now needs
+       -text in addition in order to be not ignored.
+
+-      Fixed a bug in the recognition for cdda2wav | cdrecord *.inf
+       that caused a message
+               WARNING: Stdin is connected to a terminal.
+       if not writing from a pipe.
+
+-      Small fix in auinfo.c to again allow compilation on K&R systems
+
+-      Typo fixes for the cdrecord man page
+
+-      The clone write code is now part of the GPL'd source
+       Note that this part of the code is now more than 2 years old but previously
+       has been excluded from the publically visible part of the source.
+
+       To understand how to use the clone mode read README.clone
+
+-      New option ts= to set the SCSI transfer buffer size
+
+-      Man page corrected to correctly mention current format for /etc/default/cdrecord
+
+-      call setmode(fileno, O_BINARY) for DOS/DJGPP also
+
+-      Better check if we use the FIFO to avoid core dumps with too small FIFO sizes.
+
+-      Switch off FIFO of fifo size is < 2 * SCSI transferbuffer
+
+-      Fixed a small bug in the man page (..sp instead of .sp). Thanks to Eric Raymond
+       for reporting!
+
+-      Work around for a problem in the Plextor 708 firmware (at least 1.01..1.02)
+       that caused cdrecord to be unable to recognize that a DVD medium is present instead
+       of a CD medium.
+
+-      Changed the GPL clarifications text in a way so Debian people still
+       agree with me that cdrecord is free software. The clarifications are
+       needed in order to tell people/companies (like Mr. Rosenkranzer,
+       RedHat & SuSE) who create broken branches from cdrecord that they are
+       not legally publishing their branches because they violate the
+       GPL Â§ 2 Paragraph c) and GPL Preamble Section 6).
+
+       If would be better if the named persons/companies would rather stay
+       in contact to the Authors, discuss things and contribute to the
+       community instead of creating useless/broken changes and in case
+       of SuSE Linux even creating hacks that introduce security risks.
+
+       Note that now, RedHat Linux (enterprise server) or the SuSE Linux
+       are even more expensive than e.g. Solaris x86, see:
+
+       http://www.osnews.com/story.php?news_id=5416&page=5
+       Small Correction to this web page: Solaris x86 is free again for
+       personal use.
+
+-      Extended the man page to make it more clear that all CD/DVD-writers
+       ever made use only SCSI commands.
+
+-      Another change to the man page according to a hint from
+       Eric Raimond in order to get better compliance for troff -> "*ml"
+       converters.
+
+-      Allow people who cannot provide an e-mail address or who
+       don't like to support their modifications to modify cdrecord
+
+-      Some CUE sheet modifications in drv_mmc.c now made it into
+       the official SCCS history file.
+
+-      Several fixes to avoid the need for a #define ident prod_ident
+       for SCSI Inquiry data. This #define did cause problems with the
+       latest Sun Studio 8, C compilers
+
+-      Hack to work around a POSIX real time priotity design bug that
+       causes us to become root again on e.g. Linux in order to be able
+       to lower the priority of the FIFO background process.
+
+-      Better documentation and EXAMPLE for -setdropts driveropts=
+       in the man page.
+
+-      print a help message to direct the user to use -raw96r in case
+       the drive does not accept the cue sheet with -dao.
+
+-      Mark all drives that cannot be accessed because the volume management is
+       running and no media is in the drive with '?' instead of '*', so they
+       may be distinct from non existing drives.
+
+       Read README.volmgt for more information
+
+-      Now works again suid root on Solaris 9
+
+-      Fixed a bug introduced in 2.01alpha by a source consolidation.
+       cdrecord -toc did not work anymore for CD-ROM readers
+
+-      Updated README.audio
+
+-      Make the CUE Sheet handling search for a file name from a FILE statement
+       also in the directory where the CUE sheet is found (in case there is no
+       slash (/) in the file name from 'FILE').
+
+-      Avoid coredumps when cdrecord is called with -xd and there is no known
+       driver for the current drive.
+
+-      New option -tao is now needed if you like to write in TAO mode.
+       Cdrecord now does no longer writes if no write mode has been specified.
+
+-      New option -sao as alias for -dao. As the official name for the write mode
+       is SAO, -sao is more correct than -dao.
+
+-      Fixes for minor typos in cdrecord.1
+
+-      Fixed a bug with pad=xxx and pad sizes > 2 GB.
+
+-      Trying to fix a bug introduced lately with the check for specified
+       write mode options. As a result, only TAO mode writing did work.
+
+-      Better man page & online help for the ts= option.
+
+-      Fixed a typo in the man page.
+
+-      Better error messages when audio size is < 300 Sectors or needs padding.
+       Thanks to a hint from Stefano Allrath
+
+-      cdrecord -scanbus now checks for 256 SCSI busses
+
+-      cdrecord -scanbus now checks for 256 SCSI busses
+       This has already been announced for 2.01a28 but forgotten to include
+
+-      Some Man Page Fixes trying to avoid coding problems for non 7-bit ACSII
+
+-      Several typos in the man page fixed
+
+-      Man page enhanced to include a better documentation for the driver=
+       option.
+
+-      Several other enhancements to the man page
+
+-      modified to avoid GCCs shadowed variable warnings.      
+
+-      Cdrecord now tolerates the OPC "error code" "Power calibration area almost full"
+       to not a real error.
+
+-      Fix for a bug that caused cdrecord to be unable
+       to reload the media for some drives.
+       The fix helps with the following problem:
+
+       Trying to clear drive status.
+       cdrecord: Drive needs to reload the media to return to proper status.
+       cdrecord: Cannot load media with this drive!
+       cdrecord: Try to load media by hand.
+       cdrecord: Cannot load media.
+
+-      man page enhanced
+
+-      Print the "Make sure you are root" only if root privilleges are missing.
+
+-      Avoid warning for not working nice() on DOS
+       Thanks to Alex Kopylov <reanimatolog@yandex.ru>
+
+-      -clone option documented in the man page. This has been forgotten before.
+
+-      Several typos in the man page fixed
+
+-      Do not try to call nice() on DOS/DJGPP
+
+-      cdrecord now tries to check the DMA speed if the drive supports to read the
+       drive buffer. If the DMA speed is not sufficient, then cdrecord requires 
+       that burnfree is activated. If the environment variable "CDR_FORCESPEED"
+       is set or -force has been specified, then cdrecord does not try to enforce
+       that the available DMA speed is 2x the expected write speed.
+
+-      Make some symbols static to avoid problem with a badly designed libc on
+       OpenBSD that violates POSIX by pulluting the namespace with symbols
+       like 'pl'.
+
+
+Cdda2wav (By Heiko Eißfeldt heiko@hexco.de):
+
+-      fixed typo in cdda2ogg.1
+
+-      Do not use uname() but gethostname() for portability.
+
+-      include unistd.h for abs() 
+
+-      old Toshiba's usable again
+
+-      Multisession Non-CD-Extra disks now work again
+       Now also a lot more broken disks are readable again.
+
+-      not using ioctl in signalhandler any more
+
+-      trying to support sound on Win32
+
+-      Several changes (mostly OS/2 related) for more ask Heiko
+
+-      bugfix add cdda2ogg manpage,and script and makefile install target 
+-      support BeOS shared memory and FIFO 
+-      support soundcard output under QNX 
+-      windows-users! Cygwin has fixed the bug introduced with 1.3.18. Please  
+       upgrade to the new 1.5.3-1 release. 
+
+-      call setmode(fileno, O_BINARY) for DOS/DJGPP also
+
+-      Now using the major() macro for some Linux duties.
+
+       WARNING to creators of Linux distributions:
+
+       It has _always_ been wrong to compile software only once for different 
+       kernel versions (e.g. for compile Linux-2.4 and later install a
+       2.2 kernel on the so created system).
+
+       Now that Linux-2.6 introduces incompatible changes to kernel/user
+       interfaces, the resulting binaries will not work correctly anymore.
+
+-      Made CD-Text handling reentrant to overcome a problem triggered by XCDRoast
+
+-      Now works again suid root on Solaris 9
+
+-      Fix for a Bug that prevents paranoia statistics from being printed
+       because the paranoia statistics for the forked version has not been
+       inside the shared memory.
+
+-      New paranoia sub option paraopts=overlap=xx
+
+       This is mainly a bug fix for cdda2wav. Cdda2wav previously _always_ did
+       completely deactivate the dynamic overlapping from libparanoia. Instead,
+       it did set the overlapping to the statical value 0.
+
+       If you omit paraopts=overlap=xx, cdda2wav will now use dynamic overlapping
+       with -paranoia.
+
+       If you like the old behavior, use: paraopts=overlap=0
+
+-      New paranoia sub option paraopts=minoverlap=xx
+       This sets the minimum dynamic overlap
+
+-      New paranoia sub option paraopts=maxoverlap=xx
+       This sets the maximum dynamic overlap
+
+-      Better paranoia statistics output
+
+-      Fixed a Problem with some Linux sound card drivers that caused cdda2wav to be
+       unable to output to the soundcard.
+
+-      cdda2wav now checks /etc/default/cdrecord and accepts dev=plextor as
+       cdrecord does.
+
+-      Trying to add verbose output that estimates the read quality with -paranoia
+
+-      Trying to convert non-ascii characters in user & host names into '_'
+       for better cddb compatibility.
+
+-      Some Man Page Fixes trying to avoid coding problems for non 7-bit ACSII
+       
+-      New option -scanbus
+
+-      Removed some "historical junk" that caused cdda2wav to define a
+       compile time default input device. This conflicts with cdda2wav -scanbus
+       and is superfluous and contra productive since cdda2wav reads 
+       /etc/default/cdrecord
+
+-      cdda2wav has signed bitfields of size 1 :-(
+
+-      Fixed a typo in cdda2ogg.1
+
+-      Bug fix from Heiko for index lists that contain offset values of -1 in the middle
+
+-      Trying to handle interface setup more carefully if SCSI Generic is not
+       used.
+
+-      Better Debug Code in setuid.c
+
+-      Trying to fix a bug in UID handling on FreeBSD
+       Thanks to the bugs reports and help from Fabian Keil <fk@fabiankeil.de>
+
+-      Try to workaround a bug in GCC that caused incorrect warnings
+       for "strict-aliasing rules"     
+
+
+Readcd:
+
+-      First (hacky) implementation of a way to meter the read speed
+       as a function of the disk location modeled after a idea from
+       Markus Plail <cdrecord@gitteundmarkus.de>
+
+       Call:
+               readcd dev=b,t,l meshpoints=1000 > outfile
+       then
+               gnuplot
+               gnuplot> plot "outfile" w l
+
+       or
+               
+               gnuplot> replot "outfile" w l
+
+       if you like to overlay graphs.
+
+-      New option fs=# (same syntax as with cdrecord fs=#) to allow the
+       user to set the maximum transfer size even in non-interactive mode.
+       This may help is the OS (as it has been the case for Solaris 9 x86)
+       reports a wrong maximum DMA size or there is a bug in libscg.
+
+-      Speed printing with meshpoints=# now is based on 1000 bytes == 1 kb
+       as documented in the SCSI standard.
+
+-      Stop reading if the OS replies with a DMA residual count != 0
+
+-      New option -factor will cause the read speed values to be printed
+       be based on the single speed of the current medium. This is only
+       possible if readcd is able to find out the current medium type.
+
+-      The clone read code is now part of the GPL'd source
+       Note that this part of the code is now more than 2 years old but previously
+       has been excluded from the publically visible part of the source.
+
+       Clone writing has been designed to allow to copy complex structured media
+       like e.g. SVCDs without the need to first do a sector by sector analysis
+       on the source media.
+
+       To understand how to use the clone mode read README.clone
+
+-      New option ts= to set the SCSI transfer buffer size
+
+-      call setmode(fileno, O_BINARY) for DOS/DJGPP also
+
+-      Now works again suid root on Solaris 9
+
+-      Better man page & online help for the ts= option.
+
+-      New option -scanbus
+
+-      Fixed a bug with -scanbus (did not work correctly if /etc/default/cdrecord
+       exists).
+
+-      Added an allocated list of defective sectors, that is printed to the end of
+       a read operation.
+
+
+Scgcheck:
+
+-      Trying to check if multiple scg_open() requests result in
+       usable interfaces.
+
+-      Send more outout to stdout instead of stderr.
+
+-      More correct test for max sense count.
+
+-      Eject CD _after_ asking for it.
+
+-      Abor further DMA residual tests if a basic DMA residual test fails.
+
+-      Second open test enhanced.
+
+-      A small fix to prevent a core dump caused by a problem on Mac OS X.
+
+
+Scgskeleton:
+
+-      New Skeleton program as sample and template for programs that like to 
+       use libscg.
+
+       This template has been included to help people like the Author of the
+       BTC firmware flash program to write simple portable applications that
+       send arbitrary SCSI commands to arbitrary drives.
+
+
+Mkisofs (By Jörg Schilling and James Pearson j.pearson@ge.ucl.ac.uk):
+
+-      First attempt to support ISO-9660:1999 (Version 2) via -iso-level 4
+       This allows 207 chars in filenames if Rock Ridge is not used
+       ans 197 207 chars in filenames if Rock Ridge is used.
+
+       Note that this as an absolutely nontrivial change. Problems may 
+       even occur when not using -iso-level 4. Please test and report
+       problems.
+
+       It is not clear whether mkisofs should characters in the range
+       outside 7-Bit ASCII. Currently, mkisofs allows any 7-Bit ASCII
+       character except '\0' and '/'.
+
+-      Second attempt to support ISO-9660:1999 (Version 2) via -iso-level 4
+       This allows 207 chars in filenames if Rock Ridge is not used
+       and 197 207 chars in filenames if Rock Ridge is used.
+
+       In version 2.01a01 the extended VD used the wrong signature 1.
+       This has been corrected.
+
+-      isoinfo is now able to recognize ISO-9660:1999 
+
+-      Enhanced the filename length for graft points to 2x PATH_MAX
+
+-      Abort with a warning message if the total size of the image data
+       created by mkisofs would differ from the size printed by -print-size
+
+-      udf.c indented according to hints from the program 'cstyle'
+
+-      UDF now uses the same 'now' timestamp as the ISO-9660 part of the FS.
+
+-      New Stream File feature and new options:
+
+       -stream-file-name
+       -stream-media-size
+
+       This feature has been implemented after an idea from M.H. Voase.
+       Mkisofs had to be heavily modified to allow this feature.
+
+       A typical usage would look like this:
+
+       star -c . | mkisofs -stream-media-size 333000 | cdrecord dev=b,t,l -dao tsize=333000s -
+
+       The maximum size of the tar archive is 332800 sectors.
+       Note that only plain vanilla ISO-9660 is possible in this mode.
+
+
+-      The final padding that is added by default is now 150 sectors
+       which is the required size of the track post gap on a CD.
+
+-      Inter partition padding is now only chosen to make the next partition
+       start on a sector number that is a multiple of 16.
+
+-      isoinfo now also prints root directory extent # in debug mode
+
+-      First step to allow mkisofs to support Kodak Photo CD and
+       Kodak Picture CD format:
+
+       Try to correctly support associated files in multi-session mode.
+
+
+-      Diagnostic programs modified to use ttydefs.h and to have better
+       portability for the built in "stty" features.
+
+-      isoinfo now prints the ISO-9660 directory flags.
+
+-      Make mkhybrid a symlink to mkisofs instead of a hardlink
+
+
+-      getopt.h/fnmatch.h  changed to use 'makefiles / prototype.h' based 
+       system instead FSD junk system
+
+-      Removed FSF junk from getopt.c that either created problems
+       with SCO Unixware or did not compile on AIX
+
+-      Prototype for DVDOpenFile() to avoid warning on SCO UnixWare
+       related to enum function parameter
+
+-      Fixed a bug with split symbolic links found by Klaus Kopper
+       with the new debug messages introduced with mkisofs-2.01a04
+
+-      Changed #if __STDC__ to #ifdef PROTOTYPES for better portability
+
+-      Now using character code translation for 8 Bit characters that
+       are used with -iso-level 4 (ISO-9660-1999).
+
+-      Fixed a typo in the on-line Usage information for isoinfo
+
+-      New options -XA & -xa
+
+       -XA     Generate XA iso-directory attributes with original owner
+               and mode information.
+
+       -xa     Generate XA iso-directory attributes with rationalized owner
+               and mode information (user/group == 0).
+
+       In the first phase of the implementation you need to specify -R in
+       addition.
+
+-      Try to support files >= 2 GB.
+       Note that mkisofs is not yet written cleanly so there may be problems
+       if files >= are used. In such a case, please report.
+
+-      Create XA "CD-XA001" signature in PVD with -XA or -xa
+
+       In the first phase of the implementation you need to specify -R in
+       addition to -XA or -xa or no XA signatures will be written.
+
+-      Removed a debug statement that has been introduced to implement
+       support for filees >= 2GB.
+
+-      This version of mkisofs allows to create sectors with 2056 bytes if the
+       option -XA or -xa has been used together with -sectype xa1.
+       This is 2048 bytes + sub-header.
+
+-      -apple does no longer include -R or -r.
+       If you like to use -apple, you need to use -R/-r or -XA/-xa in addition.
+
+-      New option -sectype SECTYPE / -s SECTYPE
+
+       Possible parameters are:
+
+       data    2048 bytes per sector - the old and current default
+
+       xa1     2056 bytes per sector - this is what you need for a conforming
+               CD-ROM XA multi session CD. Use -sectype xa1 together with -XA
+
+-      Fixed a bug in the Rock Ridge symlink handling with Continuation records
+       triggered by '/../' filename components.
+       Thanks to jmmikkel@bbn.com (Joanne M Mikkelson)
+       for the fix.
+
+-      man page corrected
+
+-      Moved Eltorito PVD before ISO-9660:1999 enhanced PCD to allow
+       bootable CD with ISO-9660:1999
+
+-      -sort file handling fixed: mkisofs now looks for SPACE/TAB whatever
+       comes last (as documented in the man page).
+
+-      Better error message in case of a stat(2) buffer overflow (too long
+       filename). This release now prints the file name that caused the problem.
+
+-      call setmode(fileno, O_BINARY) for DOS/DJGPP also
+
+-      Added a NOTE regarding the SILO boot program for Linux sparc to the
+       man page.
+
+-      Added support for Solaris x86 boot CDs.
+       This includes the following new options:
+
+       -       -sunx86-boot    to create a fdisk & SVr4 partition table
+
+       -       -sunx86-label   to set the "disk label" name for the
+                               SVr4 partition table.
+
+-      New file README.sunx86boot
+
+-      The file README.sunx86boot has been reworked to make it more correct
+       and contain less typos.
+
+-      Fixed a Rock-Ridge length handling bug in update_nlink()/increment_nlink() (tree.c)
+       that may have caused an endless loop.
+
+-      "Total extents including sparc boot" Message is now correctly
+       "Total extents including %s boot" sparc/sunx86
+
+-      mkisofs now checks /etc/default/cdrecord and allows e.g.
+       "mkisofs -C 0,1234 dev=plextor ...." as cdrecord does
+
+-      Unclean message ....extents written (%d Mb) changed to
+       ....extents written (%d MB) to avoid "MegaBit" confusion.
+
+-      Minor change for old UNIX versions like SCO OpenServer to get
+       smooth compilation on system where mode_t is a short.
+
+-      Fix for a bug in RockRidge name handling for long file names
+       that need to be split into more than one sector.
+       Thanks to Patrick Ohly <Patrick.Ohly@gmx.de>
+
+-      Trying to fix a bug in the multi session time stamp comparing
+       functions. CE records have not been handled correctly here.
+
+-      Support for PowerPC CHRP Boot added, thanks to
+       "Leigh Brown" <leigh@solinno.co.uk>
+
+-      Support for -uid/-gid for UDF Filesystems added
+
+-      isoinfo now is able to list ElTorito Boot information with -d
+
+-      isoinfo now correctly shows long RR filenames from CE Extension records.
+
+-      Fixed a bug in the PowerPC CHRP Boot, thanks to
+       "Leigh Brown" <leigh@solinno.co.uk>
+
+-      New options -root & -old-root from Patrick Ohly
+       This allows mkisofs to be used for "incremental backups" where
+       each backup is put into a separate directory tree on the CD.
+
+-      Default to System ID "UNIX" for unknown platforms instead of
+       uning LINUX.
+
+-      Support System ID "SCO-OPENSERVER" and "SCO-UNIXWARE"
+
+-      Better error message when a user tries to create a multi session image
+       out of a multi-volume image.
+
+-      When doing malloc(), include Null Byte at end of TRANS_TBL data to
+       avoid memory size conflicts.
+
+-      Fix for a core dump caused by a double free() when doing:
+       echo bar >/tmp/bar
+       echo foo/bar=/tmp/bar > /tmp/pathlist
+       env LD_PRELOAD=libumem.so.1 UMEM_DEBUG=default UMEM_LOGGING=transaction \
+           mkisofs -hfs -graft-points -o /tmp/foo.raw -path-list=/tmp/pathlist
+
+       Thanks to Jürgen Keil jk@tools.de
+
+-      Fixed a typo in write.c "Padbock" -> "Padblock"
+       Thanks to  Richard Dawe <rich@phekda.gotadsl.co.uk>
+
+-      Trying to fix a problem with comparing relaxed ISO-9660 file names
+       that contain a ';' which normally is a separator for the ISO-9660
+       version number. The fix is in hash.c, please test!
+
+-      Avoid GCCs shadowed variable warnings.
+
+-      Added a comment is in hope to prevent silly people from
+       e.g. SuSE (who did not yet learn C but believe that
+       they need to patch other peoples code) from changing a
+       valid cast into an illegal lhs cast expression.
+       The cast in the unodified version of write.c is the correct way to
+       handle the problem.
+
+       It would save a lot of time if people from companies like SuSE
+       would remember the Open Source software development model and
+       contact the Author for help rather than introducing proprietary
+       changes that result in worse and incompatible software variants.
+
+       The way, companies like SuSE deal with Open Source software just
+       proves that Jonathan Schwartz from Sun is not wrong when he calls
+       SuSE and RedHat proprietary software companies. Users from Open Source
+       software expect that companies like SuSE and RedHat are in close
+       contact with the software developers but they unfortunately are not.
+       They prefer to create proprietary variants that are usually much
+       worse than the original software. The only explanation I have for this
+       behaviour is that SuSE likes to deviate from RedHat and RedHat likes
+       to deviate from SuSE in hope to get customer retention this way.
+       While the last 150 years did prove that this proprietary method to
+       tie up customers works for a limited time, it did always fail after
+       some time.
+
+-      Removed verbose output for Eltorito boot method when called with -quiet
+
+-      The Eltorito boot catalog and the Eltorito boot files are now by default
+       sorted to the beginning of the filesystem image as sime BIOS versions don't
+       boot from locations beyond 512 MB.
+
+-      All programs from mkisofs/diag now support libscg so you may now 
+       use e.g. isoinfo to list end extract from CDs directly on platforms 
+       that do not support a usual driver interface (like on Win32).
+
+-      Set default SYSID to "DOS" for DJGPP
+       Thanks to Alex Kopylov <reanimatolog@yandex.ru>
+
+-      devdump isodebug isodump isoinfo isovfy
+       now include libscg and allow to use SCSI devices as input
+
+-      devdump isodebug isodump isoinfo isovfy
+       now implement a new option dev= to force to use the SCSI 
+       interface from libscg.
+
+-      isoinfo now correctly sets the filemode of stdout to O_BINARY
+       on DOS alike Platforms like Win32 & DJGPP
+       This affects the '-x pathname' option
+       Thanks to Alex Kopylov <reanimatolog@yandex.ru>
+
+-      The options -H/-L/-P from mkisofs have been marked "outdated"
+       as they are reserved by POSIX.1-2001 for other purposes.
+
+       Mkisofs-2.02 will start to implement the POSIX.1-2001 semantics for
+       these options.
+
+-      The max. length for the strings in the Primary volume descriptor
+       is now also documented in the options section of the man page.
+
+-      Speed up by 30% in the case that a directory contains many (> 5000)
+       pathological file name entries (that _all_ do not differ in 8.3).
+
+-      A minor speed up in devdump & isodump was made by no longer calling
+       strlen() in the end condition of a for loop (this still was old
+       code from Eric).
+
+-      fixed a bug with -dvd-video
+       The bug caused mkisofs not to find the IFO file when VIDEO_TS was not
+       the first entry in the unsorted source directory.
+       Thanks to a hint from Johan Borg borg@morth.org
+
+-      The option -volset-size does no longer accept numbers > 1
+
+       This change was needed because Eric Youngdale did completely
+       missunderstand the ISO-9660 standard with respect to Volume Set
+       Sizes.
+
+       A Volume Set is not a numbered set of CDs but a set of CDs that
+       contains a coherent directory tree that would not fit on a single
+       volume.
+
+-      Fixed a typo in the mkisofs man page
+
+-      man page enhanced to make clear that the options
+       -no-split-symlink-fields & -no-split-symlink-components
+       are most likely not needed as they have been introduced by Eric Youngdale
+       when serious bugs have been in mkisofs.
+
+-      Changelog updated
+
+-      Try to workaround a bug in GCC that caused incorrect warnings
+       for "strict-aliasing rules"     
+
+TODO:
+       -       read Joliet filenames with multi-session if no TRANS.TBL
+               or RR is present. I am looking for a volunteer for this task!
+
+               Note that this can never be 100% correct as there is no relation
+               between the names on the master (UNIX) filesystem, the ISO-9660
+               names and the Joliet names. Only the Rock Ridge names are
+               untranslated with respect to the original files on the
+               master (UNIX) filesystem.
+
+       -       add libecc/edc for CDI and similar.
+
+
+CYGWIN NT-4.0 NOTES:
+
+To compile on Cygwin32, get Cygwin and install it.
+For more information read README.win32
+
+The files are located on:
+
+ftp://ftp.berlios.de/pub/cdrecord/alpha ...
+
+NOTE:  These tar archives are 100% POSIX compatible. GNU tar may get some
+       minor trouble. If you like a 100% POSIX compliant tar, get star from
+       ftp://ftp.berlios.de/pub/star/
+
+WARNING: Do not use 'winzip' to extract the tar file!
+       Winzip cannot extract symbolic links correctly.
+
+Joerg
diff --git a/doc/ANNOUNCEMENTs/AN-2.01.01a01 b/doc/ANNOUNCEMENTs/AN-2.01.01a01
new file mode 100644 (file)
index 0000000..2d3a1eb
--- /dev/null
@@ -0,0 +1,91 @@
+Please have a look at the German open Source Center BerliOS at www.berlios.de
+BerliOS will continue to support free hosting of cryptography projects even
+when US laws change and don't allow to host cryptography projects in the USA.
+Also look at sourcewell.berlios.de, the first Open Source announcement service
+that itself is implemented as Open Source project.
+
+***************** Important news ****************************
+
+For the 'Slottable Source Plugin Module' SSPM Features read README.SSPM
+
+***************** Please Test *********************************
+
+NEW features of cdrtools-2.01.01a01:
+
+*******
+NOTE: this is _not_ a release that starts a new aplha/beta series of dirtibutions.
+       The only reason is to add certain new CD/DVD features that are important.
+
+       So _please_ do not send any patches except when you like to fix extreme bugs.
+       I am currently mainly working on stable incremental restore featurs for star-1.5-final.
+       Once star-1.5-final is out, cdrtools will start a new developent cycle.
+*******
+
+All:
+
+-      Better lint make rules
+
+-      Better autoconf rrules for ACLs
+
+-      Better support for Linux on IBM-390
+
+-      Better support for Linux on AMD x86-64
+
+-      Better conforming to lint warnings.
+
+Libparanoia (Ported by Jörg Schilling, originated by Monty xiphmont@mit.edu):
+
+Libedc (Optimized by Jörg Schilling, originated by Heiko Eißfeldt heiko@hexco.de):
+
+Libscg:
+
+-      Modified the remote SCSI library stuff that has been changed due
+       to a security problem on order to make it compile again on HP-UX.
+
+Rscsi:
+
+Cdrecord:
+
+-      Support for the Plextor GigaRec feature.
+       Use driveropts=gigarec=1.2 to increase CD capacity by 20%.
+
+Cdda2wav (By Heiko Eißfeldt heiko@hexco.de):
+
+Readcd:
+
+Scgcheck:
+
+Scgskeleton:
+
+Mkisofs (By Jörg Schilling and James Pearson j.pearson@ge.ucl.ac.uk):
+
+TODO:
+       -       read Joliet filenames with multi-session if no TRANS.TBL
+               or RR is present. I am looking for a volouteer for this task!
+
+               Note that this can never be 100% correct as there is no relation
+               between the names on the master (UNIX) filesystem, the ISO-9660
+               names and the Joliet names. Only the Rock Ridge names are
+               untranslated with respect to the original files on the
+               master (UNIX) filesystem.
+
+       -       add libecc/edc for CDI and similar.
+
+
+CYGWIN NT-4.0 NOTES:
+
+To compile on Cygwin32, get Cygwin and install it.
+For more information read README.win32
+
+The files are located on:
+
+ftp://ftp.berlios.de/pub/cdrecord/alpha ...
+
+NOTE:  These tar archives are 100% POSIX compatible. GNU tar may get some
+       minor trouble. If you like a 100% POSIX compliant tar, get star from
+       ftp://ftp.berlios.de/pub/star/
+
+WARNING: Do not use 'winzip' to extract the tar file!
+       Winzip cannot extract symbolic links correctly.
+
+Joerg
diff --git a/doc/ANNOUNCEMENTs/AN-2.01.01a03 b/doc/ANNOUNCEMENTs/AN-2.01.01a03
new file mode 100644 (file)
index 0000000..e7819a2
--- /dev/null
@@ -0,0 +1,150 @@
+Please have a look at the German open Source Center BerliOS at www.berlios.de
+BerliOS will continue to support free hosting of cryptography projects even
+when US laws change and don't allow to host cryptography projects in the USA.
+Also look at sourcewell.berlios.de, the first Open Source announcement service
+that itself is implemented as Open Source project.
+
+***************** Important news ****************************
+
+For the 'Slottable Source Plugin Module' SSPM Features read README.SSPM
+
+***************** Please Test *********************************
+
+NEW features of cdrtools-2.01.01a02:
+
+*******
+NOTE: this is _not_ a release that starts a new aplha/beta series of dirtibutions.
+       The only reason is to add certain new CD/DVD features that are important.
+
+       So _please_ do not send any patches except when you like to fix extreme bugs.
+       I am currently mainly working on stable incremental restore featurs for star-1.5-final.
+       Once star-1.5-final is out, cdrtools will start a new developent cycle.
+*******
+
+All:
+
+-      Now using "makefiles-1.5"
+
+-      Compilation on OS/ should work again (-Zexe -> -o xxx.$(EXEEXT)
+
+-      Sleeptime to allow reading Gmake warning reduced to 2 seconds.
+       I am still waiting for GNU make to fix the bugs I did report in 1999.
+
+-      Support for 'make DESTDIR=xxx install' added
+
+-      Workaround for a Shell Bug on BSDi
+
+-      Install workaround for the fact that BSDI has chown(1) in /usr/sbin/
+
+-      cc-config shell script reworked
+
+-      Better configure tests for procfs include files
+
+-      Configure tests for fchown, chmod, fchmod, lchmod, futimes, lutimes
+
+-      Configure tests for fdopendir
+
+-      Configure tests for broken ext2fs includes files in Linux kernel
+
+-      Better SRCROOT search function in makefiles shell scripts
+
+-      libunls reworked
+
+-      New autoconf tests for broken <linux/ext2_fs.h>, <scsi/scsi.h> & <scsi/sg.h>
+       on various Linux systems
+
+
+Libparanoia (Ported by Jörg Schilling, originated by Monty xiphmont@mit.edu):
+
+Libedc (Optimized by Jörg Schilling, originated by Heiko Eißfeldt heiko@hexco.de):
+
+Libscg:
+
+-      Trying to introduce a workaround for broken <scsi/scsi.h> & <scsi/sg.h>
+       on various Linux systems.
+
+-      Trying to introduce a workaround for the changed SCSI generic Linux
+       Kernel interface from Linux-2.6.8.1 and newer.
+
+       Be very careful with testing. The Linux adption layer for libscg
+       is already full of workarounds for bugs, unstable interfaces and
+       unwillingness of the Linux Kernel maintainers to give access to the
+       needed information for libscg. I am not sure whether this workaround
+       will not have problems. It has been tested on a Pegasus PPC running
+       Linux-2.6.8.1
+
+Rscsi:
+
+Cdrecord:
+
+-      Allow the -shorttrack option for RAW mode, thanks to a report
+       from Sebastian Trueg
+
+-      Enhance the minimal grace time from 2 to 3 seconds to make sure
+       that cdrecord will not get out of sync with locks from the 
+       Volume management system.
+
+-      Better checks and better error messages for /etc/default/cdrecord
+
+-      Correct verbose print mode for old pre-MMC TEAC drives.
+
+-      Added support for Ultra speed+ CD-RW media recognition and a check
+       whether the drive supports Ultra speed+ CD-RW media.
+       (Thanks to Alexander Noé).
+       
+
+Cdda2wav (By Heiko Eißfeldt heiko@hexco.de):
+
+Readcd:
+
+Scgcheck:
+
+Scgskeleton:
+
+Mkisofs (By Jörg Schilling and James Pearson j.pearson@ge.ucl.ac.uk):
+
+-      Better error messages with wrong Eltorito boot options
+
+-      Man page is now more explicit about requirements for DVD-video
+       directory trees.
+
+-      Better warning text for missing Rock Ridge in multi.c
+
+-      Bugs in README.sunx86boot corrected
+
+-      Multi Volume code for reading old image now gives different
+       error messages on read errors and short reads.
+
+-      Diagnostic programs isodump, isoinfo, ... no longer dump core 
+       when called with dev=<SCSI addr> parameters.
+
+TODO:
+       -       read Joliet filenames with multi-session if no TRANS.TBL
+               or RR is present. I am looking for a volouteer for this task!
+
+               Note that this can never be 100% correct as there is no relation
+               between the names on the master (UNIX) filesystem, the ISO-9660
+               names and the Joliet names. Only the Rock Ridge names are
+               untranslated with respect to the original files on the
+               master (UNIX) filesystem.
+
+       -       add libecc/edc for CDI and similar.
+
+
+CYGWIN NT-4.0 NOTES:
+
+To compile on Cygwin32, get Cygwin and install it.
+For more information read README.win32
+
+The files are located on:
+
+ftp://ftp.berlios.de/pub/cdrecord/alpha ...
+
+NOTE:  These tar archives are 100% POSIX compatible. GNU tar may get some
+       minor trouble. If you like a 100% POSIX compliant tar, get star from
+       ftp://ftp.berlios.de/pub/star/
+
+WARNING: Do not use 'winzip' to extract the tar file!
+       Winzip cannot extract symbolic links correctly.
+
+Joerg
diff --git a/doc/ANNOUNCEMENTs/AN-2.01.01a04 b/doc/ANNOUNCEMENTs/AN-2.01.01a04
new file mode 100644 (file)
index 0000000..7acaf29
--- /dev/null
@@ -0,0 +1,164 @@
+Please have a look at the German open Source Center BerliOS at www.berlios.de
+BerliOS will continue to support free hosting of cryptography projects even
+when US laws change and don't allow to host cryptography projects in the USA.
+Also look at sourcewell.berlios.de, the first Open Source announcement service
+that itself is implemented as Open Source project.
+
+***************** Important news ****************************
+
+For the 'Slottable Source Plugin Module' SSPM Features read README.SSPM
+
+***************** Please Test *********************************
+
+NEW features of cdrtools-2.01.01a04:
+
+*******
+NOTE: this is _not_ a release that starts a new aplha/beta series of dirtibutions.
+       The only reason is to add certain new CD/DVD features that are important.
+
+       So _please_ do not send any patches except when you like to fix extreme bugs.
+       I am currently mainly working on stable incremental restore featurs for star-1.5-final.
+       Once star-1.5-final is out, cdrtools will start a new developent cycle.
+*******
+
+All:
+
+-      astoull*() new in schily.h
+
+-      utypes.h now has MAX_ and MIN_ value definitions for all basic
+       system types.
+
+-      Using Makefiles-1.5a02
+
+-      Support added to compile in 64 bit mode on Solaris Sparc.
+       Use: smake CCOM=cc64
+
+-      Support added to compile shared libraries with version
+       numbers for interface levels and make inofficial "interfaces"
+       static
+
+-      Prevent gmake to go into an enless loop on Solaris
+       in case that /usr/ucb/tr is before /usr/bin/tr in PATH
+
+-      Better autoconf error message ion case that the expected
+       C-compiler could not be found.
+
+-      Mac OS X now installs files as root:wheel
+
+-      Supply linker mapfiles for all libraries. This allows cdrtools
+       to be compiles using shared libraries only and to properly 
+       hide inofficial interfaces on Solaris (using ls)
+       Note that this feature is not available with GNU ld
+
+
+Libparanoia (Ported by Jörg Schilling, originated by Monty xiphmont@mit.edu):
+
+Libedc (Optimized by Jörg Schilling, originated by Heiko Eißfeldt heiko@hexco.de):
+
+Libscg:
+
+-      Autoconf test for broken Linux sg.h headers added
+
+-      if libscg is compiles on newer Solaris systems, the warning:
+
+       "Warning: Volume management is running, medialess managed drives are invisible.\n"
+
+       is no longer printed.
+
+       Since Solaris 11 Build 21, vold no longer hides empty drives 
+       that are under volume management. This now allows cdrecord to be even 
+       used to close the tray while vold is running.
+
+       The criteria used to decide whether Solaris is "recent enough" is 
+       #ifndef SEEK_HOLE
+       The definition SEEK_HOLE has been added with Solaris 11 Build 14
+       while the fixed vold appears in Solaris 11 Build 21.
+
+-      Support for root-less cdrecord using fine-grained privileges.
+       Remote SCSI not tests for PRIV_NET_PRIVADDR instead of (geteuid() == 0)
+
+       If you like all users to be able to call cdrecord root-less, you need
+       Solaris 10 or newer.
+
+       Edit the file /etc/security/exec_attr and add:
+
+       All:solaris:cmd:::/opt/schily/bin/cdrecord: privs=file_dac_read,sys_devices,proc_lock_memory,proc_priocntl,net_privaddr
+       All:solaris:cmd:::/opt/schily/bin/readcd: privs=file_dac_read,sys_devices,net_privaddr
+       All:solaris:cmd:::/opt/schily/bin/cdda2wav: privs=file_dac_read,sys_devices,net_privaddr
+
+       If you like to allow only specific user to use cdrecord,
+       use something like:
+
+       CD RW:solaris:cmd:::/opt/schily/bin/cdrecord: privs=file_dac_read,sys_devices,proc_lock_memory,proc_priocntl,net_privaddr
+
+       instead and make the users members of the profile "CD RW"
+       by adding a line like:
+
+       joerg::::profiles=CD RW
+
+       into /etc/user_attr
+
+       Note that you either need to call cdrecord via "pfexec cdrecord ....."
+       or by using a profile aware shell (e.g. /usr/bin/pfksh)
+
+Rscsi:
+
+Cdrecord:
+
+-      Correctly evaluate the write speeds for Ultra speed+ CD-RW media.
+       This prevents wrong warnings that the "drive does not support Ultra speed+"
+
+-      Fixed a typo in the driveropts=help messages
+
+
+Cdda2wav (By Heiko Eißfeldt heiko@hexco.de):
+
+-      Added a workaround for the _POSIX_PRIORITY_SCHEDULING behavior
+       on MacosX: defined but not supported#
+       Thanks to: Emanuele Giaquinta <e.giaquinta@glauco.it>
+
+-      Bugfix: cdda2wav did previously chose to ignore the result of realloc(3)
+       This prevents core-dumps.
+
+Readcd:
+
+Scgcheck:
+
+Scgskeleton:
+
+Mkisofs (By Jörg Schilling and James Pearson j.pearson@ge.ucl.ac.uk):
+
+-      mkisofs now detects if a file grows or shrinks while being
+       read by mkisofs.
+
+
+TODO:
+       -       read Joliet filenames with multi-session if no TRANS.TBL
+               or RR is present. I am looking for a volouteer for this task!
+
+               Note that this can never be 100% correct as there is no relation
+               between the names on the master (UNIX) filesystem, the ISO-9660
+               names and the Joliet names. Only the Rock Ridge names are
+               untranslated with respect to the original files on the
+               master (UNIX) filesystem.
+
+       -       add libecc/edc for CDI and similar.
+
+
+CYGWIN NT-4.0 NOTES:
+
+To compile on Cygwin32, get Cygwin and install it.
+For more information read README.win32
+
+The files are located on:
+
+ftp://ftp.berlios.de/pub/cdrecord/alpha ...
+
+NOTE:  These tar archives are 100% POSIX compatible. GNU tar may get some
+       minor trouble. If you like a 100% POSIX compliant tar, get star from
+       ftp://ftp.berlios.de/pub/star/
+
+WARNING: Do not use 'winzip' to extract the tar file!
+       Winzip cannot extract symbolic links correctly.
+
+Joerg
diff --git a/doc/ANNOUNCEMENTs/AN-2.01.01a05 b/doc/ANNOUNCEMENTs/AN-2.01.01a05
new file mode 100644 (file)
index 0000000..f52ab26
--- /dev/null
@@ -0,0 +1,143 @@
+Please have a look at the German open Source Center BerliOS at www.berlios.de
+BerliOS will continue to support free hosting of cryptography projects even
+when US laws change and don't allow to host cryptography projects in the USA.
+Also look at sourcewell.berlios.de, the first Open Source announcement service
+that itself is implemented as Open Source project.
+
+***************** Important news ****************************
+
+For the 'Slottable Source Plugin Module' SSPM Features read README.SSPM
+
+***************** Please Test *********************************
+
+NEW features of cdrtools-2.01.01a05:
+
+*******
+NOTE: this is _not_ a release that starts a new aplha/beta series of dirtibutions.
+       The only reason is to add certain new CD/DVD features that are important.
+
+       So _please_ do not send any patches except when you like to fix extreme bugs.
+       I am currently mainly working on stable incremental restore featurs for star-1.5-final.
+       Once star-1.5-final is out, cdrtools will start a new developent cycle.
+*******
+
+All:
+
+-      Support for DragonFly BSD added, thanks to joerg@britannica.bec.de
+
+-      Default Cygwin install uid/group adapted to use available ids.
+
+-      Updated the (forgotten) autoconf to include the tests needed for Solaris
+       fine grained privileges.
+
+-      New program btcflash added. Thanks to David Huang <khym@azeotrope.org>
+
+-
+       If you like all users to be able to call cdrecord root-less, you need
+       Solaris 10 or newer.
+
+       Edit the file /etc/security/exec_attr and add:
+
+       All:solaris:cmd:::/opt/schily/bin/cdrecord: privs=file_dac_read,sys_devices,proc_lock_memory,proc_priocntl,net_privaddr
+       All:solaris:cmd:::/opt/schily/bin/readcd: privs=file_dac_read,sys_devices,net_privaddr
+       All:solaris:cmd:::/opt/schily/bin/cdda2wav: privs=file_dac_read,sys_devices,proc_priocntl,net_privaddr
+
+       If you like to allow only specific user to use cdrecord,
+       use something like:
+
+       CD RW:solaris:cmd:::/opt/schily/bin/cdrecord: privs=file_dac_read,sys_devices,proc_lock_memory,proc_priocntl,net_privaddr
+
+       instead and make the users members of the profile "CD RW"
+       by adding a line like:
+
+       joerg::::profiles=CD RW
+
+       into /etc/user_attr
+
+       Note that you either need to call cdrecord via "pfexec cdrecord ....."
+       or by using a profile aware shell (e.g. /usr/bin/pfksh)
+
+
+Libparanoia (Ported by Jörg Schilling, originated by Monty xiphmont@mit.edu):
+
+Libedc (Optimized by Jörg Schilling, originated by Heiko Eißfeldt heiko@hexco.de):
+
+Libscg:
+
+-      Support for root-less cdrecord using fine-grained privileges.
+       Remote SCSI not tests for PRIV_NET_PRIVADDR instead of (geteuid() == 0)
+       This is now active since the needed autoconf code is out.
+
+Rscsi:
+
+Cdrecord:
+
+-      Trying to work around a noncompliance (modified interface) present on newer
+       Linux kernels that causes cdrecord to be unable to allocate a SCSI transfer
+       buffer.
+
+       Newer Linux kernels do not honor a contract from mlockall(MCL_FUTURE)
+       after cdrecord turned off euid == 0 from a suid root installation.
+       Instead of honoring mlockall(MCL_FUTURE), Linux checks each mmap()
+       and compares against getrlimit(RLIMIT_MEMLOCK
+
+-      Explicit fine grained privileges support for Solaris.
+       Cdrecord now switches off all privs that are no longer needed.
+
+
+Cdda2wav (By Heiko Eißfeldt heiko@hexco.de):
+
+-      Explicit fine grained privileges support for Solaris.
+       Cdda2wav now switches off all privs that are no longer needed.
+
+Readcd:
+
+-      Allow readcd to work correctly in -scanbus mode
+       Thanks to Fabian Keil <fk@fabiankeil.de> for reporting.
+
+-      Explicit fine grained privileges support for Solaris.
+       readcd now switches off all privs that are no longer needed.
+
+Scgcheck:
+
+Scgskeleton:
+
+-      Allow readcd to work correctly in -scanbus mode
+       Thanks to Fabian Keil <fk@fabiankeil.de> for reporting.
+
+-      Explicit fine grained privileges support for Solaris.
+       Scgskeleton now switches off all privs that are no longer needed.
+
+Mkisofs (By Jörg Schilling and James Pearson j.pearson@ge.ucl.ac.uk):
+
+
+TODO:
+       -       read Joliet filenames with multi-session if no TRANS.TBL
+               or RR is present. I am looking for a volouteer for this task!
+
+               Note that this can never be 100% correct as there is no relation
+               between the names on the master (UNIX) filesystem, the ISO-9660
+               names and the Joliet names. Only the Rock Ridge names are
+               untranslated with respect to the original files on the
+               master (UNIX) filesystem.
+
+       -       add libecc/edc for CDI and similar.
+
+
+CYGWIN NT-4.0 NOTES:
+
+To compile on Cygwin32, get Cygwin and install it.
+For more information read README.win32
+
+The files are located on:
+
+ftp://ftp.berlios.de/pub/cdrecord/alpha ...
+
+NOTE:  These tar archives are 100% POSIX compatible. GNU tar may get some
+       minor trouble. If you like a 100% POSIX compliant tar, get star from
+       ftp://ftp.berlios.de/pub/star/
+
+WARNING: Do not use 'winzip' to extract the tar file!
+       Winzip cannot extract symbolic links correctly.
+
+Joerg
diff --git a/doc/ANNOUNCEMENTs/AN-2.01.01a06 b/doc/ANNOUNCEMENTs/AN-2.01.01a06
new file mode 100644 (file)
index 0000000..8a4f3e6
--- /dev/null
@@ -0,0 +1,141 @@
+Please have a look at the German open Source Center BerliOS at www.berlios.de
+BerliOS will continue to support free hosting of cryptography projects even
+when US laws change and don't allow to host cryptography projects in the USA.
+Also look at sourcewell.berlios.de, the first Open Source announcement service
+that itself is implemented as Open Source project.
+
+***************** Important news ****************************
+
+For the 'Slottable Source Plugin Module' SSPM Features read README.SSPM
+
+***************** Please Test *********************************
+
+NEW features of cdrtools-2.01.01a06:
+
+*******
+NOTE: this is _not_ a release that starts a new aplha/beta series of dirtibutions.
+       The only reason is to add certain new CD/DVD features that are important.
+
+       So _please_ do not send any patches except when you like to fix extreme bugs.
+       I am currently mainly working on stable incremental restore featurs for star-1.5-final.
+       Once star-1.5-final is out, cdrtools will start a new developent cycle.
+*******
+
+All:
+
+-      Better support for BeOS/Zeta in the makefile system
+
+-      Support for armv5teb-linux-cc was added to the makefile system
+
+-
+       If you like all users to be able to call cdrecord root-less, you need
+       Solaris 10 or newer.
+
+       Edit the file /etc/security/exec_attr and add:
+
+       All:solaris:cmd:::/opt/schily/bin/cdrecord: privs=file_dac_read,sys_devices,proc_lock_memory,proc_priocntl,net_privaddr
+       All:solaris:cmd:::/opt/schily/bin/readcd: privs=file_dac_read,sys_devices,net_privaddr
+       All:solaris:cmd:::/opt/schily/bin/cdda2wav: privs=file_dac_read,sys_devices,proc_priocntl,net_privaddr
+
+       If you like to allow only specific user to use cdrecord,
+       use something like:
+
+       CD RW:solaris:cmd:::/opt/schily/bin/cdrecord: privs=file_dac_read,sys_devices,proc_lock_memory,proc_priocntl,net_privaddr
+
+       Also edit /etc/security/prof_attr
+
+       CD RW:::CD-R/RW Recording Authorizations:auths=solaris.device.cdrw
+
+       instead and make the users members of the profile "CD RW"
+       by adding a line like:
+
+       joerg::::profiles=CD RW
+
+       into /etc/user_attr
+
+       Note that you either need to call cdrecord via "pfexec cdrecord ....."
+       or by using a profile aware shell (e.g. /usr/bin/pfksh)
+
+
+Libparanoia (Ported by Jörg Schilling, originated by Monty xiphmont@mit.edu):
+
+Libedc (Optimized by Jörg Schilling, originated by Heiko Eißfeldt heiko@hexco.de):
+
+Libscg:
+
+-      BeOS/Zeta libscg low level adoption code fixed.
+       The code now is passing a "scgcheck" test.
+
+Rscsi:
+
+Cdrecord:
+
+-      Adjust some timeouts to prevent that the drive buffer of
+       newer Pioneer DVD writers empties when writing high speed DVD
+       media.
+
+-      Support for BeOS/Zeta shared memory was added
+
+-      New tag CDR_MAXFIFOSIZE= in /etc/default/cdrecord allows to
+       limit the size of the FIFO cdrecord is using. This helps the 
+       sysadmin to prevent other people from locking up the system.
+
+Cdda2wav (By Heiko Eißfeldt heiko@hexco.de):
+
+Readcd:
+
+-      Support for BeOS/Zeta shared memory was added
+
+-      -scanbus behavior corrected
+
+Scgcheck:
+
+-      Fixed DMA overrun test. BeOS/Zeta did pass the test but
+       scgcheck did complain before.
+
+Scgskeleton:
+
+-      -scanbus behavior corrected
+
+Btcflash:
+
+-      -scanbus behavior corrected
+
+-      man page added
+
+Mkisofs (By Jörg Schilling and James Pearson j.pearson@ge.ucl.ac.uk):
+
+-      try to work around a GCC trigraph problem
+
+-      man pages for diag commands added
+
+TODO:
+       -       read Joliet filenames with multi-session if no TRANS.TBL
+               or RR is present. I am looking for a volouteer for this task!
+
+               Note that this can never be 100% correct as there is no relation
+               between the names on the master (UNIX) filesystem, the ISO-9660
+               names and the Joliet names. Only the Rock Ridge names are
+               untranslated with respect to the original files on the
+               master (UNIX) filesystem.
+
+       -       add libecc/edc for CDI and similar.
+
+
+CYGWIN NT-4.0 NOTES:
+
+To compile on Cygwin32, get Cygwin and install it.
+For more information read README.win32
+
+The files are located on:
+
+ftp://ftp.berlios.de/pub/cdrecord/alpha ...
+
+NOTE:  These tar archives are 100% POSIX compatible. GNU tar may get some
+       minor trouble. If you like a 100% POSIX compliant tar, get star from
+       ftp://ftp.berlios.de/pub/star/
+
+WARNING: Do not use 'winzip' to extract the tar file!
+       Winzip cannot extract symbolic links correctly.
+
+Joerg
diff --git a/doc/ANNOUNCEMENTs/AN-2.01.01a07 b/doc/ANNOUNCEMENTs/AN-2.01.01a07
new file mode 100644 (file)
index 0000000..2bac2f6
--- /dev/null
@@ -0,0 +1,96 @@
+Please have a look at the German open Source Center BerliOS at www.berlios.de
+BerliOS will continue to support free hosting of cryptography projects even
+when US laws change and don't allow to host cryptography projects in the USA.
+Also look at sourcewell.berlios.de, the first Open Source announcement service
+that itself is implemented as Open Source project.
+
+***************** Important news ****************************
+
+For the 'Slottable Source Plugin Module' SSPM Features read README.SSPM
+
+***************** Please Test *********************************
+
+NEW features of cdrtools-2.01.01a07:
+
+*******
+NOTE: this is _not_ a release that starts a new aplha/beta series of dirtibutions.
+       The only reason is to add certain new CD/DVD features that are important.
+
+       So _please_ do not send any patches except when you like to fix extreme bugs.
+       I am currently mainly working on stable incremental restore featurs for star-1.5-final.
+       Once star-1.5-final is out, cdrtools will start a new developent cycle.
+*******
+
+All:
+
+-      Autoconf script added to 'conf' directory
+
+Libparanoia (Ported by Jörg Schilling, originated by Monty xiphmont@mit.edu):
+
+Libedc (Optimized by Jörg Schilling, originated by Heiko Eißfeldt heiko@hexco.de):
+
+Libscg:
+
+Rscsi:
+
+Cdrecord:
+
+-      Fixed a bug caused by an uninitalized variable when handling
+       CDR_MAXFIFOSIZE= and no file /etc/default/cdrecord exists
+
+Cdda2wav (By Heiko Eißfeldt heiko@hexco.de):
+
+-      Write correct error info in case that BeOS/Zeta *_area() calls
+       fail.
+
+-      As Heiko did not work on cdda2wav during the past 2.5 years,
+       Heiko did hand over the SCCS history for cdda2wav.
+
+-      Autoconf test for <sys/cdio.h> added (FreeBSD)
+
+-      Some FreeBSD related changes from Heiko done in 2004
+
+       IMPORTANT:      I need testers for FreeBSD and DragonFly BSD as
+                       a result of the merge with the complex changes
+                       from Heiko.
+
+Readcd:
+
+Scgcheck:
+
+Scgskeleton:
+
+Btcflash:
+
+Mkisofs (By Jörg Schilling and James Pearson j.pearson@ge.ucl.ac.uk):
+
+TODO:
+       -       read Joliet filenames with multi-session if no TRANS.TBL
+               or RR is present. I am looking for a volouteer for this task!
+
+               Note that this can never be 100% correct as there is no relation
+               between the names on the master (UNIX) filesystem, the ISO-9660
+               names and the Joliet names. Only the Rock Ridge names are
+               untranslated with respect to the original files on the
+               master (UNIX) filesystem.
+
+       -       add libecc/edc for CDI and similar.
+
+
+CYGWIN NT-4.0 NOTES:
+
+To compile on Cygwin32, get Cygwin and install it.
+For more information read README.win32
+
+The files are located on:
+
+ftp://ftp.berlios.de/pub/cdrecord/alpha ...
+
+NOTE:  These tar archives are 100% POSIX compatible. GNU tar may get some
+       minor trouble. If you like a 100% POSIX compliant tar, get star from
+       ftp://ftp.berlios.de/pub/star/
+
+WARNING: Do not use 'winzip' to extract the tar file!
+       Winzip cannot extract symbolic links correctly.
+
+Joerg
diff --git a/doc/ANNOUNCEMENTs/AN-2.01.01a08 b/doc/ANNOUNCEMENTs/AN-2.01.01a08
new file mode 100644 (file)
index 0000000..b45988c
--- /dev/null
@@ -0,0 +1,96 @@
+Please have a look at the German open Source Center BerliOS at www.berlios.de
+BerliOS will continue to support free hosting of cryptography projects even
+when US laws change and don't allow to host cryptography projects in the USA.
+Also look at sourcewell.berlios.de, the first Open Source announcement service
+that itself is implemented as Open Source project.
+
+***************** Important news ****************************
+
+For the 'Slottable Source Plugin Module' SSPM Features read README.SSPM
+
+***************** Please Test *********************************
+
+NEW features of cdrtools-2.01.01a08:
+
+*******
+NOTE: this is _not_ a release that starts a new aplha/beta series of dirtibutions.
+       The only reason is to add certain new CD/DVD features that are important.
+
+       So _please_ do not send any patches except when you like to fix extreme bugs.
+       I am currently mainly working on stable incremental restore featurs for star-1.5-final.
+       Once star-1.5-final is out, cdrtools will start a new developent cycle.
+*******
+
+All:
+
+Libparanoia (Ported by Jörg Schilling, originated by Monty xiphmont@mit.edu):
+
+Libedc (Optimized by Jörg Schilling, originated by Heiko Eißfeldt heiko@hexco.de):
+
+Libscg:
+
+Rscsi:
+
+Cdrecord:
+
+Cdda2wav (By Heiko Eißfeldt heiko@hexco.de):
+
+-      Started to make cdda2wav Cstyle compliant.
+
+-      Avoid to shutdown the whole system when kill(getppid(), SKGINT)
+       would result in kill -INT 1 because the parent cdda2wav is
+       dead and the child is orphaned and cdda2wav has been called by root.
+
+-      __FreeBSD_version >= 600021 have devmajor == 0 for all devices.
+       Thanks to Marius Strobl <marius@alchemy.franken.de> for reporting.
+
+-      General #ifdef structure related to FreeBSD in mycdrom.h now
+       corrected, thanks to Marius Strobl.
+
+-      Try to fix some FreeBSD/DragonFly related problems that have been
+       introduced with a06 when Heiko's changes from 2004 have been integrated
+
+       IMPORTANT:      I need testers for FreeBSD and DragonFly BSD as
+                       a result of the merge with the complex changes
+                       from Heiko.
+
+Readcd:
+
+Scgcheck:
+
+Scgskeleton:
+
+Btcflash:
+
+Mkisofs (By Jörg Schilling and James Pearson j.pearson@ge.ucl.ac.uk):
+
+TODO:
+       -       read Joliet filenames with multi-session if no TRANS.TBL
+               or RR is present. I am looking for a volouteer for this task!
+
+               Note that this can never be 100% correct as there is no relation
+               between the names on the master (UNIX) filesystem, the ISO-9660
+               names and the Joliet names. Only the Rock Ridge names are
+               untranslated with respect to the original files on the
+               master (UNIX) filesystem.
+
+       -       add libecc/edc for CDI and similar.
+
+
+CYGWIN NT-4.0 NOTES:
+
+To compile on Cygwin32, get Cygwin and install it.
+For more information read README.win32
+
+The files are located on:
+
+ftp://ftp.berlios.de/pub/cdrecord/alpha ...
+
+NOTE:  These tar archives are 100% POSIX compatible. GNU tar may get some
+       minor trouble. If you like a 100% POSIX compliant tar, get star from
+       ftp://ftp.berlios.de/pub/star/
+
+WARNING: Do not use 'winzip' to extract the tar file!
+       Winzip cannot extract symbolic links correctly.
+
+Joerg
diff --git a/doc/DOC-OVERVIEW b/doc/DOC-OVERVIEW
new file mode 100644 (file)
index 0000000..d40ff6c
--- /dev/null
@@ -0,0 +1,35 @@
+This is the documentation collection of the cdrkit package
+
+It has been derived from the cdrtools package maintained by
+Joerg Schilling.  However, other maintainers work on this
+spinoff of the documentation.
+
+Keep in mind that cdrkit is not cdrtools when you read the
+documentation. Some details may be void in context of
+cdrkit.
+
+Contents:
+
+ANNOUNCEMENTs : directory containing AN* files with release
+                notes from old cdrtools releases
+
+READMEs : contains HOWTOs and instructions relevant to
+          various tasks, especially such where multiple
+          programs are involved
+
+wodim : contains README files relevant for the work with the
+        wodim application (writing data) and details specific
+        to its usage
+
+genisoimage : documentation for work with genisoimage program, a
+              ISO9660 filesystem creator. See genisoimage/README for
+              details.
+
+icedax : contains documentation for the CD audio
+           extraction utility icedax. See icedax/README for
+           details.
+
+platforms : contains notes about portability to different
+           platforms
+
+
diff --git a/doc/PORTABILITY b/doc/PORTABILITY
new file mode 100644 (file)
index 0000000..c694a22
--- /dev/null
@@ -0,0 +1,34 @@
+You may have heard from a certain person that cdrkit is not portable and you
+may need some help to decide whether you shall believe him/her or not. It is,
+as usual, recommended to make your own opinion before adopting someone elses
+which may be biased.
+
+What is portability? Portability is the ability for being compiled and
+deployed on a platform that an application supports. It is obvious that nobody
+can promise the unlimited portability especially not to operating systems to do
+not exist yet or that are long dead (dead like in: unsupported, unmaintained for
+many years, needing hardware which is not available in stores for many years).
+And there could always undocumented bugs which means that real life tests
+should be done on the target platform(s) again and again.
+
+Therefore, unlimited portability is pure utopia. It is required to define a
+certain degree of portability to meet the needs of the target user base.
+
+How does that work in scope of cdrkit? Main target are mainstream platforms.
+Currently, it supports Linux, FreeBSD, Cygwin (Win32), SunOS and AIX5l. This
+set should cover the majority of general purpose computer systems in the wild.
+
+Cdrkit sets some requirements on the targeted operating systems. However, most
+modern unix-like OS should be able to fullfill them. Those requirements
+include:
+
+ - an ANSI-C compiler, or a GCC port
+ - GNU make port
+ - Large File Support
+ - sane libc library
+ - some prerequisites to bootstrap CMake
+
+This cuts off support for really old operating systems, but... do you care? Do
+you need it? Or do you want to believe the tales of superiority through (just
+claimed) portability?
+
diff --git a/doc/READMEs/README.ATAPI b/doc/READMEs/README.ATAPI
new file mode 100644 (file)
index 0000000..8b2e601
--- /dev/null
@@ -0,0 +1,589 @@
+
+The file attached below provides a short explanation about the nature of ATAPI
+and the support for it on various platforms. However, it was written for an
+old version of cdrtools by Joerg Schilling and completed with even older guides
+supplied by other authors, therefore parts of the content are no longer true or
+are not applicable anymore. Read and interpret with care!
+
+See README.ATAPI.setup for a quick setup guide for Linux.
+
+Eduard Bloch, 2006
+
+# @(#)README.ATAPI     1.3 04/05/20 Copyright 1997-2004 J. Schilling
+
+People (with a Linux only background) often ask me why do you depend on 
+"ATAPI-SCSI emulation", why don't you support generic IDE?
+
+       Well first a statement: There is no single IDE burner out!
+       Even a CD-ROM cannot be used decently if you use only IDE commands.
+       Opening/closing the door, playing audio and similar things
+       cannot be done using vanilla IDE commands - you will need SCSI commands
+       to do this. But how do we do this with a drive that uses an IDE
+       interface?
+
+               ATAPI stands for ATA Packet Interface
+
+       The ATAPI standard describes method of sending SCSI commands over IDE
+       transport with some small limitations to the "real" SCSI standard.
+       SCSI commands are send via IDE transport using the 'ATA packet'
+       command. There is no SCSI emulation - ATAPI drives include native
+       SCSI command support. For this reason, sending SCSI commands to ATAPI
+       drives is the native method of supporting ATAPI devices. Just imagine
+       that IDE is one of many SCSI low level transport mechanisms.
+
+       This is a list of some known SCSI transports:
+
+       -       Good old Parallel SCSI 50/68 pin (what most people call SCSI)
+       -       SCSI over fiber optics (e.g. FACL - there are others too)
+       -       SCSI over a copper variant of FCAL (used in modern servers)
+       -       SCSI over IEEE 1394 (Fire Wire)
+       -       SCSI over USB
+       -       SCSI over IDE (ATAPI)
+
+       As you now see, the use of the naming convention "ATAPI-SCSI emulation"
+       is a little bit misleading. It should rather be called:
+               "IDE-SCSI host adapter emulation"
+
+Some naming explanations:
+
+       ATA     Attachment Adapter
+       IDE     Integrated Drive Electronics (A Drive that includes ATA)
+       ATAPI   ATA Packet Interface
+
+When wodim has problems with ATAPI drives on Linux this usually is a Linux 
+kernel problem. The Linux kernel maintainers unfortunately refuse to correct
+their current IDE driver system setup which does not support ATAPI by default.
+ATAPI _is_ SCSI over IDE transport. It is hard to understand why Linux still
+uses a default driver setup that is designed for IDE CD-ROM drives made
+before 1994 (using a IDE compat mode that only allows to use the drive
+read-only) and does not handle to send SCSI commands to ATAPI drives by
+default. This makes it hard for people who just started with Linux to do
+CD-writing on Linux if they own an ATAPI drive. Both Linus Torvalds and
+Alan Cox admit that they don't own a CD/DVD writer, how should they know about
+the problems?
+
+There are bugs with the DMA implementation that are known for many years
+but they don't get fixed.
+
+/*--------------------------------------------------------------------------*/
+Which Operating systems support ATAPI
+
+-      AIX: Status unknown! Please report your experience...
+
+-      Apple Mac OS X (Darwin): Supported
+
+-      BeOS (libscg maps ATAPI to SCSI bus # >= 8
+
+-      BSD/OS: Status unknown! Please report your experience...
+
+-      FreeBSD:
+               -       YES for the latest default kernel.
+                       It includes finally ATAPI-Cam
+
+               -       NO for the older kernels.
+                       Yes, if you install a kernel patch from
+                       Thomas Quinot <thomas@cuivre.fr.eu.org>
+                       See http://www.cuivre.fr.eu.org/~thomas/atapicam/
+                       and README.FreeBSD
+
+-      HP-UX: It looks like ATAPI does not work correctly due to kernel bugs.
+
+       New information:
+       HP supports a HP A7853A B/C class machine (s700_800) with HP-UX-11.x
+       You need to install a patch:
+
+       Patch Name: PHKL_27224 Patch Description: s700_800 11.00 IDE/ATAPI 
+       cumulative patch
+
+
+-      Linux (unfortunately not in the default configuration)
+
+       -       It works more or less if you include ide-scsi
+
+       -       Linux-2.4.xx includes a CDROM Packet interface in the
+               IDE CD driver. For this driver libscg now includes
+               support in pre-alpha status. Use wodim dev=ATAPI -scanbus
+               to check for drives and e.g. wodim dev=ATAPI:0,0 ....
+               for writing. Note that this interface is not integrated into
+               the standard libscg device naming scheme. Support for
+               this interface has been included because it is the only
+               way to use a PCCARD/PCMCIA writer - trying to use ide-scsi
+               on a PCATA interface will cause a Linux kernel panic
+               or will block all ATAPI drives.
+
+       -       Starting with Linux-2.5.45, there is a new experimental
+               ATAPI interface initiated by Linus Torvalds. Unfortunately,
+               this interface does not fit well into the rest of the Linux
+               SCSI kernel transport naming scheme. Wodim allows to
+               use this interface by calling e.g. wodim dev=ATA:1,0,0 ...
+
+       All Linux ATAPI transport implementations do not support DMA.
+       Current exceptions are:
+
+       -       ide-scsi with block size 2048 and if DMA has been enabled
+
+       -       The new experimental ATAPI interface starting with Linux-2.5.45
+               allows DMA if DMA has been enabled and the sector size is a
+               multiple of 4. This allows to use DMA for audio CDs and
+               when writing any type of CD in RAW mode.
+
+               Note that is a bad idea to first implement a new kernel
+               interface that also implements the named DMA implementation
+               bugs and later fix the DMA bug _only_ for this new
+               interface. It looks like the Linux kernel folks are not
+               very cooperative :-(
+
+       RAW mode is needed for many new and cheap drives that have bugs when
+       writing in cooked mode. If there is no DMA, you cannot write faster
+       than approx 16x.
+       
+
+-      NetBSD (releases 1.3 and newer)
+
+-      NeXT: Status unknown! Please report your experience...
+
+-      OpenBSD: (release 2.6 and newer)
+
+-      OS/2 (you need to fetch and install ATAPI support first)
+       see: http://www.leo.org/pub/comp/os/os2/leo/drivers/dasd/daniatapi.zip/
+
+-      OSF-1 / True64 Status unknown! Please report your experience...
+
+-      SCO-OpenServer: Supported with 5.0.6 and non-public patch or with
+                       5.0.7. I don't know whether you need a patch for 5.0.7
+
+-      SCO-UnixWare: partial support with UnixWare 7.1.3 - some SCSI commands
+                       that are needed for cdda2wav and DVD writing are blocked.
+                       7.1.4 will have full ATAPI support.
+
+-      SGI/IRIX: Status unknown! Please report your experience...
+
+-      Solaris (you may need to use the USCSI transport interface to address 
+       ATAPI if the IDE hostadapter idriver implementation does not follow 
+       Sun's internal standards).
+
+       ATAPI works fine on Solaris 7 sparc and on Solaris 7/8 intel.
+       
+       On Solaris 8 (intel) and newer, the ATAPI/SCSI subsystem is integrated
+       correctly according to Sun's SCSA white paper, so the 'scg' driver works.
+       This is not true for Solaris on sparc where the ATAPI driver do not conform
+       to Sun's internal structuring rules. You need to use the USCSI interface
+       on for ATAPI drives on Solaris sparc for this reason.
+       Solaris 8 sparc has a ATA DMA bug that prevents wodim from working at all.
+       There is a fix from Sun available: the patch 108974-16 
+       Solaris 9 sparc works again, it has the fix for the ATA DMA bug included.
+
+       Newer versions of Solaris 9 disable DMA for CD-ROM drives on IDE.
+       Read README.solaris-x86-ATAPI-DMA to learn how this may be circumvented.
+
+-      VMS: works on recent versions!
+
+-      Win32 using a recent ASPI Layer supports ATAPI
+       You nay need to exclude mini port drivers (see README.win32).
+
+       Newer wodim versions also support the SPTI (SCSI Pass through ioctl).
+       Libscg uses SPTI by default if you are running NT-5.x or newer and are
+       administrator. With NT-4.x it may be possible to run wodim dev=SPTI:1,0.0 ...
+       But there are reports for blue screens (kernel crashes).
+
+-      DOS DOS-7 from win98 includes a ATAPI aware aspi
+       For other versions have a look at README.msdos and use e.g. "oakaspi".
+
+/*--------------------------------------------------------------------------*/
+General hints:
+
+***********************
+NOTE: IDE/ATAPI doesn't have disconnect/reconnect! you cannot expect the needed 
+       performance for CD-writing if you connect source and destination drive
+       to the same IDE cable.
+***********************
+
+If you never like to directly write a CD from CD-ROM source, this configuration
+seems to be the best:
+
+IDE 0  MSTR    ->      HD1
+IDE 0  SLAV    ->      HD2
+
+IDE 1  MSTR    ->      CD-writer
+IDE 1  SLAV    ->      CD-ROM
+
+If you like to write from both HD source and CD-ROM source, you should have
+the following configuration:
+
+IDE 0  MSTR    ->      HD1     (does _not_ hold CD mastering data)
+IDE 0  SLAV    ->      CD-Writer
+
+IDE 1  MSTR    ->      HD2     (holds CD mastering data)
+IDE 1  SLAV    ->      CD-ROM
+
+If cou cannot set up a decent cabling (e.g. because you use a notebook)
+you may try to use wodim -immed ...
+It runs slow commands in quick (immediate) return background mode and
+tries to wait between the write commands to allow to free the IDE cable
+so the wodim read process may fill the FIFO from the other drive
+on the same IDE cable.
+
+/*--------------------------------------------------------------------------*/
+The rest of this file is only valid for Linux!
+
+This was taken out of mails from From: Dave Cohen <dcohen@richmond.infi.net>
+and From: Gadi Oxman <gadio@netvision.net.il>
+(slightly modified marked ***JS *** except typo corrects)
+
+As all current Linux versions have ATAPI support for wodim,
+I removed the patch section. If you are running a Linux version
+that does not support ATAPI<->SCSI command transport, please upgrade.
+
+The basic driver design in Solaris would also allow to use ATAPI
+drives but unfortunately, Sun made a mistake in the mid-level design.
+If you want to use ATAPI drives with Solaris, ask Sun why they don't
+support SCSI passthrough to IDE although they are using a common driver
+concept.
+
+Please use cdrecord-1.6 final or later (if available), it includes the
+modifications needed for ATAPI drives and is still working with other 
+SCSI drives. Older revisions of cdrecord do not support ATAPI drives.
+
+If you are using Linux Kernel version prior to 2.1.73 or prior to
+2.0.35, please upgrade before you try to compile and use wodim.
+
+In any case, you need to configure a kernel with ATAPI/SCSI hostadapter
+emulation. Read carefully the following instructions:
+
+In any case, you need to disable generic IDE/ATAPI CDROM support in 
+order to make ATAPI SCSI emulation working.
+
+Many people ask why I use ATAPI-SCSI emulation.
+
+       The use of the naming convention "ATAPI-SCSI emulation" is a
+       little bit misleading. It should rather be called:
+               "SCSI host adapter emulation"
+
+       The ATAPI standard describes method of sending SCSI commands over IDE
+       with some small limitations to the "real" SCSI standard.
+       For this reason ATAPI-SCSI emulation is the native method of
+       supporting ATAPI devices.
+
+If you have problems to talk to the device when it is jumpered as "slave"
+try to use it  as "master". If you connect a hard disk to the same IDE
+cable as the CD writer or if you try to read/write data from another drive
+that is connected to the same IDE cable as the CD writer you may get
+problems too.
+
+NOTICE:
+
+With the newer 2.1.x or 2.2.x kernels it seems to be possible to run 
+SCSI/ATAPI hostadapter emulation and generic IDE at the same time by 
+selectively telling the kernel what to use for which drive.  However,
+this would not be needed if the Linux SCSI CD-ROM driver would be more 
+up to date and supports standard conforming drives.
+
+Jörg Schilling <schilling@fokus.fhg.de>
+
+--------------------------------------------------
+Here is a hint from Alan Brown <alanb@manawatu.gen.nz>:
+
+To allow ATAPI cd and ide-scsi support on the same machine, add 
+`hd<x>=ide-scsi` to the lilo.conf append entry, or use 
+`hd<x>=ide-scsi` at the bootup lilo prompt. 
+
+I have my HP-7200 RW drive as the primary drive on the second IDE 
+bus, so the statement used is "hdc=ide-scsi" 
+
+--------------------------------------------------
+
+Hope that the following  is helpful to you.
+
+I recently purchased a HP-7110i CD-RW, which is the U.S. only version of
+what you have. The HP 7100 and 7110  CD rewritables use the ATAPI
+standard. Originally, the drives were not supported under Linux (due to
+some inconsistencies with SCSI translations between the kernel and the
+CD), but that problem has just recently been fixed. There are some kernel
+and wodim patches that have been made to support this device that have
+yet to be officially incorporated into cdwrite and the kernel. In order to
+get your drive supported under Linux, you will have to do the following:
+
+1. Get the proper version of cdrecord.
+
+As of this writing, I am just getting ready to test Joerg's new cdrecord.
+I am currently operational on cdrecord-1.5, so I know that works, and I
+have attached patches for that version. 
+If you are in a hurry, you can download ver. 1.5, apply patches, and
+rock-n-roll. You may want to wait, though.  Up to you ;). The version with
+ATAPI support is cdrecord-1.6alpha5. I'm not sure if the current kernel
+patches are valid for this version, but i'll know soon enough.
+**** They are valid **** JS
+
+BTW, the new version of xcdroast now supports cdrecord - this version
+is in beta testing, too (currently uses cdrecord-1.5 but cdrecord-1.6a5
+should work with the current xcdroast too).  
+
+2. Upgrade to kernel version 2.0.31
+
+IDE/SCSI translation was first added in this kernel. Because your CD-RW is
+an ATAPI device, it will support SCSI command sets.  The translation
+allows you to map the device as a SCSI generic device. This will allow
+cdrecord to recognize it as a SCSI device.
+**** 2.0.31 still needs patches, get 2.0.35 or later **** JS
+
+3. Get the patches and apply them
+
+Attached find kernel patches for kernel sources ide.h and ide-scsi.c, and
+cdrecord source scsi_cdr.c (version 1.5 only). 
+**** Get cdrecord-1.6 or later **** JS
+
+3. Recompile kernel with SCSI emulation support
+
+If you do a "make menuconfig" or "make xconfig", select SCSI emulation
+under the category "Floppy, IDE, and other block devices".
+
+WARNING:
+Do not install SCSI support as a module - there is a bug in the makefile
+structure that will cause the compile to fail.  Compile directly into the
+kernel.   
+
+4. WARNING: Disable generic IDE/ATAPI CDROM support    *** JS ***
+
+If you don't do this, the SCSI emulation will not work  *** JS ***
+
+5. This is important too:
+You also need to enable SCSI and SCSI generic support   *** JS ***
+
+6. Make sure that /dev/sg* exists.
+If they are missing, create them.
+
+Dave Cohen
+dcohen@richmond.infi.net 
+(Patch instructions below)
+
+-----------------------------------------------------------------
+From: Danilo Fiorenzano <shade@juliet.gppsd.ab.ca>
+
+Anyway, here's what I did, using kernel version 2.0.33  I believe this
+is the proper way to get an HP-7100i to work (and as far as I can tell,
+any other IDE CD-writer unit):
+
+1) patch the kernel as described by README.ATAPI
+
+2) save your current kernel config to an alternate file, then run
+   "make mrproper"
+
+3) run 'make menuconfig' or 'make xconfig', then choose "load config
+   from alternate file" to restore the original configuration
+
+4) In "Floppy, IDE and other block devices", disable "IDE/ATAPI CD-ROM
+   support" and enable instead "scsi emulation"
+
+5) in "SCSI support" enable "SCSI support", "SCSI CD-ROM support" and
+   "SCSI generic support", everything directly in the kernel.
+
+6) compile, install kernel/modules, reboot.  Now, if everything went
+   fine, your CDROM units should show up with a message like:
+ "hdb: HP CD-Writer+ 7100, ATAPI CDROM drive - enabling SCSI emulation"
+
+7) run "wodim -scanbus" to make sure wodim can see the unit and
+   talk to it.  The end.
+
+Don't forget that now -all- of your CD drives are seen as -SCSI- units
+by all programs (/dev/scd0 etc.), so you might want to relink
+/dev/cdrom to the proper scd<n> in order to get xcdplay or whatever to
+work again.
+
+
+-------------------------------------------------------------------------------
+NOTE: 
+
+1)     Current wodim releases support ATAPI
+
+2)     Linux 2.0.35 or Linux 2.1.73 or later include ATAPI support
+-------------------------------------------------------------------------------
+From whampton@staffnet.com Fri Jan 14 05:21:34 2000
+From: "W. Wade, Hampton IV" <whampton@staffnet.com>
+
+You may wish to include/append these notes to your ATAPI notes....
+
+I have my 4X Acer CD-R/RW ATAPI drive working with Linux.   My platform
+is
+RedHat 6.1 with kernel 2.2.14.  My first ATAPI CD device is a DVD with
+the second
+the CD-R.  I made the following changes:
+
+Steps:
+
+1.  Identify which device is the CD-R -- in my case the fourth ATAPI
+device, /dev/hdd.
+
+2.  Compile the kernel to include ATAPI CDROM and SCSI emulation:
+
+     Under the block devices menu:
+                Y or M     Include IDE/ATAPI CDROM support
+                Y or M     SCSI emulation
+
+3.  Build and install the upgraded kernel.
+
+4.  If you selected modules, add them to the /etc/conf.modules file.
+
+5.  In the /etc/lilo.conf file add an append line for ide-scsi, in my
+case:
+        append = "hdc=ide-scsi hdd=ide-scsi"
+
+6.  Reboot to the new kernel and make sure the ide-scsi module is loaded
+
+        /sbin/lsmod | grep ide-scsi
+
+7.  Make a link from the proper SCSI device to a symbolic, e.g.,
+/dev/cdrom:
+      In my case the DVD is the first CD, hence appears as /dev/scd0 to
+scd7
+      (cat /proc/scsi/scsi to get a full list of devices -- the first
+CD-ROM will
+      appear as scd0, etc.)  With the current ATAPI-SCSI module, each CD
+
+      device appears as 8 SCSI devices (different logical units).  If
+you have
+      two devices, like I do, you may have to make a node for the second
+device.
+      In my case I had to make scd8:
+
+            cd /dev
+            mknod scd8 b 11 8
+
+        Then make links, in my case:
+
+            ln -s scd0 cdrom
+            ln -s scd8 cdr
+
+        Note, many CD-ROM player programs expect the audio CD drive to
+        be located at /dev/cdrom (xplaycd, etc.), hence this link is
+recommended.
+
+        If you try to use /dev/hdc (or wherever your CD or CD-R is)
+after loading
+        the ide-scsi module, you may not be able to mount CD's or play
+audio
+        discs -- you have to use the new SCSI names for the device.
+
+8.  Fix your /etc/fstab file to mount the /dev/cdrom and /dev/cdr
+
+
+/*--------------------------------------------------------------------------*/
+From: Eduard Bloch <edi@gmx.de>
+
+Situation:
+   Linux: Kernel 2.2.15 (Debian package kernel-image-2.2.15)
+   Distribution: Debian Potato (deep freeze), i386
+   Devices: one CDRW-Writer, one CDROM-drive, both ATAPI
+
+1. Become root, try "grep hd.: /var/log/kern.log" to find out where your
+   ATAPI-devices are connected to (hd?-names).
+2. Edit your boot configuration file, eg. /etc/lilo.conf if you use
+   lilo or the batch-file if you boot via loadlin.
+3. Find a line where you can append additional kernel parameters, eg.
+   "append=" in lilo.conf or the loadlin-line in the batch file.
+4. Append sth. like this: "hdb=ide-scsi hdc=ide-scsi max_scsi_luns=1"
+   The hdX-parameters defines devices that should be mapped to SCSI
+   latter. You may do it with non-writers too, since the emulation layer
+   is almost complete, or let them out so the devices will use their
+   native drivers.
+5. Save the file, reinstall the bootloader (ie. running "/sbin/lilo")
+6. Call "modconf", load "sg" and "ide-scsi" from the SCSI-section
+7. Reboot Debian, watch while booting, you should see a line like this
+   "Detected scsi CD-ROM sr0 at scsi0, channel 0, id 0, lun 0".
+   Your old ATAPI devices virtually don't exist any longer, use the
+   SCSI equivalents instead.
+8. Become root, setup devices:
+      cd /dev
+      MAKEDEV sg scd
+      ln -s scd0 cdrom # NOTE: or cdrw, first check which drive is here
+      ln -s scd1 cdrw  # NOTE: see above, maybe cdrom
+   Check the new SCSI settings:
+      wodim -scanbus
+   Setup wodim's environment - edit /etc/wodim.conf:
+      CDR_DEVICE=cdrw
+      cdrw=1,0,0        4       8m
+      cdrom=1,2,0       0       0m
+   Input the right values, the fields are described in the manpage
+   of wodim. Alternatively, you may use this values as
+   wodim-parameter or take a frontend with an own configuration
+   scheme, then you don't need to modify /etc/wodim.conf.
+9. It's done! Insert a CD and try "wodim -v -toc"
+/*--------------------------------------------------------------------------*/
+He had constant buffer underrun problems:
+
+From: "Trenton D. Adams" <trenton.adams@telusplanet.net>
+
+I enabled DMA, and 32-bit mode on the CD-Writer using "hdparm". 
+This fixed the writing problem.
+
+/*--------------------------------------------------------------------------*/
+From: "Mario Moder" <clay-man@freenet.de>
+-----
+TEAC CD-W54E
+
+I recently installed a TEAC CD-W54E (an ATAPI CD-RW-Recorder) and I had
+problems with buffer underruns and other errors when burning a CD (with
+Linux and Windows 2000). My system has an old ASUS P/I-P55T2P4 Pentium
+mainboard with Intel PCI-Bus-Master-IDE (I think the chipset is an Intel
+430HX and the IDE controller is an 82371SB). The harddisk is the master on
+the primary IDE channel, and the CD-Recorder is the master on the secondary
+IDE channel.
+
+After turning off DMA for the CD-Recorder AND the harddisk, the drive had no
+longer problems with burning a CD. You can try the following things to make
+it work, if you have similar problems with a similar hardware configuration:
+
+For Linux (Kernel 2.2.19):
+Turn off "Enable DMA by default" in the kernel (and then compile a new
+kernel), if you had it turned on or use "hdparm" to turn of DMA for both the
+CD-Recorder and the harddisk
+
+For Windows 2000:
+In the Device Manager go to "IDE ATA/ATAPI-Controller" and open the
+properties for the first and second IDE channel. There you change the mode
+of the devices from DMA to PIO.
+-----
+
+/*--------------------------------------------------------------------------*/
+
+Hints for the Linux Packet code in ide-cdrom.c:
+
+       WARNING! It seems that this driver does not allow to send all
+       SCSI commands. A command that definitely fails is READ FULL TOC.
+       For this reason, you cannot read those 'defective' audio CDs
+       with broken TOC when you use this interface.
+
+       Thanks to Alexander Kern <alex.kern@gmx.de> for the idea and first 
+       code fragments for supporting the CDROM_SEND_PACKET ioctl() from 
+       the cdrom.c kernel driver. Please note that this interface in principle 
+       is completely unneeded but the Linux kernel is just a cluster of 
+       code and does not support planned orthogonal interface systems. 
+       For this reason we need CDROM_SEND_PACKET in order to work around a 
+       bug in the linux kernel that prevents to use PCATA drives because 
+       the kernel panics if you try to put ide-scsi on top of the PCATA 
+       driver. 
+
+       The code is currently in "status nascendi" but usable with some trade offs.
+
+       To use: call e.g.
+
+               wodim -scanbus dev=ATAPI:
+
+               wodim -dao -v speed=24 dev=ATAPI:0,0 ....
+
+       Be careful! This code is only needed in order to be able to use
+       PCATA CD-writers on notebooks because there is a severe kernel bug.
+       Unfortunately, this bug causes the kernel to hang (and force you
+       to reboot) if you try to call:
+
+               wodim -scanbus
+
+       without the dev=ATAPI: option. 
+
+       In this case wodim will hang infintely and unkillable 
+       in open("/dev/sg1", 2) => you need to reboot :-(
+
+       Repeat by: Insert a PCATA CD-Writer in a Sony VAIO notebook and run
+                       wodim -scanbus. 
+
diff --git a/doc/READMEs/README.ATAPI.setup b/doc/READMEs/README.ATAPI.setup
new file mode 100644 (file)
index 0000000..e283342
--- /dev/null
@@ -0,0 +1,87 @@
+Howto setup an ATAPI CD-RW/DVD+-RW recorder on Debian/Ubuntu
+============================================================
+
+This guide should be applicable to most kernel 2.6 using distributions of
+GNU/Linux. For installations with kernel 2.4, continue reading below.
+
+Kernel 2.6.*
+============
+
+If you have just one CD writer in your computer, CD-writing should work out of
+the box. There should be a symbolic link /dev/cdrw which points to your actual
+CD-Writer's device (e. g. /dev/hdb). If the link is not present (eg.  the
+system is not using udev/devfs) or if you want to use a different device as
+default, you can configure the device in /etc/wodim.conf:
+
+  CDR_DEVICE=/dev/hdd
+
+would configure the default device to be /dev/hdd, i. e. the slave
+device on the secondary IDE bus.
+
+You can always override this default setting with wodim's "dev"
+option:
+
+    wodim dev=/dev/hdc ...
+
+Only users part of the system group "cdrom" are able to write CDs.
+If you wish to allow non-root users to write CDs then add your users to the
+cdrom group ("adduser user cdrom") and let the user completely logout and
+re-login.
+Note: with certain kernel versions wodim can fail with this message:
+"wodim: Operation not permitted. Cannot send SCSI cmd via ioctl"
+In this case it still does need the suid bit - please send patches if you have
+identified the reason of that problem.
+
+Kernel 2.4.* (for 2.5/2.6, see above)
+=====================================
+
+Where we start:
+   Linux: Kernel 2.4.20-bf2.4 (Debian package kernel-image-2.4.20-bf2.4)
+   Distribution: Debian Woody 3.0r2, i386
+   Devices: one CDRW-Writer, one CDROM-drive, both ATAPI
+
+1. Become root, try "grep hd.: /var/log/kern.log" to find out where your
+   ATAPI-devices are connected to (hd?-names).
+2. Edit your boot configuration file, eg. /etc/lilo.conf if you use
+   lilo or the batch-file if you boot via loadlin.
+3. Find a line where you can append additional kernel parameters, eg.
+   "append=" in lilo.conf or the loadlin-line in the batch file.
+4. Append sth. like this: "hdb=ide-scsi hdc=ide-scsi max_scsi_luns=1"
+   The hdX-parameters defines devices that should be mapped to SCSI
+   latter. You may do it with non-writers too, since the emulation layer
+   is almost complete. Or omit some so the devices will use their
+   native drivers (eg. ide-cd).
+5. Save the file, reinstall the bootloader (ie. running "/sbin/lilo")
+6. Call "modconf" in a console or xterm, enter the section 
+   "kernel/drivers/scsi", load "sg" and "ide-scsi"
+7. Reboot Debian, watch while booting, you should see a line like this:
+   "Detected scsi CD-ROM sr0 at scsi0, channel 0, id 0, lun 0".
+   Your old ATAPI devices virtually don't exist any longer, you cannot refer to
+   /dev/hd* as CDROM drives. Use the SCSI equivalents instead, /dev/sr*.
+8. Become root, setup devices:
+      cd /dev
+      MAKEDEV sg scd
+      ln -s scd0 cdrom # NOTE: or cdrw, first check which drive is here
+      ln -s scd1 cdrw  # NOTE: see above, maybe cdrom
+   Check the new SCSI settings:
+      wodim -scanbus
+   Setup wodim's environment - edit /etc/wodim.conf:
+      CDR_DEVICE=cdrw
+      cdrw=1,0,0        4       8m
+      cdrom=1,2,0       0       0m
+   Insert the right values, the fields are described in the manpage
+   of wodim. Alternatively, you may use these values as
+   wodim-parameter or take a frontend with an own configuration
+   scheme, then you don't need to modify /etc/wodim.conf.
+   The columns must be separated by tabs.
+9. It's done! Insert a CD and try "wodim -v -toc". To create your first CD-ROM, try:
+   
+   mkisofs -v -r -J /directory/to/be/written | wodim -v -dummy -
+
+   (read wodim(1), "man 1 wodim", for details)
+
+10. If you wish to allow non-root users to write CDs, you must give them 
+    permissions to do so. Set suid-root permissions on the executable,
+    then add your users to the cdrom group ("adduser user cdrom") and
+    let the user completely logout and re-login.
+
diff --git a/doc/READMEs/README.audio b/doc/READMEs/README.audio
new file mode 100644 (file)
index 0000000..7e2d7c9
--- /dev/null
@@ -0,0 +1,50 @@
+Why do I hear only noise from my first audio CD?
+
+You may have a byte swapping problem, try wodim -swab
+but note that is is most unlikely that you need to use the -swab
+option from wodim unless your input files are broken.
+It makes more sense to find out why the inout files are not OK.
+
+wodim assumes Motorola/Network byte order (big-endian) on input
+regardless of the byte order of the CD-Recorder. If wodim
+encounters a .wav file, byte order is corrected to match the byte order
+of the .wav file.
+
+wodim by default uses Track at once. This always gives 2 seconds
+pause between two audio tracks and loweres the audio quality.
+
+For best audio CD quality, use wodim -dao (to write in Session At Once)
+ot wodim -raw (to write in RAW mode). Note that there are a lot of drives
+notably from Lite-ON that have defective firmware and will write defective
+CDs if you use either TAO or SAO mode. In RAW mode, wodim has the
+full control over the complete CD and the chance that the CD is OK
+is much higher.
+
+The 2 seconds pause between two audio tracks is the CD ***standard***
+
+The standard says:
+       Each track starts with 2 seconds of silence
+       followed by at least 4 seconds of audio data.
+
+For that reason the 2 second pause is generated by the CD-R drive in 
+Track at once (TAO) mode.
+
+CD's that have no pause between two tracks are illegal (compared to RED BOOK).
+These illegal disks may be made with Disk At Once (DAO) only.
+In DAO mode the writing software needs to send the 2 seconds pause as 
+binary zeroes and therefore is able to create illegal disks by 
+sending audio data instead. 
+
+Some drives don't accept to write illegal disks even in SAO mode.
+In this case, use the RAW mode. In RAW mode, the drive does not even
+"know" what is going on and thus cannot prevent you from writing such
+a disk.
+
+This audio data (the last two seconds of a track in this case)
+however are part of the next track from viewing the TOC of the disk.
+Digital Audio Extraction programs that work correctly (as intended by the
+CD standard) split the content of a CD into files by including the
+pre-gap (usually holding 2 seconds of pause) at the end of the previous
+track.
+
+Eduard Bloch, based on documentation from Joerg Schilling
diff --git a/doc/READMEs/README.cdplus b/doc/READMEs/README.cdplus
new file mode 100644 (file)
index 0000000..24deb0d
--- /dev/null
@@ -0,0 +1,85 @@
+Wodim and genisoimage allow you to create multi-session CD's with all
+supported drives.
+
+According to www.cd-info.com, a CD+ is a CD with two sessions.
+The first session is an audio session, the second session a data
+session.
+
+Creating a CD+ is first writing an audio session in 
+multi session mode and then writing a data session.
+
+If you like to append a filesystem to a audio CD, first extract the 
+CD by calling:
+
+       icedax -B -vall
+
+This first audio session may be written in TAO mode with the command
+
+       wodim -multi -audio file1 ....
+
+or in DAO mode with the command
+
+       wodim -dao -multi -useinfo -audio file1 ....
+
+To add the second session that contains the data track, you need
+to create an ISO-9660 file system that starts not at sector 0.
+
+With the current genisoimage, you must use the following method:
+
+-      First call wodim -msinfo for your prepared multi-session audio CD.
+
+       you will get something like 0,12345
+
+-      Now call genisoimage:
+
+       genisoimage -o fs.raw -C 0,12345 root_directory_for_new_cd
+
+       replace 0,12345 with your actual wodim -msinfo output.
+
+the image in fs.raw may now be written with wodim as second session.
+
+See my README.multi for more info on how to create multi session CD's
+
+
+The procedure again in short form:
+
+       icedax -vall -B
+
+       wodim -multi -audio audio_tracks ....
+or
+       wodim -dao -useinfo -multi -audio audio_tracks ....
+
+       wodim -msinfo ....
+       (output is e.g. 0,12345)
+
+       genisoimage -R -o cd_plus.raw -C 0,12345 root_dir_of_fs
+
+       wodim -data cd_plus.raw
+or
+       wodim -multi cd_plus.raw
+
+
+Note: If you want to create an HFS hybrid as the data track, then you must
+use the '-part' option to genisoimage. Otherwise, the data track will be mounted
+as an ISO9660/Joliet CD when used on a Mac.
+       
+Jörg
+
+Edited for cdrkit by Christian Fromme <kaner@strace.org> and Eduard Bloch
+
+This describes the programs as shipped with cdrkit, a spinoff from the
+cdrtools project. However, the cdrtools developers are no longer
+involved in the development of this spinoff and therefore shall not
+be made responsible for any problem caused by it. Do not try to get
+support for this program by contacting the original authors.
+
+If you have support questions, send them to
+
+debburn-devel@lists.alioth.debian.org
+
+If you have definitely found a bug, send a mail to this list or to
+
+submit@bugs.debian.org
+
+writing at least a short description into the Subject and "Package: cdrkit" 
+into the first line of the mail body.
diff --git a/doc/READMEs/README.cdtext b/doc/READMEs/README.cdtext
new file mode 100644 (file)
index 0000000..33df110
--- /dev/null
@@ -0,0 +1,65 @@
+CD-Text Usage (to copy CD-Text from master CD):
+
+       icedax -D 6,0 -vall -B  # To extract audio information
+       wodim dev=6,0 -vv -toc  # To extract CD-Text information
+
+       and then
+
+       wodim dev=6,0 -v -dao textfile=cdtext.dat -useinfo *.wav
+       or
+       wodim dev=6,0 -v -raw96r textfile=cdtext.dat -useinfo *.wav
+
+       If the CD-Text information contains more CRC errors than
+       wodim can correct, you need to reload the CD and to
+       re-read the CD-Text information from the master disk.
+
+       Writing of CD-Text is supported for all drives that support
+       CD-Text in SAO write mode and for all drives that support
+       to write in RAW/RAW96R mode (use -raw96r in this case).
+
+       NOTE: not all writers that support MMC SAO mode support
+               to write CD-Text in this write mode.
+               If you have a drive that does not support CD-Text
+               but supports RAW/RAW96R mode use this mode as
+               in RAW/RAW96R mode the drive does not need to know
+               about CD-Text. This way even old drives like the
+               Plextor PX-R 412C will write CD-Text.
+
+       NOTE that icedax will read CD-Text and fill in the 
+       CD-Text fields in the *.inf files if vou use -vall.
+
+       The new icedax option cddb= allows you to tell icedax to
+       retrieve CDDB information from freedb.freedb.org.
+       cddb=0 means ask if ambiguous, cddb=1 means take first entry.
+       The information in this case is filled into the fields
+       in the *.inf files.
+
+Creating a CD with CD-Text based on CDDB information from freedb.freedb.org:
+
+       Tell icedax to fetch data from freedb.freedb.org, call
+
+       icedax -D 6,0 -vall -B cddb=1   # To extract audio information/fetch CDDB data
+
+       and then call
+
+       wodim dev=6,0 -v -dao -text -useinfo *.wav
+       or
+       wodim dev=6,0 -v -raw96r -text -useinfo *.wav
+
+
+If you like to create your own CD-text data for a CD use the
+following method:
+
+       First extract all tracks with icedax -vall (see above),
+
+       then edit the *.inf Files and add album and song titles.
+
+       Now call wodim as if the *.nf files contain CD-Text 
+       information.
+
+       Note that it is recommended to use less that 160 characters
+       for a single string.
+
+Source: README.cdtext from cdrtools package
+Edited for cdrkit by Christian Fromme <kaner@strace.org> and Eduard Bloch
+
diff --git a/doc/READMEs/README.copy b/doc/READMEs/README.copy
new file mode 100644 (file)
index 0000000..dc78169
--- /dev/null
@@ -0,0 +1,53 @@
+Ho to copy CD's and CD-R/CD-RW's
+
+Copying audio CD's:
+
+If you want to copy audio CD's, look for 'icedax'.
+
+Copying data CD's:
+
+The best way to copy a data disk is to copy the raw data on the master CD.
+This may be done by reading the data from the raw device by using 'readom'.
+
+
+NOTE:  All CD-R's written in Track At Once mode end in two unreadable 
+       run-out sectors. If the disk has been written with a Yamaha CD-R100
+       or with a Yamaha CD-R102, there are even more run-out sectors.
+
+For this reason, you will not be able to read such a CD correctly with 'dd'.
+
+I recommend to write all disks in Disk at Once mode if your drive
+is supported in DAO mode with wodim. In addition, you may wish to 
+add padding (see wodim / genisoimage man pages).
+
+If you want to copy such a CD directly with wodim, you may call:
+
+       wodim -v dev=... -isosize /dev/cdrw
+
+But this may fail if the master gives read errors. To copy such a CD to a file
+you may use the program 'readom' from this package
+
+Call 'readom [target] [lun] [scsibusno]' and select function 11.
+Or call readom -help to get alternate usage.
+To prevent readom from reading the run-out sectors, reduce the 
+number of sectors to copy by 2.
+
+Recent readom versions may be called: readom dev=b,t,l f=outfile
+To reduce the numbers of sectors to copy you may use the sectors= option.
+
+If the master disk is made of several partitions (like a Solaris boot CD),
+the best way to copy a CD is to use the program 'readom'. It ignores
+the partition info and does raw SCSI reads.
+
+If you like to copy audio CD's in a way that preserves as much accuracy as
+possible, use:
+
+icedax -vall -D... -B
+wodim -v dev=... -dao -useinfo *.wav
+
+This will preserve pre-gap sizes, indices ...
+
+
+Source: README.copy from cdrtools package, version 2.01.01a08
+Edited for cdrkit by Christian Fromme <kaner@strace.org> and Eduard Bloch <blade@debian.org>
+
diff --git a/doc/READMEs/README.multi b/doc/READMEs/README.multi
new file mode 100644 (file)
index 0000000..d7d3457
--- /dev/null
@@ -0,0 +1,209 @@
+Creating multi-session CDs/DVDs Mini Howto FAQ
+
+Multi-session filesystems are a trick that comes from the Kodak photo CD.
+The OS mounts the last session that contains the sum of the current session
+and all previous sessions.
+
+To test (with Linux):
+
+ - create a iso-9660 filesystem image with genisoimage.
+ - genisoimage is included in the cdrkit release.
+ - use the -R flag to add Rock Ridge extensions (this is important).
+
+Assuming that the CD-R drive is connected to target 2 on the SCSI bus.
+
+Write the first session with:
+
+wodim -v speed=2 dev=2,0 -eject -multi isoimage.raw
+
+Note that all Sony drives do no support XA2 disks in firmware - read README.sony
+for more information.
+
+This must be a iso9660 image with Rock Ridge extensions (see above)
+
+Note the number of sectors written and check the disk, it should be mountable.
+
+Next step is to check if wodim is able to retrieve the following data:
+
+       1) The first block (sector) number in the first track of the last session
+          This must be '0' in our case.
+
+       2) The next writable address in the unwritten session following the current.
+          This should be the number of sectors written in the first
+          run + ~ 11400 sectors for about 22MB lead out/in
+
+          For the first additional session this is 11250 sectors lead-out/lead-in
+          overhead + 150 sectors for the pre-gap of the first track after the
+          lead-in = 11400 sectors.
+
+          For all further session this is 6750 sectors lead-out/lead-in
+          overhead + 150 sectors for the pre-gap of the first track after the
+          lead-in = 6900 sectors.
+
+To get this information type:
+
+wodim -msinfo dev=2,0
+
+The output should be two numbers separated by a comma.
+
+       e.g.: 0,204562
+
+The first number is (1), the second number is (2).
+
+2nd session:
+You should create a directory that contains a second directory with data in it
+for this purpose.
+
+       e.g.:
+               first_dir/
+                       second_dir/
+                               file_1
+                               file_2
+                               ...
+
+call:
+
+On Linux:
+genisoimage -o isoimage_2.raw -R  -C xx,yy -M /dev/cdwriter_blk_dev  first_dir
+
+On SunOS:
+genisoimage -o isoimage_2.raw -R  -C xx,yy -M target,lun first_dir
+
+Note that the name "first_dir" is not important.
+
+If you still keep the old raw image of the first session and there is only
+one previous session on the CD you may also call:
+
+genisoimage -o isoimage_2.raw -R  -C xx,yy -M isoimage.raw first_dir
+
+
+The argument of -C is the output of wodim -msinfo
+-      On Linux, the argument of -M is a device that would allow you to mount 
+       the current CD in the CD-writer
+-      On SunOS, target and lun refer to the SCSI target and lun of the 
+       CD-R device with the same notation as for wodim dev=xxx,yyy .
+
+Note that you can also use the -msifile=... option of wodim to store this data
+in a reliable way. This is usefull for scripting.
+
+If you want to check, whether genisoimage make everything right, you should create 
+another image by using the following command line.
+
+On Linux:
+genisoimage -o isoimage_2.raw -R  -C xx,0 -M /dev/cdwriter_blk_dev  first_dir
+
+On SunOS:
+genisoimage -o isoimage_2.raw -R  -C xx,0 -M target,lun first_dir
+
+Where xx is the first number of the pair returned by wodim -msinfo
+
+You may check ***this** image by mounting it with my "fbk" on Solaris 
+or the loopback driver on Linux.
+
+On Linux type:
+       mount isoimage_2.raw -r -t iso9660 -o loop /mnt
+
+On SunOS type:
+       mount -r -F fbk -o type=hsfs /dev/fbk0:isoimage_3.raw /mnt
+
+For Solaris 8 and later you may also use the Sun lofi driver (see README.sun-lofi)
+
+If you list /mnt, you should see all directories that have been in the first 
+session and the directory "second_dir". If you try to read a file from the
+first session, you will get an I/O error or bad data (depending on the
+block address), don't worry about that. If you try to read a file from
+the second session, you will see everything correctly.
+
+To write the second session to CD, call:
+
+wodim -v speed=2 dev=2,0 -eject -multi isoimage_2.raw
+
+If you mount this CD, you should see the first session and the second directory 
+from 2nd session added to the root directory of the CD.
+
+
+Additional check:
+
+call:
+
+wodim -msinfo dev=2,0
+
+The first number should be the first writable address which was retrieved by the
+first call to wodim -msinfo after creating the first session.
+The second number should be the first number + number of sectors of the second session
++ ~ 11400 sectors.
+
+Note: The first lead-out is 1:30 (6750 sectors) the lead-in is 1:00 (4500 sectors)
+All following sessions need only 0:30 for lead-out (2250 sectors), the lead-in
+is also 1:00. So in theory, the can be 44 sessions on s 74 minute disk if you
+take into account that the minimum track size is 4 seconds.
+
+The total amount of the overhead is 11250 + 150 sectors for the first additional
+session and 6750 + 150 sectors for all subsequent sessions.
+The 150 additional sectors are the pre-gap sectors for the first track after
+the current session.
+
+Some notes on multi-session CD's that contain only Joliet but no Rock Ridge:
+
+Joliet is a really bad idea in general:
+
+-      There is no way to find a relation between a ISO-9660 name and a Joliet
+       name. If the file has a size, you may try to match the starting sector #
+       but if the size in 0 it's impossible.
+
+
+-      Joliet does not allow long filenames (it limits names to 64 chars).
+
+-      Joliet does not allow all (usually used) characters in filenames.
+         
+       All code points between (00)(00) and (00)(1F), inclusive. (Control Characters)
+               (00)(2A) '*'(Asterisk)
+               (00)(2F) '/' (Forward Slash)
+               (00)(3A) ':' (Colon)
+               (00)(3B) ';' (Semicolon)
+               (00)(3F) '?' (Question Mark)
+               (00)(5C) '\' (Backslash) 
+
+       While '/' is not a real problem ;-) other characters may cause trouble.
+All notes above prevent you from doing reliable multi-session if the CD does
+only contain Joliet but des not contain Rock Ridge attributes.
+
+In addition, please read README.joliet in the genisoimage directory.
+
+This is the answer to a commonly asked question is why can't I continue a
+multisession CD that has been started on a Microsoft system using genisoimage. 
+
+
+Note: It is not possible to create a multi-session HFS CD. If you create
+a multi-session CD using any of the HFS options, then each new HFS
+session will ignore HFS files from any previous sessions. A warning will
+be printed if you attempt this. However, if you use the '-part' option to
+genisoimage for each session you create, then each session will appear as 
+separate volumes when mounted on a Mac. In this case, it is worth using the 
+'-V' or '-hfs-volid' option to give each session a unique volume name,
+otherwise each "volume" will appear on the Desktop with the same name.
+
+
+Joerg Schilling
+
+Edited for cdrkit by Christian Fromme <kaner@strace.org> and Eduard Bloch
+
+
+This describes the programs as shipped with cdrkit, a spinoff from the
+cdrtools project. However, the cdrtools developers are no longer
+involved in the development of this spinoff and therefore shall not
+be made responsible for any problem caused by it. Do not try to get
+support for this program by contacting the original authors.
+
+If you have support questions, send them to
+
+debburn-devel@lists.alioth.debian.org
+
+If you have definitely found a bug, send a mail to this list or to
+
+submit@bugs.debian.org
+
+writing at least a short description into the Subject and "Package: cdrkit" 
+
+
diff --git a/doc/READMEs/README.netscsid b/doc/READMEs/README.netscsid
new file mode 100644 (file)
index 0000000..07c3672
--- /dev/null
@@ -0,0 +1,145 @@
+The Remote-SCSI protocol gives you SCSI-Anywhere features.
+
+The protocol used by netscsid is based on rscsi from the cdrtools, developed by
+Joerg Schilling. However, no guarantee for the compatibility or reliability can
+be made. This documentation is based on rscsi documentation from Joerg
+Schilling, but is not identical to the original.
+
+There are three possible ways to control access to the remote users:
+
+       -       Let the remote scsi lib log in as a standard user.
+               In this case netscsid will be called via sh -c netscsid /usr/sbin/netscsid
+               NOTE: In this case, netscsid must be installed suid root. 
+               --- This would need to allow any valid local user to access SCSI ----
+               It could be a security problem.
+
+       -       Log in as root and call netscsid via sh -c netscsid
+               NOTE that this will fore you to allow remote logins as root
+               which is considered to be a security hole.
+
+       -       Create one or more special user(s) that have netscsid
+               as login shell with their own home directory.
+               You then may create special .rhosts files for each user.
+               NOTE: In this case, netscsid must be installed suid root. 
+               **** This is the preferred method ****
+
+To enable remote SCSI via the login shell method you should do the following:
+
+  -    Install netscsid into /usr/sbin. It can be set suid-root if neccessary, see
+    security section below.
+
+       -       Install a file /etc/netscsid.conf and define access rights.
+               Without this file, netscsid will not work at all.
+               The template for this file is: netscsid/netscsid.dfl
+ - For the special user method, create a user account. This can be done with a
+   frontend like adduser or useradd, if available. The user should have /usr/sbin/netscsid as the login shell.
+   If there is no frontend tool, try this:
+
+   +   Add an entry to /etc/passwd in the form:
+
+      netscsid:x:1999:1000:Tape:/home/netscsid:/usr/sbin/netscsid
+
+      (modify this according to your OS). And don't forget to
+      modify /etc/shadow the way it needs to be on your OS.
+
+   +   Create the home directory for this user, adapt the user/group ownership
+      on this directory.
+  
+  - if you use SSH as the login shell (via appropriate RSH environment variable
+    or a symlink to "rsh" which is the case for many Linux distribution),
+    consult the ssh documentation for details.
+    Note that SSH requires sufficiently powered client/server systems to
+    encrypt/decrypt data in realtime.
+
+  - if you use traditional rsh, add a .rhosts file to this directory to allow
+    access to all users you like (see rsh documentation)
+
+NETSCSID Security:
+
+-      When netscsid starts, it checks if /etc/netscsid.conf exists.
+       If not, it dies.
+
+-      If netscsid is not called by a user listed in /etc/netscsid.conf
+       it dies.
+
+-      To access a SCSI target there must be an entry that lists the user
+       rcsi hast been started from, the hostname and the SCSI target.
+
+       netscsid compares the hostname field in /etc/netscsid.conf 
+       to the peername retrived from STDIN:
+
+       - legal host name               IP connection
+       - "ILLEGAL_SOCKET"              Not an IP socket
+       - "NOT_IP"                      Not a socket
+
+NETSCSID Security hints:
+
+-      Do not generally allow other users to see your boot disk via NETSCSID.
+  All people who see this disk may edit your passwd file. This especially
+  applies to suid-root usage. For non-suid-root, check the access permissions.
+
+-      If you are in doubt, only export CD-ROM drives, scanners and similar
+       devices that are not directly security sensitive.
+
+If anybody sees a security hole in my security precautions, please send me a mail!
+
+NETSCSID usage:
+
+-      To use remote SCSI devices you need to know how to access a specific remote
+       SCSI target.
+
+       -       dev=REMOTE:host: or dev=REMOTE:host
+               will allow you to do SCSI bus scanning while you log in as yourself
+
+       -       dev=REMOTE:user@host: or dev=REMOTE:user@host
+               will allow you to do SCSI bus scanning while you log in as "user"
+
+               If you use the setup described above, you should use:
+
+                       dev=REMOTE:netscsid@babbel:
+
+               to do SCSI Bus scanning on host babbel
+
+       -       To access a specific SCSI device, you must specify
+               dev=REMOTE:host:<target spec> or dev=REMOTE:user@host:<target spec>
+               <target spec> is the SCSI target specification as it is needed
+               on the remote host
+
+                       dev=REMOTE:netscsid@babbel:1,3,0
+
+               Will let you log in as netscsid on host babbel and open Target 3 lun 0
+               on SCSI bus #1
+
+       -       If you use wodim -vv ...., wodim will on startup print some 
+               information about the remote libscg version used for the connection.
+
+-      To be able to use the remote SCSI client code from win32 you need to create
+       a file /etc/passwd with a correct entry for the user you are on win32.
+       Call 'id' to get the right user id.
+       Note that remote SCSI has not yet been tested on Win32.
+
+NETSCSID speed:
+
+-      On a Ultra-10 running Solaris 8, the command overhead time is 400 usec.
+       You may achieve up to 9900 kB/s via a 100MB/s ethernet connection
+       between two of such machines.
+
+-      With 100 MB/s, 12x recording should be no problem.
+
+-      With 10 MB/s, 4x recording is the maximum. Do tests before!
+
+-      Logging into a remote machine and running wodim on the remote machine
+       causes the buffer cache on that machine to be trashed. The main user
+       is disturbed.
+
+-      Doing cdrecording via Remote SCSI causes only the netscsid command with less
+       than 200kB to be needed on the remote machine hosting the CD recorder.
+       The main user on that machine is not disturbed.
+       The buffer cache of the machine running wodim is trashed.
+
+-      It is desirable to use a Burn-Proof recorder to make sure that network
+       load will not cause buffer underruns.
+
+
+-      USER= test and test for hostname are using a pattern matcher.
diff --git a/doc/READMEs/README.sony b/doc/READMEs/README.sony
new file mode 100644 (file)
index 0000000..3ee6da6
--- /dev/null
@@ -0,0 +1,31 @@
+The Sony CDU-924 was the first drive that has no hardware support
+for CDROM XA2 mode 1. If you want to create a multi session disk,
+you need to switch back to -data (plain CD-ROM)
+
+If you have a Sony drive that gives you problems with multi session disks,
+please always check the following:
+
+       For some Sony drives you may need to call wodim -multi -data
+       if you like to create multi-session CD's.
+
+       Some Sony drives do not allow to write XA2 tracks with
+       hardware support of the drive.
+
+There is currently a bug in the Sony code (for _old_ non MMC drives)
+of wodim that does not allow you to have different track types 
+in one session.
+
+All Sony drives that have CDUxxx type names are _old_ non MMC drives.
+       Here I expect that no XA support is in the firmware.
+
+All Sony drives that have CRXxxx type names are MMC compliant.
+       These drives should support XA-mode2-form1 as it is mandatory with MMC.
+
+NOTE: many HP CD-writers are nased on Sony OEM drives.
+
+
+NOTE: As for 18.5.2001, a fix was introduced that prevented wodim
+       to do multi session with new MMC compliant Sony drives.
+
+---
+Eduard Bloch, based on documentation from Joerg Schilling, cdrtools package 2.01.01a08
diff --git a/doc/READMEs/README.suidroot b/doc/READMEs/README.suidroot
new file mode 100644 (file)
index 0000000..b1198d6
--- /dev/null
@@ -0,0 +1,29 @@
+
+This is an example of how to install wodim and other cdrkit applications to get
+the root permissions in a safer way.
+
+Usually it is not a good idea to run the applications as root or to
+give users the means to run wodim as root. This gives them an easy way
+to fetch sensitive data by writing it to the disk, or pass arbitrary
+SCSI commands, e.g. formatting a SCSI disk.
+
+This also applies to root-mode wrappers like sudo, they should be used with
+the most possible care.
+
+The alternative way is installing wodim as suid-root application. In this
+mode, wodim checks permission of the device access by comparing the ownership
+of the device node user/group attributes for the real UID/GID of the calling
+user.
+
+To give all user access to use wodim, enter:
+
+   chown root /usr/local/bin/wodim
+   chmod 4711 /usr/local/bin/wodim
+
+To give a restricted group of users access to wodim, add a group
+"cdburners" to your system and add the trusted users to this group.
+Then enter:
+
+   chown root:cdburners /usr/local/bin/wodim
+   chmod 4710 /usr/local/bin/wodim
+
diff --git a/doc/READMEs/README.verify b/doc/READMEs/README.verify
new file mode 100644 (file)
index 0000000..28227b7
--- /dev/null
@@ -0,0 +1,75 @@
+Mini-Howto for verifying a selfmade CD
+
+1) verifying the data layer
+
+       To verify if all data on the disk can be read,
+       use SCSI verify. This can be done with the
+       sformat utility.
+
+       use: sformat -verify [target] [lun] [scsibus]
+
+       If the CD-R device is connected to target 2 on SCSI bus 0
+       sformat -verify 2  0
+
+       sformat can be found on ftp://ftp.berlios.de/pub/sformat
+
+       NOTE: Not all CD-ROm drives support verifying
+       NOTE: All TAO tracks end in 2 unreadable run-out sectors
+
+2) verifying the filesystem layer
+
+       A quick check is to mount the CD and to use star to read
+       all files on the filesystem.
+
+       mount -r /dev/cdrom /cdrom      (modify for your OS)
+       cd /cdrom
+       star -cPM . >/dev/null
+
+       If no errors can be found, all files are readable.
+
+       star can be found on ftp://ftp.berlios.de/pub/star
+
+
+       You also may want to compare the filesystem on the CD
+       with the original data. This can be done with star too.
+
+
+       (cd /master_for_cd; star -cPM .)|(cd /cdrom; star -diff -v)
+
+2a) verifying the iso image before creating the CD
+
+       You may check the filesystem image by mounting it with my 
+       "fbk" on Solaris or the loopback driver on Linux.
+
+       On Linux type:
+               mount isoimage.raw -r -t iso9660 -o loop /mnt
+
+       On SunOS type:
+               mount -r -F fbk -o type=hsfs /dev/fbk0:isoimage.raw /mnt
+
+For Solaris 8 and later you may also use the Sun lofi driver (see README.sun-lofi)
+
+       The check the filesystem with:
+
+               (cd /master_for_cd; star -cPM .)|(cd /mnt; star -diff -v)
+
+
+Solaris has a bug with hardlinks. It generates different inode numbers
+for the hardlinks to a file. This makes it impossible for star to 
+check hard links. Use
+
+(cd /master_for_cd; star -cPM .)|(cd /cdrom; star -diff -v diffopts=!hardlink)
+
+in this case.
+
+NOTE: Some operating systems have a read ahead bug that causes I/O errors for
+the last file(s) on a CD. This seems at least to be true for all Linux versions
+and for Solaris 7 FCS. For Solaris 7 there is a patch (107465-02) that you should
+install. This I/O error problem does not occur with DAO disks and with TAO disks
+that have been written with wodim -pad.
+
+Joerg Schilling
+
+Source: README.verify from cdrtools package
+Edited for cdrkit by Christian Fromme <kaner@strace.org> and Eduard Bloch
+
diff --git a/doc/WHY b/doc/WHY
new file mode 100644 (file)
index 0000000..e1a8ba1
--- /dev/null
+++ b/doc/WHY
@@ -0,0 +1,26 @@
+Why cdrkit? Why wodim? Why genisoimage? Because:
+
+ - it won't tell you that you have no /dev/pg* device file thing foo, that you
+   have never seen and you will never need
+ - it won't require to be executed as root, fail with obscure messages without
+   such permissions
+
+ - it won't force you to wait 3 seconds every time you want to start, no matter
+   what you specify as gracetime=
+ - it won't kill another burning process when you do -scanbus in another shell
+
+ - it will let you specify your device directly in the way you know it, rather
+   than forcing some weird TARGET,BUS,LUN syntax with weird numbers
+ - it will not wreak random havoc if you used spaces and not tabs in the config file
+
+ - genisoimage won't stop accepting the well known option -L in the near future
+
+ - genisoimage will stop on 2.1GiB large files rather than just "forgetting"
+   them and let you burn crap
+ - users are respected and not used as pinballs between us and the OS kernel
+   developers
+
diff --git a/doc/genisoimage/README b/doc/genisoimage/README
new file mode 100644 (file)
index 0000000..708bae5
--- /dev/null
@@ -0,0 +1,26 @@
+Cdrkit carries a fork of the mkisofs program called genisoimage.
+
+The acompanying documentation consists of the manual page genisoimage.8 and
+README files found in the following locations (shell globing used):
+
+doc/:
+
+README.multi: documentation and examples for creating
+  multi-session CDs and DVDs
+
+README.cdplus: documentation and examples for creating
+  CD-plus (aka CD-extra) disks
+
+doc/genisoimage:
+
+README.releasenotes: release notes for old mkisofs releases
+
+README.*boot: documentation for various boot loader related
+  extensions for different architectures
+
+README.hfs*: hints and usage for HFS related features
+
+README.*: additional docs for special features
+
+Eduard Bloch -- Mon, 11 Sep 2006 23:05:29 +0200
+
diff --git a/doc/genisoimage/README.alphaboot b/doc/genisoimage/README.alphaboot
new file mode 100644 (file)
index 0000000..4bd10e1
--- /dev/null
@@ -0,0 +1,28 @@
+# README.alphaboot    Steve McIntyre <steve@einval.com> 2004/07/19
+
+The alpha boot support allows you to create a bootable CD which will
+work with DEC/Compaq/HP Alpha machines, for example bootable
+installation media.
+
+The method used for this is the same as in aboot, the bootloader for
+Linux on Alpha, and works with SRM firmware. See the SRM Firmware
+HOWTO at http://www.alphalinux.org/faq/SRM-HOWTO/ for more details
+about SRM.
+
+In common with many Unix systems, the SRM code reads the first
+512-byte "sector" off a disk and parses information in that
+sector. The information in question is the location (start "sector")
+and length of the first stage boot loader. On a Linux system, this
+file will normally be called bootlx.
+
+SRM will load and execute the first stage boot loader, and from that
+point the system should be able to find the normal OS kernel and start
+up fully.
+
+To use the Alpha boot support code in genisoimage, simply specify the
+location of the first stage boot loader (relative to the CD root)
+using the -alpha-boot command line switch:
+
+genisoimage ... -alpha-boot boot/bootlx -o alpha.iso files
+
+
diff --git a/doc/genisoimage/README.compression b/doc/genisoimage/README.compression
new file mode 100644 (file)
index 0000000..4c8d425
--- /dev/null
@@ -0,0 +1,17 @@
+Transparent decompression (-z option) is available on Linux kernels
+using kernel version 2.4.14 or 2.4.9-ac14 or later.
+
+You also need the zisofs-tools package, containing the mkzftree
+utility, to create the compressed files; this package is available at:
+
+ftp://ftp.kernel.org/pub/linux/utils/fs/zisofs/
+
+The mkzftree utility can also be used to read compressed CD-ROMs on
+systems which do not support transparent decompression.
+
+The use of a separate utility allows compression to be controlled on a
+per-file basis.  A file which is not compressed can be read on any
+system.
+
+Transparent decompression is implemented as an extension to Rock
+Ridge, so Rock Ridge needs to be enabled (-R or -r options.)
diff --git a/doc/genisoimage/README.eltorito b/doc/genisoimage/README.eltorito
new file mode 100644 (file)
index 0000000..5c94cdc
--- /dev/null
@@ -0,0 +1,101 @@
+
+What is El Torito?
+------------------
+Simply put, El Torito is a specification that says how a cdrom should
+be formatted such that you can directly boot from it.
+
+The "El Torito" spec says that ANY cdrom drive should work (scsi/eide)
+as long as the BIOS supports El Torito. So far this has only been
+tested with EIDE drives because none of the scsi controllers that has
+been tested so far appears to support El Torito. The motherboard
+definately has to support El Torito. The ones that do let you choose
+booting from HD, Floppy, Network or CDROM.
+
+How To Make Bootable CDs
+------------------------
+
+For the x86 platform, many BIOS's have begun to support bootable CDs.
+The standard my patches for genisoimage is based on is called "El Torito".
+
+The "El Torito" standard works by making the CD drive appear, through BIOS
+calls, to be a normal floppy drive. This way you simply put an floppy
+size image (exactly 1440k for a 1.44 meg floppy) somewhere in the
+iso fs. In the headers of the iso fs you place a pointer to this image.
+The BIOS will then grab this image from the CD and for all purposes it
+acts as if it were booting from the floppy drive. This allows a working
+LILO boot disk, for example, to simply be used as is.
+
+It is simple then to make a bootable CD. First create a file, say "boot.img"
+which is an exact image of the boot floppu currently in use. There is
+at least one HOWTO on making bootable floppies. If you have a bootable
+floppy handy, you can make a boot image with the command
+
+dd if=/dev/fd0 of=boot.img bs=10k count=144
+
+assuming the floppy is in the A: drive.
+
+Place this image somewhere in the hierarchy which will be the source
+for the iso9660 filesystem. It is a good idea to put all boot related
+files in their own directory ("boot/" under the root of the iso9660 fs,
+for example), but this is not necessary.
+
+One caveat - Your boot floppy MUST load any initial ramdisk via LILO,
+not the kernel ramdisk driver! This is because once the linux kernel
+starts up, the BIOS emulation of the CD as a floppy disk is circumvented
+and will fail miserably. LILO will load the initial ramdisk using BIOS
+disk calls, so the emulation works as designed.
+
+The "El Torito" specification requires a "boot catalog" to be created as 
+ll.
+This is a 2048 byte file which is of no interest except it is required.
+My patches to genisoimage will cause it to automatically create the
+boot catalog. You must specify where the boot catalog will go in the
+iso9660 filesystem. Usually it is a good idea to put it the same place
+as the boot image, and a name like "boot.catalog" seems appropriate.
+
+
+So we have our boot image in the file "boot.image", and we are going to
+put it in the directory "boot/" under the root of the iso9660 filesystem.
+We will have the boot catalog go in the same directory with the name
+"boot.catalog". The command to create the iso9660 fs in the file
+bootcd.iso is then
+
+genisoimage -b boot/boot.img -c boot/boot.catalog -o bootcd.iso .
+
+The -b option specifies the boot image to be used (note the path is
+relative to the root of the iso9660 disc), and the -c option is
+for the boot catalog file.
+
+Now burn the CD and its ready to boot!
+
+CAVEATS
+-------
+
+I don't think this will work with multisession CDs.
+
+If your bootable floppy image needs to access the boot floppy, it has
+to do so through BIOS calls. This is because if your O/S tries to talk to
+the floppy directly it will bypass the "floppy emulation" the El Torito spec
+creates through BIOS. For example, under Linux it is possible to
+have an initial RAM disk loaded when the kernel starts up. If you let the
+kernel try to read in the initial RAM disk from floppy, it will fail
+miserably because Linux is not using BIOS calls to access the floppy drive.
+Instead of seeing the floppy image on the CD, Linux will be looking at
+the actually floppy drive.
+
+The solution is to have the initial boot loader, called LILO, load your
+initial RAM disk for you.  LILO uses BIOS calls entirely for these
+operations, so it can grab it from the emulated floppy image.
+
+I don't think making a CD bootable renders it unreadable by non-El Torito
+machines. The El Torito spec uses parts of the iso9660 filesystem which
+were reserved for future use, so no existing code should care what it does.
+
+Genisoimage currently stores identification records in the iso9660 filesystem
+saying that the system is a x86 system. The El Torito spec also allows
+one to write PowerPC or Mac id's instead. If you look at the code in write.c
+you could figure out how to change what is written.
+
+/* @(#)README.eltorito 1.2 00/03/18 eric */
+/* Edited for name change by Eduard Bloch, mkisofs -> genisoimage */
+
diff --git a/doc/genisoimage/README.graft_dirs b/doc/genisoimage/README.graft_dirs
new file mode 100644 (file)
index 0000000..da05e29
--- /dev/null
@@ -0,0 +1,151 @@
+This is from "Eduardo M. A. M. Mendes" <mendes@mgconecta.com.br>
+
+Creating multi-session CD's with dir=/ feature Micro Howto
+
+This mini-howto was written as guide to help me to create multi-session CD's
+with the possibility of determining the location of files. I hope
+that this guide helps you too.
+
+In order to use wodim it is first necessary to define to which scsi bus
+the cd-writer is connected. In my case the setup is dev=0,3,0. It is also
+interesting to have a separate directory in which all image files can
+be dumped: /home/cdsource is the directory I chose for dumping the images.
+
+The best way to understand how to create multi-session cds is to read
+README.multi. Most of what is going to be said here is based on that
+README file and on the help of several wodim users. 
+
+This Micro Howto is divided into two parts as follows:
+
+Example a) A dir/=/dir1/dir2 example
+
+Example b) A dir1/dir2/=/dir3/dir4 and dir1/dir2a=/dir5/dir6 example
+
+
+We are now ready to start.
+
+Example a) An dir/=/dir1/dir2 example
+
+A simple example will demonstrate that we can create multi-session cds 
+with the dir_feature of the type dir/=/dir1/dir2
+
+Objetive: Saving root directories of Redhat 6.1 and Col 2.3 on a single CD.
+
+Observation: Redhat installation is mounted on COL 2.3 at /mnt/redhat
+
+First image - RedHat 6.1 - /mnt/redhat/root
+
+genisoimage -D -l -r -f -m core -L -o image1.raw redhat/=/mnt/redhat/root
+
+This will create a redhat directory on the cd. The option -D should be
+used with care. The other options used in the above command are just 
+to demonstrate the use of genisoimage.  Please
+refer to man genisoimage if you want to know more.
+
+
+To see if the image is created as expected, we need to mount image1.raw using
+the option -o loop (Linux only! for information on Solaris read README.verify)
+as follows:
+
+mount -t iso9660 image1.raw /mnt/image -o loop
+
+To see the contents type:
+
+ls -l /mnt/image/redhat
+
+Does it look ok?  Great! Unmount /mnt/image. Now the burning process itself:
+
+wodim -v -dev=0,3,0 -multi -eject image1.raw 
+
+To check the burned image we need to mount the cd; something like
+
+mount -t iso9660 /dev/scd0 /mnt/cdroms
+
+/mnt/cdroms is the device file for the cdrom I use.
+
+
+Second image - Caldera 2.3 - /root
+
+
+To create the second image on our cd, we need get information
+about sectors related to the first track. To do that, issue the command
+
+wodim -v -dev=0,3,0 -msinfo 
+
+wodim returns the following number
+
+0,135563
+
+This number is the format XX,YY discussed on README.multi.  XX would be used
+for testing the images as well as burning the new track.
+
+genisoimage -D -l -r -f -m core -L -C 0,135563 -M /dev/scd0 -o image2.raw  caldera/=/root
+
+Now we need to check of image2.raw is ok. The following command creates exactly what we 
+need.  Plese note that -C option. Only the first number changes in this case. The second one
+is always zero.  In our case the first number is zero due to wodim -msinfo.  When 
+more tracks are added to the cd this number will change.
+
+genisoimage -D -l -r -f -m core -L -C 0,0 -M /dev/scd0 -o image2_test.raw  caldera/=/root
+
+mount -t iso9660 image2_test.raw /mnt/image -o loop
+
+ls -l /mnt/image shows that there are two directories: redhat and caldera, just the way
+we wanted.
+
+Now let us burn image2.raw (not image2_test.raw)
+
+wodim -v -dev=0,3,0 -multi -eject image2.raw
+
+We can mount the CD again to see that the two directories are there.  We can carry on
+doing this until we decide to close the CD. If this is the case, don't use -multi when
+burning the last session.
+
+b) A dir1/dir2/=/dir3/dir4 and dir1/dir2a=/dir5/dir6 example
+
+The above example seems a bit silly, one could argue. Why did I create a single directory
+called root and within two sub-directories: redhat and caldera?  
+
+Using the procedure described above we would do as follows:
+
+genisoimage -D -l -r -f -m core -L -o image1.raw etc/redhat/=/mnt/redhat/etc
+
+wodim -v -dev=0,3,0 -multi -eject image1.raw 
+
+To check the burned image we need to mount the cd; something like
+
+mount -t iso9660 /dev/scd0 /mnt/cdroms
+
+wodim -v -dev0,3,0 -msinfo 
+
+wodim returns the following number
+
+0,14391
+
+The second image can be created using
+
+genisoimage -l -r -f -m core -L -C 0,14391 -M /dev/scd0 -o image2.raw  etc/caldera/=/etc  
+
+Creating a test image2
+
+genisoimage -l -r -f -m core -L -C 0,0 -M /dev/scd0 -o image2_test.raw etc/caldera/=/etc 
+
+mount -t iso9660 image2_test.raw /mnt/image1 -o loop
+
+It works!!   That is great!!!
+
+Now the burning process itself.
+
+wodim -v -dev=0,3,0 -multi -eject image2.raw
+
+and we're done !!!!
+
+To add more tracks just do as indicated above.
+
+Good luxk!!!
+
+Eduardo Mendes - 11/23/99
+
+Source: README.graft_dirs from cdrtools package
+Edited for cdrkit by Christian Fromme <kaner@strace.org> and Eduard Bloch
+
diff --git a/doc/genisoimage/README.hfs_boot b/doc/genisoimage/README.hfs_boot
new file mode 100644 (file)
index 0000000..378bb95
--- /dev/null
@@ -0,0 +1,76 @@
+Making HFS bootable CDs
+
+*******
+The HFS boot code in genisoimage/mkhybrid is now very out of date ...
+it does not support booting from IDE CDROMS, and probably won't work on
+"newer" Macs.
+
+The HFS boot code will be updated at some point in the future
+*******
+
+It *may* be possible to make the hybrid CD bootable on a Mac. As I do not
+have easy access to a CD-R (nor a Mac) at the moment, I have not actually
+created and written a bootable hybrid to CD - however, I *think* it will work!
+
+A bootable HFS CD requires an Apple CD-ROM (or compatible) driver, a bootable
+HFS partition and the necessary System, Finder, etc. files.
+
+A driver can be obtained from any other Mac bootable CD-ROM using the
+"apple_driver" utility (to make, type "make apple_driver"). This file can
+then be used with the -boot-hfs-file option. See below for usage.
+
+The HFS partition (i.e. the hybrid disk in our case) must contain a
+suitable System Folder, again from another CD-ROM or disk.
+
+For a partition to be bootable, it must have it's "boot block" set. The boot
+block is in the first two blocks of a partition. For a non-bootable partition
+the boot block is full of zeros. Normally, when a System file is copied to
+partition on a Mac disk, the boot block is filled with a number of required
+settings - unfortunately I don't know the full spec for the boot block ...
+
+I'm guessing that this will work OK ...
+
+Therefore, the utility "apple_driver" also extracts the boot block from the
+first HFS partition it finds on the given CD-ROM and this is used for the
+HFS partition created by mkhybrid.
+
+To extract the driver and boot block:
+
+apple_driver CDROM_device > HFS_driver_file
+
+where CDROM_device is the device name used by the CD-ROM (e.g. /dev/cdrom)
+
+The format of the HFS driver file is:
+
+       HFS CD Label Block                              512 bytes
+       Driver Partition Map (for 2048 byte blocks)     512 bytes
+       Driver Partition Map (for 512 byte blocks)      512 bytes
+       Empty                                           512 bytes
+       Driver Partition                                N x 2048 bytes
+       HFS Partition Boot Block                        1024 bytes
+
+The Perl script "hdisk.pl" can be used to give a listing of what's on
+a Mac CD. hdisk.pl is part of hfsutils.
+
+A hybrid CD is made using the option "-boot-hfs-file" e.g.
+
+mkhybrid -boot-hfs-file HFS_driver_file -o hfs.raw src_files/
+
+The -boot-hfs-file implies the -hfs option.
+
+PLEASE NOTE:
+
+By using a driver from an Apple CD and copying Apple software to your CD,
+you become liable to obey Apple Computer, Inc. Software License Agreements.
+
+The driver code (both extracting the driver and creating partitions etc.
+is based on code from "mkisofs 1.05 PLUS" by Andy Polyakov
+<appro@fy.chalmers.se> (see http://fy.chalmers.se/~appro/mkisofs_plus.html)
+
+
+Any comments, bug reports/fixes to the address below
+
+James Pearson (j.pearson@ge.ucl.ac.uk)
+19-Jul-2000
+
+Edited for program name change by Eduard Bloch, 2006
diff --git a/doc/genisoimage/README.hfs_magic b/doc/genisoimage/README.hfs_magic
new file mode 100644 (file)
index 0000000..814d59e
--- /dev/null
@@ -0,0 +1,69 @@
+
+Find file types by using a modified "magic" file
+
+Based on file v3.22 by Ian F. Darwin (see libfile/LEGAL.NOTICE and
+libfile/README.dist - File v3.22 can be found at many archive sites)
+
+For each entry in the magic file, the "message" for the initial offset MUST
+be 4 characters for the CREATOR and 4 characters for the TYPE - white space is
+optional between them. Any other characters on this line are ignored.
+Continuation lines (starting with a '>') are also ignored i.e. only the initial
+offset lines are used.
+
+e.g magic entry for a GIF file:
+
+# off  type            test            message
+#
+# GIF image
+0       string          GIF8            8BIM GIFf
+>4      string          7a              \b, version 8%s,
+>4      string          9a              \b, version 8%s,
+>6      leshort         >0              %hd x
+>8      leshort         >0              %hd,
+#>10    byte            &0x80           color mapped,
+#>10    byte&0x07       =0x00           2 colors
+#>10    byte&0x07       =0x01           4 colors
+#>10    byte&0x07       =0x02           8 colors
+#>10    byte&0x07       =0x03           16 colors
+#>10    byte&0x07       =0x04           32 colors
+#>10    byte&0x07       =0x05           64 colors
+#>10    byte&0x07       =0x06           128 colors
+#>10    byte&0x07       =0x07           256 colors
+
+Just the "8BIM" "GIFf" will be used whatever the type of GIF file it is.
+The continuation lines are used by the "file" command, but ignored by
+mkhybrid. They could be left out completely.
+
+The complete format of the magic file is given in the magic man page (magic.5).
+
+See the file "magic" for other examples
+
+Use with the -magic magic_file option, where magic_file is a file
+described above.
+
+The magic file can be used with the mapping file (option -map) - the order
+these options appear on the command line is important.  mkhybrid will try to
+detect if the file is one of the Unix/Mac files (e.g. a CAP or Netatalk
+file) first. If that fails, it will then use the magic and/or mapping
+file e.g:
+
+mkhybrid -o output.raw -map mapping -magic magic src_dir
+
+The above will check filename extensions first, if that fails to set the
+CREATOR/TYPE, the magic file will be used. To check the magic file
+before the filename extensions, use:
+
+mkhybrid -o output.raw -magic magic -map mapping src_dir
+
+
+Using just a magic file - filename extensions will not be checked e.g:
+
+mkhybrid -o output.raw -magic magic src_dir
+
+For the magic method to work, each file must be opened and read twice
+(once to find it's CREATOR/TYPE, and a second time to actually copy the
+file to the CD image). Therefore the -magic option may significantly
+increase processing time.
+
+If a file's CREATOR/TYPE is not set via the magic and mapping matches,
+then the file is given the default CREATOR/TYPE.
diff --git a/doc/genisoimage/README.hide b/doc/genisoimage/README.hide
new file mode 100644 (file)
index 0000000..ae8521b
--- /dev/null
@@ -0,0 +1,208 @@
+Hiding files on a CD
+=====================
+
+This document attempts to show how to hide files from being seen by an
+operating system accessing a CD as an ISO9660/Rock Ridge, Joliet or HFS
+CD. It also highlights some of the limitations ...
+
+Note: this document is about the various -hide options - not be confused with
+the -hidden options.
+
+The -hidden options set the 'EXISTENCE' bit in the directory entry which
+means the file or directory will be invisible - unless some special option
+is used to mount or view the CD - Linux has the 'unhide' mount option to
+make these files visible. i.e. the directory entry exists on the CD.
+
+With hindsight, to avoid confusion with the -hidden option, it would have
+been better to chose an option name like '-omit' instead of '-hide'...
+
+The various -hide options actually exclude the relevant directory entry
+from the directory tree. Therefore, it is not possible to access a file
+or directory that has be hidden with the -hide option when the ISO9600/Rock
+Ridge directory is mounted - because the directory entry does not exist on the
+CD (but the file data does). You would probably be able to access this file
+or directory when mounted as a Joliet or HFS CD (depending on other options
+used). Similarly, a directory entry hidden with the -hide-joliet option
+will not be accessible when mounted as an Joliet CD. Similarly for -hide-hfs
+etc.
+
+If you don't want a file or directory to appear on the CD at all, then use the
+-exclude options, not the -hide options (genisoimage completely ignores any
+file/directory excluded with the -exclude options).
+
+
+Using the hide options
+======================
+
+There are 6 hide options:
+
+-hide             Hide a file/directory from the ISO9660/Rock Ridge directory
+-hide-list        As above, but read file names from a file
+-hide-joliet      Hide a file/directory from the Joliet directory
+-hide-joliet-list  As above, but read file names from a file
+-hide-hfs         Hide a file/directory from the HFS directory
+-hide-hfs-list    As above, but read file names from a file
+
+You can use the -hide, -hide-joliet and/or -hide-hfs options as many times
+as you like on the command line, but if you have many files to hide, then
+it may be better to put your file names in a file (one per line) and use
+the corresponding 'list' option. You can also use the three -hide-list options
+as many times as you want.
+
+The arguments to the -hide options are either the 'basename' or the 'whole
+path name' of a file. That is, if you use the option:
+
+% genisoimage -hide ABC [-other-options] CD_directory
+
+then any file with the name ABC will be hidden. If you want to be more
+specific, then use the whole name - as seen by genisoimage e.g.:
+
+% genisoimage -hide CD_directory/XYZ/ABC [-other-options] CD_directory
+
+will hide just the file 'CD_directory/XYZ/ABC' - not any other file called
+'ABC' that might exist under 'CD_directory'. However, if your command line
+is like:
+
+% genisoimage -hide CD_directory/XYZ/ABC [-other-options] ./CD_directory
+
+Then the file 'CD_directory/XYZ/ABC' will not be hidden because as far as
+genisoimage is concerned. Its whole path is actually './CD_directory/XYZ/ABC'.
+
+You can use wild cards in the -hide arguments.
+
+If the file name to be hidden is a directory, then the directory and all
+its contents are hidden.
+
+The main use of the hide options is on a multi platform (hybrid CD) to hide
+various files/directories that are operating system specific from been seen
+on the CD when mounted on another OS. i.e. You may want to hide Macintosh
+executables from being seen when the CD is mounted as a Joliet CD on a PC etc.
+
+For example, say we want to create a ISO9660/Rock Ridge, Joliet, HFS hybrid
+CD from files/directories in the directory called 'cd_dir' - which are:
+
+MAC/
+MAC/app
+MAC/data/
+MAC/data/file1
+PC/
+PC/app
+PC/data/
+PC/data/file1
+UNIX/
+UNIX/app
+UNIX/data
+UNIX/data/file1
+COMMON/
+COMMON/some_files
+
+We could use the command line:
+
+% genisoimage -r -J -hfs -hide MAC -hide PC -hide-joliet MAC \
+       -hide-joliet UNIX -hide-hfs PC -hide-hfs UNIX -o cd.iso cd_dir
+
+This will give a CD that when mounted as a Rock Ridge CD, you will only 
+see the directories UNIX and COMMON, as a Joliet CD the directories
+PC and COMMON, and as an HFS CD the directories MAC and COMMON.
+
+If you also had the three files in the current directory called README.hfs,
+README.joliet and README.unix - but you wanted to have each of these
+files appear as just 'README' when mounted, then you could use the above
+command line with the following:
+
+% genisoimage -r -J -hfs -graft-points -hide MAC -hide PC -hide-joliet MAC \
+       -hide-joliet UNIX -hide-hfs PC -hide-hfs UNIX \
+       -hide README.hfs -hide README.joliet -hide-joliet README.hfs \
+       -hide-joliet README.uni -hide-hfs README.joliet -hide-hfs README.unix \
+       README=README.hfs README=README.joliet README=README.unix \
+       -o cd.iso cd_dir
+
+Note: we've used the -graft-points option as we're using the '=' syntax
+to insert the files called README.hfs, README.joliet and README.unix as
+'README'
+
+The resulting CD when mounted as a Rock Ridge CD, will have the directories
+UNIX and COMMON - with the file called README - which was originally 
+called README.unix.
+
+However, in most circumstances, it would be better to have the contents
+of each of the OS specific directories (plus the contents of the COMMON
+directory) to appear at the top level of the CD. i.e. when the CD is mounted
+(as ISO9660/Rock Ridge, Joliet or HFS) it has the contents:
+
+README
+app
+data/file1
+some_files
+
+Unfortunately, this is not as straight forward as it may seem - i.e. doing
+the following may seem OK, but it won't work - for reasons I'll explain 
+later:
+
+It gets a bit messy using the -graft-points syntax above, so we'll assume
+each of the MAC, UNIX and PC directories contain the correct README, We'll
+also change to the 'cd_dir' directory and use the command:
+
+genisoimage -r -J -hfs -hide MAC -hide PC -hide-joliet MAC \
+       -hide-joliet UNIX -hide-hfs PC -hide-hfs UNIX \
+       -o cd.iso MAC PC UNIX COMMON
+
+You will get errors like:
+
+genisoimage: Error: UNIX/README and MAC/README have the same Rock Ridge name
+...
+genisoimage: Unable to sort directory 
+
+This is because you can not hide "pathspecs" that are directories ("pathspecs"
+are file names given on the command line, or in a path-list file). This a 
+"feature" of genisoimage. In this case nothing is actually hidden at all.
+
+So you might think that the following may work:
+
+genisoimage -r -J -hfs -hide "MAC/*" -hide "PC/*" -hide-joliet "MAC/*" \
+       -hide-joliet "UNIX/*" -hide-hfs "PC/*" -hide-hfs "UNIX/*" \
+       -o cd.iso MAC PC UNIX COMMON
+
+which may appear to work - but when the CD is mounted as an ISO9660/Rock Ridge
+or Joliet CD, then the directory "data" is missing.
+
+Again this is a feature of genisoimage - the directories PC/data and UNIX/data
+are mapped by genisoimage to the same output directory called "/data" - the
+various "hide" flags are stored with this directory info - in this case as 
+the output directory "/data" is first hidden from the ISO9660/Rock Ridge and
+then the Joliet directory, the net result is that "/data" gets hidden from
+both directories ... the way genisoimage hides HFS directories is slightly
+different, so in this case the directory "data" exists on the HFS volume
+and contains the correct contents.
+
+However, it is possible to obtain the required result, but we have to be
+careful about hiding multiple input directories that map to a single output
+directory.
+
+To do this we have to hide just the files in these directories (or more
+accurately, all the non-directories). This is best done by using lists of
+files to hide for example: 
+
+find PC -type f -print > pc.list
+find UNIX -type f -print > unix.list
+find MAC -type f -print > mac.list
+
+genisoimage -r -J -hfs -hide-list pc.list -hide-list mac.list \
+       -hide-joliet-list unix.list -hide-joliet-list mac.list \
+       -hide-hfs-list pc.list -hide-hfs-list unix.list \
+       -o cd.iso MAC PC UNIX COMMON
+
+i.e. instead of trying to hide a directory and letting genisoimage hide its
+contents, we explicitly hide all the files in the directory, but not the
+directory and any of its sub-directories.
+
+This will work for the above input files, but if your directory trees contain
+symbolic links and/or directories that will not get merged, then the hide lists
+will have to be tailored to get the required result.
+
+
+James Pearson 22-Nov-2001
+
+Any comments/problems to j.pearson@ge.ucl.ac.uk
+
+Modified for cdrkit/genisoimage by Eduard Bloch, Wed, 27 Dec 2006
diff --git a/doc/genisoimage/README.hppaboot b/doc/genisoimage/README.hppaboot
new file mode 100644 (file)
index 0000000..a7a7549
--- /dev/null
@@ -0,0 +1,38 @@
+# README.hppaboot    Steve McIntyre <steve@einval.com> 2004/07/19
+
+The hppa boot support allows you to create a bootable CD which will
+work with HP PA/RISC machines, for example bootable installation
+media.
+
+The method used for this is the same as in palo, the bootloader for
+Linux on hppa. See the palo README for more details about supported
+hardware etc.
+
+The HPPA firmware reads the first 2048-byte sector off a disk and
+parses information in that sector. The information in question is the
+location (start sector) and length of various files:
+
+ * a 32-bit kernel image
+ * a 64-bit kernel image
+ * first stage bootloader (iplboot)
+ * (optional) ramdisk
+
+and also the system command line to use, e.g.
+
+ "5/vmlinux HOME=/ TERM=linux console=tty"
+
+The firmware will load and execute the first stage boot loader, and
+that should be able to find the (32- or 64-bit) kernel and boot
+normally. Whether you need a 32- or 64-bit kernel depends on your
+hardware; some will even support both.
+
+To use the hppa boot support code in genisoimage, simply specify the boot
+command line and file locations (relative to the CD root) as follows:
+
+genisoimage ... -hppa-cmdline <cmdline, parts separated by spaces or commas> \
+            -hppa-kernel-32  <32-bit kernel> \
+            -hppa-kernel-64  <64-bit kernel> \
+            -hppa-bootloader <bootloader> \
+            -hppa-ramdisk    <ramdisk file> \
+            -o hppa.iso hppa-files
+
diff --git a/doc/genisoimage/README.joliet b/doc/genisoimage/README.joliet
new file mode 100644 (file)
index 0000000..ab9bf5d
--- /dev/null
@@ -0,0 +1,53 @@
+Some thoughts on Joliet - why it is a dumb idea to have a CD
+with Joliet enhancements but without Rock Ridge.
+It also helps you to understand why it it not possible to append
+a new session to a multi-session Joliet CD when Rock Ridge is
+missing.
+
+-      Joliet is not an accepted independant international standard
+       like ISO-9660 or Rock Ridge (IEEE-P1282).
+       Joliet has been created in 1995 - Rock Ridge in 1990.
+       Rock Ridge became a IEEE standard around 1992.
+
+Joliet is an unjustified addition to ISO-9660.
+
+-      The Joliet tree has no relation to the
+       ISO-9660 tree. Files from the ISO-9660 tree and from the
+       Joliet tree only share content. In general, it is not
+       possible to find the ISO-9660 name from a Joliet name
+       and vice versa if you check both trees on a CD.
+
+       Rock Ridge extensions are located at the end of each
+       ISO-9660 directory record. This makes the Rock Ridge
+       tree closely coupled to the ISO-9660 tree.
+
+-      Joliet does not allow all characters too, so the
+       Joliet filenames are not identical to the filenames
+       on disk.
+
+       As the ISO-9660 tree is the standard reference tree
+       on a CD and the ISO-9660 filenames don't allow all
+       characters and there is a length limitation, the
+       ISO-9660 names cannot be mapped to the filenames on the
+       OS reference tree on disk for doing multi-session.
+
+       Due to different limitations, the short ISO-9660 name 
+       is in most cases not equal to the Joliet name or the
+       Rock Ridge name.
+
+-      Joliet has a filename length limitation of 64 chars (independent
+       from the character coding and type e.g. European vs. Japanese)
+       This is annoying as modern filesystems all allow 255 chars
+       per path name component.
+
+       Joliet uses UTF-16 coding while Rock Ridge uses ISO-8859 or
+       UTF-16 based chars and allows 255 octets. Using UTF-8,
+       Rock Ridge allows 85 Japanese characers or 255 US-ASCII chars.
+
+Other than slightly longer filenames, Joliet offers no new properties
+over plain ISO 9660. Rock Ridge is an open extendable standard and
+there is no filesystem property on Win32 that could not be implemented 
+using Rock Ridge.
+
+Except Linux and FreeBSD, there is no POSIX-like like OS that supports
+Joliet. Never create Joliet only CD's for that reason.
diff --git a/doc/genisoimage/README.macosx b/doc/genisoimage/README.macosx
new file mode 100644 (file)
index 0000000..e082bfc
--- /dev/null
@@ -0,0 +1,43 @@
+Notes on using the --osx-hfs option when running genisoimage on MacOS X
+
+genisoimage does not use any of the MacOS APIs to access files - it uses
+standard (POSIX style) library calls. Under normal circumstances, all
+genisoimage will 'see' is the data fork of files on an HFS (or HFS+) file system.
+
+However, Apple have provided a way for POSIX style applications to 
+access the resource fork - using the following syntax:
+
+If a file exists on an HFS volume with the name 'foo', then the resource fork
+can be accessed using the file name 'foo/rsrc' or foo/..namedfork/rsrc'
+(the data fork can also be accessed using 'foo/..namedfork/data').
+
+These 'pseudo' file names are not normally visible in a directory - unless
+you access them directly (e.g. 'ls -l */rsrc etc).
+
+To access the finder information, Apple have provided an undocumented library
+function called getattrlist(). Fortunately there are example of its usage
+in the Darwin (MacOS kernel) source code.
+
+
+Although MacOS X can use HFS(+) as its file system, Apple have decided to
+move away from using HFS to store finder info and resource data - for 
+example, the TYPE of a file may be based on its file name extension and the
+TYPE field in the finder info empty.
+
+genisoimage knows nothing about these file name extension mappings, so if the
+--osx-hfs option is used and the source files are on MacOS X HFS(+) volumes,
+by the fact that they are HFS files, they will get identified as 'MacOS X HFS'
+and the resulting file on the output CD image will have empty TYPE and CREATOR
+fields.
+
+Therefore, if the input finderinfo is blank and the the resource fork is
+empty, genisoimage will assume the input file is not a 'real' HFS file - which
+means the TYPE and CREATOR may then be set using the file's magic number or
+genisoimage' file name extension mapping.
+
+The only real benefit of using the --osx-hfs option is when the source files
+are on an OS9 or earlier HFS or HFS+ volume e.g. an existing HFS CD.
+
+James Pearson 3-Jul-2002
+Edited for program name change by Eduard Bloch, 2006
+
diff --git a/doc/genisoimage/README.mipsboot b/doc/genisoimage/README.mipsboot
new file mode 100644 (file)
index 0000000..1e5227a
--- /dev/null
@@ -0,0 +1,26 @@
+# README.mipsboot    Steve McIntyre <steve@einval.com> 2004/07/19
+
+The mips/SGI boot support allows you to create a bootable CD which
+will work with big-endian mips SGI machines, for example bootable
+installation media.
+
+The method used for this is the same as in genisovh, a tool to make
+CDs bootable for Linux on SGI.
+
+The SGI firmware reads the first 512-byte "sector" off a disk and
+parses information from a volume descriptor header in that sector. The
+information in question is the location (start sector) and length of
+bootable kernel images; up to 15 are supported.
+
+The firmware will load and execute kernels listed. (I'm not sure what
+it will do if more than one kernel is listed - it may display a boot
+menu).
+
+To use the SGI boot support code in genisoimage, simply specify the kernel
+file locations (relative to the CD root) as follows:
+
+genisoimage ... -mips-boot <kernel file #1> \
+            ... 
+            -mips-boot <kernel file #n> \
+            -o mips.iso mips-files
+
diff --git a/doc/genisoimage/README.mipselboot b/doc/genisoimage/README.mipselboot
new file mode 100644 (file)
index 0000000..af3979b
--- /dev/null
@@ -0,0 +1,29 @@
+# README.mipselboot    Steve McIntyre <steve@einval.com> 2004/07/19
+
+The mips/DEC boot support allows you to create a bootable CD which
+will work with little-endian mips DEC machines (e.g. older
+DECstations), for example bootable installation media.
+
+The method used for this is the same as in delo, the Linux-on-mipsel
+bootloader. See the delo README for more information about how to
+configure the DECstation's firmware to find and boot the CDROM.
+
+The DEC firmware reads the first 512-byte "sector" off a disk and
+parses information from that sector. The information in question is
+the location (start sector) and length of the first stage boot
+loader.
+
+(On Linux, this boot loader is in ELF format and the firmware does not
+know how to deal with ELF directly, we have to parse the ELF headers
+and find the raw binary data needed inside it. Pointers to the start
+and length of that raw binary are what is stored in the boot sector.)
+
+The firmware will load and execute the first stage boot loader, and
+from that point the system should be able to find the normal OS kernel
+and start up fully.
+
+To use the DEC boot support code in genisoimage, simply specify the kernel
+file location (relative to the CD root) as follows:
+
+genisoimage ... -mipsel-boot <kernel file> -o mipsel.iso mipsel-files
+
diff --git a/doc/genisoimage/README.mkhybrid b/doc/genisoimage/README.mkhybrid
new file mode 100644 (file)
index 0000000..49036a1
--- /dev/null
@@ -0,0 +1,145 @@
+
+mkhybrid v1.13 has merged with mkisofs which was forked to genisoimage later
+
+HFS hybrid code Copyright (C) James Pearson 1997, 1998, 1999, 2000
+libhfs code Copyright (C) 1996, 1997 Robert Leslie
+libfile code Copyright (c) Ian F. Darwin 1986, 1987, 1989,
+       1990, 1991, 1992, 1994, 1995
+mkisofs code Copyright 1993 Yggdrasil Computing, Incorporated
+
+*** NEWS ***
+
+Macs can now read Joliet CDs - see http://www.tempel.org/joliet/
+
+***
+
+*** IMPORTANT ***
+
+The meaning of some of the HFS command line options has changed since
+version 1.12b5.2. This change is to make the way genisoimage decodes the 
+various Apple/Unix file formats (CAP, AppleDouble, MacBinary etc.) less
+confusing and more logical. To decode one or more of the Apple/Unix files,
+then the corresponding "double dash" option must be given (i.e. --cap, 
+--double, --macbin etc.) genisoimage can search for all known Apple/Unix files
+by using the -probe option.
+
+The options that have changed are:
+
+Option         old meaning                     new meaning
+======         ===========                     ===========
+
+-hfs           Create an HFS hybrid CD         Create an HFS hybrid CD.
+               and attempt to decode all       Any Apple/Unix file is only
+               Apple/Unix files (except        decoded if one or more of
+               MacBinary and AppleSingle)      the "double dash" options are
+                                               given
+
+-apple         Create an ISO9660 with          Create an ISO9660 with
+               Apple extensions CD and         Apple extensions CD. Any
+               attempt to decode all           Apple/Unix file is only decoded
+               Apple/Unix files (except        if one or more of the
+               MacBinary and AppleSingle)      "double dash" options are given
+
+-no-mac-files  Do not attempt to decode        No longer used
+               any Apple/Unix file
+
+-probe         Attempt to decode               Attempt to decode all
+               MacBinary and AppleSingle       Apple/Unix files
+               as well as the other
+               Apple/Unix files
+
+***
+
+Most of the HFS features work fine, however, some are not fully tested.
+These are marked as "Alpha" in the man page.
+
+See "ChangeLog.mkhybrid" for any minor changes/bug fixes
+
+If you are using SunOS 4.1.[34], then you need the following patches
+to read CDs with associated files:
+
+SunOS 4.1.3:           Patch 101832-05
+SunOS 4.1.3_U1:                Patch 101833-02
+SunOS 4.1.4:           Patch 102583-02
+
+
+EXAMPLES
+
+To create a HFS hybrid CD with the Joliet and Rock Ridge extensions of
+the source directory cd_dir:
+
+% genisoimage -o cd.iso -r -J -hfs cd_dir
+
+To create a HFS hybrid CD from the source directory cd_dir that contains
+Netatalk Apple/Unix files:
+
+% genisoimage -o cd.iso --netatalk cd_dir
+
+To create a HFS hybrid CD from the source directory cd_dir, giving all files
+CREATOR and TYPES based on just their filename extensions listed in the file 
+"mapping".:
+
+% genisoimage -o cd.iso -map mapping cd_dir
+
+To create a CD with the 'Apple Extensions to ISO9660', from the source
+direcories cd_dir and another_dir. Files in all the known Apple/Unix format
+are decoded and any other files are given CREATOR and TYPE based on their
+magic number given in the file "magic":
+
+% genisoimage -o cd.iso -apple -magic magic -probe cd_dir another_dir
+
+The following example puts different files on the CD that all have
+the name README, but have different contents when seen as a
+ISO9660/RockRidge, Joliet or HFS CD.
+
+Current directory contains:
+
+% ls -F
+README.hfs     README.joliet  README.unix    cd_dir/
+
+The following command puts the contents of the directory "cd_dir" on the
+CD along with the three README files - but only one will be seen from
+each of the three filesystems:
+
+% genisoimage -o cd.iso -hfs -J -r \
+        -hide README.hfs -hide README.joliet \
+        -hide-joliet README.hfs -hide-joliet README.unix \
+        -hide-hfs README.joliet -hide-hfs README.unix \
+        README=README.hfs README=README.joliet README=README.unix \
+        cd_dir
+
+i.e. the file README.hfs will be seen as README on the HFS CD and the
+other two README files will be hidden. Similarly for the Joliet and
+ISO9660/RockRidge CD.
+
+There are probably all sorts of stange results possible with
+combinations of the hide options ...
+
+
+Any comments, bug reports/fixes about the HFS parts of genisoimage to the
+address below.
+
+Please state the version, platform and command line used when submitting
+a bug report - the output from "-log-file -v" would help.
+
+Original author: James Pearson (j.pearson@ge.ucl.ac.uk)
+
+This describes the program as shipped with cdrkit, a spinoff from the
+cdrtools project. However, the cdrtools developers are no longer
+involved in the development of this spinoff and therefore shall not
+be made responsible for any problem caused by it. Do not try to get
+support for this program by contacting the original authors.
+
+If you have support questions, send them to
+
+debburn-devel@lists.alioth.debian.org
+
+If you have definitely found a bug, send a mail to this list or to
+
+submit@bugs.debian.org
+
+writing at least a short description into the Subject and "Package: cdrkit"
+
+Source: README.mkhybrid from cdrtools package
+Edited for cdrkit by Christian Fromme <kaner@strace.org> and Eduard Bloch
+
diff --git a/doc/genisoimage/README.prep_boot b/doc/genisoimage/README.prep_boot
new file mode 100644 (file)
index 0000000..f406735
--- /dev/null
@@ -0,0 +1,45 @@
+I have extended mkhybrid to create a CD that is bootable via PPCbug
+on a PowerPC Reference Platform compliant machine (referred to as
+PReP).
+
+This includes a number of IBM RS-6000 clones, along with most of
+Motorola's embedded PowerPC boards, such as the MTX and MVME
+boards. (The motorola boards are sometimes referred to as PowerPlus)
+
+To build a bootable CD, you will first need a kernel image for your
+machine. Put the image somewhere in the filesystem you want
+to generate and ISO9660 image from.
+
+The '-B' or '-prep-boot' flags are used to specify the image file
+to use. The path must be relative to the root of the CD filesytem,
+NOT from the current directory.
+
+For example: to make an image of /tmp/cd and use the image file
+/tmp/cd/zImage, (with rock ridge extensions) use:
+
+mkhybrid -r -B zImage /tmp/cd -o cd.img
+
+Since there are four entries for bootable 'partitions', I have
+allowed up to 4 different images to be used. This might be 
+usefull if one has need of different kernel images for different
+machines on the same CD.
+
+The first image will be in the first partition entry, so if one
+uses:
+
+mkhybrid -r -B zImage1 -B zImage2 -B zImage3 -B zImage4 /tmp/cd
+
+This will result in 4 bootable images. To boot off the first image
+from PPCbug, use 'pboot 0 41' from the ppcbug> prompt.
+(assuming the CDROM is at SCSI ID 4.. replace the 4 with the SCSI
+ID of the CDROM if not.) The second image is at 'pboot 0 42', etc.
+
+There should not be any conflicts with any of the HFS or hybrid
+functions, since the space used by the PReP partition maps is
+unused by anything else. If fact, the goal is to make a CD
+bootable on both Mac's and PReP machines ;)
+
+For any questions contact me at one of the following addresses:
+troy@microux.com
+troy@blacklablinux.com
+hozer@drgw.net
diff --git a/doc/genisoimage/README.releasenotes b/doc/genisoimage/README.releasenotes
new file mode 100644 (file)
index 0000000..d4f3898
--- /dev/null
@@ -0,0 +1,154 @@
+# @(#)README   1.7 99/11/23 joerg
+#                   06/09/11 christian
+
+This describes the program as shipped with cdrkit, a spinoff from the
+cdrtools project. However, the cdrtools developers are no longer 
+involved in the development of this spinoff and therefore shall not
+be made responsible for any problem caused by it. Do not try to get 
+support for this program by contacting the original authors.
+
+Note:
+
+       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.
+
+
+*****************************
+Notes for version 1.12
+
+       Joliet support is now complete.  See the -J option.
+
+       The file scanning code is much improved - mkisofs can use multiple
+       sources of input files and merge them together to form the output
+       image.  In addition, each source can be grafted at any point in the
+       iso9660 image.
+
+       The image writing code has been cleaned up to make it much easier
+       to add custom extensions.
+
+       The ADD_FILES feature has been removed as it didn't work well,
+and it was hard to figure out.  The recent rearrangements in the
+file scanning code would tend to solve these issues.
+
+*****************************
+Notes for version 1.11
+
+       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.
+
+*****************************
+Notes for version 1.10b1
+
+       Big news is that multi-session capability is very close to being
+       done.  There is still a missing interface to cdwrite that is
+       used to determine the next writable address and the sector number
+       of the last existing session.  Until we get the interface to cdwrite
+       done, this is a beta version.
+
+       Bug involving DST fixed (dates are always calculated, since some
+       files may be DST and other ones would not be).
+
+       Unfortunately the notes on some of the small patches got lost.
+
+*****************************
+Notes for version 1.06
+
+       Jan-Piet Mens <jpm@mens.de> added support for the '-m' switch. This
+       allows exclusion of shell-style globs from the CDROM.
+       See manual mkisofs.8 for more information.
+
+*****************************
+Notes for version 1.05
+
+       Added support for '-r' switch.  This is very similar to -R for
+Rock Ridge, but echos of the development environment are removed
+(i.e. uid/gid set to 0, and permissions of the files are canonicalized).
+Useful in applications where a distribution medium is being produced.
+
+*****************************
+Notes for version 1.04
+
+       No notes for 1.04.
+
+*****************************
+Notes for version 1.03
+
+       No notes for 1.03.
+
+*****************************
+Notes for version 1.02.
+
+       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).
+
+
+Source: README from cdrtools package
+Edited for cdrkit by Christian Fromme <kaner@strace.org>
+
diff --git a/doc/genisoimage/README.rootinfo b/doc/genisoimage/README.rootinfo
new file mode 100644 (file)
index 0000000..b3bc447
--- /dev/null
@@ -0,0 +1,90 @@
+The -icon-position option will attempt to preserve folder window positions,
+scroll bars, views etc. for Apple/Unix file formats that support this
+information (see below for which Apple/Unix encoding are supported).
+
+This information is stored in the 'FinderInfo' part of a Apple/Unix directory.
+For example, in a CAP directory structure a directory called 'dirA' will
+have the necessary FinderInfo stored in file '.finderinfo/dirA'. This file
+stores information including, the folder's location and size on screen,
+its scroll positions, folder View (view as Icons, Small Icons, etc.).
+
+However, the similar FinderInfo data for the 'root' folder is a special case.
+For example, if a directory called '/some/dir/macfiles' is a CAP volume that
+is mounted on a Mac as 'macfiles', then the FinderInfo for this directory
+is stored in the file '/some/dir/.finderinfo/macfiles' - which is outside
+the CAP directory structure.
+
+To get round this, an extra option, '-root-info' is used that takes as its
+argument the name of the file that stores the root folder's FinderInfo.
+
+Using the above example, the command file options will be something like:
+
+% mkhybrid --cap -root-info /some/dir/.finderinfo/macfiles /some/dir/macfiles
+
+The format of the root FinderInfo file must be the same as the 'double-dash'
+option(s) given on the command line.
+
+The Apple/Unix encodings that mkhybrid can decode the root FinderInfo are:
+
+CAP:
+       CAP directory:          /some/dir/macfiles
+       Root FinderInfo file:   /some/dir/.finderinfo/macfiles
+
+Netatalk:
+       Netatalk directory:     /some/dir/macfiles
+       Root FinderInfo file:   /some/dir/.AppleDouble/RootInfo
+
+EtherShare:
+       EtherShare directory:   /some/dir/macfiles
+       Root FinderInfo file:   /some/dir/.rsrc/macfiles
+
+If an HFS disk is mounted on a Linux platform, then the root FinderInfo
+files are:
+
+Option 'fork=cap':
+       Root FinderInfo file:   /mountpoint/.rootinfo
+
+Option 'fork=double':
+       Root FinderInfo file:   /mountpoint/%RootInfo
+
+Option 'fork=netatalk':
+       Root FinderInfo file:   /mountpoint/.AppleDouble/RootInfo
+
+
+The '-root-info' option implies the '-icon-position' option. Future releases
+of mkhybrid may automatically find the root FinderInfo file.
+
+The volume name is not set from the root FinderInfo file. Use the -V or
+-hfs-volid options to set the volume name.
+
+Currently UShare, SGI/XINET, PC Exchange and SFM Apple/Unix root FinderInfo
+files are not supported by mkhybrid - more information about these formats
+is required in order to supoort them.
+
+AppleSingle and MacBinary are file only formats - they don't support folders
+or volumes.
+
+Using this option, it is now possible to make a nearly true representation
+of a Mac folder layout on a Unix/Linux platform.
+
+Original author: James Pearson 26-Apr-2000
+
+This describes the program as shipped with cdrkit, a spinoff from the
+cdrtools project. However, the cdrtools developers are no longer
+involved in the development of this spinoff and therefore shall not
+be made responsible for any problem caused by it. Do not try to get
+support for this program by contacting the original authors.
+
+If you have support questions, send them to
+
+debburn-devel@lists.alioth.debian.org
+
+If you have definitely found a bug, send a mail to this list or to
+
+submit@bugs.debian.org
+
+writing at least a short description into the Subject and "Package: cdrkit"
+
+Source: README.rootinfo from cdrtools package
+Edited for cdrkit by Christian Fromme <kaner@strace.org>
+
diff --git a/doc/genisoimage/README.session b/doc/genisoimage/README.session
new file mode 100644 (file)
index 0000000..a4126fb
--- /dev/null
@@ -0,0 +1,53 @@
+/* @(#)README.session  1.3 99/03/02 eric */
+
+       This release of genisoimage has basic support completed for
+multiple sessions.  However, we still need some interaction 
+between wodim and genisoimage for this to work correctly. This is needed as
+only wodim knows the different ways to gather these numbers for all 
+different drives. It may be that future versions of genisoimage will include 
+the needed support for MMC compliant drives.
+
+       There are a few new options to genisoimage to allow for this.
+The first one is "-M /dev/scd0", and is used so that genisoimage can examine
+the entirety of the previous image so that it can figure out what additional
+files need to be written in the new session. Note that there are operating
+systems that don't allow to read from CD drives with a sector size
+of 2048 bytes per sector. To use genisoimage on such an operating system, you
+will need a version of genisoimage that includes the SCSI transport library 
+from wodim. Simply use the dev= syntax from wodim with -M in
+such a case. It will tell genisoimage to use the SCSI transport library to 
+read from the CD instead of using the standard read() OS interface.
+
+       There is also a temporary hack in genisoimage in the form of a '-C' option.
+The -C option takes two numbers as input, which are delimited by commas.
+For example, you could specify "-C 1000,1020", but you should never just
+make up numbers to use here.  These numbers are determined from wodim.
+
+       Note that if you use -C and omit -M, it effectively means that
+you are writing a new session, starting at a non-zero block number,
+and you are effectively ignoring all of the previous session contents.
+When this session is sent to the writer, the new session effectively
+"erases" the previous session.
+
+       In practice you should be able to do something like:
+
+genisoimage [other options] -C `wodim dev=b,t,l -msinfo` \
+               -M /dev/cdblkdev
+
+Replace 'b,t,l' by the aproriate numbers for SCSIbus, target and lun
+of your drive.
+
+Note: As of the 1.12b5 release, the multi-session technology has
+matured quite significantly.  It is entirely possible that bugs
+exists, or that further tweaks will be required somewhere along the
+way to get things working correctly.  The data gathering mode of
+wodim has been tested, and I believe it works correctly.  Caveat
+Emptor.
+
+[Mar 1, 1999].
+
+
+Source: README.session from cdrtools package
+Edited for cdrkit by Christian Fromme <kaner@strace.org> and 
+Eduard Bloch <blade@debian.org>
+
diff --git a/doc/genisoimage/README.sort b/doc/genisoimage/README.sort
new file mode 100644 (file)
index 0000000..1e377bc
--- /dev/null
@@ -0,0 +1,102 @@
+Sort the order of file data on the CD
+=====================================
+
+Note: this option does not sort the order of the file names that appear
+in the ISO9660 directory. It sorts the order in which the file data is
+written to the CD image.
+
+This option is useful in order to optimize the data layout on a CD.
+
+To use, type something like:
+
+genisoimage -o cdimage.iso -sort sort_file [other_options] cd_dir
+
+The file 'sort_file' contains two columns of:
+
+filename       weight
+
+where filename is the whole name of a file/directory as genisoimage will see it
+and weight is a whole number between +/- 2147483647
+
+The files will be sorted with the highest weights first and lowest last.
+The default weight is zero.
+
+If the filename is a directory name, then all the files in that directory (and
+sub-directories) will use its weight as their default weight.
+
+e.g.
+
+If the directory 'cd_dir' contains two directories called 'dir1' and 'dir2'
+with files 'A', 'B' and 'C' in dir1 and 'X', 'Y' and 'Z', the the file
+'sort_file' could look something like:
+
+cd_dir/dir2    1000
+cd_dir/dir2/Y  2000
+cd_dir/dir1/B  -2000
+cd_dir/dir1/A  -8000
+
+Note: There must be only one space or tab character between the filename and
+the weight and the weight must be the last characters on a line. The filename
+is taken to include all the characters from the first in a line, up to, but
+not including the last space or tab character on a line. This is to allow
+for space characters to be in, or at the end of a filename.
+
+
+The command:
+
+genisoimage -o cdimage.iso -sort sort_file cd_dir
+
+will sort the above file data as:
+
+cd_dir/dir2/Y
+cd_dir/dir2/X
+cd_dir/dir2/Z
+cd_dir/dir1/C
+cd_dir/dir1/B
+cd_dir/dir1/A
+
+Note: files 'X' and 'Z' both have the weight 1000 - their sort order will then
+be the normal ISO9660 sort order (i.e. alphabetical in this case).
+
+File C will have the default weight of 0
+
+Warning: the filenames in the sort list MUST match the whole path as seen by
+genisoimage. i.e. in the above case, if the command line was:
+
+genisoimage -o cdimage.iso -sort sort_file ./cd_dir
+
+then the sort_file filename will have to changed as accordingly.
+
+Notes
+=====
+
+CDs are written from the middle outwards. High weighted files will be nearer
+the inside of the CD.
+
+Wildcards in the filename list should work.
+
+If a file appears more than once in the source directory tree, then the file
+is only added once to the CD image - i.e. a hard linked file, or symbolic
+link if using the -f option. The file will be sorted according to the
+highest weighting given to any of the linked files.
+
+Zero length files are not sorted - the 'start extent' *may* appear to be in
+the middle of another file after sorting. This is because zero length files
+are given the start extent after the last file added to the CD at that time.
+This address is not changed by the sorting, so it may appear that the file
+address is in another file - however as they are zero length, this will
+not matter!
+
+Directories are not sorted by this flag - directories HAVE to be in the
+ISO9660 sort order - however, the files the directory entry points to, can be
+anywhere on the CD.
+
+Existing files from any previous sessions will not be sorted - they already
+exist on the CD and can not be moved!
+
+I have no idea if this is really useful ...
+
+
+James Pearson 22-Nov-2001
+
+Any comments/problems to j.pearson@ge.ucl.ac.uk
diff --git a/doc/genisoimage/README.sparcboot b/doc/genisoimage/README.sparcboot
new file mode 100644 (file)
index 0000000..b9bcbf2
--- /dev/null
@@ -0,0 +1,77 @@
+# @(#)README.sparcboot 1.1 99/12/12 joerg
+# Edited for program name change by Eduard Bloch, 2006
+
+The sparc boot feature does allow you to create your own Sun sparc boot disk.
+This will allow you to create modified Solaris install disks or to create
+installation CD's for other OS that run on sparc systems.
+
+A CD that is bootable on a Sun sparc system has a Sun disk label on sector 0
+and some Sun sparc disk partitions behind the ISO-9660 filesystem image.
+
+The layout of a sparc boot CD:
+
+----------------------------------------------------------------------------------------------------
+|Sun disk label| Iso 9660 filesystem |Generic sun4 boot|sun4c boot|sun4m boot|sun4d boot|sun4e boot|
+----------------------------------------------------------------------------------------------------
+
+On older system CD's all boot partition contain a full UFS miniroot filesystem.
+On newer CD's the images on slice 2 and above only contain boot redirects to
+slice 1.
+
+To create a CD that is bootable on Sun sparc systems you need to have the
+boot images for the apropriate sparc architecture.
+
+A boot image file usually is a UFS filesystem image that contains the 
+primary boot image at byte offset 512 ... 8191.
+
+You may get such boot images by extracting partitions 1..5 from a Sun Solaris install CD,
+but any bootable image should work.
+
+Here is an expample how to do this with the Solaris 7 install CD.
+
+dd if=/vol/dev/dsk/c0t6/sol_7_sparc_sun_srvr/s1 of=sun4
+dd if=/vol/dev/dsk/c0t6/sol_7_sparc_sun_srvr/s2 of=sun4c
+dd if=/vol/dev/dsk/c0t6/sol_7_sparc_sun_srvr/s3 of=sun4m
+dd if=/vol/dev/dsk/c0t6/sol_7_sparc_sun_srvr/s4 of=sun4d
+dd if=/vol/dev/dsk/c0t6/sol_7_sparc_sun_srvr/s5 of=sun4e
+
+
+genisoimage -R -sparc-boot sun4,sun4c,sun4m,sun4d,sun4e -o boot.img /mnt/install
+
+Will create the bootable image in boot.img.
+
+If you like to make the boot images smaller, you may call 'fstyp -v'
+on the images and use the 'size' value to get the needed minimal 
+boot image size in kB.
+
+The result for the S7 boot CD is:
+
+ufs
+magic   11954   format  dynamic time    Wed Oct  7 00:00:30 1998
+sblkno  8       cblkno  12      iblkno  16      dblkno  252
+sbsize  2048    cgsize  2048    cgoffset 20     cgmask  0xfffffff0
+ncg     7       size    25704   blocks  23987
+                       ^^^^^
+                       This is the number of interest.
+bsize   8192    shift   13      mask    0xffffe000
+fsize   2048    shift   11      mask    0xfffff800
+frag    4       shift   2       fsbtodb 2
+minfree 10%     maxbpg  2048    optim   time
+maxcontig 256   rotdelay 0ms    rps     90
+csaddr  252     cssize  2048    shift   9       mask    0xfffffe00
+ntrak   14      nsect   72      spc     1008    ncyl    102
+cpg     16      bpg     1008    fpg     4032    ipg     3776
+nindir  2048    inopb   64      nspf    4
+nbfree  1768    ndir    667     nifree  24329   nffree  9
+cgrotor 2       fmod    0       ronly   0
+
+So you should call:
+
+dd if=/vol/dev/dsk/c0t6/sol_7_sparc_sun_srvr/s1 of=sun4 bs=1k count=25704
+
+To modify this filesystem, you can mount it using the fbk driver:
+
+chmod +t ./sun4                # Need to do this to avoid vm cache aliasing problems
+
+mount -F fbk -o rw,type=ufs /dev/fbk0:sun4 /mnt
+
diff --git a/doc/genisoimage/README.sunx86boot b/doc/genisoimage/README.sunx86boot
new file mode 100644 (file)
index 0000000..2286a57
--- /dev/null
@@ -0,0 +1,77 @@
+# @(#)README.sunx86boot        1.3 05/02/25 Copyright 2003 J. Schilling
+# Edited for program name change by Eduard Bloch, 2006
+
+A Solaris x86 Boot CD looks the like this:
+
+-      A PC type fdisk partition map is in CD sector 0 at offset 0
+       This fdisk partition map contains a single Solaris 0x82 type
+       partition starting at CD sector 0 at offset 512.
+
+-      A SVr4 disk partition label is at CD sector 0 at offset 1024.
+       This equates the usual 512 byte offset to the primary partition
+       used by SVr4.
+
+       This SVr4 partition label defines:
+
+       -       Partition 0 to contain a usually UFS type boot filesystem
+
+       -       Partition 1 to map the ISO-9660 filesystem.
+
+               This seems to be a conceptual bug from Sun, as it is
+               impossible to mount this partition because this partition
+               would point outside the primary fdisk partition type 0x82
+
+       -       Partition 2 maps the whole CD.
+
+
+A boot CD created by Sun contains a master boot record in CD sector 0 offset 0.
+The size if this MBR is 0x1BE (446 decimal) as usual on PCs.
+
+At CD sector 0 offset 512, there is a "primary boot sector". The MBR assumes
+that is always gets loaded together with the ""primary boot sector".
+
+The El-Torito map for this CD defines a "no-emulation" boot sitting at CD sector 0
+and being 4 512 byte sectors in size. This covers the 1024 bytes of above 
+boot code. Note that genisoimage will not put the no-emulation boot at sector 0
+as it keeps the boot inside the area used for other file content data.
+
+At CD sector 1..15, there is a secondary boot code that understands UFS and tries
+to boot from UFS slice 0. If you like to boot from different filesystem types,
+you need to replace this boot code. The real size used by the secondary boot
+is 31 x 512 bytes == 15872 bytes.
+
+To get hold of the three boot files, do the following with e.g. a Solaris 10
+boot CD:
+
+readcd dev=1,0 f=CD.out sectors=0-32
+
+Replace dev=1,0 with the apropriate values for your system (see readcd -scanbus).
+
+sdd if=CD.out bs=446 count=1 of=mboot
+sdd if=CD.out count=1 iseek=512 of=pboot
+sdd if=CD.out count=60 iseek=2048 of=bootblk
+
+To create the needed files for the misofs command line example below, do the
+following:
+
+sdd if=mboot -fill of=eltoritoboot
+cat pboot >> eltoritoboot
+
+sdd -inull bs=2k count=1 of=genboot
+cat bootblk >> genboot
+
+If you like the CD to look more similar to the original Sun CDs, use:
+
+cp eltoritoboot genboot
+sdd -inull bs=1k count=1 >> genboot
+cat bootblk >> genboot
+
+If you like to create a CD similar to the Solaris 10 boot CD, do the following:
+
+mkdir isodir
+star -cPM -C /vol/dev/dsk/c1t1d0/multi_icd_sol_10_x86/s2 . | star -xp -xdot -C isodir
+cp eltoritoboot isodir/.bootimage
+
+genisoimage -G genboot  -no-emul-boot -b .bootimage -c .catalog -R -o bootcd.iso -sunx86-boot /vol/dev/dsk/c1t1d0/multi_icd_sol_10_x86/s0 isodir/
+
+
diff --git a/doc/icedax/FAQ b/doc/icedax/FAQ
new file mode 100644 (file)
index 0000000..815f579
--- /dev/null
@@ -0,0 +1,296 @@
+Frequently Asked Questions
+
+Status
+======
+
+
+Q: What is the copyright status of icedax?
+
+A: icedax is software copyrighted by Heiko Eissfeldt and others, and
+   released under the General Public License from the Free Software
+   Foundation (see file GPL).
+
+Compilation
+===========
+
+
+Q: What are the requirements to run icedax?
+
+A: All operating systems that are supported by wodim should also be able to
+   run icedax. Currently DOS and Windows are not covered.
+   Requirements of previous versions of icedax have been cut down for the
+   sake of portability. Features like fork(), realtime scheduling, or shared
+   memory are all optional now. You need Cmake and its dependencies, an
+   ANSI C compiler and a C library to build icedax
+   on a supported operating system. To run icedax, a SCSI transport
+   implementation for the os, a cdrom or cd burner device to read from, and
+   at least say 65K of memory for buffers are needed.
+
+
+Q: Why does it not compile under Linux, although I am using the newest kernel?
+
+A: There have been changes in the generic driver by Douglas Gilbert, that are
+   in its first release not compatible with the scsi library from Joerg
+   Schilling. We are working on this problem...
+   In the meantime better do not use this variant, use the older one instead.
+
+
+Q: Why does it not compile using standard make?
+
+A: Like wodim, icedax uses the cmake system, which requires a
+   sophisticated make program like GNU make.
+   Pure posix make functionality is not enough.
+
+Setting Up (for now Linux only)
+===============================
+
+
+Q: Should I use scsi emulation or the eide driver for my ATAPI cdrom drive?
+
+A: Scsi emulation is preferred, since it enables icedax to use more commands
+   and is often the only way to get special information like track titles with
+   cd-text. The emulation module is called ide-scsi, the eide module is called
+   ide-cd.
+
+
+Q: How can I use my parallel-port-connected cdrom with icedax?
+
+A: Under Linux there is a driver, that makes this device under SCSI
+   emulation available. For more information see the wodim documentation.
+
+
+Q: How do I check, if the current Linux kernel does support generic SCSI?
+
+A: run 'cat /proc/devices | grep "21 sg"' and see, if a line with 'sg' appears.
+   If it does not appear, the current kernel is not able to use the generic_scsi
+   interface. If you have generic SCSI support compiled as a module, see next
+   question, otherwise you need to recompile the kernel and enable generic SCSI.
+   You might try to use the 'cooked_ioctl' interface as a last resort, but then
+   you need to supply a cdrom device with -D (like -D/dev/cdrom). In this case
+   icedax completely relies on the cdda reading methods from the kernel
+   driver, so it might not work (due to unsupported). 
+
+
+Q: How do I load the generic SCSI module by hand?
+
+A: run 'insmod sg' and check the result (see above).
+
+
+Q: How do I find the device setting for my drive?
+
+A: Under Linux use the script scan_scsi.Linux. It prints the available devices
+   and their respective device option to be used.
+   Be aware of the fact that the generic device naming may change whenever the
+   devices on the SCSI bus change (present or not present).
+
+General usage (sampling)
+========================
+
+
+Q: How do I record the whole cd, each track in a seperate file?
+
+A: Use the '-B' option. This will automagically create a file for each track.
+
+
+Q: How do I record the whole cd into one file?
+
+A: Just extend the default recording time from one track to a big enough
+   time in seconds to cover the whole cd (like -d99999).
+
+
+Q: How do I record successive tracks (a track range) into seperate files?
+
+A: Use the '-B' option and -t<first tracknumber>+<last track number>.
+
+
+Q: How do I record successive tracks (a track range) into one file?
+
+A: Use -t<first tracknumber>+<last track number>.
+
+
+Q: How do I record different tracks into seperate files with individual file
+   names?
+
+A: Use the supplied script 'readmult'. For usage see the comments at the
+   beginning of the script.
+
+
+Q: How can I get the highest speed out of icedax?
+
+A: See the file README. There is a section about performance and what is
+   influencing it.
+
+
+Q: How can I burn audio cds with icedax and wodim on-the-fly?
+
+A: This has not been tested very well, so caveat emptor. It is possible to
+   use icedax and wodim with pipes, _but_ there are several issues.
+   1.: The cd drive may become too slow to keep wodim's buffer happy, when
+       a scratch on the audio cd is encountered, and several retries take place.
+   2.: Currently there is no way to carry individual track information from
+       icedax to wodim.  Several information bits are available very late
+       but are needed in advance from wodim.
+   3.: Some operating systems have limitations in multiple SCSI accesses and
+       other resources (shared memory). icedax and wodim may block each
+       other, or might fight over limited resources.
+   For these reasons it is not recommended to burn on-the-fly with icedax.
+
+Frontends
+=========
+
+
+Q: Which frontends for icedax are available?
+
+A: See the file 'Frontends'. There are command line and graphical frontends.
+
+Album and track titles
+======================
+
+
+Q: Does icedax support titles from cd extra (aka cd plus aka enhanced cd)?
+
+A: In general, yes. In order to get this information, icedax needs to read
+   a data sector from the second session of the cd. This requires multisession
+   support and the capability to read XA sectors. The titles are printed on the
+   screen and written into the inf files, then.
+
+
+Q: Does icedax support titles from cd-text?
+
+A: Newer versions support the most important features of cd-text like titles
+   and creators. Non-supported are currently 16-bit characters, so asian
+   titles etc. are currently not available.
+
+
+Q: Does icedax support CDDB ids?
+
+A: Yes, while it does not make CDDB lookups itself, it supplies an cddb file
+   with the table of contents and the cddb id. For cddb lookups see the
+   perl script tracknames.pl and tracknames.txt. If the titles are known to
+   icedax, it fills the titles itself in the cddb file.
+
+
+Q: What is the MCN?
+
+A: The media catalog number is an unique id for the audio cd release. It is
+   similar to the ISBN for books, but unfortunately it is included only on
+   some audio cds.
+
+
+Q: What is the ISRC?
+
+A: The International Standard Record Code is an unique id for a track. Like the
+   MCN (see above) it is an optional item.
+
+MP3 coding
+==========
+
+
+Q: Does icedax support on-the-fly mp3-coding?
+
+A: Yes. As of version 1.9alpha I integrated the LAME encoding engine as a new
+   output format.
+   To support external encoders, I added two scripts. The trick
+   is to avoid big temporary files. There are three versions (cdda2mp3.file,
+   cdda2mp3.pipe, and cdda2mp3.fifo), the first using files, the second uses
+   pipes, and the last uses a named pipe (also called fifo). The examples
+   use the Fraunhofer encoder 'l3enc', which is a commercial product and has
+   to be purchased seperately. Other encoders should be usable in a similar way.
+
+Conversions
+===========
+
+
+Q: How do I create a file suitable for cd burning?
+
+A: If you are using wodim, you can produce cdr or wav files.  To select
+   cdr files, use -Ocdr, to select wav files use -Owav (the default).
+   Audio files that have been recorded with a length not a multiple of the 
+   audio sector size 2352 bytes, should be used with wodim's -pad option.
+
+
+Q: How do I convert a wav file into a cdr file (my other cd burning program
+   does not accept wav format)?
+
+A: Use 'dd if=wavfile of=cdrfile conv=swab ibs=44 skip=1 obs=2352' 
+
+
+Q: How to convert cdr to wav?
+
+A: Use sox, the sound utility. It supports other formats as well.
+
+Specials
+========
+
+
+Q: Does icedax support the pre-emphasis bit?
+
+A: If the table of contents marks a track as pre-emphasized, the corresponding
+   inf file will have this information, too. That enables a cd burning program
+   to retain the state of the track.
+
+
+Q: Can icedax undo the pre-emphasis effect in the samples?
+
+A: Yes, if the -T option is given (and cd quality is selected),
+   icedax filters the samples with the reverse emphasis on-the-fly. This has
+   been checked with a sine sweep from a pre-emphasized test cd.
+
+
+Q: My cdrom delivers the stereo channels swapped. How can I undo this?
+
+A: Use the -cs option.
+
+
+Q: Does icedax support indices?
+
+A: Yes, but since there are positioning problems with a lot of drives,
+   information might be inaccurate. A start index can be specified with the
+   -i option. To get all indices, use the -v7 option.
+
+
+Q: Can icedax avoid including the pre-gap region at the end of the track?
+
+A: Currently not. This might be added later, but is not easily done.
+
+
+Q: How can I get all information about the cd without writing files?
+
+A: Use the -J option, which switches analysis to the max, and aborts after
+   the report.
+
+
+Q: Can icedax display/save the graphics on my CD+graphics disc?
+
+A: No, this is not planned. A seperate X11 program could do that probably
+   better.
+
+
+Q: Can icedax read the audio portion from my CD-I/Video-CD/DVD mpeg streams?
+
+A: No, these are special formats, which require much more effort.
+
+User support/feedback
+=====================
+
+
+Q: icedax is great. How can I support you to encourage further development?
+
+A: Look into the file NEEDED. Also constructive criticism and feedback is
+   appreciated.
+
+
+Q: I want to port cdrkit (wodim/genisoimage/icedax) to a new platform (like
+   DJGPP,cygwin,os/2). How should I proceed?
+
+A: It would be convenient to have a unix like environment (like cygwin provides)
+   A shell, and a make program would be needed to first create smake (in order
+   to make the makefile system working). Another critical component is autoconf.
+   Once that is running, os dependent interfaces and the SCSI library should be
+   adjusted. For the makefile system and the scsi library please contact Joerg
+   Schilling.
+
+
+Q: icedax sucks. Are there other alternatives available?
+
+A: Yes, for Linux you might try 'cdparanoia' from Monty (see README file).
diff --git a/doc/icedax/Frontends b/doc/icedax/Frontends
new file mode 100644 (file)
index 0000000..779af6e
--- /dev/null
@@ -0,0 +1,34 @@
+This file lists additional free frontend software to be combined with icedax:
+
+graphical frontends
+===================
+
+BurnIT (http://sunsite.auc.dk/BurnIT/)
+       by Jesper Petersen
+       a Java based frontend for cdrecord and icedax/cdparanoia
+
+Grip   (http://www.ling.ed.ac.uk/~oliphant/grip)
+       by Mike Oliphant
+       a GTK+ Frontend for audio extraction and MPEG 1 Layer 3 conversion
+       (incl. CDDB support)
+       requires libcdaudio (also by Mike Oliphant)
+
+Krabber (http://members.tripod.com/~fehlfarben/download.html)
+       by Adrian Schroeter
+       a KDE frontend for cdparanoia and MPEG 1 Layer 3 conversion
+       (incl. CDDB support)
+
+script frontends
+================
+
+Cdr    Create/Duplicate/Rip (ftp://ftp.burdell.org/pub/)
+       by David Cantrell
+       a ncurses based Perl script for CDDA to MPEG 1 Layer 3 conversion
+       (incl. CDDB support)
+       requires xmcd
+
+Ripenc rip encoder (http://www.asde.com/~mjparme/index.htm)
+       by Michael J. Parmeley
+       a shell script frontend for CDDA extraction and MPEG 1 Layer 3
+       conversion
+       (incl. CDDB support)
diff --git a/doc/icedax/HOWTOUSE b/doc/icedax/HOWTOUSE
new file mode 100644 (file)
index 0000000..1ab9d77
--- /dev/null
@@ -0,0 +1,101 @@
+Icedax User guide
+=================
+
+NOTE: expressions in angle braces have to be substituted with
+      the corresponding numerical values.
+      For example: <delay in seconds> has to be substituted
+       with the numerical value to be used.
+
+Common tasks
+============
+NOTE: The examples used here depend on proper default settings for interface
+method and devices as specified in the Makefile. They can be overriden with
+command line parameters, but here I choose to focus on simple examples. 
+
+Copy complete audio CDs
+
+1. Copy an audio CD into wav files one per track.
+
+       icedax -B
+
+   will produce the sample wav files (one per track)
+       audio_01.wav
+       audio_02.wav
+       ...
+
+   and the corresponding description files
+       audio_01.inf
+       audio_02.inf
+       ...
+
+2. Same as above but include MD-5 type signatures
+
+       icedax -B -M<length>
+
+
+3. Same as above but use other file name ('party_cd.wav')
+
+       icedax -B -M<length> party_cd.wav
+
+
+Copy single tracks
+
+1. Copy one track (eg track 6) into a wav file.
+
+       icedax -t6
+
+   will produce a wav file including track 6
+
+       audio.wav
+
+   and
+
+       audio.inf
+
+
+Copy parts of tracks
+
+1. Copy from given start time to end of track
+
+       icedax -t6 -o<delay in 1/75 seconds>
+
+   will record track 6 starting at track time <delay>/75 seconds
+   from track beginning upto the end of track.
+
+2. Copy from given start time and record for a given time
+
+       icedax -t6 -o<delay in 1/75 seconds> -d<time to record in seconds>
+
+   will record track 6 starting at track time <delay>/75 seconds
+   from track beginning for <time to record in seconds> seconds.
+
+
+
+Copy tracks into a pipe
+
+       icedax -t6 -Oraw - | audio_compressor
+
+   will feed the audio samples (in big endian format) of track 6
+   into a secondary program audio_compressor.
+(See also script cdda2mp3(.new) for a suggestion, how to process all tracks of
+an audio cd with a MPEG-Layer3 encoder (not included here).)
+
+
+Miscellaneous
+
+1. Use icedax as a cd player
+
+       icedax -eN -t6
+
+   will copy the audio samples into a sound card (if sound card support
+   is compiled in) and will not write any file.
+
+
+
+2. Get complete information on the cd
+
+       icedax -v63 -Nd0.01
+
+   will try to find out a media catalog number and track related
+   information (ISRCs) in addition to indices. For CD-Extra discs
+   limited support exists to retrieve additional information.
diff --git a/doc/icedax/NEEDED b/doc/icedax/NEEDED
new file mode 100644 (file)
index 0000000..361cc29
--- /dev/null
@@ -0,0 +1,10 @@
+Here I list some things, which would be very helpful for the further
+development of cdrtools/icedax, but I currently have no access to.
+User support for the acquisition of these items is appreciated :-)
+
+Access to all 'coloured books' from Philips/Sony
+(Red/Yellow/Green/Orange/White/Blue,...).
+
+CD-extra discs with a lot of features/entries in the data sectors (SUB_INFO*).
+
+CD-text discs with a lot of features/entries. 
diff --git a/doc/icedax/OtherProgs b/doc/icedax/OtherProgs
new file mode 100644 (file)
index 0000000..8c6fa41
--- /dev/null
@@ -0,0 +1,2 @@
+dagrab         works with ioctls, includes cddb lookups
+cdparanoia     has sophisticated jitter correction
diff --git a/doc/icedax/README b/doc/icedax/README
new file mode 100644 (file)
index 0000000..4b65532
--- /dev/null
@@ -0,0 +1,549 @@
+Hi dear cdrom drive users,
+
+This README describes hardware related matters as well as the installation of 
+icedax, the sampling utility. 
+
+This icedax utility comes with the Cdrkit project. Cdrkit is a spinoff from 
+cdrtools. However, the cdrtools developers are not involved in the 
+development of this spinoff and therefore shall not be made responsible for 
+any problem caused by it. Please do not try to get support for this program by 
+contacting the original authors.
+
+Requirements
+============
+
+For SCSI cdroms and CD-writers, as well as SCSI-emulated ATAPIS and parallel
+    port drives
+1s. kernel support for SCSI, the host adapter, SCSI cdroms and the
+    generic SCSI interface (if under Linux). You need to have the proper device
+    descriptors (get them under Linux with the MAKEDEV script from /dev).
+
+For ATAPI cdroms under Linux
+1a. kernel support for the ATAPI cdrom driver or alternatively ide-scsi
+    emulation. You need to have the proper device descriptors (get them
+    with the MAKEDEV script from /dev).
+
+For parallel port cdroms under Linux
+    With newer kernels icedax uses the same parallel port access
+    as does wodim.  Please refer additionally to the wodim documentation.
+    There are generally two drivers to access the cdrom through the parallel
+    port: the ATAPI cd emulation (called pcd), and the SCSI device emulation
+    (called pg). The pcd driver does NOT support cdda reading (kernel 2.2.12),
+    while the pg driver has no restriction. So you have to use pg for that.
+
+
+For cdrom drives with proprietary busses under Linux
+1p. Please check the CDROM-HOWTO for features of the respective
+    drivers. The sbpcd driver is very demanding due to the lack of
+    interrupts.
+
+optionally currently for Solaris and all platforms running 4fronts
+OpenSoundSystems:
+2. kernel sound card support.
+
+
+Recommendations for higher throughput on Linux SCSI systems
+===========================================================
+
+Higher throughput will give better chances for non-interrupted
+sampling. This should avoid typical interruption errors (cracklings
+at buffer boundaries).
+
+1. Increase SG_BIG_BUFF to (128*1024) in /usr/src/linux/include/scsi/sg.h
+   (and recompile your kernel and boot it :-).
+NOTE: Some kernel configurations will lead to 'out of kernel memory' errors.
+   If you encounter this message regularly, better leave SG_BIG_BUFF at
+   32768.
+
+1a.There is a patch for multiple sg device access under Linux. It uses
+   up to 128 K buffer for each device. See here:
+ftp://ftp.fokus.gmd.de/pub/unix/cdrecord/alpha/sg*
+
+2. Ensure your harddisk has write cache enabled (For SCSI hard disks I
+   switched it on with the scsiinfo program from tsx-11.mit.edu), but
+   enable this only if it is correctly working ;-)
+
+This has boosted the throughput of icedax considerably.
+
+
+Supported interfaces
+====================
+
+Non SCSI drives (Linux only):
+       ATAPI:
+       The greatest group nowadays are ATAPI (EIDE) cdrom drives.
+       Support is only limited by the drive. Kernel and icedax
+       are ready for them (unless the drive uses a very uncommon method).
+
+        Newer kernels can do an scsi emulation for ATAPI devices.
+        This interface is supported.
+
+       Parallel port interface:
+       There is a driver that maps the parallel port driver to an generic
+       scsi like driver. Should work with newer kernels.
+
+       Proprietary interfaces:
+       Older drives with proprietary interfaces are supported only
+       if the kernel driver allows reading cdda audio data via ioctl().
+       Currently only Eberhard Moenkeberg's sbpcd and Corey Minyard's
+       cdu31a driver do allow this. The sbpcd driver of kernels earlier than
+       2.0.30 and 2.1.57 needs a patch before satisfying output can be
+       obtained (see README.sbpcd).
+
+SCSI drives:
+       For these drives the SCSI library from Joerg Schilling is used.
+       Thus we need kernel support (compiled-in or as a module) for it.
+        The generic SCSI interface allows multi sector transfers (max. 128 KB)
+       which lowers cpu load considerably.
+
+       ** NEW **
+       I added a script 'scsi_scan.linux' to find the generic devices for all
+       SCSI CDROM- or WORM-type drives.
+
+Configuration
+=============
+
+There are some adjustable parameters in the beginning of the Makefile
+(which is called local.cnf.in) . They describe default settings of icedax:
+
+INTERFACE:     How the cdrom is accessed. Choose one method for INTERFACE.
+DEVICE:                The default cdrom device is set in DEF_DEVICE.
+
+SOUND FILE FORMAT DEFAULTS:
+The default format can be 'wav', 'sun pcm au', 'aiff', 'aifc', or
+'raw bigendian samples'.
+It is determined by the Makefile variable DEF_TYPE.
+
+AUDIO FILENAME:
+The default filename is given by DEF_FILE. Unless 'cdr' format is being used,
+this name is appended with '.wav', '.au', '.aiff' or '.aifc'.
+
+RATE: the default rate is given by setting DEF_UNDERSAMPLING to the divisor
+for the audio cd sampling frequency (44100 Hz).
+
+       RATE = 44100 Hz / DEF_UNDERSAMPLING
+
+DEF_UNDERSAMPLING can be any multiple of a half greater than one half.
+
+DYNAMIC: The default dynamic range of one sample in one channel is defined in 
+DEF_BITS which can be one of 8, 12 or 16.
+
+CHANNELS: set DEF_CHANNELS to 1 for mono and 2 for stereo.
+
+RECORDING TIME: set DEF_TIME to the amount of seconds to record (or 0 for
+the whole track).
+
+SOUND DEVICE: set SOUND_DEVICE to the device name of your sound card.
+               The line containing HAVESOUND should be 
+               uncommented also, if you want the option to hear
+               what you record.
+
+All of those values can be overridden by command line parameters.
+
+
+Compiling icedax
+==================
+
+Adjust the Makefile (named local.cnf.in) for your cdrom interface and
+device setting first.
+
+Then type
+       make
+and as root
+       make install
+
+This will compile icedax and copy the binary to /usr/local/bin and the
+man page to /usr/local/man/man1 (defaults).
+
+
+Privileges
+==========
+
+You can setgid the binary, if you want to allow access to a CDROM's
+scsi_generic interface for icedax but not for arbitrary programs.
+Giving away permissions to send SCSI commands directly to a device is
+not something you want to do lightly on a multi-user server system.
+The setgid privileges will only be used to access the scsi generic
+interface; for cooked_ioctl, the setgid privileges are not necessary
+and they are simply dropped.
+
+Previous versions of icedax had to be setuid to root.  Such privileges
+are no longer necessary and will be dropped if present.
+
+Select device
+=============
+
+By default icedax uses the generic SCSI interface and a device tripel for
+SCSI bus, id, and lun.
+This setting can be overridden by specifying '-Iinterface' and
+'-D cdromdevice'.
+The following command line example uses the generic_scsi interface and the 
+SCSI device with bus 1, id 2 and lun 3:
+icedax -Igeneric_scsi -D1,2,3
+
+The shell script 'scan_scsi.linux' will report the generic devices for
+all SCSI cdrom drives.
+
+If you need to use another interface, check the device setting also as they
+need to fit together.
+Here is an example for an ATAPI cdrom using the cooked_ioctl interface and
+the cdrom device /dev/hdb:
+icedax -Icooked_ioctl -D/dev/hdb
+
+
+Features
+========
+
+I added an optional on-the-fly correction for pre-emphasized samples
+(available for original CDDA format only).
+If the -T option is given, the samples will be filtered before they
+are written to disk. The samples then have a linear frequency response again.
+
+When recording in mono, both channels are summed with halved amplitude.
+
+Undersampling is done by summing several samples with reduced amplitude to
+prevent overflows. This damps higher freqencies as well. Compared to
+exact resampling icedax does not use a very sophisticated (expensive)
+filter algorithm. It currently uses quadratic interpolation for
+noninteger subsampling factors.
+
+Sampling can be aborted by pressing the Interrupt-Key (eg control-C)
+at anytime. Unless streaming to a pipe, the wav header will be updated
+to contain the actual length of the sample. The same will happen, if
+disk space becomes exhausted.
+
+Fast options
+============
+
+The options can also influence the performance greatly.
+The fastest case is given when the samples don't need to be changed from
+their original form or analysed, that is the output format uses the same
+parameters as the drive: 16-bit samples, stereo at 44100 Hz sample rate
+AND with the same endianess (-Cbig and -Ebig, or -Clittle and -Elittle).
+To be sure all parameters can be given explicitly on the command line.
+This avoids an analysis of icedax.
+
+icedax -P0 -q -S<maximum speed> 
+run as root will read with maximum speed and copy its output into the
+wav file, taking advantage of realtime scheduling as well.
+
+For throughput testing the additional option -N can be used. Write
+operations will be suppressed then.
+
+Options that slow down initially
+================================
+-v<level> needs some time for analysis before the actual sampling starts
+
+Options that slow down during sampling
+======================================
+-P1    causes overlap reading, the slowdown depends on the amount of jitter
+-e     synchronous output to a sound card slows down to onefold speed
+
+Options that need more cpu power
+================================
+-p<rate> resamples the output send to the sound card
+-M<count> calculates checksums
+-T     on-the-fly preemphasis filtering
+-F     checking for extremal samples
+-G     checking for differences in both channels
+-C<endianess>  if a conversion is required (see below)
+-E<endianess>  if a conversion is required (see below)
+-Oaudiotype    if a conversion is required (see below)
+-c 1
+-c s
+-m
+-b 8
+-b 12
+-a <not 1>
+-r <not 44100>
+
+When are one or two endianess (byte order) conversions required?
+================================================================
+There are three stages where the endianess matters:
+1.) on the input side the cd drive can deliver in two flavors (called F1).
+    When the flavor is unknown, icedax needs to find out the endianess.
+    A simple voting method is used. Successive samples are compared in both
+    flavors and the flavor with the statistically smaller changes is taken. 
+    The flavor can be defined with the -C option, avoiding the analysis. 
+2.) For any calculation with samples (and echoing to the sound card),
+    the samples are needed in the byte order of the machine (in this case
+    I set 'need_host_order' to yes). The flavor of the machine endianess
+    is called F2.
+3.) Finally, there are two flavors of output sound formats (called F3):
+    wav uses little endian samples
+    cdr and au use big endian samples
+    If the samples currently in memory have the wrong endianess a
+    (possibly second) conversion is required.
+
+This gives the following table:
+F1     F2      need_host_order F3      conversions
+little little  no              little          0
+little little  yes             little          0
+little little  no              big             1
+little little  yes             big             1
+little big     no              little          0
+little big     yes             little          2
+little big     no              big             1
+little big     yes             big             1
+big    little  no              little          1
+big    little  yes             little          1
+big    little  no              big             0
+big    little  yes             big             2
+big    big     no              little          1
+big    big     yes             little          1
+big    big     no              big             0
+big    big     yes             big             0
+
+
+Known problems
+==============
+
+1. Sound quality
+
+Audible errors caused by hesitations:
+
+When recording the same audio track twice, recordings can slightly differ.
+Furthermore depending on the firmware in the cdrom drive, positioning
+errors can be so severe that they cannot be easily corrected by icedax.
+This will unfortunately lead to audible errors.
+
+In this case some overlap or even underlap between successive portions
+is introduced from the cdrom drive.
+Here is this case demonstrated graphically:
+
+Sec 1    ...       Sec n
+|----------------------|                          first  read delivered
+                       |------------------------| second read wanted
+                     |------------------------|   second read delivered
+                     |-|                          extra bogus bytes
+                                              |-| missing bytes
+
+This is due to synchronisation problems between sectors inside the cdrom 
+drive. When the drive has been forced to wait, these problems arise.
+
+Audio cds are lacking sector headers, so it's a difficult job to do the
+positioning right (in the firmware). The frequency of these errors is
+reduced when the reading process can continue undisturbed for longer periods.
+So, a high throughput is essential.
+
+You may want to fine-tune your update daemon to use shorter intervals
+(see 'man 8 update'). Shorter intervals are better because the update
+interruptions are shorter when not so much write requests can pile up.
+
+The plextor 4plexplus drive (PX-4XCE) and newer models, newer pioneer
+models as well as CD-writers with large buffers don't suffer from this
+errors. Here the default is to switch off overlap reading.
+
+If you cannot get good samples from your drives you might consider an
+alternative program. Monty's cdparanoia program goes to great lengths
+in order to seperate the good bits from the bad ones.
+
+2. The index scanner has caused timeouts on my toshiba 3401 due to fast
+   random accesses.
+
+3. Retrieval of media catalog numbers and International Standard Recording
+   Codes may fail due to firmware bugs.
+
+Audio Format Conversion
+=======================
+Currently wav, sun (au-pcm), Apple/SGI aiff/aifc, and raw formats are supported.
+
+I try to write correct wav files (little endian samples), but some
+cd-writers might swap them, which would result in sort of white noise
+instead of the original sounds.  icedax has an endianness detector
+for these cases, but as for all automatics, it might fail on bizarre samples.
+
+Hint: icedax can be forced to use a given input endianness with the
+-C option (arguments are 'little', 'big' or 'guess').
+
+The sun format is a pcm variant, and uses big endian samples.
+The other more common sun format with logarithmically scaled samples (au)
+is not supported but can be obtained from sox's conversion.
+
+The raw format is like the sun format except it has no header. I
+changed the endianness to big endian samples in order to comply
+with popular cd burning software like the wodim program.
+
+The sound converter 'sox' can be used to obtain other sound formats.
+(Note however, that the current sox player and a newer sound driver do not
+harmonize well, use the player from the wavplay package instead (available
+at sunsite)).
+
+
+Feedback
+========
+
+Tested patches, any hardware information regarding drives as well as success/
+failure reports are always welcome at heiko@colossus.escape.de.
+
+
+known cdda capable drives
+=========================
+Check out these web pages for uptodate information:
+
+<http://www.tardis.ed.ac.uk/~psyche/pc/cdrom/CDDA.html>
+
+and
+
+<http://www.anime.net/~goemon/linux-cd/cdda-list.html>
+
+From a news posting from Björn Wiberg
+
+> The following table was generated using the CDROM.CFG file from Nero
+> v3.0.4.2.
+> 
+> It shows different CD-ROM models and what speeds they can do DAE at. I
+> guess the values are "safe ones"; i.e. the speeds at which each drive
+> can perform DAE reliably.
+> 
+> A value of "0x" means the drive doesn't support DAE.
+> 
+> For your convenience, the maximum data transfer speed of the drives
+> (for reading conventional files and data from the CD-ROM) are also
+> included.
+> 
+> Hopefully, this will help some of you who are looking for a good
+> CD-ROM drive to choose a model which seems fast enough both for data
+> and DAE.
+> 
+> The models which support DAE:
+> (Sorted by DAE speed, data speed and model)
+> 
+> CD-ROM model                     DAE     Data   Interface
+> ---------------------------------------------------------
+> PLEXTOR  CD-ROM PX-32TS          16x     16x    SCSI
+> TEAC     CD-524E                 14x     24x    IDE
+> CREATIVE CD620E                  12x     5x     IDE
+> MITSUMI  CD-ROM FX320S !B        12x     32x    IDE
+> TEAC     CD-532E                 12x     32x    IDE
+> HITACHI  CDR-8335                12x     24x    IDE
+> PIONEER  CD-ROM DR-A02S          12x     24x    IDE
+> TEAC     CD-ROM CD-532S          12x     14x    SCSI
+> PIONEER  CD-ROM DR-A12X          12x     12x    IDE
+> PIONEER  CD-ROM DR-U06S          12x     12x    SCSI
+> PLEXTOR  CD-ROM PX-20TS          12x     12x    SCSI
+> MITSUMI  CD-ROM FX120T !B        11x     12x    IDE
+> PIONEER  CD-ROM DR-A04S          11x     32x    IDE
+> PIONEER  CD-ROM DR-U12X          10x     12x    SCSI
+> HITACHI  CDR-8330                9x      24x    IDE
+> SONY     CD-ROM CDU711           9x      14x    IDE
+> MATSHITA CD-ROM CR-584           9x      12x    IDE
+> MATSHITA CD-ROM CR-586           8x      32x    IDE
+> CDM-T531         Ver1.041        8x      18x    IDE
+> TEAC     CD-516E                 8x      16x    IDE
+> TOSHIBA  CD-ROM XM-6201TA        8x      16x    SCSI
+> PLEXTOR  CD-ROM PX-12CS          8x      12x    SCSI
+> PLEXTOR  CD-ROM PX-12TS          8x      12x    SCSI
+> PIONEER  CD-ROM DR-U10X          8x      10x    SCSI
+> SONY     CD-ROM CDU611           8x      10x    IDE
+> FUNAI    E285X                   8x      8x     IDE
+> MITSUMI  CD-ROM FX810T4!B        8x      8x     IDE
+> SONY     CD-ROM CDU511           8x      8x     IDE
+> SONY     CD-ROM CDU571-Q         8x      8x     IDE
+> TEAC     CD-C68E                 8x      8x     IDE
+> MITSUMI  CD-ROM FX400E !B        8x      4x     IDE
+> HITACHI  CDR-8130                7x      16x    IDE
+> MATSHITA CD-ROM CR-585           6x      24x    IDE
+> CREATIVE CD2422E  MC102          6x      12x    IDE
+> MATSHITA CD-ROM CR-508           6x      12x    SCSI
+> IBM      PD-1 LF-1195            6x      6x     IDE
+> PLEXTOR  CD-ROM PX-6XCS          6x      6x     SCSI
+> LITEON   CD-ROM LTN301           5x      32x    IDE
+> LITEON   CD-ROM LTN242F          5x      24x    IDE
+> HITACHI  CDR-7930                5x      8x     IDE
+> ASUS     CD-S340                 4x      34x    IDE
+> E-IDE    CD-ROM 32X/AKU          4x      32x    IDE
+> ATAPI CDROM                      4x      24x    IDE
+> LITEON   CD-ROM LTN244           4x      24x    IDE
+> PHILIPS  PCA248CD                4x      24x    IDE
+> TEAC     CD-524EA                4x      24x    IDE
+> LITEON   CD-ROM LTN202           4x      21x    IDE
+> ATAPI    CD-ROM DRIVE-24X        4x      20x    IDE
+> CREATIVE CD2423E  NC101          4x      20x    IDE
+> SAMSUNG  CD-ROM SCR-2431         4x      20x    IDE
+> TAE IL   CD-ROM CDD-7240J        4x      20x    IDE
+> TEAC     CD-220E                 4x      20x    IDE
+> CREATIVE CD1620E SL970404        4x      16x    IDE
+> LITEON   CD-ROM LTN262           4x      16x    IDE
+> TEAC     CD-ROM CD-516S          4x      16x    SCSI
+> ATAPI    CD-ROM DRIVE            4x      15x    IDE
+> BCD 16XA  CD-ROM                 4x      10x    IDE
+> MATSHITA CD-ROM CR-506           4x      8x     SCSI
+> SONY     CD-ROM CDU311           4x      8x     IDE
+> MATSHITA CD-ROM CR-504-J         4x      4x     SCSI
+> MITSBISH CDRW226                 4x      4x     SCSI
+> SONY     CD-ROM CDU625-S         4x      4x     SCSI
+> SONY     CD-ROM CDU-76S          4x      4x     SCSI
+> SONY     CD-ROM CDU77E           4x      4x     IDE
+> PLEXTOR  CD-ROM PX-4XCE          4x      4x     SCSI
+> SONY     CD-ROM CDU55E           4x      2x     IDE
+> PIONEER  CD-ROM DR-U24X          3x      24x    SCSI
+> LITEON   CD-ROM LTN204           3x      21x    IDE
+> PIONEER  CD-ROM DR-A01S          3x      20x    IDE
+> PIONEER  CD-ROM DR-A24X          3x      20x    IDE
+> FUNAI    E295X                   3x      16x    IDE
+> PIONEER  CD-ROM DR-U03S          3x      12x    SCSI
+> BTC      24X CD-ROM SLL24        3x      10x    IDE
+> PLEXTOR  CD-ROM PX-8XCS          3x      4x     SCSI
+> CyberDrv  CD-ROM TW240S          3x      3x     SCSI
+> COMPAQ   CRD-8320B               2x      32x    IDE
+> LG    CD-ROM CRD-8320B           2x      32x    IDE
+> TOSHIBA  CD-ROM XM-6202B         2x      32x    IDE
+> CREATIVE DVD-ROM DVD2240E        2x      24x    IDE
+> TOSHIBA  CD-ROM XM-6102D         2x      24x    IDE
+> BTC      16X CD-ROM SLL16        1x      10x    IDE
+> NEC      CD-ROM DRIVE:282        2x      8x     IDE
+> HITACHI  GD-2000                 2x      4x     IDE
+> MATSHITA CD-ROM CR-581           2x      4x     IDE
+> NEC      CD-ROM DRIVE:222        2x      4x     SCSI
+> MATSHITA CD-ROM CR-8004          2x      2x     SCSI
+> GoldStar CD-ROM CRD-8240B        1x      24x    IDE
+> TOSHIBA  CD-ROM XM-6102B         1x      24x    IDE
+> CyberDrv  IDE CD-ROM 120D        1x      12x    IDE
+> I DE CD-ROM TW120D               1x      12x    IDE
+> NEC      CD-ROM DRIVE:464        1x      12x    SCSI
+> TORiSAN  CD-ROM CDR_U112         1x      12x    IDE
+> TOSHIBA  CD-ROM XM-5701TA        1x      12x    SCSI
+> TOSHIBA  CD-ROM XM-5702B         1x      12x    IDE
+> CyberDrv SCSI CD-ROM 120S        1x      10x    IDE
+> NEC      CD-ROM DRIVE:463        1x      10x    SCSI
+> COMPAQ   DVD-ROM SD-M1002        1x      8x     IDE
+> MATSHITA CD-ROM CR-583           1x      8x     IDE
+> NEC      CD-ROM DRIVE:462        1x      8x     SCSI
+> TEAC     CD-58E                  1x      8x     IDE
+> OPTICS_S 8622 SCSI               1x      8x     SCSI
+> TOSHIBA  CD-ROM XM-5602B         1x      8x     IDE
+> TOSHIBA  CD-ROM XM-3801TA        1x      7x     SCSI
+> NEC      CD-ROM DRIVE:461        1x      6x     SCSI
+> IBM      CDRM00203               1x      6x     SCSI
+> TEAC     CD-46E                  1x      6x     IDE
+> TEAC     CD-56E                  1x      6x     IDE
+> TEAC     CD-ROM CD-56S           1x      6x     SCSI
+> TOSHIBA  CD-ROM XM-5502TA        1x      6x     IDE
+> TOSHIBA  CD-ROM XM-3701TA        1x      6x     SCSI
+> NEC      CD-ROM DRIVE:502        1x      4x     SCSI
+> TOSHIBA  CD-ROM XM-1502BN        1x      4x     IDE
+> TOSHIBA  CD-ROM XM-5302TA        1x      4x     IDE
+> TOSHIBA  CD-ROM XM-5401TA        1x      4x     SCSI
+> TOSHIBA  CD-ROM XM-5402TA        1x      4x     IDE
+> TOSHIBA  CD-ROM XM-1502B         1x      4x     IDE
+> TOSHIBA  CD-ROM XM-3501TA        1x      4x     SCSI
+> TOSHIBA  CD-ROM XM-5301TA        1x      4x     SCSI
+> TOSHIBA  CD-ROM XM-5201TA        1x      2x     SCSI
+
+known cdda uncapable drives
+===========================
+
+Pioneer                DRM-602X, DRM-604X
+Teac           CD-55A          (panasonic bus)
+Philips                CM206/10        serial RS-422
+               CM207
+               CM226/10        serial RS-422
+               CDD462/01       serial RS-422
+Orchid         CDS3110
+
+Additions to the tables above are welcome.
+
+and now catch your sounds,
+Heiko          heiko@colossus.escape.de (Original author)
+Changes for the Cdrkit project by Christian Fromme <kaner@strace.org>, Eduard Bloch
diff --git a/doc/icedax/THANKS b/doc/icedax/THANKS
new file mode 100644 (file)
index 0000000..801f7df
--- /dev/null
@@ -0,0 +1,36 @@
+Cdda2wav development has been funded by
+
+Project MODE
+http://www.mode.net/
+
+and 
+
+Fraunhofer Institut für integrierte Schaltungen (FhG-IIS)
+http://www.iis.fhg.de/
+
+Code for extraction of ISRC and MCN codes as well as MD5 signatures
+has been made possible by their contributions, thanks very much.
+
+Thanks to Rik Swusten of Plextor Europe for supplying a cd burner
+for development.
+
+Thanks to Ricoh for supplying a cd burner for development.
+
+Thanks to Sanyo for supplying a Burn-Proof cd burner with documentaion
+for development.
+
+More thanks goto
+Joerg Schilling (helped a lot to integrate his SCSI library)
+Aaron Newsome (which created an account on his machine for me to do testing)
+Christopher Montgomery (aka Monty, for his work on jitter correction)
+Zygo Blaxell (a lot of code improvements)
+Thomas Niederreiter (extensions for cd-writers)
+Piercarlo Grandi (rewrote of cdda2wav's man page)
+Stewart Addison (suggestions and a fine web page on cdda)
+Leland Olds (the cdda2wav debian maintainer)
+Francesco Chemolli (getopt_long patches)
+
+Thanks to all testers and finally Jim McLaughlin for supplying
+the first cdda-reader source code (that got me started).
+
+Heiko Eißfeldt
diff --git a/doc/icedax/TODO b/doc/icedax/TODO
new file mode 100644 (file)
index 0000000..5fb1fdd
--- /dev/null
@@ -0,0 +1,41 @@
+improved Indexscan without playing sectors
+use C2 pointers to reduce speed 
+Solaris handling with volumed
+SunOS/Solaris and 512 byte sectors??
+setuid.c group ids on WinXP??
+
+stabilization:
+check all exit codes (exit with error if sync failed)
+new ioctl support for Solaris, FreeBSD-3.x, FreeBSD-4.x
+find cause of ringbuffer assertions (resource temporarily unavailable)
+
+new features:
+enable hidden (audio) track recording
+thread support
+more sound support
+CDIndex, CDDB lookups
+prepare for MP3 inclusion (lame)
+cut off silence at start and end of track
+interpolation for massive read errors
+
+internal:
+get cache setting/set cache to zero/reset cache size at the end...
+maybe add something for pioneer cd drives (spin up problems)
+develop a new transport to read cdda sectors with complete subchannels
+use index0 optionally to cut off the pregap portion
+detect type of hidden track (data/audio)
+implement capability to add a global shift
+enhance cd text:
+       increase buffer size
+       add tab semantics
+       support 16-bit characters
+       try fallback read text info from program area
+
+structural:
+plug-in infrastructure
+
+BeOS:  cddbp support, sound support
+QNX:   realtime support RR-scheduler message, sound support in lconfig Makefiles
+OS/2:  sound support
+cygwin:        sound support
+
diff --git a/doc/icedax/cdda_links b/doc/icedax/cdda_links
new file mode 100644 (file)
index 0000000..0371896
--- /dev/null
@@ -0,0 +1,4 @@
+http://www.escape.de/icedax/icedax.html
+http://www.geocities.com/SiliconValley/Bay/6893/multi.htm
+http://www.mp3.com/cdrom.html
+http://www.emi.u-bordeaux.fr/~morel/
diff --git a/doc/icedax/tracknames.pl b/doc/icedax/tracknames.pl
new file mode 100755 (executable)
index 0000000..09f0fcf
--- /dev/null
@@ -0,0 +1,245 @@
+#!/usr/local/bin/perl 
+# A quick perl hack to get rename files pulled in with icedax.
+# by billo@billo.com
+#
+use Socket;
+use IO::Handle;
+use Env qw(USER);
+use strict;
+no strict 'subs'; # can't get it to stop complaining about SOCK
+
+my $state = "header";
+
+my $global_album = "Artist / Title";
+my $global_title = "Title";
+my $global_artist = "Artist";
+my @global_tracks = ("") x 100;
+my $global_ntracks = 0;
+
+my @track_offsets = ();
+my $disc_id = 0;
+my $disc_time = 0;
+
+
+if ($#ARGV != 1)
+{
+    print "usage: cddbhack.pl CDDBHOST PORT < audio.cddb\n";
+    exit 0;
+}
+
+while (<STDIN>)
+{
+    if ($state eq "header")
+    {
+       if (/#\s[\s]*(\d[\d]*)$/)
+       {
+           push @track_offsets, $1;
+       } elsif (/#\s[\s]*Disc length:\s(\d[\d]*)/) {
+           $disc_time = $1;
+           $state = "discid";
+        }
+    } elsif ($state eq "discid")
+    {
+       if (/DISCID=(\w[\w]*)/)
+       {
+           $disc_id = $1;
+           last;
+       } 
+    }
+}
+
+my $query_string = "cddb query $disc_id " . ($#track_offsets + 1);
+foreach my $offset (@track_offsets)
+{
+    $query_string .= " $offset";
+}
+$query_string .= " $disc_time";
+
+print "$query_string\n";
+
+my $host = $ARGV[0];
+my $port = $ARGV[1];
+
+my $iaddr = inet_aton($host);
+my $paddr = sockaddr_in($port, $iaddr);
+
+
+socket(SOCK, AF_INET, SOCK_STREAM, getprotobyname('tcp')) or die "socket: $!";
+
+connect(SOCK, $paddr) or die "connect: $!";
+
+autoflush SOCK 1;
+
+print "Connected.\n";
+
+my ($status, $result) = &resp(\*SOCK);
+
+if (int($status) != 201)
+{
+    print "Unexpected status.\n";
+    close(\*SOCK);
+    exit 0;
+}
+
+$host = `hostname`;
+
+$host =~ s/\n//g;
+
+&cmd(\*SOCK, "cddb hello $USER $host billo-scan 0.1");
+($status, $result) = &resp(\*SOCK);
+if (int($status) != 200)
+{
+    print "Unexpected status.\n";
+    close(\*SOCK);
+    exit 0;
+}
+
+&cmd(\*SOCK, "$query_string");
+($status, $result) = &resp(\*SOCK);
+if (int($status) != 200)
+{
+    print "Unexpected status.\n";
+    close(\*SOCK);
+    exit 0;
+}
+
+my ($ignore, $cat, $id, @rest) = split (" ", $result);
+
+
+
+my $read_string = "cddb read $cat $id";
+
+&cmd(\*SOCK, $read_string);
+&resp(\*SOCK);
+while (<SOCK>)
+{
+    if (/^\./)
+    {
+       # print $_;
+       # print "last line\n";
+       last;
+    } else {
+       &process($_);
+       # print $_;
+    }
+}
+
+&cmd(\*SOCK, "quit");
+&resp(\*SOCK);
+
+close(\*SOCK);
+
+&rename;
+
+exit 0;
+
+sub cmd
+{
+    my ($S, $cmd) = @_;
+
+    print "$cmd\n";
+    print $S "$cmd\r\n";
+}
+
+sub resp
+{
+    my ($S) = @_;
+    my ($code, $message);
+    while (<$S>)
+    {
+       if (/^(\d[\d]*)\s.*/)
+       {
+           # print "\n$1\n";
+           print "$_\n";
+           $code = $1;
+           $message = $_;
+           last;
+       }
+       sleep(1);
+    }
+    my @return_array = ($code, $message);
+    return @return_array;
+}
+
+sub process 
+{
+    my ($line) = @_;
+
+    $_ = $line;
+    if (/^DTITLE=(.*)$/)
+    {
+       $global_album = $1;
+       $_ = $global_album;
+       if (m/([^\/][^\/]*)\s\/\s([^\/][^\/\n\r]*)/)
+       {
+           $global_artist = $1;
+           $global_title = $2;
+       }
+       print "$global_album\n";
+       print "$global_title\n";
+       print "$global_artist\n";
+       return;
+    }
+    if (/^TTITLE(\d[\d]*)=(.*)$/)
+    {
+       my $track = $1 + 1;
+       if ($track > $global_ntracks)
+       {
+           $global_ntracks = $track;
+       }
+       $global_tracks[$track] = sprintf ("%s-%02d-%s", $global_title, 
+                                         $track, $2);
+       $global_tracks[$track] =~ s/\s$//g;
+       $global_tracks[$track] =~ s/'//g;
+       $global_tracks[$track] =~ s/\s/_/g;
+       $global_tracks[$track] =~ s/:/_/g;
+       $global_tracks[$track] =~ s/\?//g;
+       $global_tracks[$track] =~ s/\*//g;
+       $global_tracks[$track] =~ s/\\/_/g;
+       $global_tracks[$track] =~ s/\s/_/g;
+       $global_tracks[$track] =~ s/\//_/g;
+       print "Track match " . $global_tracks[$track] . "\n";
+    }
+}
+
+sub rename
+{
+    my $i = 1;
+    
+    for ($i = 1; $i <= $global_ntracks; $i++)
+    {
+       my $track_name = $global_tracks[$i];
+       if ($track_name ne "")
+       {
+           my $file_name = sprintf("audio_%02d.wav", $i);
+           my $new_file_name = sprintf("$track_name.wav", $i);
+           
+           my $mv_cmd = "mv '" . $file_name . "' '" 
+               . $new_file_name . "'";
+           print "$mv_cmd\n";
+           `echo $mv_cmd >> rename.sh`;
+       }
+    }
+}
+
+sub unrename
+{
+    my $i = 1;
+    
+    for ($i = 1; $i <= $global_ntracks; $i++)
+    {
+       my $track_name = $global_tracks[$i];
+       if ($track_name ne "")
+       {
+           my $file_name = sprintf("$track_name.wav", $i);
+           my $new_file_name = sprintf("audio_%02d.wav", $i);
+           
+           my $mv_cmd = "mv '" . $file_name . "' '" 
+               . $new_file_name . "'";
+           print "$mv_cmd\n";
+           `echo $mv_cmd >> unrename.sh`;
+       }
+    }
+}
+
+
diff --git a/doc/icedax/tracknames.txt b/doc/icedax/tracknames.txt
new file mode 100644 (file)
index 0000000..9a94e66
--- /dev/null
@@ -0,0 +1,34 @@
+Date: Fri, 2 Oct 1998 16:58:15 -0400
+From: Bill O'Donnell <billo@billo.com>
+To: heiko@colossus.escape.de
+Subject: CDDB/icedax quick lookup utility
+
+
+Hello, I just started using icedax to capture CD audio on Linux.
+It's working great on my 2.0.22 kernel with NEC CD-ROM DRIVE:273 (ATAPI).
+
+Anyway, I noticed that you're dumping out cddb query info, but not
+doing the query yet, so I hacked a quick perl program to do it. 
+
+If you run with a default extraction like this:
+
+   icedax -B -D /dev/hda
+
+then run the program included something like this:
+
+   cddbhack.pl ma.us.cddb.com 8880 < audio.cddb
+
+It looks up the names, and creates a file "rename.sh" which can be
+used to rename all the audio_XX.wav files to a nice name.
+
+Anyway, thought you might find it useful, feel free to include in your
+next beta distribution or not.  Sorry if I made any stupid perl
+mistakes, I only just learned it last week.  I would have done it in C
+or python but I need to learn perl for another job...
+
+Cheers,
+
+-billo
+
+Bill O'Donnell                     Independent Software Developer
+billo@billo.com                              http://www.billo.com  
diff --git a/doc/plattforms/README.aix5l b/doc/plattforms/README.aix5l
new file mode 100644 (file)
index 0000000..8c697d7
--- /dev/null
@@ -0,0 +1,16 @@
+Cdrkit can be built on AIX 5 using the following instructions. Note that the
+SCSI transport has not been tested yet because of missing hardware.
+
+ - install cmake either from source or from binaries downloadable on cmake.org.
+   Make sure the cmake is in your PATH and it can find its modules.
+ - GCC compiler (available on gcc.org) is recommended, however the native xlc
+   compiler should work as well.
+
+Follow instructions from the INSTALL file.
+
+If you installed a local version of GNU libiconv and ld is confused and spews
+linking errors related to .libiconv, check the linker paths with 
+"cmake -LA build | grep lib". Probably your local path is not listed there and
+you may need to set LDFLAGS make variable. See INSTALL file for details.
+
+ -- Eduard Bloch -- Sun, 26 Nov 2006 23:06:25 +0100
diff --git a/doc/plattforms/README.freebsd b/doc/plattforms/README.freebsd
new file mode 100644 (file)
index 0000000..6e51a30
--- /dev/null
@@ -0,0 +1,31 @@
+These instructions have been tested with FreeBSD 6.2-PRERELEASE, but
+should work on any 6.x release.  If you're having trouble (with any
+release, not just 6.x), please let us know.
+
+Building
+========
+
+You need to have cmake installed.  It is available in the ports
+collection or from cmake.org.  You also need GNU make. It is also in the
+ports collection, and can be alternatively obtained from gnu.org.
+
+Most users have libiconv installed under /usr/local.  If you wish to add
+support for it (used by genisoimage, and recommended), build with
+
+       gmake CFLAGS=-I/usr/local/include LDFLAGS=-L/usr/local/lib
+
+instead of just plain
+
+       gmake
+
+Short note on using wodim
+=========================
+
+If you want to use wodim with ATAPI drives, make sure you load the
+atapicam module before using wodim.  Not even "wodim -scanbus" works
+usually if this is not done.  The command for loading the atapicam
+module is (for root)
+
+       /sbin/kldload atapicam
+
+ -- Lorenz Minder -- Mon Nov 27 23:23:01 CET 2006
diff --git a/doc/plattforms/README.linux b/doc/plattforms/README.linux
new file mode 100644 (file)
index 0000000..da8f759
--- /dev/null
@@ -0,0 +1,46 @@
+
+Requirements of cdrkit on Linux:
+
+ - Linux kernel 2.4 or newer 
+ - Glibc 2.2 or newer
+ - libcap library package is required, with development files (headers)
+ - kernel headers useable with the combination of glibc and kernel, as approved
+   by the distribution. Do not blindly use random kernel headers, do not
+   symlink them to /usr/include/linux or /usr/include/asm*.
+
+Notes about support on Linux:
+
+ - Linux kernel versions between 2.6.8 and 2.6.11 are known to have invasive
+   SCSI command filtering which makes the use of wodim almost inpossible or
+   complicated for non-root users. Avoid those kernel versions, unless they
+   have been patched to disable that filtering.
+
+ - support of generic scsi was limited on 2.4, ie. not available directly with
+   IDE/ATAPI devices. The ide-scsi driver could be used map ATAPI devices to
+   SCSI ids, however this driver had other problems. See README.ATAPI for
+   details. Note that there also the ATAPI:... device access method which uses
+   deprecated funtionality of kernel 2.4. Don't use it unless it is really
+   neccessary. The support for it may be removed in future versions of cdrkit.
+
+ - the DMA transfer size is limited with some device controllers and the Linux
+   kernel 2.6.x (2.6.19 currently) provides no method to retrieve it for
+   exactly one device. Wodim scans sysfs to retrieve this information, but it
+   needs to be mounted. Use the ts= option of wodim to limit the transfer size
+   on problems.
+
+
+Additional comments moved from the wodim.1 manpage (originaly cdrecord.1):
+
+The sg driver on Linux has several severe bugs:
+
+ - It cannot see if a SCSI command could not be sent at all.
+ - It cannot get the SCSI status byte.  wodim for that reason cannot report
+   failing SCSI commands in some situations.
+ - It cannot get real DMA count of transfer. wodim cannot tell you if there is
+   an DMA residual count.
+ - It cannot get number of bytes valid in auto sense data. wodim cannot tell
+   you if device transfers no sense data at all.
+ - It fetches too few data in auto request sense (CCS/SCSI-2/SCSI-3 needs
+   >= 18).
+
+ -- Reviewed by Eduard Bloch -- 12/2006
diff --git a/doc/plattforms/README.parallel b/doc/plattforms/README.parallel
new file mode 100644 (file)
index 0000000..22b9e09
--- /dev/null
@@ -0,0 +1,59 @@
+This file is intended to help with ATAPI <-> Parallel Port devices on Linux
+
+Before you start, read 
+
+       http://www.torque.net/parport/paride.html
+
+Make sure that your parallel port device is set up to EPP mode
+from within the BIOS. In many cases it is best to set the PP delay to 0.
+
+Here is a short explanation how to make the FreeCom Traveller work
+in 4x speed on a notebook:
+
+1.) Set BIOS for parallel port to 'EPP'.
+
+2.) Load drivers in default mode:
+
+   # modprobe paride
+   # modprobe <driver for parallel port adaptor>
+   # modprobe pg
+
+in case of a FreeCom Traveller this is:
+
+   # modprobe paride
+   # modprobe friq
+   # modprobe pg
+
+3.) Check kernel log for paride messages:
+
+   # dmesg
+   ...
+   paride: version 1.04 installed
+   paride: friq registered as protocol 0
+   ...
+   parport0: PC-style at 0x378 [SPP,PS2,EPP]
+   parport0: no IEEE-1284 device present.
+   ...
+   pg: pg version 1.02, major 97
+   pg0: Sharing parport0 at 0x378
+   pg0: friq 1.01, Freecom IQ ASIC-2 adapter at 0x378, mode 4 (EPP-32), delay 1
+   pg0:  CD-R/RW RW8040A, master
+   ...
+
+4.) load module again but use different parameters:
+       'drive0=IO-Port,Protocol,Unit,Mode,Master/Slave,Delay drive1=...'
+       if you have only one drive at the parallel port
+       'drive0=IO-Port,0,0,-1,-1,Delay' e.g. for Delay = 0:
+
+   # modprobe -r pg
+   # modprobe pg drive0=0x378,0,0,-1,-1,0
+
+5.) Check for optimum delay using for maximum speed using wodim -dummy 
+
+6.) Use the file rc.pp and modify for your needs
+
+7.) Your CD drive now appears as /dev/pcd?
+
+Source: README.cdtext from cdrtools package
+Edited for cdrkit by Christian Fromme <kaner@strace.org>
+
diff --git a/doc/plattforms/README.sunos b/doc/plattforms/README.sunos
new file mode 100644 (file)
index 0000000..6fc3a0d
--- /dev/null
@@ -0,0 +1,10 @@
+
+Cdrkit have been built and partially tested on SunOS 5.8.
+
+To compile, run "gmake". CMake must be installed (with its modules), the cmake
+binary must available in your path. Installing GNU libiconv is also recommended.
+
+On linking problems with 3rd-party libraries involved, make sure that you have
+matching configuration of CFLAGS and LDFLAGS vars.
+
+ -- Eduard Bloch -- Tue, 28 Nov 2006 00:01:47 +0100
diff --git a/doc/plattforms/README.win32 b/doc/plattforms/README.win32
new file mode 100644 (file)
index 0000000..1714ed6
--- /dev/null
@@ -0,0 +1,31 @@
+
+Cdrkit suite can be compiled on Windows XP (Service Pack 2) using cygwin
+environment and tools set, available on:
+
+       http://sources.redhat.com/cygwin/
+
+and many mirrors.
+
+To compile on Cygwin, execute setup.exe to install it. You will need to select
+cmake, make, libiconv and gcc compiler in the package selection. Also choose
+subversion if you wish to fetch the latest development version.
+
+When done, you can start the Cygwin Shell by the new icon in the Start menu or
+on the desktop. Visit cdrkit.org and download a tarball of a recent version and store it under <cygwin_directory>\home\your_user_name.
+
+Untar the package with tar -z -x -f <tarball>, go into this directory and run
+"make", followed by "make install". Ignore messages about clock skew etc.
+
+NOTE: with some versions of Cygwin or cmake shipped with it, the installation
+fails for unknown reason. In this case, you can browse trough the build/
+directory, pick up the .exe files there and read the manpage files in
+application directories with the man command ("man wodim/wodim.1").
+
+Windows drives are available in paths like /cygdrive/c/, /cygdrive/d/. The
+drive IDs can be detected using "wodim -scanbus". See wodim's manpage for
+details.
+
+STANDARD WARNING: test in dummy mode before you really write data to the disks.
+Report trouble to Cdrkit maintainers.
+
+ -- Eduard Bloch <blade@debian.org> -- Tue, 12 Sep 2006 10:06:34 +0200
diff --git a/doc/wodim/README.DiskT@2 b/doc/wodim/README.DiskT@2
new file mode 100644 (file)
index 0000000..f94e124
--- /dev/null
@@ -0,0 +1,67 @@
+New driveropts= option "tattoofile=". Use together with -checkdrive 
+to write an image of the right size to disk.
+
+       DiskT@2 hints:
+
+       In order to have "DISKTATTOO" listed in the "Driver flags",
+       the disk currently inserted must be usable for the DiskT@2 feature.
+       This means that there needs to be enough space on it.
+
+       You need an B&W image with 3744 pixels per line
+
+       Best start with a 3744 x 320 pixel image.
+       The correct size may be retrieved with
+               wodim driveropts=tattooinfo -checkdrive
+
+       To get RAW image data:
+
+       -       Take 'xv' and save the image in PBM/PGM/PPM (raw) mode
+
+       -       use a binary aware (must support unlimited linelength)
+               editor such as 'ved' and remove the header lines.
+               These lines look like:
+
+               P5
+               # CREATOR: XV Version 3.10a  Rev: 12/29/94 (PNG patch 1.2)
+               # CREATOR: XV Version 3.10a  Rev: 12/29/94 (PNG patch 1.2)
+               3744 144
+               255
+
+               Now you should have (in case of the file above) a file that
+               has exactly 539136 Bytes.
+
+       -       Note that the tattoo image must be left to right flipped
+               (a mirror image).
+
+From a hint from "E. Robert Bogusta" <rob23@tmr.com>: 
+
+Take an image, and do:
+
+  djpeg myface.jpg | ppmtopgm | pnmflip -lr | 
+    pnmscale -xsi 3744 -ysi 320 | sed '1,/255/d' >myface.tattoo 
+So: 
+  djpeg extracts ppm from a jpeg. Use your favorite other way of getting 
+this far is you wish. 
+  ppmtopgm changes color to grey scale 
+  pnmflip -lr flips left to right, the small image is faster 
+  pnmscale makes it 3644x320 regardless of starting size. This may make it 
+look really odd on the CD if it doesn't start off the right size. More on 
+this after I try it. 
+  sed strips from the first line to the line containing 255, which is the 
+last header line. 
+Note that it would be better to use the actual height of the applicable image instead
+of the maximum value of 320 and it would be even more correct to create an
+image that has the right width/height ratio for the target on CD in order
+get an undistorted view of the image on CD.
+
+For best visibility, use black text on light background.
+
+Source: README.cdtext from cdrtools package
+Edited for cdrkit by Christian Fromme <kaner@strace.org>
+
diff --git a/doc/wodim/README.WORM b/doc/wodim/README.WORM
new file mode 100644 (file)
index 0000000..d3e2ace
--- /dev/null
@@ -0,0 +1,10 @@
+CD-R drives are anything but WORM drives, but older drives identify themselves
+as WORM drives.
+A Worm drive is able to write each sector once at any time without preparation.
+A CD-R drives is not and never will be able to do this.
+However some old drives identify as WORM drives.
+
+For this reason the SCSI-3 standard tells CD-R drives simply CD drives
+with multi media extensions.
+
+
diff --git a/doc/wodim/README.cdrw b/doc/wodim/README.cdrw
new file mode 100644 (file)
index 0000000..cda86e9
--- /dev/null
@@ -0,0 +1,17 @@
+Using CD-RW media Mini Howto FAQ
+
+CD-RW drives usually support packet writing, but as there
+is currently no usable UDF filesystem support you may only use
+the simple wodim approach.
+
+wodim writes to CD-RW media in exactly the same way as it
+does with CD-R.
+
+You may erase a complete disk in preparation to reuse it.
+Check the man page entry for the blank= option of wodim.
+Not all drives support all blanking modes. Usually
+blank=fast or blank=full are working.
+
+Source: README.cdtext from cdrtools package
+Edited for cdrkit by Christian Fromme <kaner@strace.org>
+
diff --git a/doc/wodim/README.clone b/doc/wodim/README.clone
new file mode 100644 (file)
index 0000000..4964730
--- /dev/null
@@ -0,0 +1,27 @@
+Hints for how to copy a CD using the clone method:
+
+Step 1 (read master CD):
+
+       Call "readcd dev=b,t,l -clone f=somefile" and the files
+
+       somefile
+       and
+       somefile.toc
+
+       will be generated.
+
+       If the disk contains many sectors that are unreadable by intention,
+       call "readcd dev=b,t,l -clone -nocorr f=somefile" 
+
+
+Step 2 (write copy):
+
+       Call "wodim dev=b,t,l -raw96r -clone -v somefile"
+
+If wodim complains that your drive does not support -raw96r, but the
+drive is able to do clone writing at all, then wodim will propose you
+a different write mode that works with the drive.
+
+Source: README.clone from cdrtools package
+Edited for cdrkit by Christian Fromme <kaner@strace.org>
+
diff --git a/doc/wodim/README.raw b/doc/wodim/README.raw
new file mode 100644 (file)
index 0000000..4629f66
--- /dev/null
@@ -0,0 +1,71 @@
+Tips for MMC RAW mode writing.
+
+       This allows to do disk at once recording on Philips drives that
+       do not support SAO.
+
+       You may write audio tracks in RAW mode. There are some new
+       and most likely transient options:
+
+       -raw16          Write 2352 Bytes sectors + P+Q Subchannel
+
+       -raw96r         Write 2352 Bytes sectors + P+W Subchannel (R-W in raw mode)
+
+       -raw96p         Write 2352 Bytes sectors + P+W Subchannel (R-W in packed mode)
+
+       NOTE that the MMC standard does not allow -dummy in RAW mode.
+       There may be drives which allow it but don't bother if it does not work.
+
+       Indices are fully supported in RAW mode.
+
+       MCN & ISRC are not yet supported in RAW mode, they are silently discarded.
+
+       If you find other problems in RAW mode or if you find
+       new bugs introduced in old write modes, please send a bug report.
+
+       wodim now checks the properties of the writer. If a specific write
+       mode is not supported by the writer, wodim warns you and makes
+       a suggestion for a similar alternate write mode.
+
+       With the curent structure of wodim, it is not possible to silently
+       e.g. change the write mode from -dao to -raw96r
+
+       MMC compliant drives are automatically scanned for supported write modes.
+       This should help to make wodim work without manual static configuration.
+       My hope is still to have no need to know all drive properties in 
+       advance, so new drives will continue to work as long as they
+       are standard compliant enough for wodim.
+
+EXAMPLES:
+
+       wodim dev=1,0 -v -raw96r *.wav
+
+       will write a audio CD in raw mode using (computed) 2448 byte sectors 
+       with raw P-W subchannels. This works e.g. with Plextor drives.
+
+
+       wodim dev=1,0 -v -raw16 *.wav
+
+       will write a audio CD in raw mode using (computed) 2368 byte sectors 
+       with raw P+Q subchannels. This works e.g. with Philips drives.
+
+
+       NOTE: The input sector size always is 2352 bytes for audio.
+
+IMPORTANT:
+
+       -       if the drive supports RAW/R96R among with other raw write modes,
+               use -raw96r
+
+       -       if the drive does _only_ supports RAW/R16, use -raw16
+
+       -       ... else if the drive supports RAW/R96P, use -raw96p
+
+               The packed raw mode (RAW/R96P) is buggy in Plextor drives and
+               the RAW/R16 mode is buggy in TEAC drives. Plextor creates
+               unreadable disks and TEAC hangs the drive.
+
+               For this reason, it is important to select the raw writing
+               mode accoding to the notes above.
+
+Source: README.raw from cdrtools package
+Edited for cdrkit by Christian Fromme <kaner@strace.org>
diff --git a/genisoimage/CMakeLists.txt b/genisoimage/CMakeLists.txt
new file mode 100644 (file)
index 0000000..303ba4d
--- /dev/null
@@ -0,0 +1,70 @@
+PROJECT (MKISOFS C)
+
+INCLUDE(../include/AddScgBits.cmake)
+INCLUDE(../include/AddSchilyBits.cmake)
+
+INCLUDE_DIRECTORIES(../include ../libhfs_iso ../wodim ${CMAKE_BINARY_DIR} ${CMAKE_BINARY_DIR}/include)
+
+INCLUDE(CheckIncludeFiles)
+CHECK_INCLUDE_FILES("magic.h" USE_MAGIC)
+IF(USE_MAGIC)
+       ADD_DEFINITIONS(-DUSE_MAGIC)
+       SET(MAGICLIBS magic)
+ENDIF(USE_MAGIC)
+
+CHECK_INCLUDE_FILES("pthread.h" USE_PTHREAD)
+IF(USE_PTHREAD)
+       ADD_DEFINITIONS(-DTHREADED_CHECKSUMS)
+       LIST(APPEND EXTRA_LIBS "pthread")
+ENDIF(USE_PTHREAD)
+
+    IF(HAVE_ICONV_H)
+    ADD_DEFINITIONS(-DUSE_ICONV)
+    #INCLUDE(CheckLibraryExists)
+#    CHECK_LIBRARY_EXISTS (iconv "iconv_open(argv[0],argv[0])" "" USE_LIBICONV)
+IF(USE_LIBICONV)
+    LIST(APPEND EXTRA_LIBS "iconv")
+ELSE(USE_LIBICONV)
+#           MESSAGE("No additional libiconv found, maybe not required. If required, change linker flags, see TROUBLESHOOTING in the INSTALL file")
+ENDIF(USE_LIBICONV)
+ENDIF(HAVE_ICONV_H)
+
+ADD_DEFINITIONS(-DUSE_LARGEFILES -DABORT_DEEP_ISO_ONLY -DAPPLE_HYB -DUDF -DDVD_VIDEO -DSORTING -DHAVE_CONFIG_H -DUSE_LIBSCHILY -DUSE_SCG -DJIGDO_TEMPLATE)
+
+SET(MKISOFS_MOST_SRCS apple.c boot.c desktop.c dvd_file.c dvd_reader.c eltorito.c exclude.c files.c fnmatch.c hash.c ifo_read.c joliet.c mac_label.c match.c multi.c name.c rock.c scsi.c stream.c tree.c udf.c vms.c volume.c write.c boot-alpha.c boot-hppa.c boot-mips.c md5.c jte.c rsync.c        boot-mipsel.c endian.c sha1.c sha256.c sha512.c checksum.c )
+  
+INCLUDE(CheckFunctionExists)
+SET(CMAKE_REQUIRED_DEFINITIONS -D_GNU_SOURCE)
+CHECK_FUNCTION_EXISTS("getopt_long" HAVE_GETOPT_LONG)
+IF(NOT HAVE_GETOPT_LONG)
+    LIST ( APPEND MKISOFS_MOST_SRCS  getopt.c getopt1.c )
+ENDIF(NOT HAVE_GETOPT_LONG)
+
+#SET_SOURCE_FILES_PROPERTIES(${MKISOFS_MOST_SRCS} PROPERTIES )
+LINK_DIRECTORIES(../libhfs_iso ../librols ../libusal ../libunls  ../wodim)
+
+ADD_EXECUTABLE (genisoimage genisoimage.c ${MKISOFS_MOST_SRCS})
+TARGET_LINK_LIBRARIES(genisoimage wodimstuff hfs_iso  ${MAGICLIBS} c unls z bz2 ${EXTRA_LIBICONV} ${EXTRA_LIBS})
+
+# common lib set and genisoimage source parts for the rest
+LINK_LIBRARIES(wodimstuff ${EXTRA_LIBS}  unls ${EXTRA_LIBICONV} )
+ADD_EXECUTABLE(devdump diag/dump.c scsi.c)
+ADD_EXECUTABLE(isodebug        diag/isodebug.c scsi.c)
+ADD_EXECUTABLE(isodump diag/isodump.c scsi.c)
+ADD_EXECUTABLE(isoinfo diag/isoinfo.c scsi.c)
+ADD_EXECUTABLE(isovfy  diag/isovfy.c scsi.c)
+
+
+SET_TARGET_PROPERTIES(genisoimage devdump isodebug isodump isoinfo isovfy PROPERTIES  SKIP_BUILD_RPATH TRUE)
+
+INSTALL(TARGETS genisoimage devdump isodebug isodump isoinfo isovfy DESTINATION bin)
+INSTALL(FILES 
+genisoimage.1
+diag/devdump.1
+diag/isodebug.1
+diag/isodump.1
+diag/isoinfo.1
+diag/isovfy.1
+DESTINATION ${MANSUBDIR}/man1)
+INSTALL(FILES genisoimagerc.5 DESTINATION "${MANSUBDIR}/man5")
diff --git a/genisoimage/COPYING b/genisoimage/COPYING
new file mode 100644 (file)
index 0000000..946cb19
--- /dev/null
@@ -0,0 +1,345 @@
+ The GPL below is copyrighted by the Free Software
+ Foundation, but the instance of code that it refers to (the mkisofs
+ utility is copyrighted by Yggdrasil Computing, Incorporated).
+
+----------------------------------------
+
+                   GNU GENERAL PUBLIC LICENSE
+                      Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                          675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                           Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+\f
+                   GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+\f
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+\f
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+\f
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                           NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                    END OF TERMS AND CONDITIONS
+\f
+       Appendix: How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) 19yy  <name of author>
+
+    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 of the License, 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.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) 19yy name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/genisoimage/ChangeLog b/genisoimage/ChangeLog
new file mode 100644 (file)
index 0000000..681a6ce
--- /dev/null
@@ -0,0 +1,3866 @@
+****** Version 2.01 ******
+
+Wed Sep  8 20:28:58 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * isoinfo.c 1.47
+       * isovfy.c 1.23
+       * dump.c 1.21
+       * isodebug.c 1.9
+       * isodump.c 1.24
+       * mkisofs.c 1.161
+         Version -> 2.01
+
+Thu Sep  2 13:05:11 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.8 1.108
+         -D Hinweis auf ISO9660:1999
+
+Mon Aug 30 12:24:17 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.8 1.107
+         ISO-9690 -> ISO-9660
+
+Tue Aug 24 19:21:54 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * write.c 1.85
+         Intermediate Cast auf (void *) damit GCC nicht wegen "strict-aliasing rules" meckert
+
+Tue Aug  3 21:21:54 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.8 1.106
+         Hinweis auf Bugfix fuer -no-split-symlink-components / -no-split-symlink-fields
+
+Sat Jul 31 17:11:30 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.8 1.105
+         Schreibfehler beseitigt
+
+Sat Jul 17 23:42:14 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.8 1.104
+       * mkisofs.c 1.160
+         Version -> 2.01a34
+         -volset-size ist nun auf 1 begrenzt
+
+Sun Jul 11 18:30:27 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.159
+         Fehlermeldung bei -L/-H/-P weis nun korrekt auf 2.02 hin
+
+Sun Jul 11 02:03:26 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.158
+         -> NEED_O_BINARY
+
+Fri Jul  9 17:34:41 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.157
+         Version -> 2.01a33
+
+Fri Jul  9 16:06:36 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * volume.c 1.14
+       * write.c 1.84
+         static -> LOCAL + EXPORT
+
+Fri Jul  9 15:32:26 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * write.c 1.83
+         'VIDEO_TS' wird jetzt immer gefunden und mkisofs bricht ab wenn es nicht gefunden werden konnte und -dvd-video
+
+Fri Jun 18 11:17:08 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * hash.c 1.18
+         Nachdenken ueber Speedup
+
+Thu Jun 17 12:25:43 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.156
+         Version -> 2.01a32
+
+Thu Jun 17 11:22:11 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * dump.c 1.20
+       * isodump.c 1.23
+         For Schleife ohne strlen() in Ende Bedingung
+
+Sat Jun 12 16:15:16 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * tree.c 1.82
+         sprintf() zur besseren Geschwindigkeit beim Erzeugen von 8.3 Filenamen in sort_n_finish() vermeiden
+
+Mon Jun  7 13:02:01 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.8 1.103
+         Dokumentation der maximalen Stringlaenge der Eintraege im PVD nun auch bei den Optionen
+
+Sat Jun  5 16:48:02 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.8 1.102
+       * mkisofs.c 1.155
+         Optionen -H/-L/-P sind veraltet und werden mit 2.02 POSIX.1-2001 konform
+
+Tue Jun  1 18:27:04 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.154
+         Version -> 2.01a31
+
+Tue Jun  1 16:53:24 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * tree.c 1.81
+         Bei DJGPP auch alle Files eXecutable machen.
+
+Tue Jun  1 16:52:47 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.153
+         load_nls("cp437") per Default auch fuer DJGPP
+
+Tue Jun  1 16:51:47 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * defaults.h 1.18
+         SYSTEM_ID -> DOS fuer DJGPP
+
+Tue Jun  1 16:50:58 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * isoinfo.c 1.46
+         setmode(fileno(stdout), O_BINARY) beim Extrahieren von Dateien nach STDOUT
+
+Tue Jun  1 14:07:06 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * isodebug.c 1.8
+         Funktionen moeglichst LOCAL 
+
+Tue Jun  1 13:50:50 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * dump.mk 1.4
+       * dump.c 1.19
+       * isoinfo.8 1.7
+       * isodump.c 1.22
+       * isoinfo.mk 1.5
+       * isodump.mk 1.4
+       * isovfy.mk 1.4
+       * isovfy.c 1.22
+       * isodebug.mk 1.2
+       * isodebug.c 1.7
+         Umstellung auf libusal
+
+Sat May 29 17:46:26 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * isoinfo.c 1.45
+         cdr_defaults() nur mit libusal rufen
+
+Sat May 29 16:55:08 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * isodebug.c 1.6
+         Version -> 2.01a31
+         Cstyle
+
+Fri May 28 13:51:13 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * isoinfo.c 1.44
+         Support fuer cdr_defaults() (/etc/default/cdrecord) neu
+
+Fri May 28 13:39:35 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * isoinfo.c 1.43
+         Cstyle
+
+Fri May 28 13:37:39 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * isoinfo.c 1.42
+         Version -> 2.01a31
+         Umbau auf libusal
+
+Fri May 28 13:36:25 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * isodump.c 1.21
+       * isovfy.c 1.21
+         Version -> 2.01a31
+         Cstyle
+
+Fri May 28 01:09:55 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * dump.c 1.18
+         Version -> 2.01a31
+         Cstyle
+
+Thu May 27 01:54:59 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.h 1.94
+         scsi.c Prototypen -> scsi.h
+
+Thu May 27 01:54:31 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi.h 1.1
+         date and time created 04/05/27 00:54:31 by joerg
+
+Sun May 23 23:46:05 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * eltorito.c 1.32
+         Debug Messages beseitigt
+
+Sun May 23 23:23:27 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.8 1.101
+       * tree.c 1.80
+       * eltorito.c 1.31
+       * match.h 1.9
+       * mkisofs.c 1.152
+       * match.c 1.18
+         Version -> 2.01a30
+         Eltorito Boot Images per Default nach Vorne Sortieren
+
+Thu May 20 13:38:31 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * eltorito.c 1.30
+         Copyright J. Schilling neu
+
+Thu May 20 13:33:59 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * eltorito.c 1.29
+         Keine Ausgabe der Bootmethode bei mkisofs -quiet
+
+Sat May 15 22:25:17 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.151
+         Version -> 2.01a29
+         Hinweis auf unerwuenschte SILO Optionen
+
+Sat May 15 21:48:26 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * write.c 1.82
+         Neuer Kommentar damit SuSE keine sinnlosen Patches anbringt
+
+Sat May 15 21:05:49 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * isoinfo.c 1.41
+         Version -> 2.01a29
+
+Sat May 15 19:59:40 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * multi.c 1.66
+       * mkisofs.c 1.150
+       * isoinfo.c 1.40
+         GCC shadowed Variblen beseitigt
+
+Thu Apr 15 16:33:41 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.149
+         Version -> 2.01a28
+
+Thu Apr 15 16:30:40 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * hash.c 1.17
+         isoname_endsok() neu zum besseren Vergleich von ISO-9660 namen
+
+Thu Apr 15 14:51:22 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * hash.c 1.16
+       * udf.c 1.14
+         Cstyle
+
+Wed Apr 14 12:55:56 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * write.c 1.81
+         Schreibfehler beseitigt (Initial Padbock)
+
+Tue Apr  6 12:30:26 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * tree.c 1.79
+         Fix fuer doppeltes Free von Juergen Keil
+         Absturz durch:
+         echo bar >/tmp/bar
+         echo foo/bar=/tmp/bar > /tmp/pathlist
+         env LD_PRELOAD=libumem.so.1 UMEM_DEBUG=default UMEM_LOGGING=transaction mkisofs -hfs -graft-points -o /tmp/foo.raw -path-list=/tmp/pathlist
+
+Tue Apr  6 11:57:30 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * tree.c 1.78
+         beruecksichtigung des Null Bytes beim malloc() fuer die Datei TRANS_TBL
+
+Sun Apr  4 20:24:38 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * multi.c 1.65
+         Bessere Fehlermeldung bei multi Session mit volset size > 1
+
+Mon Mar 15 15:43:58 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * defaults.h 1.17
+         "SCO-OPENSERVER"/"SCO-UNIXWARE", Default ist nun "UNIX" statt "LINUX"
+
+Fri Mar  5 00:22:28 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.148
+         Version -> 2.01a27
+
+Fri Mar  5 00:12:50 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mac_label.c 1.9
+       * match.c 1.17
+       * name.c 1.28
+       * scsi.c 1.19
+       * stream.c 1.3
+       * files.c 1.12
+       * exclude.c 1.9
+       * dvd_reader.c 1.3
+       * eltorito.c 1.28
+       * ifo_read.c 1.5
+       * dvd_file.c 1.3
+       * desktop.c 1.6
+       * apple_driver.c 1.6
+       * vms.c 1.9
+       * volume.c 1.13
+         Cstyle
+
+Thu Mar  4 22:47:39 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * multi.c 1.64
+       * mkisofs.h 1.93
+       * mkisofs.c 1.147
+       * mkisofs.8 1.100
+         Neue Optionen -root & -old-root von Patrik Ohly
+
+Thu Mar  4 22:40:24 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mac_label.c 1.8
+         Korrektur fuer PREP/CHRP Erweiterung
+
+Tue Mar  2 00:54:16 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * fnmatch.h 1.4
+       * exclude.h 1.3
+       * diskmbr.h 1.2
+       * defaults.h 1.16
+       * bootinfo.h 1.3
+       * apple.h 1.7
+       * apple.c 1.19
+       * ifo_read.h 1.2
+       * ifo_types.h 1.2
+       * iso9660.h 1.19
+       * mac_label.h 1.3
+       * mactypes.h 1.3
+       * match.h 1.8
+         Cstyle
+
+Tue Mar  2 00:50:27 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * dvd_reader.h 1.2
+         Cstyle 
+
+Mon Mar  1 12:05:40 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * vms.h 1.3
+       * udf.h 1.2
+       * udf_fs.h 1.2
+         Cstyle
+
+Sun Feb 29 17:53:16 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * isoinfo.c 1.39
+         Eltorito Boot mit -d anzeigen
+         Extension Records fuer lange RR Namen korrekt anzeigen
+
+Sun Feb 29 17:20:47 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mac_label.h 1.2
+       * write.c 1.80
+       * mkisofs.c 1.146
+       * mkisofs.h 1.92
+       * mac_label.c 1.7
+         CHRP Support von "Leigh Brown" <leigh@solinno.co.uk>
+
+Sun Feb 29 16:49:18 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * rock.c 1.42
+       * multi.c 1.63
+         }; in Funktionen -> }
+
+Sun Feb 29 16:43:37 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * multi.c 1.62
+         Korrekte Behandlung von CE Extension Records fuer RR NM & fue rTime Stamps
+
+Wed Feb 25 00:16:47 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * udf.c 1.13
+         Support fuer rationalize_uid/rationalize_gid
+
+Sun Feb 22 16:27:28 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.145
+         Version -> 2.01a26
+         Mb -> MB
+
+Sun Feb 22 16:26:26 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * rock.c 1.41
+         gen_xa_attr(mode_t attr) ANSI C Variante wegen aelteren UNIX Versionen mit mode_t == short
+
+Sun Feb 22 16:25:09 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * boot.c 1.13
+         Total extents including sparc boot -> Total extents including %s boot
+
+Sun Feb 22 16:13:43 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi.c 1.18
+         cdr_defaults() wird nun fuer das SCSI dev= gerufen (/etc/default/cdrecord)
+
+Wed Jan  7 00:23:46 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.144
+         Copyright -> 2004
+
+Tue Jan  6 23:53:42 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.143
+         Version -> 2.01a24
+
+Tue Jan  6 22:37:55 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * tree.c 1.77
+         Rock Ridge Laengenbehandlung in update_nlink()/increment_nlink() korrigiert (Bugfix)
+
+Mon Dec 29 14:46:02 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.142
+       * boot.c 1.12
+         Cstyle Anpassungen
+
+Mon Dec 29 14:36:10 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * boot.c 1.11
+         Neue Optionen -sunx86-boot & -sunx86-label
+
+Mon Dec 29 14:35:05 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.141
+         Version -> 2.01a22
+         Neue Optionen -sunx86-boot & -sunx86-label
+
+Mon Dec 29 14:34:16 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.8 1.99
+         Neue Optionen -sunx86-boot & -sunx86-label
+         -sparc-label war vergessen - nun dokumentiert
+
+Mon Dec 29 13:31:28 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.8 1.98
+         Kommentar zu SILO in den NOTES
+         Fehlende backslashes for diversen - Zeichen eingefuegt
+
+Sun Dec 28 14:46:10 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * sunlabel.h 1.5
+         Cstyle Aenderungen
+
+Sun Dec 28 14:44:50 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * sunlabel.h 1.4
+         Erweiterungen fuer Solaris x86 Disk Label und fdisk
+
+Sun Dec 28 14:38:51 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.h 1.91
+         Cstyle Anpassungen
+
+Sun Dec 28 14:37:09 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.h 1.90
+         make_sunx86_label()/scan_sunx86_boot()/sunx86_boot_label() neu
+
+Sat Nov 29 23:58:30 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.140
+         #include <io.h> fuer setmode(fileno, OBINARY)
+         #include <io.h> auch fuer DJGPP
+
+Sat Nov 29 23:11:14 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.139
+         Version -> 2.01a20
+         setmode(fileno, O_BINARY) auch fuer DJGPP
+
+Sun Jul 13 15:42:15 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * write.c 1.79
+       * mkisofs.h 1.89
+       * mkisofs.c 1.138
+         secsize -> osecsize, Version -> 2.01a17
+
+Fri Jul 11 11:42:32 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.8 1.97
+         Schreibfehler
+
+Thu Jul 10 01:26:47 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * tree.c 1.76
+         Bessere Meldung bei Stat Buffer Overflow
+
+Sat Jun 21 14:28:25 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.137
+         Eltorito PVD muss vor direkt nach dem Primaeren PVD kommen -> also vor Enhanced PVD
+
+Sat Jun 21 14:16:30 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * match.c 1.16
+         Wenn ein TAB nach einem Space im Sort File kommt, dann wird dieses genommen
+
+Sat Jun 21 14:11:05 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.8 1.96
+         Schreibfehler und Formulierungen korrigiert
+
+Sat Jun 21 14:10:13 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * eltorito.c 1.27
+         Schreibfehler bei 'is not the an allowable size' beseitigt
+
+Tue May  6 19:04:03 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * rock.c 1.40
+         Fix fuer defekte CE Signaturen bei ../../../ in Symlinks
+
+Wed Apr 30 01:19:33 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.136
+         no_rr nur dann automatisch setzen wenn keine XA Signaturen gefunden wurden
+
+Wed Apr 30 01:18:10 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * multi.c 1.61
+         find_rr() nun mit XA Flag
+
+Wed Apr 30 01:15:59 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.h 1.88
+         Rock Ridge Defines neu
+
+Tue Apr 29 21:22:52 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * write.c 1.78
+         Variable secsize neu, struct xa_subhdr neu
+
+Tue Apr 29 21:20:40 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.h 1.87
+         Neue Variable secsize
+
+Tue Apr 29 21:19:13 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.135
+         Neue Option -sectype
+
+Tue Apr 29 01:39:14 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.134
+         -apple bedeutet nicht mehr -r
+
+Tue Apr 29 01:17:55 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * tree.c 1.75
+         insert_file_entry() erzeugt auch XA oder RockRidge Signaturen fuer rsrc Files
+
+Tue Apr 29 01:06:32 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * write.c 1.77
+         Umbau von xfwrite() fuer XA subheader
+
+Mon Apr 28 01:44:30 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.8 1.95
+         Hinwies, dasz -apple nicht mehr -R beinhaltet
+
+Mon Apr 28 01:36:07 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * joliet.c 1.37
+       * eltorito.c 1.26
+       * boot.c 1.10
+       * stream.c 1.2
+       * udf.c 1.12
+       * mkisofs.h 1.86
+         Umbau von xfwrite() fuer XA subheader
+
+Mon Apr 28 01:06:38 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * iso9660.h 1.18
+         XA Sektor Subheader Definitionen neu
+
+Sun Apr 27 15:46:18 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * tree.c 1.74
+       * eltorito.c 1.25
+         generate_rock_ridge_attributes() -> generate_xa_rr_attributes(), if (use_RockRidge) -> if (use_XA || use_RockRidge)
+
+Sun Apr 27 15:38:59 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * rock.c 1.39
+         generate_rock_ridge_attributes() -> generate_xa_rr_attributes(), if (!use_RockRidge) goto xa_only;
+
+Sun Apr 27 15:36:45 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.h 1.85
+         generate_rock_ridge_attributes() -> generate_xa_rr_attributes()
+
+Sun Apr 27 15:35:49 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.133
+         Version -> 2.01a12
+
+Sun Apr 27 14:09:25 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * TODO 1.6
+         13.4.2003 HFS > 2 GB
+
+Tue Apr 15 18:47:55 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * write.c 1.76
+         CD-XA001 Signatur hinzufuegen
+
+Sun Apr 13 19:05:06 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * isoinfo.c 1.38
+         Version -> 2.01a10
+         st_size ist unsigned bei ISO-9660, map auf Llong
+
+Sun Apr 13 01:36:22 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * write.c 1.75
+       * tree.c 1.73
+       * mkisofs.h 1.84
+         Erster Versuch Files bis zu 4 GB zu unterstuetzen
+
+Sun Apr 13 01:32:15 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * vms.h 1.2
+       * vms.c 1.8
+         vms_write_one_file() mit off_t size
+
+Fri Apr 11 19:19:24 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * rock.c 1.38
+         gen_xa()/gen_xa_attr() neu
+
+Thu Apr 10 15:38:04 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * iso9660.h 1.17
+         Kommentar fuer XA Flags korrigiert
+
+Thu Apr 10 15:37:25 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.132
+         Version -> 2.01a10, Optionen -XA/-xa neu, Schreibfehler bei -iso-level beseitigt
+
+Thu Apr 10 15:36:03 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.h 1.83
+         use_XA neu
+
+Thu Apr 10 15:34:30 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * write.c 1.74
+         Skip XA Record neu
+
+Sat Apr  5 13:39:51 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * isoinfo.c 1.37
+         Usage Schreibfehler beseitigt
+
+Fri Apr  4 23:42:02 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * name.c 1.27
+         conv_charset() bei -iso-level 4 fuer 8 Bit Zeichen
+
+Fri Apr  4 23:41:05 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * rock.c 1.37
+         statis -> LOCAL, unsigned char -> Uchar
+
+Fri Apr  4 23:40:06 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * ifo_read.c 1.4
+         Umbau um ANSI C Warnungen zu vermeiden
+
+Sat Mar 29 13:01:43 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * udf.c 1.11
+         Hinweis auf VIDEO_TS in joliet.c
+
+Sat Mar 29 12:59:14 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * joliet.c 1.36
+       * write.c 1.73
+         #ifdef __STDC__ -> PROTOTYPES, Eingerueckt nach cstyle
+
+Sat Mar 29 12:43:35 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * multi.c 1.60
+       * rock.c 1.36
+         #ifdef __STDC__ -> PROTOTYPES
+
+Thu Mar 27 00:19:50 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * rock.c 1.35
+         Anpassungen fuer cstyle
+
+Thu Mar 27 00:05:17 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * rock.c 1.34
+         Bessere Debug Ausgaben fuer add_CE_entry & Bug Fix fuer Split Symplinks (2 Byte Offsetfehler)
+
+Tue Mar 25 21:31:29 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * bswap.h 1.2
+       * mkisofs.h 1.82
+         Eingerueckt nach cstyle
+
+Tue Mar 25 20:51:55 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * multi.c 1.59
+         Eingerückt nach cstyle
+
+Tue Mar 25 20:48:56 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.131
+         Version -> 2.01a07, Eingerueckt nach cstyle
+
+Sun Mar  9 13:38:18 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * getopt.c 1.6
+         FSF Junk Code (#define _NO_PROTO) beseitigt der #include strings.h verhinderte; stattdessen #define getopt __nothing_
+
+Thu Mar  6 22:11:16 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * getopt.h 1.3
+       * fnmatch.h 1.3
+         mconfig.h statt (internem) protoyp.h
+
+Thu Mar  6 22:03:51 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * getopt.h 1.2
+       * fnmatch.h 1.2
+         Umbau auf prototyp.h & PROTOTYPES statt __STDC__ damit Prototypen korrekt auch bei SCO Unixware gehen
+
+Thu Mar  6 22:01:40 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * dvd_reader.c 1.2
+         DVDOpenFile() mit Prototype implementierung wegen SCO cc (enum)
+
+Sun Mar  2 17:33:16 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * tree.c 1.72
+         strdup() -> libport
+
+Sat Mar  1 21:19:56 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * match.c 1.15
+         #include match.h nach #include libport.h wegen MAX define in param.h bei Linux
+
+Sat Mar  1 19:25:08 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * match.c 1.14
+         #includ <libport.h> fuer strdup()
+
+Sat Mar  1 18:56:35 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * multi.c 1.58
+         *nent -> *nentp & nent
+
+Sat Mar  1 18:41:25 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * multi.c 1.57
+         pnt->assoc schon direkt nach dem Einlesen der direcory zuweisen damit es zuverlaessig funktioniert
+
+Sat Mar  1 13:00:37 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * isoinfo.c 1.36
+         Ausgabe der ISO-9660 directory flags
+
+Sat Mar  1 12:54:45 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * iso9660.h 1.16
+         Definitionen fuer XA attributes neu
+
+Fri Feb 28 01:32:10 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * write.c 1.72
+       * vms.c 1.7
+       * mkisofs.c 1.130
+       * mkisofs.h 1.81
+         strdup() -> libport.h
+
+Fri Feb 28 01:23:34 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * isodump.c 1.20
+       * dump.c 1.17
+         Umbau auf ttydefs.h und Portabilitaet fuer alte UNIX Versionen ohne termio*
+
+Sun Feb 23 19:34:23 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * tree.c 1.71
+         LOCAL statt static & Umbau wegen cstyle
+
+Sun Feb 23 14:25:55 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * multi.c 1.56
+       * mkisofs.h 1.80
+         Einige Funktionen in multi.c -> LOCAL, Eingerueckt nach cstyle
+
+Sat Feb 22 21:57:34 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * joliet.c 1.35
+         sort_goof -> jsort_goof
+
+Sun Feb 16 01:17:25 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * apple_driver.c 1.5
+         Unsinniger Parameter aus comerr() Aufruf beseitigt
+
+Sat Feb 15 22:05:58 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * isoinfo.c 1.35
+         Bei -debug wird nun auch der root directory extent ausgegeben
+
+Sat Feb 15 22:03:43 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.8 1.94
+         Padding neu beschrieben (150 Sektoren)
+
+Sat Feb 15 22:00:28 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * write.c 1.71
+         Interpad rundet nur noch auf ein Vielfaches von 16 Sektoren auf
+
+Sat Feb 15 21:50:27 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * stream.c 1.1
+         date and time created 03/02/15 21:50:27 by joerg
+
+Sat Feb 15 21:01:49 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.h 1.79
+       * mkisofs.c 1.129
+       * udf.c 1.10
+       * write.c 1.70
+         Umbau auf 150 Sektoren Padding am Ende des FS Images
+
+Sat Feb 15 13:59:11 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.8 1.93
+       * mkisofs.c 1.128
+         Neue Option -stream-media-size
+
+Thu Feb 13 09:37:52 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * write.c 1.69
+         time_t begun -> EXTERN Freigeben fuer UDF & Stream.c
+
+Thu Feb 13 09:34:41 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.h 1.78
+         Definitionen fuer stream.c
+
+Thu Feb 13 09:33:19 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * udf.c 1.9
+         Externe time_t begun aus write.c uebernehmen fuer: PDV, LVDESC, File Set Desc, Main Seq
+
+Mon Feb 10 01:47:19 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * isoinfo.c 1.34
+         Eingerueckt nach cstyle
+
+Sun Feb  9 21:49:45 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * udf.c 1.8
+         Umformatier fuer cstyle
+
+Fri Feb  7 11:15:06 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.127
+         Version -> 2.01a03, Graft-point nodename ist nun [2*PATH_MAX + 1 + 1] grosz
+
+Tue Jan 28 01:28:37 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * isoinfo.c 1.33
+         Erkennung von ISO-9660:1999
+
+Tue Jan 28 01:27:23 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.126
+         Version -> 2.01a02
+
+Tue Jan 28 01:25:58 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.125
+         ISO-9660:1998 -> ISO-9660:1999, Schreibfehler bei -pad help beseitigt
+
+Tue Jan 28 01:25:04 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * write.c 1.68
+         Bei ISO-9660:1999 ist der 2. VD ein ISO_VD_SUPPLEMENTARY (war vorher wie PVD)
+
+Tue Jan 28 01:24:09 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.8 1.92
+       * iso9660.h 1.15
+         ISO-9660:1998 -> ISO-9660:1999
+
+Sun Jan 19 20:18:08 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.8 1.91
+         Warnung vor Suns Eltorito Patch bei -iso-level 4
+
+Sun Jan 19 16:19:29 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * name.c 1.26
+         Bei relaxed Filenames wird '/' verboten.
+
+Sun Jan 19 16:00:57 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.8 1.90
+       * iso9660.h 1.14
+       * mkisofs.h 1.77
+       * rock.c 1.33
+       * mkisofs.c 1.124
+       * multi.c 1.55
+       * write.c 1.67
+         Version -> 2.01a01, Erweiterungen fuer ISO-9660:1998
+
+Sun Jan 19 15:55:18 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * tree.c 1.70
+         Bessere RR overflow Meldung
+
+Wed Dec 25 15:16:49 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * name.c 1.25
+       * files.c 1.11
+       * multi.c 1.54
+         ctype.h nach schily.h wegen OpenBSD #define EOF Bug
+
+Tue Dec 24 16:39:28 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.8 1.89
+       * isoinfo.8 1.6
+         Version -> 2.0
+
+Mon Dec 23 18:25:55 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * dvd_file.c 1.2
+         Support fuer 0 Byte VIDEO_TS/VTS_xx_0.VOB Files
+
+Mon Dec 16 22:37:04 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.8 1.88
+         Umbau auf Berlios & fhg.de
+
+Sun Dec 15 02:03:20 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * write.c 1.66
+         DVD-Video Pad Ausgaben auch ohne DEBUG
+
+Sat Dec 14 19:03:33 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * ChangeLog 1.22
+         -> Version 2.0
+
+Sat Dec 14 19:03:09 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * TODO 1.5
+         Hints for ISO 9660:1988
+
+Thu Dec 12 01:25:27 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * write.c 1.65
+         Consistency check for DVD-Video Pad (<0)
+
+Thu Dec 12 01:25:01 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * ifo_read.c 1.3
+         open() with O_BINARY
+
+Sat Dec  7 21:40:44 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * tree.c 1.69
+         in #ifdef ABORT_DEEP_ISO_ONLY print a hint for -R/-r and -D
+
+Sat Dec  7 21:14:50 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * udf.c 1.7
+         write_udf_file_entries() now ignores de->de_flags & RELOCATED_DIRECTORY
+         and does not create a broken FS if RR_MOVED exists
+
+Sat Dec  7 21:02:08 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * write.c 1.64
+       * mkisofs.h 1.76
+       * mkisofs.c 1.123
+         opnt->of_start_extent new for Constistency Check
+
+Sat Dec  7 20:41:36 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.8 1.87
+         Better Documentation for -split-output
+
+Sat Dec  7 19:37:11 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.122
+         Cast to int forr name_end-name (parameter in %.*s)
+
+Sat Nov 30 17:10:36 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.121
+         Version -> 2.0
+
+Sun Nov 24 12:54:45 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * TODO 1.4
+         Open Problems for time past 2.0
+
+Sun Nov 24 01:17:25 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * udf.c 1.6
+         Patch from Wei DING <ding@memory-tech.co.jp> for UDF Files > 1 GB
+
+Fri Nov 22 17:32:25 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * tree.c 1.68
+         Another attempt to fix mkisofs -f
+
+Fri Nov 22 17:16:43 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.120
+         Disable Joliet for -dvd-video (because of Sort in joliet.c)
+         -s/-S Warning disabled until 2.1alpha
+
+Fri Nov 22 17:15:34 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * joliet.c 1.34
+         Make VIDEO_TS.IFO 1st dir entry with -dvd-video
+
+Sun Nov 17 15:42:19 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.119
+         Mark -s/-S as reserved options
+
+Sat Nov  2 21:41:25 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.118
+         Version -> 1.15a40, Tags in ~/.mkisofsrc have '_' in HFS_*
+
+Thu Oct 24 22:12:30 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * tree.c 1.67
+         scan_directory_tree() with new Flag DIR_WAS_SCANNED to avoid double scan
+         scan_directory_tree() more stable by setting errno = 0 before readdir()
+         no_scandir = 1 commented out to make mkisofs -f not to omit dir content with symlinks to dies
+
+Thu Oct 24 22:03:25 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.h 1.75
+         #define DIR_WAS_SCANNED new
+
+Mon Oct 21 19:29:14 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.8 1.86
+       * tree.c 1.66
+         Typo removed
+
+Mon Oct 21 19:28:25 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.117
+         Typo efective -> effective uid
+
+Sat Oct  5 00:38:01 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * write.c 1.63
+       * volume.c 1.12
+       * mkisofs.8 1.85
+       * mkisofs.c 1.116
+       * mkisofs.h 1.74
+         Version -> 1.15a36, New Option -hfs-parms for better HFS > 4 GB Support from James Pearson
+
+Sat Oct  5 00:17:22 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.115
+         Version -> 1.15a35, Warning for -L/-P/-H Options in POSIX.1-2001
+
+Tue Oct  1 01:13:40 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * write.c 1.62
+       * volume.c 1.11
+       * mkisofs.8 1.84
+       * desktop.c 1.5
+         Patch from James for HSFS > 4 GB
+
+Sat Sep 28 16:55:52 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.8 1.83
+       * mkisofs.h 1.73
+       * write.c 1.61
+       * volume.c 1.10
+         Fix from James for 4 GB HFS Support
+
+Tue Sep 24 15:41:27 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * write.c 1.60
+       * volume.c 1.9
+         Patches from James to aboert on HFS volume size > 2 GB
+
+Sun Sep  1 23:59:52 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * udf.c 1.5
+         Make sure directories have execute permission in default permissions.
+
+Sat Aug 10 23:33:36 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.114
+         UDF Filenames may be 255 chars if not using Joliet
+
+Thu Aug  8 23:48:11 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * rock.c 1.32
+       * tree.c 1.65
+         Symlink buffer size -> PATH_MAX to avoid Overflow
+
+Thu Aug  8 23:25:14 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * ifo_read.c 1.2
+         Comment around Tag past #endif
+
+Thu Aug  8 23:24:37 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * joliet.c 1.33
+       * mkisofs.8 1.82
+       * mkisofs.c 1.113
+       * mkisofs.h 1.72
+         New Option -joliet-long
+
+Sun Jul 28 01:29:19 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.h 1.71
+         Tag past #endif now as comment
+
+Sun Jul 28 01:28:29 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * write.c 1.59
+         Defect Debug printf() with newline in String fixed
+
+Sun Jul 21 17:36:20 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.8 1.81
+         -dvd-video Option new
+
+Sun Jul 21 17:00:26 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * joliet.c 1.32
+       * write.c 1.58
+       * mkisofs.h 1.70
+         Pathtable now works wth more than 65535 Dires if all Parent indices are <= 65535 
+
+Sun Jul 21 16:42:36 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * dvd_reader.c 1.1
+         date and time created 02/07/21 15:42:36 by joerg
+
+Sun Jul 21 16:40:43 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * ifo_read.c 1.1
+         date and time created 02/07/21 15:40:43 by joerg
+
+Sun Jul 21 16:23:35 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * apple.c 1.18
+       * multi.c 1.53
+         malloc() -> e_malloc()
+
+Sun Jul 21 15:51:54 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * dvd_file.c 1.1
+         date and time created 02/07/21 14:51:54 by joerg
+
+Sun Jul 21 15:18:47 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * dvd_file.h 1.1
+         date and time created 02/07/21 14:18:47 by joerg
+
+Sun Jul 21 15:16:26 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * write.c 1.57
+         Support for DVD-Video -dvd-video
+
+Sun Jul 21 14:59:31 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.112
+       * multi.c 1.52
+       * tree.c 1.64
+       * files.c 1.10
+         1024 -> PATH_MAX
+
+Sun Jul 21 14:21:02 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * rock.c 1.31
+         Hack against wrong GCC warning
+
+Sat Jul 20 17:57:49 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * apple.c 1.17
+         Function perr() now uses comerr()
+
+Sat Jul 20 17:54:57 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * ifo_types.h 1.1
+       * dvd_reader.h 1.1
+         date and time created 02/07/20 16:54:57 by joerg
+
+Sat Jul 20 17:54:56 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * ifo_read.h 1.1
+         date and time created 02/07/20 16:54:56 by joerg
+
+Sat Jul 20 17:37:32 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.h 1.69
+         Enhancements for DVD-Video -dvd-video
+
+Sat Jul 20 17:28:10 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * bswap.h 1.1
+         date and time created 02/07/20 16:28:10 by joerg
+
+Sat Jul 20 01:17:52 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * udf.c 1.4
+         DVD-Video comment new
+
+Sat Jul 20 01:15:19 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.111
+         Version -> 1.15a27, Option -dvd-video new
+
+Sat Jul 20 01:13:31 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * tree.c 1.63
+         Sort Video Files only with -dvd-video
+
+Tue Jul 16 21:32:42 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * tree.c 1.62
+       * mkisofs.c 1.110
+       * mactypes.h 1.2
+       * mkisofs.8 1.80
+       * apple.h 1.6
+       * apple.c 1.16
+         Support for Apple files on MacOS X
+
+Thu Jul  4 12:31:42 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.109
+         Version -> 1.15a25, verbose > 1 writes debug info for output fragments.
+
+Thu May 30 01:48:28 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * udf.c 1.3
+       * write.c 1.56
+       * joliet.c 1.31
+       * eltorito.c 1.24
+       * boot.c 1.9
+       * mkisofs.h 1.68
+         of_name in struct output_fragment new
+
+Mon May 20 13:58:11 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mac_label.c 1.6
+         ISO_ROUND_UP(mac_boot->size) / SECTOR_SIZE -> ISO_BLOCKS(mac_boot->size)
+
+Mon May 20 13:55:53 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * write.c 1.55
+         Unused Var in graftcp() removed
+
+Mon May 20 13:51:28 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.h 1.67
+         HFS_BLOCKS() new
+
+Tue May 14 21:13:04 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * write.c 1.54
+         graftcp() Bug fixed (simple Filenames as Arg not shortened)
+
+Mon May 13 00:45:28 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * udf.c 1.2
+         Now using ISO_ROUND_UP()/ISO_BLOCKS()/SEC_SIZE
+
+Mon May 13 00:40:04 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * write.c 1.53
+       * joliet.c 1.30
+         Now using ISO_ROUND_UP()/ISO_BLOCKS()
+
+Mon May 13 00:24:43 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * multi.c 1.51
+         Now using ISO_ROUND_UP()
+
+Mon May 13 00:22:40 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.108
+         Version -> 1.15a23, Now using ISO_ROUND_UP()/ISO_BLOCKS()
+
+Mon May 13 00:08:55 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * eltorito.c 1.23
+         Now using ISO_BLOCKS()
+
+Sun May 12 14:42:18 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.h 1.66
+         Comment for ISO_ROUND_UP(X)/ISO_BLOCKS(X)
+
+Sun May 12 14:10:20 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * tree.c 1.61
+         Function filetype() better
+
+Sun May 12 00:32:18 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.h 1.65
+         ISO_BLOCKS() new
+
+Sat May  4 15:31:00 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * multi.c 1.50
+         file_addr now based on sectors not on bytes to avoid overflow with DVDs
+
+Fri May  3 01:17:51 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * name.c 1.24
+       * mkisofs.c 1.107
+         -no-iso-translate now also using '-'
+
+Sun Apr 28 14:50:15 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.8 1.79
+         Remove outdated hint that at least one "pathspec" is needed
+         (even for File from list List)
+
+Sun Apr 28 14:48:46 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.106
+         Version -> 1.15a22, susage() Bugfix (program_name missing)
+
+Tue Apr 16 19:19:41 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * eltorito.c 1.22
+         make boot.catalog sortable via -sort
+
+Sun Apr 14 22:53:26 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * write.c 1.52
+       * mkisofs.h 1.64
+       * mkisofs.c 1.105
+         Avoid to put unwanted information into the version info
+
+Thu Apr 11 23:53:41 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.104
+         Support for xxx/../yyy in graft-points
+
+Thu Apr 11 19:27:13 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * tree.c 1.60
+       * mkisofs.c 1.103
+         Fix -graft-points /a/b//.///=some_dir bug (doubled / Dir), Version -> 1.15a21
+
+Thu Apr 11 18:55:48 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.8 1.78
+         UTF comment corrected
+
+Thu Apr 11 18:55:23 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.h 1.63
+         debug new
+
+Wed Apr  3 19:47:46 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.102
+         Version -> 1.15a20
+
+Wed Apr  3 19:42:41 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.101
+         Corrected file type recognition for graft points
+
+Wed Apr  3 19:00:32 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * rock.c 1.30
+       * mkisofs.c 1.100
+       * mkisofs.8 1.77
+         Transparent compression (-z) from H.P. Anvin integrated
+
+Wed Apr  3 18:12:07 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.99
+         escstrcpy() corrected for multiple '//', new option -debug
+
+Tue Apr  2 00:57:38 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.98
+         short usage added
+
+Fri Mar  8 16:44:37 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.8 1.76
+         Hint for multisession on MAC -> -part
+
+Fri Mar  8 16:43:46 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mac_label.c 1.5
+         Mac Label mpm[mpc].start = session_start + ... -> mpm[mpc].start = hce->hfs_map_size ...
+
+Tue Feb 26 22:39:16 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * boot.c 1.8
+         Support generic boot for CD-extra (session_start != 0 Dreamcast)
+
+Sun Feb 10 20:18:32 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * hash.c 1.15
+         use Prototyped function definition if we have dev_t arg because it may be < int
+
+Sun Feb 10 16:13:16 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * fnmatch.c 1.4
+         Now using utypes.h, >=/<= compare with Uchar cast
+
+Sun Feb 10 15:56:51 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * apple.c 1.15
+         cast info->nlen to int for comparison
+
+Sat Feb  9 22:21:33 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * apple.c 1.14
+         strcmp() -> memcmp() for sfm_magic/sfm_version
+
+Fri Jan 18 12:48:35 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.8 1.75
+          Write correct size info (1440 kB instead of 1.44 meg) for boot floppy sizes, correct .R typo (used instead of .B) at -magic
+
+Fri Jan 18 12:47:51 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * eltorito.c 1.21
+         Write correct size info (1440 kB instead of 1.44 meg) for boot floppy sizes
+
+Mon Dec 10 01:05:06 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.8 1.74
+         -udf option documented
+
+Mon Dec 10 01:04:38 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * getopt.c 1.5
+         prototype for my_index()
+
+Sun Nov 25 12:53:17 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.8 1.73
+         long unreadable option list removed from sysnopsis line
+
+Thu Nov 22 22:34:18 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.97
+         Version -> 1.15a12
+
+Thu Nov 22 22:24:38 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * udf_fs.h 1.1
+       * udf.c 1.1
+       * udf.h 1.1
+         date and time created 01/11/22 22:24:38 by joerg
+
+Thu Nov 22 16:42:30 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * Makefile 1.10
+       * Makefile 1.10
+       * mkisofs.c 1.96
+       * mkisofs.h 1.62
+         Enhancements for UDF support
+
+Thu Nov 22 16:41:13 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * tree.c 1.59
+         add sort criteria for UDF VIDEO_TS and AUDIO_TS files.
+
+Thu Nov 22 16:40:47 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * joliet.c 1.29
+         make convert_to_unicode()/joliet_strlen() global if UDF support is compiled in
+
+Thu Nov 22 15:24:44 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.8 1.72
+         better documentation for README.sort/README.hide from James Pearson
+
+Thu Nov 22 00:42:31 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * write.c 1.51
+         compare_sort() now behaves correctly if the parameters are exchanged so qsort() may sort correctly
+
+Tue Nov 20 00:55:44 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.8 1.71
+         better documentation for -print-size, use \& if '.' is at beginning of line
+
+Tue Nov 20 00:54:35 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * write.c 1.50
+         avoid #if defined(sun) || defined(_AUX_SOURCE), better error messages
+
+Fri Nov 16 18:15:42 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * desktop.c 1.4
+         nitialize the whole struct hfsdirent in make_desktop()
+
+Sun Nov 11 20:38:20 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * apple.h 1.5
+         d_dtoutime() Prototype new
+
+Sun Nov 11 20:28:56 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * apple.h 1.4
+       * apple.c 1.13
+         Preserves HFS file dates for AppleDouble, AppleSingle and NetaTalk files
+
+Sun Nov 11 13:38:45 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * rock.c 1.29
+         QNX Neutrino has no st_ftime
+
+Sun Oct 21 01:01:23 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * getopt.c 1.4
+         Try to compensate FSF rubish code and supress warnings by always including standard include files
+
+Sun Oct 21 01:00:30 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.95
+         Always use local getopt.h, version -> 1.15a09
+
+Tue Oct  9 01:27:16 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.h 1.61
+         sys/types.h & sys/stat.h -> statdefs.h
+
+Thu May 31 10:56:32 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.8 1.70
+         -split-output description new, -hard-disk-boot/-no-emul-boot/-no-boot hint added to -b
+
+Sun Apr 22 11:34:46 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.94
+         Comment for memset() in e_malloc()
+
+Fri Apr 20 23:53:40 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * ChangeLog 1.21
+         Late changes for 1.14
+
+Fri Apr 20 18:46:36 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * multi.c 1.49
+         Initalize more data from struct directory_record
+
+Fri Apr 20 18:45:47 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.93
+         Always clear allocated memory to avoid uninitialized data.
+
+Tue Apr 17 00:57:30 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.8 1.69
+         Hint to mailman
+
+Fri Apr 13 23:31:42 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * ChangeLog 1.20
+         updated to release 1.14
+
+Fri Apr 13 20:42:30 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.92
+         Version -> 1.14 final
+
+Fri Apr 13 20:12:50 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.8 1.68
+         New Support mail Adresses
+
+Thu Apr 12 19:36:39 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.91
+         make insert_file_entry() failure non fatal in mkisofs main code
+
+Sat Apr  7 17:31:44 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * multi.c 1.48
+         starting to implement associated files in multi-session
+
+Sat Apr  7 14:47:49 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * tree.c 1.58
+       * mkisofs.c 1.90
+         No exit() for warnings
+
+Tue Apr  3 23:33:26 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * Makefile 1.9
+       * defaults.h 1.15
+         APPID_DEFAULT now includes Copyright messages
+
+Mon Apr  2 23:17:05 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * multi.c 1.47
+         unused vars removed
+
+Mon Apr  2 20:09:22 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.89
+         Fixed -check-session handling for -C0,0 default, Search for SUSP RR record in '.' of root
+
+Mon Apr  2 20:05:48 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.8 1.67
+         New option -force-rr
+
+Mon Apr  2 20:05:25 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * multi.c 1.46
+         rr_flags()/parse_rrflags()/find_rr() new, get_session_start() handling for -check-session fixed
+
+Mon Apr  2 20:04:34 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.h 1.60
+         rr_flags()/parse_rrflags()/find_rr() new
+
+Sun Apr  1 21:51:43 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.8 1.66
+         -check-session new
+
+Sun Apr  1 21:51:11 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.88
+         Parameter for -check-session added to usage
+
+Sun Apr  1 21:49:56 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.h 1.59
+         -check-session neu
+
+Sun Apr  1 19:13:37 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.87
+       * multi.c 1.45
+         Need to handle -C (cdrecord_data) special if -check-session is set
+
+Sun Apr  1 17:46:59 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * name.c 1.23
+         Back up to last '.' found if trying to find a better '.' did not work
+
+Sun Apr  1 17:45:17 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.86
+         New option -check-session
+
+Tue Mar 20 01:09:27 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * volume.c 1.8
+       * mkisofs.h 1.58
+       * mkisofs.c 1.85
+       * mkisofs.8 1.65
+         New options for writable HFS files from James Pearson
+
+Sun Mar  4 15:13:00 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.8 1.64
+         Better documentation for -no-cache-inodes
+
+Sun Mar  4 00:53:59 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.84
+         Fix a bug with '-- filename'
+
+Sun Mar  4 00:52:29 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.8 1.63
+       * hash.c 1.14
+       * mkisofs.h 1.57
+       * mkisofs.c 1.83
+         new options -no-cache-inodes/-cache-inodes as a workaround for non unique inodes on Cygwin
+
+Fri Feb 23 21:58:52 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.8 1.62
+         Einfo for RR_MOVED dir added
+
+Fri Feb 23 17:33:54 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * apple.c 1.12
+         set_Dinfo(hfs_info->finderinfo, hfs_ent); -> set_Finfo(hfs_info->finderinfo, hfs_ent); according to James Pearson to make --xinet option work
+
+Thu Feb 15 23:04:00 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * write.c 1.49
+         output_fraagment now copied to allocated space to allow a desc to be used more than once
+
+Thu Feb 15 23:02:53 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.82
+         version -> 1.14a14
+
+Thu Jan 25 23:28:32 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * Makefile 1.8
+       * eltorito.c 1.20
+       * apple.c 1.11
+       * mkisofs.h 1.56
+       * tree.c 1.57
+       * write.c 1.48
+         changes to support large files
+
+Tue Jan 23 13:27:44 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * tree.c 1.56
+       * mkisofs.c 1.81
+       * mkisofs.h 1.55
+       * write.c 1.47
+       * apple.c 1.10
+       * rock.c 1.28
+       * eltorito.c 1.19
+       * joliet.c 1.28
+         Avoid gcc -W warnings (e.g. signed/unsigned)
+
+Sat Jan 20 23:17:37 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * write.c 1.46
+       * mkisofs.8 1.61
+       * mkisofs.c 1.80
+         -quiet make mkisofs really quiet
+
+Sat Jan 20 23:03:26 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.79
+         Modified to allow EBCDIC
+
+Sat Jan 20 22:46:10 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.8 1.60
+       * mkisofs.h 1.54
+       * mkisofs.c 1.78
+       * rock.c 1.27
+       * joliet.c 1.27
+       * apple.c 1.9
+         Better charset tables for Apple
+
+Fri Jan 19 19:26:19 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * tree.c 1.55
+       * mkisofs.c 1.77
+       * mkisofs.8 1.59
+       * mkisofs.h 1.53
+         better rationalized uid/gid/modes
+
+Sat Dec  9 19:55:17 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * apple.c 1.8
+         u_short -> Ushort, u_int -> Uint
+
+Sat Dec  9 19:36:48 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * joliet.c 1.26
+         u_char -> Uchar
+
+Tue Dec  5 15:25:02 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * volume.c 1.7
+       * write.c 1.45
+       * vms.c 1.6
+       * tree.c 1.54
+       * rock.c 1.26
+       * name.c 1.22
+       * multi.c 1.44
+       * mkisofs.h 1.52
+       * mkisofs.c 1.76
+       * match.c 1.13
+       * match.h 1.7
+       * mac_label.c 1.4
+       * joliet.c 1.25
+       * hash.c 1.13
+       * files.c 1.9
+       * exclude.c 1.8
+       * eltorito.c 1.18
+       * desktop.c 1.3
+       * apple_driver.c 1.4
+       * boot.c 1.7
+       * apple.c 1.7
+         Completed conversion to Schily SING autoconfiguration
+
+Mon Dec  4 12:56:49 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.h 1.51
+         Now first includes mconfig.h then stdio.h (for largefiles), now uses strdefs.h, standard.h for const abstraction, stdxlib.h instead of stdlib.h
+
+Mon Dec  4 12:53:32 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * multi.c 1.43
+       * scsi.c 1.17
+         lseek now using SEEK_* macros
+
+Mon Dec  4 12:53:11 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mac_label.c 1.3
+       * apple_driver.c 1.3
+       * apple.c 1.6
+         fseek now using SEEK_* macros
+
+Fri Dec  1 14:14:23 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * multi.c 1.42
+         Now working without usal_prbytes() from libusal
+
+Fri Nov 24 10:49:58 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.75
+         -print-size now also prints an easy to parse string to stdout
+
+Fri Nov 24 10:49:29 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.8 1.58
+          New -print-size behavior documented
+
+Sun Nov 19 16:34:56 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.74
+         New option -no-pad, -pad now default, support for Cygwin-1.x
+
+Sun Nov 19 16:33:13 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * Makefile 1.7
+         Umbau fuer mkhybrid
+
+Sun Nov 19 16:32:40 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * Makefile.man 1.3
+         INSMODE= beseitigt
+
+Sun Nov 19 13:03:18 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * name.c 1.21
+         Special handling for '#' and '~' disabled because the code created infinite dir tree loops
+
+Sat Nov  4 17:59:36 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.8 1.57
+         New option -no-pad, -pad now default
+
+Sat Oct 14 15:33:50 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.8 1.56
+         hint for CD-Extra usage (-M/-C), note for -graft-points option in examples that need -graft-points
+
+Fri Sep  8 02:49:31 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi.c 1.16
+         Call to usal_remote()
+
+Fri Sep  8 02:49:00 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.73
+         Warning for using Joliet without Rock Ridge
+
+Fri Aug 25 15:31:13 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * match.c 1.12
+       * mkisofs.c 1.72
+         new-line discarded only if really present
+
+Mon Aug 14 01:36:38 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.71
+         Graft-points repariert fuer esacped =
+
+Sun Jul 30 14:08:38 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * multi.c 1.41
+       * scsi.c 1.15
+         Modified for new libusal with usal_*()
+
+Thu Jul 20 19:29:19 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.70
+         Version -> 1.13
+
+Thu Jul 20 19:27:54 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mac_label.c 1.2
+         Size arithmetic fix for HFS vol size
+
+Thu Jul 20 19:27:12 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.8 1.55
+         Small typo fixes
+
+Tue Jun 27 19:12:02 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.69
+       * mkisofs.8 1.54
+         New option -graft-points
+
+Tue Jun 27 01:38:35 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.68
+         1.13a02 -> 1.13a03
+
+Tue Jun 27 01:31:27 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.67
+         allow -path-list option to work without a command line arg, graft pointer escapes haf way ready
+
+Tue Jun 27 01:20:27 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * match.c 1.11
+         better parser for -sort option, avoid buffer overflows by not using fscanf
+
+Tue Jun 27 01:18:01 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.8 1.53
+         Better doc for -sort option
+
+Mon Jun 26 23:50:33 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * apple_driver.c 1.2
+         Converted for Schily SING makefile system, made portable
+
+Mon Jun  5 03:19:54 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * write.c 1.44
+         percent output now even works with NO_FLOATINGPOINT
+
+Sat Jun  3 14:24:26 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * write.c 1.43
+         buffer[] -> static in write_one_file() for sake of the silly  Metrowerks C found on BeOS/PPC
+
+Sun May 28 17:41:40 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.66
+         version -> 1.13a02
+
+Sun May 28 17:03:48 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * eltorito.c 1.17
+       * mkisofs.8 1.52
+       * mkisofs.h 1.50
+       * mkisofs.c 1.65
+         New option -eltorito-alt-boot
+
+Sun May 28 16:28:01 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.8 1.51
+         Integration of mkisofs/mkhybrid to one single application
+
+Sun May 28 13:21:51 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * multi.c 1.40
+         Check for reloc_dir != NULL in match_cl_re_entries() 
+
+Sun May  7 17:23:57 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * match.c 1.10
+       * scsi.c 1.14
+       * boot.c 1.6
+       * eltorito.c 1.16
+       * name.c 1.20
+       * joliet.c 1.24
+       * multi.c 1.39
+       * rock.c 1.25
+       * hash.c 1.12
+       * write.c 1.42
+       * tree.c 1.53
+       * mkisofs.c 1.64
+         #include <schily.h>
+
+Sun May  7 17:14:34 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.63
+         Release -> 1.13a01, removed comment for associated files as it has been wrong
+
+Thu Apr 27 14:11:30 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * RELEASE 1.31
+         Release 1.12.1
+
+Thu Apr 27 14:06:09 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.8 1.50
+         New Opton -root-info, typo's corrected
+
+Thu Apr 27 13:54:09 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * apple.c 1.5
+         cast for correct char * / unsigned char * handling
+
+Thu Apr 27 13:36:25 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * volume.c 1.6
+       * apple.h 1.3
+       * desktop.c 1.2
+       * apple.c 1.4
+         Major changes to implement new HFS option -root-info and -jcharset mac-roman
+
+Thu Apr 27 12:47:26 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * Makefile 1.6
+         New file place sorting option activated with -DSORTING
+
+Thu Apr 27 12:46:35 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * ChangeLog 1.19
+         updated to release 1.12.1
+
+**************** Release 1.12.1 *******************
+
+Thu Apr 27 12:44:54 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * tree.c 1.52
+       * rock.c 1.24
+       * mkisofs.h 1.49
+       * mkisofs.c 1.62
+         New HFS option -root-info
+
+Fri Apr 21 22:11:17 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * write.c 1.41
+         better double conversion for estimation time computation
+
+Fri Apr 21 22:04:56 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * name.c 1.19
+         Name trucation warning removed because it does not work.
+
+Fri Apr 21 18:37:36 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * name.c 1.18
+       * mkisofs.h 1.48
+       * mkisofs.c 1.61
+       * mkisofs.8 1.49
+         -max-iso0660-filenames
+
+Fri Apr 21 18:09:55 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * tree.c 1.51
+         Creating unique filenames now works even if we are creating 37 char names
+
+Thu Apr 20 22:14:55 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * tree.c 1.50
+         Make TRANS.TBL wider to allow 37 char iso names, avoid hard coded values
+
+Thu Apr 20 21:44:34 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * multi.c 1.38
+         Parsing of TRANS.TBL now adaptive instead of using hard coded numbers
+
+Wed Apr 19 23:59:22 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * tree.c 1.49
+       * multi.c 1.37
+       * iso9660.h 1.13
+         MAX_ISONAME fom 38 -> 37
+
+Tue Apr 18 16:22:56 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * volume.c 1.5
+         Use HFS_FNDR_ISINVISIBLE for dirs too
+
+Tue Apr 18 16:20:03 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * name.c 1.17
+       * tree.c 1.48
+       * multi.c 1.36
+       * mkisofs.h 1.47
+       * mkisofs.c 1.60
+       * mkisofs.8 1.48
+         Removed Option -all-files, New options -iso-level, -allow-lowercase, -allow-multidot, -relaxed-filenames, -use-fileversion, name.c completely rewritten
+
+Sun Apr 16 16:30:40 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.8 1.47
+       * name.c 1.16
+       * mkisofs.h 1.46
+       * mkisofs.c 1.59
+         New Option -no-iso-translate
+
+Sun Apr 16 16:26:37 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.8 1.46
+         New Options -sort & -ucs-level
+
+Sun Apr 16 15:24:16 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * defaults.h 1.14
+       * mkisofs.h 1.45
+       * multi.c 1.35
+         Copyright Schilling added
+
+Sun Apr 16 15:22:32 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * iso9660.h 1.12
+         struct iso_ext_attr_record new
+
+Sun Apr 16 14:47:53 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * joliet.c 1.23
+       * mkisofs.h 1.44
+       * mkisofs.c 1.58
+         New Option -ucs-level
+
+Sun Apr 16 14:12:24 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.h 1.43
+       * mkisofs.c 1.57
+       * tree.c 1.47
+       * hash.c 1.11
+       * write.c 1.40
+         New sort code from James Pearson
+
+Sun Apr 16 13:39:46 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * match.h 1.6
+       * match.c 1.9
+         Converted to unified match code, new sort match code
+
+Sat Apr 15 21:59:15 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * volume.c 1.4
+         Apply ISO Hidden flag to files on HFS volume too
+
+Sat Apr 15 20:57:06 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * name.c 1.15
+         Handle '.' and '..' entries corretly in iso9660_check()
+
+Wed Apr 12 23:56:56 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.8 1.45
+         New option -check-oldnames
+
+Wed Apr 12 23:44:18 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * apple.c 1.3
+         strcasecmp() local implementation
+
+Wed Apr 12 23:24:10 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * Makefile 1.5
+         HFILES added to get better ctags
+
+Wed Apr 12 23:23:34 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * multi.c 1.34
+       * name.c 1.14
+       * mkisofs.h 1.42
+       * mkisofs.c 1.56
+         New Option -check-oldnames, new function iso9660_check() to check/repair filenames from old session, better error messages for bad RR attributes, avoid coredump with calling memset with negative count.
+
+Tue Apr 11 10:50:04 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * iso9660.h 1.11
+       * tree.c 1.46
+         iso_directory_record now uses MAX_ISONAME (38) old was 34
+
+Sun Apr  9 22:04:42 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * multi.c 1.33
+         Better error messages for bad XA disks.
+
+Sun Apr  9 17:06:34 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.55
+         Version -> 1.12.1a06, corrected help for -l (30 chars!)
+
+Sun Apr  9 17:05:47 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * tree.c 1.45
+         Put number to make names unique before the dot to retain the suffix
+
+Sun Apr  9 14:28:01 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * tree.c 1.44
+         some more curly brackets....
+
+Sat Apr  8 23:51:20 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.54
+         removed duplicate OPTION_H_LIST
+
+Sat Apr  8 23:44:43 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.8 1.44
+       * tree.c 1.43
+       * mkisofs.c 1.53
+       * match.c 1.8
+       * mkisofs.h 1.41
+       * match.h 1.5
+         New option -hidden & -hidden-list to implement hidden (ISO existence flag) files
+
+Sat Apr  8 23:32:45 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.8 1.43
+         better padding documentation (-pad)
+
+Sat Apr  8 20:55:49 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.8 1.42
+         added description for mkhybrid
+
+Sat Apr  8 20:50:47 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.8 1.41
+         add \ before some - signs and mark some mkisofs places with \& to prevent repleacement with sed script
+
+Sat Apr  8 19:40:05 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.8 1.40
+         typo correction and preparation towards unified manual (mkisofs/mkhybrid)
+
+Sat Apr  8 16:05:51 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * volume.c 1.3
+       * write.c 1.39
+       * tree.c 1.42
+       * multi.c 1.32
+       * joliet.c 1.22
+       * eltorito.c 1.15
+       * iso9660.h 1.10
+       * mkisofs.h 1.40
+         Now using iso directory flag definition from iso9660.h
+
+Mon Apr  3 23:59:05 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * multi.c 1.31
+         Minor clean up, Message about XA records
+
+Mon Apr  3 23:40:21 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.h 1.39
+       * match.c 1.7
+       * exclude.c 1.7
+         indented
+
+Mon Apr  3 21:06:04 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * eltorito.c 1.14
+         insert_boot_cat() prototype
+
+Mon Apr  3 02:22:16 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * tree.c 1.41
+       * write.c 1.38
+       * mkisofs.c 1.52
+       * rock.c 1.23
+       * name.c 1.13
+       * joliet.c 1.21
+       * hash.c 1.10
+       * files.c 1.8
+       * eltorito.c 1.13
+       * vms.c 1.4
+         indented
+
+Mon Apr  3 00:38:28 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * tree.c 1.40
+       * multi.c 1.30
+         parse_xa() new to skip XA extended directory attributes
+
+Sun Apr  2 22:24:43 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.h 1.38
+       * write.c 1.37
+         version_desc new
+
+Sun Apr  2 21:15:21 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.51
+         version desc new
+
+Sun Apr  2 20:28:06 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * vms.c 1.5
+         eric -> joerg
+
+Sun Apr  2 19:10:28 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * iso9660.h 1.9
+         struct iso_xa_dir_record new
+
+Sun Apr  2 19:01:16 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * joliet.c 1.20
+         stdlib.h -> stdxlib.h, rtmp, ltmp (short -> char[2]) for correct byteorder handling
+
+Sun Apr  2 18:14:35 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * files.c 1.7
+         Typo correction
+
+Sat Apr  1 22:29:29 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * iso9660.h 1.8
+         Indented
+
+Fri Mar 31 18:50:41 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * volume.c 1.2
+         New function set_cusstom_icon()
+
+Fri Mar 31 18:48:21 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * apple.h 1.2
+       * apple.c 1.2
+         sys/param.h removed, MAXPATHLEN -> PATH_MAX for portability
+
+Fri Mar 31 18:44:31 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * joliet.c 1.19
+         Now sort joliet tree according to Unicode order
+
+Fri Mar 31 18:38:55 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.8 1.39
+       * write.c 1.36
+       * mkisofs.h 1.37
+       * mkisofs.c 1.50
+         New option -pad
+
+Fri Mar 31 12:59:06 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.8 1.38
+         -jcharset implies -J
+
+Fri Mar 31 12:55:30 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.49
+         hfs_ct var new, -hfs-creator typo in option parsing fixed
+
+Thu Mar 30 02:47:14 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.48
+         1.8.1a04 -> 1.8.1a05, -icon-position option needs no argument, -jcharset now implies -J
+
+Thu Mar 30 02:43:18 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.h 1.36
+         #include limits.h for NAME_MAX, PATH_MAX definition new
+
+Wed Mar 29 10:33:45 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * apple.c.bak 1.1
+         date and time created 00/03/29 09:33:45 by joerg
+
+Sun Mar 26 18:44:46 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.8 1.37
+         Better doc for -jcharset
+
+Sun Mar 26 18:40:23 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.47
+         Unicode mapping now defaults to iso8859-1 resp. cp437
+
+Sun Mar 26 18:31:24 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.46
+       * defaults.h 1.13
+         defined(__CYGWIN__) added for Cygwin recognition
+
+Sat Mar 25 17:10:43 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.8 1.36
+       * joliet.c 1.18
+       * Makefile 1.4
+       * mkisofs.c 1.45
+         Joliet character translation using different character sets (-jcharset)
+
+Sun Mar 19 20:08:24 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * boot.c 1.5
+         -B ... zum Duplizieren der letzten Partition bis zum Ende der Partitions Map
+
+Sun Mar 19 20:02:40 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.8 1.35
+         New usage for -B option: ... means replicate previous boot partition
+
+Sun Mar 19 19:19:46 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * defaults.h 1.12
+         Mac OS X definition new
+
+Sun Mar 19 16:46:31 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * tree.c 1.39
+       * multi.c 1.29
+       * mkisofs.c 1.44
+       * mkisofs.h 1.35
+         RR deep directory relocation fixes for multi-session from: "Artem Hodyush" <artem@duma.gov.ru>
+
+Sun Mar 19 16:15:54 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * multi.c 1.28
+         made conform to schily programming rules
+
+Sun Mar 19 16:02:46 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * multi.c 1.27
+         indented
+
+Sat Mar 18 23:59:42 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * README.eltorito 1.2
+         typo corrected
+
+Sat Mar 18 22:43:10 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.43
+       * tree.c 1.38
+         added code for APPLE_HYBRID
+
+Sat Mar 18 19:39:14 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.8 1.34
+         removed superfluous spaces
+
+Sat Mar 18 19:24:34 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * apple.h 1.1
+         date and time created 00/03/18 19:24:34 by joerg
+
+Sat Mar 18 19:24:13 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mac_label.h 1.1
+         date and time created 00/03/18 19:24:13 by joerg
+
+Sat Mar 18 19:23:54 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mactypes.h 1.1
+         date and time created 00/03/18 19:23:54 by joerg
+
+Sat Mar 18 19:18:36 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * desktop.c 1.1
+         date and time created 00/03/18 19:18:36 by joerg
+
+Sat Mar 18 19:18:09 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mac_label.c 1.1
+         date and time created 00/03/18 19:18:09 by joerg
+
+Sat Mar 18 19:16:33 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * volume.c 1.1
+         date and time created 00/03/18 19:16:33 by joerg
+
+Sat Mar 18 17:56:59 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * apple.c 1.1
+         date and time created 00/03/18 17:56:59 by joerg
+
+Sat Mar 18 13:52:21 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * write.c 1.35
+       * mkisofs.h 1.34
+         added code for APPLE_HYBRID, ROUND_UP() -> ISO_ROUND_UP()
+
+Sat Mar 18 13:44:25 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * defaults.h 1.11
+         Use better recognition code for Rhapsody
+
+Sat Mar 18 13:41:24 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * joliet.c 1.17
+         ROUND_UP() -> ISO_ROUND_UP()
+
+Sat Mar 18 13:02:55 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * boot.c 1.4
+         2048 -> SECTOR_SIZE
+
+Sat Mar 18 13:00:02 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * eltorito.c 1.12
+         csum_buffer[2048] -> csum_buffer[SECTOR_SIZE]
+
+Sun Mar 12 20:50:51 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * joliet.c 1.16
+       * rock.c 1.22
+         added code for APPLE_HYBRID
+
+Sat Mar 11 14:00:40 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * match.c 1.6
+         added match code for APPLE_HYBRID, better error messages
+
+Sat Mar 11 13:38:16 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * hash.c 1.9
+         New function flush_hash() for APPLE_HYBRID
+
+Sat Mar 11 13:21:13 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * match.h 1.4
+         Added definitions for APPLE_HYBRID
+
+Sat Mar 11 13:19:07 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * defaults.h 1.10
+         Defaults for HFS (mkhybrid), SYSTEM_ID_DEAULT for Rhapsody
+
+Sun Mar  5 18:08:30 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * joliet.c 1.15
+         Always sort root dir to be first in path table
+
+Sun Mar  5 14:28:41 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.8 1.33
+         correction for boot.catalog description, -table-name documented
+
+Sun Mar  5 14:27:21 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * name.c 1.12
+         replace forgotten but illegal chars by '_'
+
+Sat Mar  4 16:33:38 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.42
+         close_merge_image() call from multi.c, do not close merge image a second time
+
+Sat Mar  4 16:32:32 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.h 1.33
+       * multi.c 1.26
+         new function clode_merge_image(), close_merge_image() -> mkisofs.c
+
+Thu Feb 17 00:10:46 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * sunlabel.h 1.3
+       * boot.c 1.3
+         splitted into boot.c and sunlabel.h
+
+Wed Feb 16 17:55:06 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * getopt.c 1.3
+         Prototypes for exchange() & _getopt_initialize()
+
+Wed Feb 16 17:08:57 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.h 1.32
+         prototype for scsidev_close()
+
+Wed Feb 16 17:08:36 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * multi.c 1.25
+         merge_previous_session() now calls scsidev_close() to allow mkisofs | cdrecord with multi session
+
+Mon Feb 14 15:58:26 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * bootinfo.h 1.2
+         comment added
+
+Thu Feb 10 01:10:21 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi.c 1.13
+         scsidev_close() neu
+
+**************** Release 1.12 *******************
+
+Mon Jan 17 23:53:16 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * RELEASE 1.30
+       * mkisofs.c 1.41
+       * mkisofs.8 1.32
+         Release 1.12
+
+Fri Jan 14 02:26:40 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.8 1.31
+         -no-rr new, Bugs section
+
+Wed Jan 12 16:19:55 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * README.graft_dirs 1.1
+         date and time created 00/01/12 16:19:55 by joerg
+
+Tue Jan 11 13:17:32 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * joliet.c 1.14
+         allow odd to buffer sizes when converting to unicode
+
+Mon Jan 10 23:17:25 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * tree.c 1.37
+       * rock.c 1.21
+         now using device.h
+
+Mon Jan 10 02:26:07 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.40
+         -no-rr new
+
+Mon Jan 10 01:45:07 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * multi.c 1.24
+       * mkisofs.h 1.31
+         no_rr new
+
+Sat Jan  8 23:42:24 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi.c 1.12
+         scsi_read() beachtet nun is_atapi damit mkisofs auch mit ATAPI multi-session kann
+
+Fri Jan  7 20:51:10 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * tree.c 1.36
+         print file typee, better error messages, no_scandir added
+
+Fri Jan  7 20:42:00 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * rock.c 1.20
+       * exclude.c 1.6
+         better error messages
+
+Fri Jan  7 20:41:04 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.39
+         new -U flag, -F flag removed, new list match code
+
+Fri Jan  7 20:32:22 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * match.c 1.5
+         new list match code
+
+Fri Jan  7 19:26:08 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.8 1.30
+         new hide options, -F removed -U new
+
+Fri Jan  7 18:58:12 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * write.c 1.34
+         make TRANS.TBL a variable, gui code gives faster verbose message
+
+Fri Jan  7 18:55:19 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * multi.c 1.23
+         make TRANS.TML name a variable
+
+Fri Jan  7 18:52:55 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.h 1.30
+         -U new, new match list code
+
+Fri Jan  7 18:07:38 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * match.h 1.3
+         new match list code
+
+Wed Jan  5 20:06:55 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * name.c 1.11
+         -U flag new
+
+Sun Jan  2 00:37:28 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.38
+         Version js-a38
+
+Sat Jan  1 23:05:28 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * write.c 1.33
+         using offsetof() to get around odd structure length, better error messages
+
+Sat Jan  1 23:03:42 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * joliet.c 1.13
+       * multi.c 1.22
+       * tree.c 1.35
+         using offsetof() to get around odd structure length
+
+Sat Jan  1 20:31:59 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * iso9660.h 1.7
+         Note for odd length added
+
+Sat Jan  1 20:31:53 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.h 1.29
+         offsetof() macro new
+
+Wed Dec 29 14:38:31 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.8 1.29
+       * mkisofs.h 1.28
+       * mkisofs.c 1.37
+         New options -hide-rr-moved & -hide-joliet-trans-tbl
+
+Wed Dec 29 14:21:22 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * tree.c 1.34
+         New options -hide-rr-moved & -hide-joliet-trans-tbl, better error messages
+
+Tue Dec 28 18:23:43 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * multi.c 1.21
+         better error messages, free more structures, check for bad RR Version, fix direactory handling code for graft pointers
+
+Tue Dec 28 16:32:00 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * getopt.c 1.2
+         fixed uninitialized variable
+
+Tue Dec 28 15:12:05 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * hash.c 1.8
+       * files.c 1.6
+       * write.c 1.32
+         better error messages
+
+Tue Dec 28 15:07:29 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * eltorito.c 1.11
+         better error messages, make boot file/ boot catalog hidable
+
+Tue Dec 28 14:21:26 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * joliet.c 1.12
+         Error message made different from others
+
+Mon Dec 27 15:34:43 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * iso9660.h 1.6
+         indented
+
+Mon Dec 20 00:14:20 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * tree.c 1.33
+         config.h must be first, boot catalog becomes MEMORY FILE
+
+Sun Dec 19 22:31:42 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.36
+         hard disk boot, no emulation boot
+
+Sun Dec 19 21:29:59 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * eltorito.c 1.10
+         better autoconf, hd boot, no emulation boot, boot catalog as memory file
+
+Sun Dec 19 21:06:46 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * name.c 1.10
+         fix with file priority
+
+Sun Dec 19 21:01:37 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.h 1.27
+         hard disk boot/ no emulation boot new, MEMORY FILE new
+
+Sun Dec 19 20:58:32 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * write.c 1.31
+         config.h must be first get_731()/get_732() new
+
+Sun Dec 19 20:57:02 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * rock.c 1.19
+       * multi.c 1.20
+         config.h must be first
+
+Sun Dec 19 20:55:22 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * hash.c 1.7
+         include stdlib.h past config.h
+
+Sun Dec 19 20:33:49 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * diskmbr.h 1.1
+         date and time created 99/12/19 20:33:49 by joerg
+
+Sun Dec 19 19:54:43 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * iso9660.h 1.5
+         changes for NOEMUL BOOT
+
+Sun Dec 19 18:16:10 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * bootinfo.h 1.1
+         date and time created 99/12/19 18:16:10 by joerg
+
+Sun Dec 19 16:38:04 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.8 1.28
+         hard disk boot and no emulation boot
+
+Sun Dec 19 16:13:21 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * sunlabel.h 1.2
+       * boot.c 1.2
+         Ueberfluessige Variablen beseitigt, Prototypen fuer geboot_*()
+
+Sat Dec 18 01:11:43 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * Makefile.in 1.16
+         Erics final changes
+
+Wed Dec 15 01:24:58 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.35
+         sparc boot new, -nomak new, suid mode now safe
+
+Sun Dec 12 22:01:32 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * README.sparcboot 1.1
+         date and time created 99/12/12 22:01:32 by joerg
+
+Sun Dec 12 19:26:57 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * write.c 1.30
+       * mkisofs.8 1.27
+       * mkisofs.h 1.26
+         sparc boot new
+
+Sun Dec 12 18:28:09 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * Makefile 1.3
+         boot.c new
+
+Sun Dec 12 18:03:39 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * sunlabel.h 1.1
+       * boot.c 1.1
+         date and time created 99/12/12 18:03:39 by joerg
+
+Sat Dec 11 16:26:54 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * tree.c 1.32
+         rstr() new to check for .bak files
+
+Fri Dec 10 01:58:22 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * multi.c 1.19
+         Check first if -M file exists before trying to use scsidev_open()
+
+Tue Dec  7 00:33:13 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * write.c 1.29
+         new sort_dir code checks for is_rr_dir
+
+Tue Dec  7 00:21:00 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * tree.c 1.31
+         Do not make directory loop fatal, new sort_directory code
+
+Tue Dec  7 00:19:32 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.h 1.25
+         sort directory prototyp modified
+
+Mon Dec  6 23:40:22 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * joliet.c 1.11
+         use comerr()
+
+Mon Dec  6 22:46:07 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.34
+         Version js-a34
+
+Sat Dec  4 20:56:21 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * multi.c 1.18
+         Allow RR Version 2 for Mac, memcmp() returns != null for misscompare of date!!!
+
+Sat Dec  4 20:48:22 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * write.c 1.28
+         Allow the same name in rr_moved
+
+Tue Nov 30 17:16:47 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * joliet.c 1.10
+         strncmp() for max of 64 chars in Joliet dirs
+
+Sat Nov 27 22:05:15 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * tree.c 1.30
+         Force graft dirs to be at least SECTOR_SIZE, dup missing whole_name
+
+Thu Nov 25 10:44:05 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * defaults.h 1.9
+         Various new system definitions
+
+Thu Nov 25 00:25:08 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.33
+         -version new
+
+Tue Nov 23 00:11:24 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.8 1.26
+         Hint to new maintainer Joerg Schilling
+
+Tue Nov 23 00:05:30 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.32
+         Version js-a32, -cdwrite-params -> -cdrecord-params
+
+Tue Nov 23 00:03:15 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * README 1.7
+         cdwrite hint removed
+
+Tue Nov 23 00:01:13 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * multi.c 1.17
+         TRANS.TBL handling corrected
+
+Mon Nov 22 23:47:21 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi.c 1.11
+         Abbruch bei Lesefehlern in readsecs()
+
+Mon Nov 22 21:41:38 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * rock.c 1.18
+         #ifdef corrected for BLK/CHR devices
+
+Fri Nov 19 23:01:59 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * tree.c 1.29
+         S_IFBLK checked for OS/2
+
+Fri Nov 12 11:55:44 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * eltorito.c 1.9
+         clean castings
+
+Fri Nov 12 11:53:07 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * write.c 1.27
+         clean casting
+
+Fri Nov 12 11:45:03 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.h 1.24
+         #include statdefs.h
+
+Wed Nov  3 23:56:49 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.31
+         Release js-a31
+
+Mon Nov  1 22:29:15 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * Makefile.man 1.2
+         INSMODE new
+
+Sat Oct 16 18:52:16 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.30
+         Release 1.12b5-js-a30, removed & before array
+
+Fri Oct 15 22:01:18 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * multi.c 1.16
+         Removed & before array
+
+Fri Oct  8 19:54:24 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * match.c 1.4
+         make it work correctly on 64 bit systems
+
+Mon Sep 13 12:10:13 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.29
+         Version to 1.12b5-js-28
+
+Tue Sep  7 16:45:13 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi.c 1.10
+         Umbau auf neues open_scsi(), commerr() statt fprintf(stderr)
+
+Tue Sep  7 14:52:25 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * rock.c 1.17
+         HAVE_READLINK test, use comerr()
+
+Tue Sep  7 14:50:50 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * joliet.c 1.9
+       * hash.c 1.6
+       * files.c 1.5
+       * eltorito.c 1.8
+       * multi.c 1.15
+       * write.c 1.26
+         use comerr()
+
+Tue Sep  7 14:32:27 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * tree.c 1.28
+         use comerr(), HAVE_READLINK test
+
+Tue Sep  7 14:13:12 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.28
+         use comerr()/save_args()
+
+Tue Sep  7 14:10:48 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * Makefile 1.2
+         USE_LIBSCHILY new
+
+Sun Aug 29 01:59:22 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.h 1.23
+         HAVE_LSTAT test new
+
+Sun Aug  1 22:50:12 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * defaults.h 1.8
+         SYSTEM ID DEFAULT for OS/2
+
+Sun Jul 11 19:32:42 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * multi.c 1.14
+         <translation table> -> TRTANS.TBL for Joliet, round up to SECSIZE for reading TRANS.TBL
+
+Sun Jul 11 19:30:08 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * tree.c 1.27
+         <translation table> -> TRTANS.TBL for Joliet, ignore-loops new
+
+Mon Jun 21 11:46:40 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * write.c 1.25
+         Check for Rock Ridge files with same name
+
+Thu Jun 17 16:31:43 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * name.c 1.9
+         cleaned up
+
+Thu Jun 17 16:30:18 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.8 1.25
+         Better words, -F option new
+
+Thu Jun 17 16:17:18 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.27
+         wildcard for EMX, ignore loops, no-split-symlink-fields/no-split-symlink-components now work
+
+Tue May 25 21:09:44 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.h 1.22
+         ignore-loops new
+
+Wed May 19 16:41:02 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * joliet.c 1.8
+         debug print for joliet files wirh same name
+
+Wed Apr 28 16:58:37 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * name.c 1.8
+         Better handling for chars > 128
+
+Sat Apr 24 18:39:19 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi.c 1.9
+         Wegen OS/2 wird nun scsi_getbuf() aufgerufen, wait_inut_ready() neu, read_capacity() neu, Schleife ueber read_scsi, falls der transfer groeszer als der SCSI Puffer ist.
+
+Sat Apr 24 18:25:00 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * mkisofs.c 1.26
+         #ifdef for EMX (OS/2)
+
+**************** Release 1.12b5 *******************
+
+Mon Mar  8 01:32:05 1999 Eric Youngdale <eric@andante.org>
+       * RELEASE 1.29
+         Release1.12b5
+
+Mon Mar  8 01:31:05 1999 Eric Youngdale <eric@andante.org>
+       * mkisofs.8 1.24
+         many new options from Joerg Schilling, Release 1.12b5
+
+Sun Mar  7 22:48:49 1999 Eric Youngdale <eric@andante.org>
+       * mkisofs.c 1.25
+         several new options, binary open for Win32
+
+Sun Mar  7 18:41:19 1999 Eric Youngdale <eric@andante.org>
+       * write.c 1.24
+         split-output new, binary open for Win32, avoid incorrect sorting for ./.. with -L, ISO hide code
+
+Sun Mar  7 18:41:19 1999 Eric Youngdale <eric@andante.org>
+       * tree.c 1.26
+         Inhibit code, sprintf() now correct, varoius other fixes
+
+Sun Mar  7 18:41:19 1999 Eric Youngdale <eric@andante.org>
+       * joliet.c 1.7
+         Let all iso8859-1 chars be unicode, Joliet hide code
+
+Tue Mar  2 05:16:41 1999 Eric Youngdale <eric@andante.org>
+       * multi.c 1.13
+         Prototypes and other various bug fixes
+
+Tue Mar  2 05:16:41 1999 Eric Youngdale <eric@andante.org>
+       * mkisofs.h 1.21
+         better prototypes, INHIBIT_ISO9660_entry new, volume_set_size/volume_sequence_number
+
+Tue Mar  2 05:16:40 1999 Eric Youngdale <eric@andante.org>
+       * Makefile.in 1.15
+         Release 1.12b5
+
+Tue Mar  2 05:16:40 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * README.session 1.3
+         Modified for cdrecord
+
+Tue Mar  2 04:41:26 1999 Eric Youngdale <eric@andante.org>
+       * rock.c 1.16
+         Binary open for Win32, some other fixes
+
+Tue Mar  2 04:41:26 1999 Eric Youngdale <eric@andante.org>
+       * name.c 1.7
+         casts for unsigned char *
+
+Tue Mar  2 04:41:25 1999 Eric Youngdale <eric@andante.org>
+       * match.h 1.2
+       * match.c 1.3
+         Joliet/ISO hide code new
+
+Tue Mar  2 04:41:25 1999 Eric Youngdale <eric@andante.org>
+       * defaults.h 1.7
+         APPID_DEFAULT new
+
+Tue Mar  2 04:41:25 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * exclude.h 1.2
+         __PR() macros
+
+Tue Mar  2 04:41:25 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * fnmatch.c 1.3
+         some casts for unsigned char *
+
+Tue Mar  2 04:41:25 1999 Eric Youngdale <eric@andante.org>
+       * eltorito.c 1.7
+         small bug fixes
+
+Sun Nov 29 19:13:43 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi.c 1.8
+         usalio.h -> usalcmd.h/usalio.h, usalio.h usalcmd.h scsidefs.h scsireg.h scsitransp.h -> include/usal
+
+Sun Nov 29 18:30:41 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * Makefile 1.1
+         date and time created 98/11/29 18:30:41 by joerg
+
+Sat Nov 14 04:20:05 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * Makefile.man 1.1
+         date and time created 98/11/14 04:20:05 by joerg
+
+Fri Oct 30 02:06:35 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi.c 1.7
+         open_scsi() returniert nun SCSI *usalp, wird auch fuer read_scsi() verwendet
+
+Sat Oct 24 01:29:24 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi.c 1.6
+         open_scsi(dev, timeout, verboseopen) -> open_scsi(dev, debug, verboseopen)
+
+**************** Release 1.12b4 *******************
+
+Tue Jun  2 06:44:45 1998 Eric Youngdale <eric@andante.org>
+       * RELEASE 1.28
+         Release 1.12b4
+
+Tue Jun  2 06:43:45 1998 Eric Youngdale <eric@andante.org>
+       * mkisofs.c 1.24
+         New options -print-size & -split-output, put Joliet & ElTorite PVD in right order
+
+Tue Jun  2 06:43:44 1998 Eric Youngdale <eric@andante.org>
+       * mkisofs.8 1.23
+         -print-size/-split-output new, Release 1.12b4
+
+Tue Jun  2 06:14:58 1998 Eric Youngdale <eric@andante.org>
+       * tree.c 1.25
+         Win32 changes, do not use sprintf result, some other fixes
+
+Tue Jun  2 05:40:39 1998 Eric Youngdale <eric@andante.org>
+       * write.c 1.23
+         -split-output, several fixes
+
+Tue Jun  2 05:40:38 1998 Eric Youngdale <eric@andante.org>
+       * multi.c 1.12
+         Some fixes with DOT/DODOT, create whole_name by strdup
+
+Tue Jun  2 05:40:38 1998 Eric Youngdale <eric@andante.org>
+       * mkisofs.h 1.20
+         Win32, -print-size, -split-output
+
+Tue Jun  2 05:40:38 1998 Eric Youngdale <eric@andante.org>
+       * name.c 1.6
+         No version number if it is part of the filename
+
+Tue Jun  2 05:40:37 1998 Eric Youngdale <eric@andante.org>
+       * eltorito.c 1.6
+         O_BINARY for Win32
+
+Tue Jun  2 05:40:37 1998 Eric Youngdale <eric@andante.org>
+       * joliet.c 1.6
+         bug fix for ce_bytes and chars > 128
+
+Tue Jun  2 05:40:37 1998 Eric Youngdale <eric@andante.org>
+       * defaults.h 1.6
+         Defaults for Win32
+
+Tue Jun  2 05:40:36 1998 Eric Youngdale <eric@andante.org>
+       * Makefile.in 1.14
+         CFLAGS new
+
+Fri Apr 17 12:39:39 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi.c 1.5
+         Prototypen entfernt fuer K&R C
+
+**************** Release 1.12b3 *******************
+
+Wed Feb 18 05:51:47 1998 Eric Youngdale <eric@andante.org>
+       * RELEASE 1.27
+       * mkisofs.c 1.23
+       * mkisofs.8 1.22
+         Release 1.12b3
+
+Wed Feb 18 05:48:24 1998 Eric Youngdale <eric@andante.org>
+       * tree.c 1.24
+         check for relocated dirs
+
+Wed Feb 18 05:48:23 1998 Eric Youngdale <eric@andante.org>
+       * rock.c 1.15
+         check strlen of symlink buffer
+
+**************** Release 1.12b2 *******************
+
+Mon Feb 16 18:57:56 1998 Eric Youngdale <eric@andante.org>
+       * RELEASE 1.26
+       * mkisofs.c 1.22
+       * mkisofs.8 1.21
+         Release 1.12b2
+
+Mon Feb 16 18:56:56 1998 Eric Youngdale <eric@andante.org>
+       * tree.c 1.23
+         small bug fixes, Ingoring file message
+
+Mon Feb 16 18:56:56 1998 Eric Youngdale <eric@andante.org>
+       * write.c 1.22
+         bug fix....
+
+Mon Feb 16 18:56:55 1998 Eric Youngdale <eric@andante.org>
+       * mkisofs.h 1.19
+         better autoconf, better prototypes
+
+Mon Feb 16 18:56:55 1998 Eric Youngdale <eric@andante.org>
+       * joliet.c 1.5
+         several casts to unsigned char *
+
+**************** Release 1.12b1 *******************
+
+Mon Dec 15 13:48:59 1997 Eric Youngdale <eric@andante.org>
+       * RELEASE 1.25
+       * mkisofs.c 1.21
+       * mkisofs.8 1.20
+         Release 1.12b1
+
+Mon Dec 15 13:47:59 1997 Eric Youngdale <eric@andante.org>
+       * rock.c 1.14
+         mkdev() autoconf corrected
+
+Mon Dec 15 13:47:59 1997 Eric Youngdale <eric@andante.org>
+       * mkisofs.h 1.18
+         string.h/strings.h autoconf
+
+Mon Dec 15 13:47:59 1997 Eric Youngdale <eric@andante.org>
+       * tree.c 1.22
+         set isorec.size later
+
+Mon Dec 15 13:47:58 1997 Eric Youngdale <eric@andante.org>
+       * eltorito.c 1.5
+         some printf's moved to stderr to avoid problems
+
+Mon Dec 15 13:47:57 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * configure.in 1.4
+         several new tests
+
+**************** Release 120697 *******************
+
+Sat Dec  6 22:06:07 1997 Eric Youngdale <eric@andante.org>
+       * RELEASE 1.24
+       * ChangeLog 1.18
+         Release 120697
+
+Sat Dec  6 22:05:07 1997 Eric Youngdale <eric@andante.org>
+       * write.c 1.21
+       * tree.c 1.21
+       * rock.c 1.13
+         Fix uninitialized memory usage that screwed up lots of stupid things.   Add support for non-split symlinks.
+
+Sat Dec  6 22:05:05 1997 Eric Youngdale <eric@andante.org>
+       * multi.c 1.11
+         init struct directory to null
+
+Sat Dec  6 22:05:05 1997 Eric Youngdale <eric@andante.org>
+       * mkisofs.h 1.17
+         readdir include handling new, *split_SL* new
+
+Sat Dec  6 22:05:05 1997 Eric Youngdale <eric@andante.org>
+       * mkisofs.c 1.20
+       * mkisofs.8 1.19
+         new option -no-split-symlink-fields/-no-split-symlink-components
+
+Sat Dec  6 22:05:03 1997 Eric Youngdale <eric@andante.org>
+       * defaults.h 1.5
+         SunOS/Solaris switch
+
+**************** Release 112597 *******************
+
+Tue Nov 25 14:09:37 1997 Eric Youngdale <eric@andante.org>
+       * RELEASE 1.23
+         Release 112597
+
+Tue Nov 25 14:08:37 1997 Eric Youngdale <eric@andante.org>
+       * mkisofs.8 1.18
+         Release 112597, -quiet option new
+
+Tue Nov 25 14:08:37 1997 Eric Youngdale <eric@andante.org>
+       * mkisofs.c 1.19
+         verbose levels, -quiet
+
+Tue Nov 25 14:06:43 1997 Eric Youngdale <eric@andante.org>
+       * write.c 1.20
+         vervose levels
+
+Tue Nov 25 14:06:42 1997 Eric Youngdale <eric@andante.org>
+       * joliet.c 1.4
+         some bug fixes, handling of reloc dir
+
+Tue Nov 25 14:06:42 1997 Eric Youngdale <eric@andante.org>
+       * tree.c 1.20
+       * hash.c 1.5
+         verbose levels
+
+**************** Release 112397 *******************
+
+Mon Nov 24 03:52:49 1997 Eric Youngdale <eric@andante.org>
+       * RELEASE 1.22
+         Release 112397
+
+Mon Nov 24 03:51:49 1997 Eric Youngdale <eric@andante.org>
+       * multi.c 1.10
+         print error messages to stderr
+
+Mon Nov 24 03:51:49 1997 Eric Youngdale <eric@andante.org>
+       * joliet.c 1.3
+         fixed some bugs that prevented images working on NT, convert to unicode new
+
+Mon Nov 24 03:51:49 1997 Eric Youngdale <eric@andante.org>
+       * tree.c 1.19
+         put error/debug messages to stderr, INHIBIT_JOLIET_ENTRY new
+
+Thu Nov 13 06:01:42 1997 Eric Youngdale <eric@andante.org>
+       * name.c 1.5
+         typo fix
+
+Mon Nov 10 04:27:17 1997 Eric Youngdale <eric@andante.org>
+       * write.c 1.19
+         casting to unsigned char *
+
+**************** Release 110997 *******************
+
+Sun Nov  9 19:56:51 1997 Eric Youngdale <eric@andante.org>
+       * RELEASE 1.21
+         110997
+
+Sun Nov  9 19:55:51 1997 Eric Youngdale <eric@andante.org>
+       * mkisofs.c 1.18
+         getopt_long() codem, graft pointers, struct output_fragment new
+
+Sun Nov  9 19:55:44 1997 Eric Youngdale <eric@andante.org>
+       * mkisofs.8 1.17
+         Joliet new, Graft pointers new
+
+Sun Nov  9 19:54:58 1997 Eric Youngdale <eric@andante.org>
+       * tree.c 1.18
+         Joliet handling and graft pointer handling
+
+Sun Nov  9 19:54:45 1997 Eric Youngdale <eric@andante.org>
+       * write.c 1.18
+         struct output_fragment new, sort goof check new, free unused space, better statistics
+
+Sun Nov  9 19:54:27 1997 Eric Youngdale <eric@andante.org>
+       * multi.c 1.9
+         correct line length for TRANS.TBL, graft pointer merging code new
+
+Sun Nov  9 19:43:36 1997 Eric Youngdale <eric@andante.org>
+       * mkisofs.h 1.16
+         struct output_fragment new, some defines for the tree
+
+Sun Nov  9 19:43:36 1997 Eric Youngdale <eric@andante.org>
+       * iso9660.h 1.4
+         defines for unicode level, PVD ID for Joliet
+
+Sun Nov  9 19:43:36 1997 Eric Youngdale <eric@andante.org>
+       * joliet.c 1.2
+         first code added
+
+Sun Nov  9 19:43:36 1997 Eric Youngdale <eric@andante.org>
+       * Makefile.in 1.13
+         joliet.c, getopt*.c new
+
+Sun Nov  9 19:43:36 1997 Eric Youngdale <eric@andante.org>
+       * name.c 1.4
+         mapping chars > 128
+
+Sun Nov  9 19:43:36 1997 Eric Youngdale <eric@andante.org>
+       * eltorito.c 1.4
+         error messages to stderr, struct output_fragement new
+
+Sun Nov  9 19:43:36 1997 Eric Youngdale <eric@andante.org>
+       * README 1.6
+         Notes for Release 1.12 added
+
+Thu Nov  6 20:19:25 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi.c 1.4
+         #include <mconfig.h> fuer AIX
+
+Tue Nov  4 03:27:44 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * getopt.h 1.1
+         date and time created 97/11/04 03:27:44 by joerg
+
+Tue Nov  4 03:27:39 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * getopt1.c 1.1
+         date and time created 97/11/04 03:27:39 by joerg
+
+Tue Nov  4 03:27:32 1997 Eric Youngdale <eric@andante.org>
+       * getopt.c 1.1
+         date and time created 97/11/04 03:27:32 by eric
+
+Sat Oct 18 19:14:05 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi.c 1.3
+         stdlib.h -> stdxlib.h, unistd.h -> unixstd.h
+
+Wed Oct 15 07:25:15 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * TODO 1.3
+         New list for 1.12
+
+**************** Release 1.11.1 *******************
+
+Mon Oct 13 05:56:49 1997 Eric Youngdale <eric@andante.org>
+       * RELEASE 1.20
+       * mkisofs.8 1.16
+         Release 1.11.1
+
+Mon Oct 13 05:55:49 1997 Eric Youngdale <eric@andante.org>
+       * mkisofs.c 1.17
+         Release 1.11.1, let path_table start on correct sector # depending on El Torito or not
+
+Mon Oct 13 05:46:46 1997 Eric Youngdale <eric@andante.org>
+       * multi.c 1.8
+         better checking for null pointers, USE_SCG code included, type casts for unsigned char *
+
+Mon Oct 13 05:46:01 1997 Eric Youngdale <eric@andante.org>
+       * write.c 1.17
+         Make local time a structure rahte than a pointer so data will not overwritten, add Joliet support
+
+Mon Oct 13 05:41:16 1997 Eric Youngdale <eric@andante.org>
+       * tree.c 1.17
+         file renaming code corrected, iso9660_file_length() called correctly (not dir!) for TRANS.TBL
+
+Mon Oct 13 05:32:57 1997 Eric Youngdale <eric@andante.org>
+       * mkisofs.h 1.15
+         prototypes for readsecs() and scsidev_open()
+
+Mon Oct 13 05:30:51 1997 Eric Youngdale <eric@andante.org>
+       * name.c 1.3
+         seen_dot new, include '%' to illegal characters
+
+Mon Oct 13 05:30:21 1997 Eric Youngdale <eric@andante.org>
+       * rock.c 1.12
+         major() autoconf changed
+
+Mon Oct 13 05:29:40 1997 Eric Youngdale <eric@andante.org>
+       * eltorito.c 1.3
+         Limit publisher ID to 23 chars
+
+Wed May 21 18:11:25 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * scsi.c 1.2
+         scsireg.h Include
+
+Sat May 17 18:49:03 1997 Eric Youngdale <eric@andante.org>
+       * joliet.c 1.1
+         date and time created 97/05/17 17:49:03 by eric
+
+Fri May 16 15:46:48 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de>
+       * config.h 1.1
+       * scsi.c 1.1
+         date and time created 97/05/16 14:46:48 by joerg
+
+**************** Release 1.11 *******************
+
+Thu Apr 10 06:46:21 1997 Eric Youngdale <eric@andante.org>
+       * RELEASE 1.19
+       * RELEASE 1.18
+       * mkisofs.8 1.15
+         Release 1.11
+
+Thu Apr 10 06:43:02 1997 Eric Youngdale <eric@andante.org>
+       * write.c 1.16
+         Check for . and .. entries in dir
+
+Thu Apr 10 06:41:49 1997 Eric Youngdale <eric@andante.org>
+       * tree.c 1.16
+         Strip off non-significant part of filename
+
+/*--------------------------------------------------------------------------*/
+The text below is not autogenerated from SCCS comments:
+
+Wed Nov  5 10:46:29 1997  Andreas Buschmann US/EC4 60/1F/110 #40409  <buschman@lts.sel.alcatel.de>
+
+       Circumvent a bug in the SunOS / Solaris CD-ROM driver (and maybe HP/UX, too).
+       
+       * mkisofs.8 (-S): Document switch.
+       *  mkisofs.c (split_SL_field): new Variable, new switch -S.
+       *  mkisofs.h (split_SL_field): new Variable.
+       * rock.c (generate_rock_ridge_attributes): only split SL field,
+       when split_SL_field is set.
+Tue Jun  3 15:32:21 1997  Andreas Buschmann <buschman@lts.sel.alcatel.de>
+       Circumvent a bug in the SunOS CD-ROM driver (and maybee HP/UX, too).
+       * mkisofs.8 (-s): Document switch.
+       * mkisofs.c (split_SL_component): new Variable, new switch -s.
+       * mkisofs.h (split_SL_component): new Variable.
+       * rock.c (generate_rock_ridge_attributes): only split SL
+       components, when split_SL_component is set.
+       
+       * defaults.h: Added SunOS string.
+       
+
+Wed Mar 19 16:50:17 1997  Fred Fish  <fnf@ninemoons.com>
+
+       * Makefile.in (CFLAGS): Let configure set basic flags.  Move
+       compilation option -c to actual CC commands.
+       (LDFLAGS): Let configure set basic flags.
+       (Makefile): Depends upon config.status, not configure.
+       Regenerate if necessary from Makefile.in using config.status.
+       (configure): Cd to srcdir before running autoconf.
+       * acconfig.h: New file to hold nonstandard entries used in
+       config.h.in.  Used by autoheader to generate config.h.in.
+       * config.h.in: Regenerated with autoheader.
+       * configure.in: Check for existance of sbrk() function.
+       * configure: Regenerated with autoconf 2.12.
+       * fnmatch.c (FMN_FILE_NAME): Define if not already defined.
+       (FNM_LEADING_DIR): Ditto.
+       (FNM_CASEFOLD): Ditto.
+       * mkisofs.c (main): Only use sbrk() if system supports it.
+
+Fri Mar 14 21:54:37 1997  Eric Youngdale  <eric@andante.jic.com>
+
+       * Bump version number to 1.10, public release.
+
+       * Put entire thing under RCS.  History is buried there now.
+
+       * Fix bug involving empty directories, translation tables and
+       malloc(0).
+
+Mon Feb 17 12:44:03 1997  Eric Youngdale  <eric@andante.jic.com>
+
+       * Bump version number to 1.10b7.
+
+       * Makefile.in, configure.in, config.in: Change to use GNU autoconf.
+
+       * Configure: Delete old configuration script.
+
+       * tree.c: Fix bug where we had a rename limit of 1000 files
+       instead of 0x1000.
+
+       * mkisofs.c: Fix sign of timezone offset.  Linux iso filesystem
+       also need to be fixed, unfortunately.
+       
+Tue Dec  3 22:21:21 1996  Eric Youngdale  <eric@sub2317.jic.com>
+
+       Fixed a couple of multi-session bugs.  Discs now seem to
+       work on both Solaris and Windows-NT.
+
+       * Bump version number to 1.10b6.
+
+Tue Dec  3 22:21:21 1996  Eric Youngdale  <eric@sub2317.jic.com>
+
+       Multi-session stuff *almost* there.  Discs seem to work
+       under Linux without any problem, but under DOS only
+       the first session is seen.  The patch to write.c
+       inspired by disc written by Windows generated multi-session
+       disc, which will hopefully make the discs usable under
+       DOS as well.
+       
+       * Bump version number to 1.10b5.
+
+       * write.c: use size of new session, not total of all sessions
+       in volume_space_size field.
+
+       * mkisofs.8: Update with current location of cdwrite.
+
+Mon Nov  4 23:45:01 1996  Eric Youngdale  <eric@sub2317.jic.com>
+
+       * Bump version number to 1.10b4.
+
+       * Add cdwrite.c.diff file, which provides a very crude, minimal
+       interface between mkisofs and cdwrite.  It should be enough to
+       generate a multi-session disc, but it hasn't been tested yet.
+
+Thu Oct 17 00:39:52 1996  Eric Youngdale  <eric@sub2317.jic.com>
+
+       * Bump version number to 1.10b3.
+
+Wed Oct 16 23:40:44 1996  Michael Fulbright <msf@redhat.com>
+
+       Add support for 'El Torito' specification which allows for bootable
+       cdroms.
+
+       * Makefile.in: Add eltorito.[c,o].
+
+       * defaults.h: Add default settings for El Torito related things.
+
+       * iso9660.h: Add structure definitions for El Torito.
+
+       * mkisofs.8: Document new options.
+
+       * mkisofs.c: Add support for new options related to El Torito.
+
+       * mkisofs.h: Add definitions, prototypes as required.
+
+       * tree.c: Add search_tree_file function to search for a specified
+       file.
+
+       * write.c: Add support for writing special records for El Torito.
+
+       * eltorito.c: New file.
+
+       
+Wed Oct 16 23:40:44 1996  Eric Youngdale  <eric@sub2317.jic.com>
+
+       * rock.c: Fix bug whereby we made assumptions about how
+       dev_t was split into major/minor.  Use major() and minor()
+       macros to do this for us, since each system should
+       do this correctly.
+
+       * write.c: Fix bug whereby abstract, copyright and appid
+       strings were not properly filled if application ID weren't
+       in use.
+
+Sun Sep 29 10:05:10 1996  Eric Youngdale  <eric@sub2317.jic.com>
+
+       * Bump version number to 1.10b2.  Minor bug fixes here
+       and there.
+
+Sun Sep 15 18:54:05 1996  Eric Youngdale  <eric@sub2317.jic.com>
+
+       * Bump version number to 1.10b1.  Major new functionality is
+       support for multi-session.  Still a bit preliminary, but
+       most of the pieces are there now.
+
+Wed Dec 20 16:44:44 1995  Eric Youngdale  (eric@andante.aib.com)
+
+        * mkisofs.c, mkisofs.8, Makefile (version_string): Bump to 1.05.
+
+       * rock.c: Bugfix for cases where sizeof(int) == 4 and
+       sizeof(dev_t) > 4.
+
+       * rock.c: Bugfix for long symbolic links ('/' characters were
+       being dropped).
+
+       Patches from Peter Miller <pmiller@agso.gov.au>:
+
+       * mkisofs.8: Documentation fix (some versions of nroff don't
+       like '.' in column 1 if it is not a nroff command).
+
+       * mkisofs.c: Add support for 'rationalize' option.
+       Similar to rock ridge, except echos of development environment
+       are removed.
+
+       * write.c Status indicator now indicates percent finished, and
+       estimated time of completion.
+
+Sun Feb 26 01:52:06 1995  Eric Youngdale  (eric@largo)
+
+       * Add patches from Ross Biro to allow you to merge arbitrary
+       trees into the image.  This is not compiled in by default but
+       you need to add -DADD_FILES when compiling.
+
+Fri Feb 17 02:29:03 1995  Paul Eggert  <eggert@twinsun.com>
+
+       * tree.c: Port to Solaris 2.4.  Prefer <sys/mkdev.h> if
+       HASMKDEV.  Cast unknown integer types to unsigned long and
+       print them with %lu or %lx.
+
+Thu Jan 26 15:25:00 1995  H. Peter Anvin  (hpa@yggdrasil.com)
+
+       * mkisofs.c: Substitute underscore for leading dot in non-Rock
+       Ridge filenames, since MS-DOS cannot read files whose names
+       begin with a period.
+
+Mon Jan 16 18:31:41 1995  Eric Youngdale  (eric@aib.com)
+
+       * rock.c (generate_rock_ridge_attributes): Only use ROOT
+       record for symlinks if we are at the start of the symlink.
+       Otherwise just generate an empty entry.
+
+Mon Jan 16 16:19:50 1995  Eric Youngdale  (eric@aib.com)
+
+       * diag/isodump.c: Use isonum_733 instead of trying to dereference
+       pointers when trying to decode 733 numbers in the iso9660 image.
+
+       * diag/isovfy.c: Likewise.
+
+       * write.c: Always assign an extent number, even for zero length
+       files.  A zero length file with a NULL extent is apparently dropped
+       by many readers.
+
+Wed Jan 11 13:46:50 1995  Eric Youngdale  (eric@aib.com)
+
+       * mkisofs.c: Modify extension record to conform to IEEE P1282
+       specifications.  This is commented out right now, but a trivial
+       change to a #define enables this.   I need to see the specs
+       to see whether anything else changed before this becomes final.
+
+       * write.c (FDECL4): Fix so that we properly determine error
+       conditions.
+
+       * mkisofs.h: Change rr_attributes to unsigned.
+
+       * tree.c(increment_nlink): Change pnt since rr_attributes is now
+         unsigned.
+
+       Ultrix patches from petav@argon.e20.physik.tu-muenchen.de (Peter Averkamp)
+
+       * rock.c: Fix for ultrix systems, we have 64 bit device numbers.
+       Type cast when generating file size.  Change rr_attributes to
+       unsigned.
+
+       * mkisofs.c: For ultrix systems, define our own function
+       for strdup.  
+
+       * mkisofs.c: Fix usage() since some compilers do not concatenate
+       strings properly (i.e. ultrix).
+
+       Bugs found with Sentinel II:
+
+       * write.c: Fix a couple of memory leaks.
+
+       * mkisofs.c: Bugfix - always put a zero byte at end of name
+       for ".." entry.
+
+       * tree.c: Set isorec.date from fstatbuf.st_ctime, not current_time,
+         since current_time might not be set.
+
+Sat Dec  3 14:55:42 1994  Eric Youngdale  (eric@andante)
+
+       * mkisofs.c: When returning entry for ".." file, set second byte
+       to 0.
+
+       * write.c: Free name and rr_attributes fields when writing.
+
+Mon Nov 28 13:36:27 1994  Eric Youngdale  (eric@andante)
+
+       * mkisofs.h: Change rr_attributes to unsigned.
+
+       * rock.c: Ditto.  Work around >>32 bug in ultrix for 64 bit data types.
+
+       * mkisofs.c (usage): Fix for ultrix - use continuation lines
+       instead of assuming that strings are catenated by the compiler.
+
+Mon Jun 20 20:25:26 1994  Eric Youngdale  (eric@esp22)
+
+        * mkisofs.c, mkisofs.8, Makefile (version_string): Bump to pre-1.02.
+
+       * mkisofs.h: Fix declaration of e_malloc to use DECL macros.
+
+       * tree.c: Fix bug in previous change.
+
+       * diag/*.c: Add appropriate copyright notices.
+
+Sat Apr  9 13:30:46 1994  Eric Youngdale  (ericy@cais.com)
+
+        * Configure: New file - shell script that determines a bunch of
+       things to properly build mkisofs.
+
+       * Makefile.in: New file - copy of Makefile, but Configure sets a
+       few things up for it.
+
+       * tree.c: Do not depend upon opendir to return NULL if we cannot
+       open a directory - actually try and read the first entry.  The
+       foibles of NFS seem to require this.
+
+       * write.c: Fix definition of xfwrite (Use FDECL4)
+
+       Add some changes to allow more configurability of some of the
+       volume header fields:
+
+       * mkisofs.8: Document new configuration options.
+
+       * mkisofs.c: Add variables to hold new fields.  Add function to
+       read .mkisofsrc files.
+
+       * defaults.h: Another way of configuring the same things.
+
+       Add some changes from Leo Weppelman leo@ahwau.ahold.nl.
+
+       * mkisofs.c:  Allow -A to specify application ID.  Fix usage(),
+       getopt and add case switch.
+
+       * rock.c: Fix handling of device numbers (dev_t high should only
+       be used when sizeof(dev_t) > 32 bits).
+
+       Add a bunch of changes from Manuel Bouyer.
+
+       * diag/Makefile: New file.
+
+       * diag/dump.c, diag/isodump.c: Use termios if system supports it.
+
+       * (throughout): Replace all occurences of "malloc" with e_malloc.
+
+       * mkisofs.c:  For NetBSD, attempt to increase the rlimit for
+       the size of the data segment to about 33 Mb.
+
+       * mkisofs.c (e_malloc): New function.  Calls malloc, and prints
+       nice error message and exits if NULL is returned.
+
+Sun Jan 23 19:23:57 1994  Eric Youngdale  (eric@esp22)
+
+        * mkisofs.c, mkisofs.8, Makefile (version_string): Bump to 1.01.
+
+    Add a bunch of stuff so that mkisofs will work on a VMS system.
+
+       * (ALL): Change any direct use of the "st_ino" field from
+       the statbuf to use a macro.
+
+       * mkisofs.h: Define appropriate macros for both VMS and unix.
+
+       * (ALL): Add type casts whenever we use the UNCACHED_DEV macro.
+
+       * rock.c: Wrap a #ifndef VMS around block and character device
+       stuff.
+
+       * write.c: Add prototype for strdup if VMS is defined.
+
+       * make.com: Script for building mkisofs on a VMS system.
+
+       * Makefile: Include make.com in the distribution.
+
+       * mkisofs.c: Include <sys/type.h> on VMS systems.
+
+       * tree.c: Include <sys/file.h> and "vms.h" on VMS systems.
+
+       * mkisofs.h (PATH_SEPARATOR, SPATH_SEPARATOR):  New macros
+       that define the ascii character that separates the last directory
+       component from the filename.
+
+       * tree.c, mkisofs.c: Use them.
+
+       * vms.c: New file.  Contains version of getopt, strdup, opendir,
+       readdir and closedir.
+
+       * vms.h: New file.  Defines S_IS* macros.  Define gmtime as
+       localtime, since gmtime under VMS returns NULL.
+
+Sat Jan 15 13:57:42 1994  Eric Youngdale  (eric@esp22)
+
+       * mkisofs.h (transparent_compression): New prototype.
+
+       * mkisofs.c (transparent_compression): Declare, use
+       '-z' option to turn on.
+
+       * tree.c: Change TRANS.TBL;1 to TRANS.TBL (version gets
+       added later, if required).
+
+       * rock.c: If transparent compression requested, verify
+       file is really suitable (check magic numbers), and extract
+       correct file length to store in SUSP record.
+
+Sat Jan 15 01:57:42 1994  Eric Youngdale  (eric@esp22)
+
+       * write.c (compare_dirs): Bugfix for patch from Jan 6.
+
+       * mkisofs.h (struct directory_entry): Add element total_rr_attr_size.
+       (struct file_hash): Add element ce_bytes.
+
+       * write.c (iso_write): Update last_extent_written, as required,
+       and check it against last_extent as a sanity check.
+       (generate_one_directory): If ce_bytes is non-zero, allocate
+       a buffer and fill it with the CE records.  Also, update
+       the extent and offset entries in the CE SUSP field and
+       output after directory is written.
+       (assign_directory_addresses): Allow for CE sectors after each
+       directory.
+
+       * tree.c (sort_n_finish): Set field ce_bytes by summing
+       the sizes of all CE blocks in each files RR attributes.
+       Do not count these bytes for main directory.
+
+       * rock.c (generate_rock_ridge_attributes): Generate
+       CE entries to break up large records into manageable sizes.
+       Allow long names to be split, and allow long symlinks to be split.
+       Allow splitting before each SUSP field as well, to make
+       sure we do not screw outselves.
+
+Thu Jan  6 21:47:43 1994  Eric Youngdale  (eric@esp22)
+
+    Bugfix.
+
+       * write.c (compare_dirs): Only compare directory names up to
+       the ';' for the version number.
+
+    Add four new options: (1) Full 31 character filenames,
+    (2) Omit version number, (3) Omit trailing period from filenames,
+    (4) Skip deep directory relocation.
+
+       * iso9660.h: Allow 34 characters for filename.
+
+       * mkisofs.8: Update for new options.
+
+       * mkisofs.c: Add flag variables for new options.
+       Mention new options in usage(), tell getopt about
+       new options, and set appropriate flags when
+       new options are specified.
+
+       * mkisofs.c (iso9660_file_length): Implement new options.
+
+       * mkisofs.h: Declare flag variables for new options.
+
+       * tree.c (sort_n_finish): Increase declaration of newname and
+       rootname to 34 characters.  If full_iso9660_filenames in effect,
+       use different rules for making unique names.
+
+       * tree.c (scan_directory_tree): Use RR_relocation_depth instead of
+       constant for threshold for starting deep directory relocation.
+
+Wed Jan  5 01:32:34 1994  John Brezak (brezak@ch.hp.com)
+
+       * Makefile.bsd: New file.  For NetBSD.
+
+       * rock.c, tree.c: Do not include sys/sysmacros.h for NetBSD.
+
+Fri Dec 31 13:22:52 1993  Eric Youngdale  (eric@esp22)
+
+        * mkisofs.c, mkisofs.8, Makefile (version_string): Bump to 1.00.
+
+       * tree.c (scan_directory_tree): Handle case where we do not
+       have permissions to open a directory.
+
+       * write.c (xfwrite): New function - wrapper for fwrite,
+       except that we print message and punt if write fails.
+
+       * write.c: Move include of mkisofs.h and iso9660.h until after
+       string.h and stdlib.h is included.
+
+       * write.c: Do not attempt to use strerror on sun systems.
+
+Thu Dec 9  13:17:28 1993  R.-D. Marzusch (marzusch@odiehh.hanse.de)
+
+        * exclude.c, exclude.h: New files.  Contains list of files to
+       exclude from consideration.
+
+       * Makefile: Compile exclude.c, add dependencies to other files.
+
+       * mkisofs.8: Describe -x option.
+
+       * mkisofs.c: Include exclude.h, handle -x option.
+
+
+Fri Dec 10 01:07:43 1993  Peter van der Veen (peterv@qnx.com)
+       * mkisofs.c, mkisofs.h: Moved declaration of root_record.
+       * mkisofs.h: Added prototype for get_733().
+       * write.c(iso_write), tree.c, rock.c(generate_rock_ridge_attributes):
+       Added defines for QNX operation system
+       * rock.c(generate_rock_ridge_attributes): symbolic links should
+       not have CONTINUE component flag set unless there are multiple
+       component records, and mkisofs does not generate these.
+       st_ctime was stored as the creation time, changed to attribute time.
+       QNX has a creation time, so that is stored as well under QNX.
+Thu Oct 28 19:54:38 1993  Eric Youngdale  (eric@kafka)
+
+        * mkisofs.c, Makefile (version_string): Bump to 0.99.
+
+       * write.c(iso_write): Put hour, minute, second into date fields in
+       volume descriptor.
+
+       * write.c (iso_write): Set file_structure_version to 1, instead of
+       ' ' (Seems to screw up Macs).
+
+Sun Oct 17 01:13:36 1993  Eric Youngdale  (eric@kafka)
+
+        * mkisofs.c, Makefile (version_string): Bump to 0.98.
+
+    Increment nlink in root directory when rr_moved directory is present.
+
+        * tree.c (increment_nlink): New function.
+
+       * tree.c (finish_cl_pl_entries): Call increment_nlink for all
+       references to the root directory.
+
+       * tree.c (root_statbuf): New variable.
+
+       * tree.c (scan_directory_tree): Initialize root_statbuf when we
+       stat the root directory.
+
+       * tree.c (generate_reloc_directory): Use root_statbuf when
+       generating the Rock Ridge stuff for the ".." entry in the
+       reloc_dir.
+
+       * tree.c (scan_directory_tree): Use root_statbuf when generating
+       the ".." entry in the root directory.
+
+Sat Oct 16 10:28:30 1993  Eric Youngdale  (eric@kafka)
+
+    Fix path tables so that they are sorted.
+
+       * tree.c (assign_directory_addresses): Move to write.c
+
+       * write.c (generate_path_tables): Create an array of pointers to
+       the individual directories, and sort it based upon the name and
+       the parent path table index.  Then update all of the indexes and
+       repeat the sort until the path table indexes no longer need to be
+       changed, and then write the path table.
+
+    Fix problem where hard links were throwing off the total extent count.
+
+       * write.c (iso_write): Call assign_file_addresses, and then
+       use last_extent to determine how big the volume is.
+
+       * write.c (generate_one_directory): Decrement n_data_extents
+       for hard links to non-directories so that the expected number
+       of extents is written correctly.
+
+       * write.c(assign_file_addresses): New function.
+
+Fri Oct 15 22:35:43 1993  Eric Youngdale  (eric@kafka)
+
+    The standard says we should do these things:
+
+       * tree.c (generate_reloc_directory): Add RR attributes to
+       the rr_moved directory.
+
+       * mkisofs.c(main): Change ER text strings back to recommended
+       values.
+
+Tue Oct 12 21:07:38 1993  Eric Youngdale  (eric@kafka)
+
+        * mkisofs.c, Makefile (version_string): Bump to 0.97.  
+
+       * tree.c (scan_directory_tree): Do not insert PL entry into
+       root directory record (i.e. !parent)
+
+       * tree.c (finish_cl_pl_entries): Do not rely upon name
+       comparison to locate parent - use d_entry->self instead,
+       which is guaranteed to be correct.
+
+       * mkisofs.h: New variable n_data_extents.
+
+       * tree.c: Declare and initialize n_data_extents to 0.
+       (scan_directory_tree) for non-directories, add
+       ROUND_UP(statbuf.st_size) to n_data_extents.
+       (sort_n_finish): Increment n_data_extents for translation tables,
+       as appropriate.
+
+       * write.c(iso_write): Add n_data_extents to the
+       volume_space_size field.
+
+       * hash.c(add_hash): If size != 0 and extent == 0, or
+       if size == 0 and extent != 0, then complain about
+       inserting this into the hash table.  Kind of a sanity check.
+
+Sat Oct  9 16:39:15 1993  Eric Youngdale  (eric@kafka)
+
+        * mkisofs.c, Makefile (version_string): Bump to 0.96.  
+
+       Numerous bugfixes, thanks to a one-off disc from rab@cdrom.com.
+
+       * write.c(generate_one_directory): Wait until after we have
+       filled in the starting_extent field to s_entry before calling
+       add_hash.  This fixes a problem where the hash table gets an
+       extent of 0 for all regular files, and this turns up when you have
+       hard links on the disc. (The hash table allows us to have each
+       hard link point to the same extent on the cdrom, thereby saving
+       some space).
+
+       * tree.c(scan_directory_tree): Set statbuf.st_dev and
+       statbuf.st_ino to the UNCACHED numbers for symlinks that we
+       are not following.  This prevents the function find_hash from
+       returning an inode that cooresponds to the file the symlink points
+       to, which in turn prevents generate_one_directory from filling in
+       a bogus file length (should be zero for symlinks).
+
+       * tree.c(scan_directory_tree): Always call lstat for the file
+       so that non-RockRidge discs get correct treatment of symlinks.
+       Improve error message when we ignore a symlink on a non-RR disc.
+       
+       * write.c(generate_one_directory): Set fields for starting_extent
+       and size in the "." and ".." entries before we add them to the
+       file hash.  Fixes problems with incorrect backlinks for second
+       level directories.
+
+Wed Oct  6 19:53:40 1993  Eric Youngdale  (eric@kafka)
+
+       * write.c (write_one_file): Print message and punt if we are
+       unable to open the file.
+
+       * tree.c(scan_directory_tree): For regular files, use the access
+       function to verify that the file is readable in the first place.
+       If not, issue a warning and skip it.  For directories, it probably
+       does not matter, since we would not be able to descend into them
+       in the first place.
+
+Wed Sep 29 00:02:47 1993  Eric Youngdale  (eric@kafka)
+
+        * mkisofs.c, Makefile (version_string): Bump to 0.95.
+
+       * write.c, tree.c: Cosmetic changes to printed information.
+
+        * tree.c(scan_directory_tree): Set size to zero for
+       special stub entries that correspond to the
+       relocated directories.  Hopefully last big bug.
+
+       * mkisofs.h: Change TABLE_INODE, UNCACHED_* macros
+       to be 0x7fff... to be compatible with signed datatypes.
+
+Mon Sep 27 20:14:49 1993  Eric Youngdale  (eric@kafka)
+
+        * mkisofs.c, Makefile (version_string): Bump to 0.94.
+
+       * write.c (write_path_tables): Actually search the
+       directory for the matching entry in case we renamed
+       the directory because of a name conflict.
+
+       * tree.c(scan_directory_tree): Take directory_entry pointer
+       as second argument so that we can create a backpointer
+       in the directory structure that points back to the original
+       dir.
+
+       * mkisofs.c: Fix call to scan_directory_tree to use new calling
+       sequence.
+
+       * write.c(generate_one_directory): Punt if the last_extent counter
+       ever exceeds 700Mb/2048.  Print name of responsible file,
+       extent counter, and starting extent.  Perhaps we can catch it in
+       the act.
+
+Sun Sep 26 20:58:05 1993  Eric Youngdale  (eric@kafka)
+
+        * mkisofs.c, Makefile (version_string): Bump to 0.93.
+
+       * tree.c(scan_directory_tree): Handle symlinks better.  Either
+       leave them as symlinks, or erase any trace that they were a
+       symlink but do not do it 1/2 way as before.  Also, watch for
+       directory loops created with symlinks.
+
+       * mkisofs.h: Add new flag follow_links.
+
+       * mkisofs.c: Add command line switch "-f" to toggle follow_links.
+
+       * mkisofs.8: Document new switch.
+
+       * tree.c: Add code to handle symlinks using new flag.
+
+       * hash.c: Add add_directory_hash, find_directory_hash functions.
+
+       * mkisofs.h: Add prototypes.
+
+Sat Sep 25 14:26:31 1993  Eric Youngdale  (eric@kafka)
+
+        * mkisofs.c, Makefile (version_string): Bump to 0.92.
+
+       * mkisofs.c: Make sure path is an actual directory before trying
+       to scan it.
+
+       * mkisofs.h: Add DECL and FDECL? macros for sparc like systems.
+       Do proper define of optind and optarg under SVr4.
+
+       * tree.c: Change translation table name from YMTRANS.TBL to TRANS.TBL.
+
+       * mkisofs.c: Neaten up message in extension record when RRIP is
+       in use.
+
+       * Throughout - change all function declarations so that
+       traditional C compilers (i.e. sparc) will work.
+
+       * Makefile: Change to use system default C compiler.
+
+       * mkisofs.c: Add some stuff so that this will compile under VMS.
+       Many things missing for VMS still.
+
+       * iso9660.h: Do not use zero length array in struct definition.
+
+       * tree.c (sort_n_finish): Account for this.
+
+       * Change copyright notice.
+
+
+Wed Aug 25 08:06:51 1993  Eric Youngdale  (eric@kafka)
+
+        * mkisofs.c, Makefile (version_string): Bump to 0.91.
+
+       * mkisofs.h: Only  include sys/dir.h for linux.  Other systems
+       will need other things.
+
+       * mkisofs.c,  tree.c: Include unistd.h.
+
+       * Makefile:  Use OBJS to define list of object files.
+
+Sun Aug 22 20:55:17 1993  Eric Youngdale  (eric@kafka)
+
+        * mkisofs.c, Makefile (version_string): Bump to 0.9.
+
+       * write.c (iso_7*): Fix so that they work properly  on Motorola
+       systems. 
+
+Fri Aug 20 00:14:36 1993  Eric Youngdale  (eric@kafka)
+
+        * mkisofs.c, Makefile (version_string): Bump to 0.8.
+
+       * rock.c: Do not mask off write permissions from posix file modes.
+
+Wed Aug 18 09:02:12 1993  Eric Youngdale  (eric@kafka)
+
+        * mkisofs.c, Makefile (version_string): Bump to 0.7.
+
+        *  rock.c: Do not  write  NM field  for . and .. (redundant and a
+       waste of space).
+
+       * mkisofs.c: Take -P and -p options for publisher and preparer id
+       fields.
+
+       * write.c: Store  publisher and preparer id  in  volume
+       descriptor.
+
+       * rock.c: Write  optional  SP field to identify  SUSP.  Write
+       optional CE field to point to the extension header.
+
+       * tree.c: Request  SP and  CE fields be added to root directory.
+
+        * tree.c: Fix bug in name conflict resolution.
+
+        * write.c: Fill in date fields in the  colume descriptor.
+
+        * write.c (write_one_file): If the file is large enough, write  in
+       chunks of 16 sectors to improve performance.
+
+       * hash.c (add_hash, find_hash, etc): Do  not hash s_entry, instead
+       store relevant info in hash structure (we free s_entry  structs as
+       we write files, and we need to have access to the hash table  the
+       whole  way through.
+
+       * write.c: Add a few statistics about directory sizes, RR sizes,
+       translation table sizes, etc.
+
+       * tree.c: Use major, not MAJOR.  Same for minor.  Define S_ISSOCK
+       and S_ISLNK if not defined.
+
+       * rock.c: Define S_ISLNK if not defined.
+
+       * mkisofs.c: Print out max memory usage.  Fix bug in call to getopt.
+
+        * mkisofs.c, Makefile (version_string): Bump to 0.6.
+
+       * tree.c: Simplify the calculation of isorec.len,  isorec.name_len
+       and the calculation of the path table sizes by doing it all at
+       one point after  conflict resolution is done.
+
+       * tree.c: scan_directory_tree is now  responsible for generating
+       the line that goes into the YMTRANS.TBL file.  These lines are
+       collected later  on into something that will be dumped to the
+       file. Correctly handle all of the special file types.
+
+Mon Aug 16 21:59:47 1993  Eric Youngdale  (eric@kafka)
+
+        * mkisofs.c, Makefile (version_string): Bump to 0.5.
+
+       * mkisofs.c: Add -a option  (to force all files to be
+       transferred).  Remove find_file_hash stuff.
+
+       * write.c: Pad length even if Rock Ridge is not in use.
+
+       * hash.c: Rewrite hash_file_* stuff so that it  can be used to
+       easily  detect (and look up) filenames that have been  accepted
+       for use  in this directory.  Used for name collision detection.
+
+       * tree.c (sort_n_finish): If two names collide, generate a unique
+       one (verified with the hash routines).  Change the lower priority
+       name if there is a difference.
+
+
+
+Sat Aug 14 13:18:21 1993  Eric Youngdale  (eric@kafka)
+
+        * mkisofs.c, Makefile (version_string): Bump to 0.4.
+
+       * tree.c (load_translation_table): New  function - read
+       YMTRANS.TBL.  (scan_directory_tree) Call it.
+
+       * mkisofs.c (iso9660_file_length): Call find_file_hash to see
+       if translated name is specified.  If so, use it.
+
+       * hash.c (name_hash, add_file_hash, find_file_hash,
+       flush_file_hash): New functions for hashing stuff from
+       YMTRANS.TBL.
+
+       * mkisofs.h: Add a bunch of prototypes for the new functions.
+
+       * mkisofs.8: Update.
+
+        * mkisofs.c, Makefile (version_string): Bump to 0.3.
+
+        * Makefile: Add version number to tar file in dist target.
+
+       * mkisofs.c: Call finish_cl_pl_entries() after directories have
+       been generated, and extent numbers assigned.
+
+       * write.c (generate_one_directory): Update s_entry->size  for
+       directories (as well as isorec.size).
+
+       * rock.c:  Add  code to generate CL, PL, and RE entries.  The
+       extent numbers for the CL and PL  entries are  NULL, and these
+       are filled in  later once we know where they actually belong.
+
+       * mkisofs.h: Add parent_rec to directory_entry.  Used to fix CL/PL
+       stuff.
+
+       * tree.c (scan_directory_tree): Set  flag to generate  CL/PL/RE
+       entries  as required, update sizes as well.
+
+Fri Aug 13 19:49:30 1993  Eric Youngdale  (eric@kafka)
+
+        * mkisofs.c (version_string): Bump to 0.2.
+
+       * hash.c: Do not use entries with inode  == 0xffffffff or dev  ==
+       0xffff.
+
+       * write.c (write_path_tables):  Strip leading directory specifications.
+
+       * mkisofs.h: Add  definition for reloc_dir symbol.  Add prototype
+       for sort_n_finish, add  third parameter  to  scan_directory_tree
+       (for true parent, when directories are relocated).
+
+       * mkisofs.c (main): Modify call to scan_directory_tree.  Call
+       sort_n_finish for reloc_dir.
+
+       * tree.c (sort_n_finish): New function - moved code from
+       scan_directory_tree. 
+
+       * tree.c (generate_reloc_directory): New function.  Generate
+       directory to hold relocated directories.
+
+       * tree.c (scan_directory_tree): Strip leading directories when
+       generating this_dir->name.  If depth is  too great,  then move
+       directory to reloc_dir (creating if it does not exist, and leave
+       a dummy (non-directory) entry  in the regular directory  so that
+       we can eventually add the required Rock Ridge record.
+
+       * tree.c (scan_directory_tree): Use s_entry instead of sort_dir,
+       assign to this_dir->contents sooner.
+
+Thu Aug 12 22:38:17 1993  Eric Youngdale  (eric@kafka)
+
+       * mkisofs.c (usage): Fix syntax.
+
+       * mkisofs.c (main): Add new argument to scan_directory_tree
+
+       * tree.c (scan_directory_tree): If directory is at  depth 8 or
+       more, create rr_moved directory in main directory.
+
+Mon Jul 26 19:45:47 1993  Eric Youngdale  (eric@kafka)
+
+       * mkisofs v 0.1 released.
+
diff --git a/genisoimage/ChangeLog.mkhybrid b/genisoimage/ChangeLog.mkhybrid
new file mode 100644 (file)
index 0000000..e641d96
--- /dev/null
@@ -0,0 +1,482 @@
+Mon May  1 14:51:00 BST 2000  James Pearson <j.pearson@ge.ucl.ac.uk>
+
+       Version 1.13a01
+
+       mkhybrid has now been merged with, and is now part of mkisofs
+
+Wed Apr 26 10:18:44 BST 2000  James Pearson <j.pearson@ge.ucl.ac.uk>
+
+       Version 1.12.1a10
+
+       The -icon-position will now attempt to preserve folder window
+       positions, scroll bars, views etc. for Apple/Unix file formats
+       that support this information (currently CAP, EtherShare, Netatalk)
+
+       Added -root-info option - which works with the -icon-position
+       option to preserve the root folder window characteristics.
+       See README.rootinfo for more about this option.
+
+       Added 'mac-roman' to the -jcharset option. Converts Macintosh
+       Roman file name characters to the correct Joliet characters.
+
+Tue Apr 18 14:06:00 BST 2000  James Pearson <j.pearson@ge.ucl.ac.uk>
+
+       Version 1.12.1a07
+
+       HFS files/directories are made invisible (HFS_FNDR_ISINVISIBLE
+       flag set) if the ISO file/directory is hidden.
+
+Mon Apr  3 22:04:00 BST        2000  James Pearson <j.pearson@ge.ucl.ac.uk>
+
+       Version 1.12.1a05
+
+       Custom HFS volume or folder icons are now recoginised
+
+Sun Mar 19 19:12:00 GMT 2000  James Pearson <j.pearson@ge.ucl.ac.uk>
+
+       Version 1.12.1a03
+
+       New options -hfs-type & -hfs-creator
+
+Wed Mar  8 11:26:00 GMT 2000  James Pearson <j.pearson@ge.ucl.ac.uk>
+
+       Version 1.12
+
+       Final release of mkhybrid v1.12
+
+       mkhybrid will now be integrated with the cdrecord package (see:
+       ftp://ftp.fokus.gmd.de/pub/unix/cdrecord/alpha)
+
+       
+Wed Feb 23 14:35:20 GMT 2000  James Pearson <j.pearson@ge.ucl.ac.uk>
+
+       Version 1.12b6.0
+
+       Now based on mkisofs v1.12 available as part of the cdrecord
+       package from ftp://ftp.fokus.gmd.de/pub/unix/cdrecord/
+
+       Will now create an HFS volume of at least 800k in size.
+
+       Added option to preserve the HFS icon position (if it exists)
+       from a Apple/Unix file. Use -icon-position (Alpha)
+
+Thu Nov 25 19:59:27 GMT 1999  James Pearson <j.pearson@ge.ucl.ac.uk>
+
+       Version 1.12b5.4
+
+       Added partial support for Microsoft's "Services for Macintosh"
+       format files. See the man page for details.
+
+       mkhybrid no longer tries to work out the "disk cluster size"
+       for use with Apple File Exchange. The disk cluster size now needs
+       to be given on the command line (-cluster-size). The code involved
+       was not portable across various operating systems.
+
+       Added minor changes for Rhapsody and BeOS.
+
+       Cleaned up the code in apple.c (thanks to Ed Randall
+       <ed_randall@yahoo.com>).
+
+       mkhybrid will now create a valid HFS partition as the last session
+       on a multisession CD. (Alpha)
+
+Sun Aug  8 10:36:15 BST 1999  James Pearson <j.pearson@ge.ucl.ac.uk>
+
+       Version 1.12b5.3
+
+       Changed the nature of the -hfs and -apple command line options -
+       see README.mkhybrid for details
+
+       Added PReP boot option from Troy Benjegerdes - see README.prep_boot
+
+       Added support for AppleDouble/Single file names as "Pascal Strings"
+
+       Added checks for Joliet and Rock Ridge filename clashes.
+
+       Fixed minor install bug in Makefile.in
+
+Tue Apr 30 21:33:39 BST 1999  James Pearson <j.pearson@ge.ucl.ac.uk>
+
+       Version 1.12b5.2
+
+       Fixed bug where CREATOR/TYPE not padded with spaces if less
+       than 4 characters
+
+       Added support for "DAVE" format files (and AppleDouble v2)
+       use --dave
+
+       Fixed a small signed char bug in name.c
+
+       Fixed bug in diag/isoinfo.c - didn't support UCS level 1
+       filenames that mkisofs/mkhybrid now creates with the -J option.
+
+
+Thu Apr  7 20:29:04 BST 1999  James Pearson <j.pearson@ge.ucl.ac.uk>
+
+       Version 1.12b5.1
+
+       Fixed bugs with MacBinary names and symbolic links to HFS files
+       when using the -f option
+
+       Re-introduced some minor changes "lost" from v1.12b4.8
+
+       Forgot to add -hide-hfs-list option in previous version ...
+
+Tue Mar 30 08:31:13 BST 1999  James Pearson <j.pearson@ge.ucl.ac.uk>
+
+       Version 1.12b5.0
+
+       Now based on mkisofs v1.12b5
+
+       Option -mac-name now only uses the HFS name if the file is one
+       of the known HFS file types
+
+       Added -hide-list, -hide-joliet-list, -hide-hfs-list, -exclude-list
+       and -path-list options. Allows a list of filenames to be excluded or
+       hidden to be given in a file instead of on the command line.
+
+       Added option -hfs-volid to give the HFS volume its own name (not
+       using the ISO9660 volume name).
+       
+
+Tue Jan  5 15:44:24 GMT 1999  James Pearson <j.pearson@ge.ucl.ac.uk>
+
+       Version 1.12b4.8
+
+       Fixed an AppleDouble bug and added better support for more Unix
+       flavours.
+
+       Fixed -hide-hfs bug that corrupted some HFS hidden files
+
+       Made the verbose output less verbose.
+
+       Added initial support for the AutoStart feature.
+
+       HFS partition maps can now be added without having to create
+       a bootable HFS CD (as pre-v1.12a4.7).
+
+       Added option to specify the PC Exchange "cluster size".
+
+Mon Aug 24 23:18:38 BST 1998  James Pearson <j.pearson@ge.ucl.ac.uk>
+
+       Version 1.12a4.7
+
+       Fixed SGI/XINET and PC Exchange bugs
+
+       By default, the output image no longer has an HFS partition map
+       (as pre-v1.12a3.4). Partition maps are only added if making a
+       bootable HFS CD
+
+       Fixed possible bug with odd-length structure alignment with gcc on
+       some architectures
+
+Tue Aug  4 23:09:17 BST 1998  James Pearson <j.pearson@ge.ucl.ac.uk>
+
+       Version 1.12a4.6
+
+       Made a couple of Netatalk changes
+
+       Altered way Apple/Unix associated files are excluded - e.g.
+       if just --cap is selected, then files associated with the other
+       Apple/Unix encodings are processed as normal files. Previously they
+       would have been ignored
+
+       Added option (-no-desktop) to prevent the (empty) HFS desktop files
+       being created. These will be created when the CD is used on a
+       Macintosh (and stored in the System Folder).
+
+Sun Jul 26 09:44:50 BST 1998  James Pearson <j.pearson@ge.ucl.ac.uk>
+
+       Version 1.12a4.5
+
+       Fixed serious bug that could cause corrupt output when used with
+       the -J option
+
+Tue Jul 21 14:33:20 BST 1998  James Pearson <j.pearson@ge.ucl.ac.uk>
+
+       Version 1.12a4.4
+
+       HFS file/directory names that share the first 31 characters have
+       '_N' (N == decimal number) substituted for the last few characters
+       to generate unique names.
+
+       1 year since the first release ...
+
+Sat Jul 11 12:57:04 BST 1998  James Pearson <j.pearson@ge.ucl.ac.uk>
+
+       Version 1.12a4.3
+
+       Added options to "hide" (options -hide and -hide-joliet) files
+       or directories from the ISO9660/RockRidge and/or Joliet directory
+       trees.
+
+       Renamed the -hfs-exclude option to -hide-hfs to be compatible
+       with the above options.
+
+       Fixed a bug with the -hide-hfs option (very rare case ...)
+       
+Thu Jun 25 20:02:20 BST 1998  James Pearson <j.pearson@ge.ucl.ac.uk>
+
+       Version 1.12a4.2
+
+       Fixed an HFS bug introduced with v1.12a3.4 that created some
+       corrupt HFS volumes over about 400Mb
+
+       Tighten up checking for MacBinary files to prevent false matches
+
+Sun Jun 21 11:55:09 BST 1998  James Pearson <j.pearson@ge.ucl.ac.uk>
+
+       Version 1.12a4.1
+
+       Default TYPE and CREATOR can now be set via the .mkisofsrc file
+
+       Order of magic and mapping file on the command line is now
+       important. This defines the order in which TYPE and CREATOR are set.
+
+       Apple/Unix file types found are logged as part of the verbose output
+       (need to give -v twice)
+
+       Added option (-log-file) to redirect stderr messages
+
+       Added option (-hfs-exclude) to exclude files/directories from
+       the HFS part of the CD.
+
+       Fixed a couple of MacBinary/AppleSingle bugs.
+
+Thu Jun  8 23:40:56 BST 1998  James Pearson <j.pearson@ge.ucl.ac.uk>
+
+       Version 1.12a4.0
+
+       Resource fork file names not added to TRANS.TBL
+
+       Re-enabled support of non-regular Win32 files. GNU-Win32 can
+       create symbolic links etc. These are now recognised.
+
+       mkhybrid man page added.
+
+       Based on mkisofs v1.12b4
+
+Wed May 20 12:54:36 BST 1998  James Pearson <j.pearson@ge.ucl.ac.uk>
+
+       Version 1.12a3.5
+
+       Added support for using a "magic" file to set CREATOR/TYPE for
+       a file - see README.hfs_magic for details.
+
+Mon May 18 16:22:32 BST 1998  James Pearson <j.pearson@ge.ucl.ac.uk>
+
+       Version 1.12a3.4
+
+       Added possible support for bootable Mac CDs - see README.hfs_boot 
+       or details.
+
+       Fixed -x bug (mkisofs v1.12 bug)
+
+Mon May  4 14:23:46 BST 1998  James Pearson <j.pearson@ge.ucl.ac.uk>
+
+       Version 1.12a3.3
+
+       Added support for UShare Mac/Unix files
+
+       Individual Mac/Unix file types can now be selected instead
+       of searching for all possible types. See README.mkhybrid for
+       details.
+
+Fri May  1 10:34:29 BST 1998  James Pearson <j.pearson@ge.ucl.ac.uk>
+
+       Version 1.12a3.2
+
+       Various bug fixes to Mac file names
+
+Tue Mar 10 14:42:03 GMT 1998  James Pearson <j.pearson@ge.ucl.ac.uk>
+
+       Version 1.12a3.1
+
+       Added -no-hfs-files option that assumes there are no Unix/Mac
+       files (CAP, Netatalk, etc) - speeds up processing in these cases
+
+       Case insensitive HFS file/folder names that are the same are now
+       allowed - one or more '_' characters are added to one or more of
+       the filenames.
+
+       (Changed -macname option to -mac-name option)
+
+Mon Feb 23 16:09:27 GMT 1998  James Pearson <j.pearson@ge.ucl.ac.uk>
+
+       Version 1.12a3.0
+
+       Based on mkisofs v1.12b3
+
+       Fixed serious HFS bug that crept in from v1.11 -> v1.12
+
+Tue Feb 17 16:20:12 GMT 1998  James Pearson <j.pearson@ge.ucl.ac.uk>
+
+       Version 1.12a2.0
+
+       Based on mkisofs v1.12b2
+
+       Improved Win32 support: using -r now makes all files executable
+       when run under Win95/NT4
+       
+Tue Feb  3 10:30:18 GMT 1998  James Pearson <j.pearson@ge.ucl.ac.uk>
+
+       Version 1.12a1.2
+
+       Fixed memory bug when used without any HFS options
+
+       Improved PC Exchange support (although still needs testing)
+
+Tue Jan 27 10:32:26 GMT 1998  James Pearson <j.pearson@ge.ucl.ac.uk>
+
+       Version 1.12a1.1
+
+       Can now handle multiple hard linked source files with the -hfs option
+       (multiple hard linked source files are handled as separate files)
+
+       configure script changed to check for ranlib
+
+       Fixed a couple of AppleSingle bugs.
+
+       Added option to use Mac names as starting point for ISO9660, Joliet
+       and RockRidge names
+
+Wed Jan 21 14:00:56 GMT 1998  James Pearson <j.pearson@ge.ucl.ac.uk>
+
+       Version 1.12a1
+
+       See README.mkhybrid for details
+
+Fri Jan 16 17:09:48 GMT 1998  James Pearson <j.pearson@ge.ucl.ac.uk>
+
+       Version 1.11
+
+       Changed version numbering to be the same as mkisofs
+
+       Code no longer considered beta level
+
+       Minor changes to allow the code to be complied and run
+       on Win95/NT using Cygnus' GNU-Win32 (available from
+       http://www.cygnus.com/misc/gnu-win32/)
+       
+Thu Dec  4 17:17:45 GMT 1997  James Pearson <j.pearson@ge.ucl.ac.uk>
+
+       Version 0.49b
+
+       Fixed an HFS bug that caused a failure with directory names that
+       had special AUFS characters
+
+       Fixed mkisofs bug in eltorito.c that wrote warning messages
+       to stdout not stderr
+
+       Code no longer considered alpha level
+
+Thu Nov 27 19:00:02 GMT 1997  James Pearson <j.pearson@ge.ucl.ac.uk>
+
+       Version 0.48a
+
+       Added Apple's extensions to ISO9660 that can be used instead of
+       the HFS options (see README.mkhybrid for more details).
+
+       Added more verbose HFS error messages.
+
+       Changed the Joliet option flag to -J (-j still works) to be
+       compatible the with next release of mkisofs (v1.12)
+
+Wed Oct 15 11:16:21 BST 1997  James Pearson <j.pearson@ge.ucl.ac.uk>
+
+       Version 0.47a
+
+       Fixed bug that prevented volume_space_size not being set in the
+       PVD (or SVD)
+       
+Mon Oct  6 15:46:24 BST 1997  James Pearson <j.pearson@ps.ucl.ac.uk>
+
+       Version 0.46a
+
+       Small Joliet bug fix - source directories that are not readable
+       are set to empty ordinary files in the ISO9660 filesystem - this
+       is now true for the Joliet directory (partially responsible
+       for NT4 having problems with CDs where this happened)
+
+       Minor documentation updates.
+
+Mon Sep 15 14:15:11 BST 1997  James Pearson <j.pearson@ps.ucl.ac.uk>
+
+       Version 0.45a
+
+       Attempt to prevent the HFS Catalog file growing (see
+       "Implementation" in README.mkhybrid for more details)
+       This is only likely to be a problem where folders have lots
+       of small files.
+
+Mon Aug 18 12:00:24 BST 1997  James Pearson <j.pearson@ps.ucl.ac.uk>
+
+       Version 0.44a
+
+       If the directories were deeper than 8 and the -D flag was not
+       used, then the "rr_moved" directory was not added to the Joliet
+       directory tree. This has now been fixed - but one day, the deep
+       Joliet directories may not have to be relocated ...
+
+       Fixed memcmp problem with possible uninitialised memory in
+       j_compare_paths(), which *might* cause incorrect Joliet directory
+       sort order
+
+Wed Aug 13 14:58:56 BST 1997  James Pearson <j.pearson@ps.ucl.ac.uk>
+
+       Version 0.43a
+
+       Fixed bug for incorrect Joliet path table size
+
+       Fixed some old minor mkisofs bugs (TRANS.TBL not having a
+       version number by default and incorrect date in the PVD).
+
+Mon Aug 11 17:17:07 BST 1997  James Pearson <j.pearson@ps.ucl.ac.uk>
+
+       Version 0.42a
+
+       Now will not try to create the HFS "Desktop DB" and "Desktop DF"
+       if they already exist when used with the HFS options.
+
+       Fixed a serious bug in the hfs code that truncated some files.
+
+       "TRANS.TBL" was missed out of the Joliet directory if the -T
+       option was given (previously an empty file with no name was used
+       which could cause problems on NT 4)
+
+Fri Aug  8 10:19:46 BST 1997  James Pearson <j.pearson@ps.ucl.ac.uk>
+
+       Version 0.41a
+
+       Fixed bug which created invalid HFS/ISO9660 volumes if the -j (Joliet)
+       option was not used
+
+Mon Aug  4 15:08:43 BST 1997  James Pearson <j.pearson@ps.ucl.ac.uk>
+
+       Version 0.4a
+
+       Added (partial?) Joliet support.
+
+       Now based on mkisofs v1.11
+
+Tue Jul 29 11:57:14 BST 1997  James Pearson <j.pearson@ps.ucl.ac.uk>
+
+       Version 0.32a
+
+       Allocation sizes improved to cut down on wasted space. Now uses
+       the HFS "allocation" size rounded up to the nearest 2048 bytes.
+       Savings can be significant with a large volume containing lots
+       of smallish files.
+
+Wed Jul 23 15:36:08 BST 1997  James Pearson <j.pearson@ps.ucl.ac.uk>
+
+       Version 0.31a
+
+       Deep directories (greater than RR_relocation_depth) cause core
+       dump in "copy_to_mac_volume" as the relocated directory was not
+       marked as an HFS folder. Fixed by putting deep HFS folders in
+       their correct location. 
+
+Mon Jul 21 15:50:05 BST 1997  James Pearson <j.pearson@ps.ucl.ac.uk>
+
+       Version 0.3a, first public release.
diff --git a/genisoimage/RELEASE b/genisoimage/RELEASE
new file mode 100644 (file)
index 0000000..c547f6e
--- /dev/null
@@ -0,0 +1,3 @@
+# @(#)RELEASE  1.35 04/09/09 joerg
+
+Release 2.01
diff --git a/genisoimage/TODO b/genisoimage/TODO
new file mode 100644 (file)
index 0000000..cce3b24
--- /dev/null
@@ -0,0 +1,57 @@
+/* @(#)TODO    1.6 03/04/27 joerg */
+       1) Finish multiple paths.  Update nlink count on directories if it is
+       different than what stat returned.  Save the nlink count that we store in
+       the rock ridge attributes so know when we don't have to adjust it.
+
+
+Andy Polyakov <appro@fy.chalmers.se>
+Well, it was rather hard to get it wrong... But the answer is "yes" if
+you have to hear this very word.
+
+And while we're discussing this code. A *cosmetic* *suggestion*.
+Consider modifying two lines above the "if(is_directory)" as following:
+
+        set32(&fe->uid,0);
+        set32(&fe->gid,0);
+
+or to any other small number. Problem is that with -1 as now 'ls -l'
+results in wider output which is rather annoying (it has to print
+4294967295 twice while it formats for 8 chars).
+
+Cheers. A.
+
+/*--------------------------------------------------------------------------*/
+
+Option to modify Volume id, ... in PVD after the image has been
+created?
+
+/*--------------------------------------------------------------------------*/
+http://www.y-adagio.com/public/standards/iso_cdromr/tocont.htm
+
+Annex B has:
+
+Changes from ISO 9660:1988 to this International Standard:
+
+a) The Volume Descriptor Version is changed to indicate the new structure; 
+     Version number 2 indicated the new specification. 
+b) The File Structure Version is changed to indicate the new structure; 
+     Version number 2 indicated the new specification. 
+c) The limitation in the Depth of Hierarchy is lifted; 
+     The levels in the hierarchy can exceed eight. 
+d) The File Identifier is not separated to components; 
+     The SEPARATORS are not specified.
+     A complex file name can be expressed. 
+e) The File Identifier does not have File Version Numbers; 
+     File with and without Version Numbers should not exist in the same directory. 
+f) The character used for filling byte positions which are specified to be characters is subject to agreement
+between the originator and the recipient of the volume; 
+g) The length of File Identifier is limited to 207; 
+     Long file name can be expressed. 
+h) The length of a Directory Identifier is limited to 207; 
+     Long directory name can be expressed. 
+/*--------------------------------------------------------------------------*/
+
+Extent # auch als off_t statt int
+
+Wenn HFS, dann max File size == 2 GB?
+
diff --git a/genisoimage/apple.c b/genisoimage/apple.c
new file mode 100644 (file)
index 0000000..3939504
--- /dev/null
@@ -0,0 +1,2688 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)apple.c 1.19 04/03/02 joerg, Copyright 1997, 1998, 1999, 2000 James Pearson */
+/*
+ *      Copyright (c) 1997, 1998, 1999, 2000 James Pearson
+ *
+ * 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; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ *     Unix-HFS file interface including maping file extensions to TYPE/CREATOR
+ *
+ *     Adapted from mkhfs routines for mkhybrid
+ *
+ *     James Pearson 1/5/97
+ *     Bug fix JCP 4/12/97
+ *     Updated for 1.12 and added more Unix HFS filetypes. JCP 21/1/98
+ *     Tidy up to use Finfo and Dinfo for all formats where
+ *             possible JCP 25/4/2000
+ *
+ *     Things still to de done:
+ *
+ *             Check file size = finder + rsrc [+ data] is needed
+ */
+
+#ifdef APPLE_HYB
+
+#include <mconfig.h>
+#include "genisoimage.h"
+#include <errno.h>
+#include <fctldefs.h>
+#include <utypes.h>
+#include <ctype.h>
+#include <netinet/in.h>
+#include "apple.h"
+#include <schily.h>
+
+#ifdef USE_MAGIC
+#include <magic.h>
+magic_t magic_state = NULL;
+#ifndef MAGIC_ERROR
+/* workaround for older Â´API */
+#define MAGIC_ERROR 0
+#endif
+#endif /* USE_MAGIC */
+
+/* tidy up genisoimage definition ... */
+typedef struct directory_entry dir_ent;
+
+/* routines for getting HFS names and info */
+#ifndef        HAVE_STRCASECMP
+static int     strcasecmp(const char *s1, const char *s2);
+#endif
+static int     get_none_dir(char *, char *, dir_ent *, int);
+static int     get_none_info(char *, char *, dir_ent *, int);
+static int     get_cap_dir(char *, char *, dir_ent *, int);
+static int     get_cap_info(char *, char *, dir_ent *, int);
+static int     get_es_dir(char *, char *, dir_ent *, int);
+static int     get_es_info(char *, char *, dir_ent *, int);
+static int     get_dbl_dir(char *, char *, dir_ent *, int);
+static int     get_dbl_info(char *, char *, dir_ent *, int);
+static int     get_mb_info(char *, char *, dir_ent *, int);
+static int     get_sgl_info(char *, char *, dir_ent *, int);
+static int     get_fe_dir(char *, char *, dir_ent *, int);
+static int     get_fe_info(char *, char *, dir_ent *, int);
+static int     get_sgi_dir(char *, char *, dir_ent *, int);
+static int     get_sgi_info(char *, char *, dir_ent *, int);
+static int     get_sfm_info(char *, char *, dir_ent *, int);
+
+#ifdef IS_MACOS_X
+static int     get_xhfs_dir(char *, char *, dir_ent *, int);
+static int     get_xhfs_info(char *, char *, dir_ent *, int);
+#else
+#define        get_xhfs_dir    get_none_dir
+#define        get_xhfs_info   get_none_info
+#endif /* IS_MACOS_X */
+
+static void    set_ct(hfsdirent *, char *, char *);
+static void    set_Dinfo(byte *, hfsdirent *);
+static void    set_Finfo(byte *, hfsdirent *);
+static void    cstrncpy(char *, char *, int);
+static unsigned char dehex(char);
+static unsigned char hex2char(char *);
+static void    hstrncpy(unsigned char *, char *, int);
+static int     read_info_file(char *, void *, int);
+
+/*static unsigned short        calc_mb_crc     __PR((unsigned char *, long, unsigned short));*/
+static struct hfs_info *get_hfs_fe_info(struct hfs_info *, char *);
+static struct hfs_info *get_hfs_sgi_info(struct hfs_info *, char *);
+static struct hfs_info *match_key(struct hfs_info *, char *);
+
+static int     get_hfs_itype(char *, char *, char *);
+static void    map_ext(char *, char **, char **, short *, char *);
+
+static afpmap  **map;          /* list of mappings */
+static afpmap  *defmap;        /* the default mapping */
+static int     last_ent;       /* previous mapped entry */
+static int     map_num;        /* number of mappings */
+static int     mlen;           /* min extension length */
+static char    tmp[PATH_MAX];  /* tmp working buffer */
+static int     hfs_num;        /* number of file types */
+static char    p_buf[PATH_MAX]; /* info working buffer */
+static FILE    *p_fp = NULL;   /* probe File pointer */
+static int     p_num = 0;      /* probe bytes read */
+static unsigned        int hselect;    /* type of HFS file selected */
+
+struct hfs_type {      /* Types of various HFS Unix files */
+       int     type;   /* type of file */
+       int     flags;  /* special flags */
+       char    *info;  /* finderinfo name */
+       char    *rsrc;  /* resource fork name */
+       int     (*get_info)(char *, char *, dir_ent *, int); /* finderinfo */
+                                                                   /*  function */
+       int     (*get_dir)(char *, char *, dir_ent *, int);  /* directory */
+                                                                   /* name */
+                                                                   /* function */
+       char    *desc;  /* description */
+};
+
+/* Above filled in */
+static struct hfs_type hfs_types[] = {
+       {TYPE_NONE, INSERT, "", "", get_none_info, get_none_dir, "None"},
+       {TYPE_CAP, INSERT, ".finderinfo/", ".resource/",
+                               get_cap_info, get_cap_dir, "CAP"},
+       {TYPE_NETA, INSERT, ".AppleDouble/", ".AppleDouble/",
+                               get_dbl_info, get_dbl_dir, "Netatalk"},
+       {TYPE_DBL, INSERT, "%", "%", get_dbl_info, get_dbl_dir, "AppleDouble"},
+       {TYPE_ESH, INSERT, ".rsrc/", ".rsrc/",
+                               get_es_info, get_es_dir, "EtherShare/UShare"},
+       {TYPE_FEU, NOPEND, "FINDER.DAT", "RESOURCE.FRK/",
+                               get_fe_info, get_fe_dir, "Exchange"},
+       {TYPE_FEL, NOPEND, "finder.dat", "resource.frk/",
+                               get_fe_info, get_fe_dir, "Exchange"},
+       {TYPE_SGI, NOPEND, ".HSancillary", ".HSResource/",
+                               get_sgi_info, get_sgi_dir, "XINET/SGI"},
+       {TYPE_MBIN, PROBE, "", "", get_mb_info, get_none_dir, "MacBinary"},
+       {TYPE_SGL, PROBE, "", "", get_sgl_info, get_none_dir, "AppleSingle"},
+       {TYPE_DAVE, INSERT, "resource.frk/", "resource.frk/",
+                               get_dbl_info, get_dbl_dir, "DAVE"},
+       {TYPE_SFM, APPEND | NORSRC, ":Afp_AfpInfo", ":Afp_Resource",
+                               get_sfm_info, get_none_dir, "SFM"},
+       {TYPE_XDBL, INSERT, "._", "._", get_dbl_info, get_dbl_dir,
+                               "MacOS X AppleDouble"},
+       {TYPE_XHFS, APPEND | NOINFO, "/rsrc", "/rsrc", get_xhfs_info, get_xhfs_dir,
+                               "MacOS X HFS"}
+};
+
+/* used by get_magic_match() return */
+static char    tmp_type[CT_SIZE + 1],
+               tmp_creator[CT_SIZE + 1];
+
+#ifdef __used__
+/*
+ *     An array useful for CRC calculations that use 0x1021 as the "seed"
+ *     taken from mcvert.c modified by Jim Van Verth.
+ */
+
+static unsigned short mb_magic[] = {
+       0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
+       0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
+       0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
+       0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
+       0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
+       0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
+       0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
+       0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
+       0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
+       0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
+       0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
+       0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
+       0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
+       0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
+       0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
+       0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
+       0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
+       0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
+       0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
+       0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
+       0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
+       0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
+       0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
+       0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
+       0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
+       0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
+       0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
+       0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
+       0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
+       0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
+       0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
+       0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
+};
+
+#endif /* __used__ */
+
+#ifndef        HAVE_STRCASECMP
+static int
+strcasecmp(const char *s1, const char *s2)
+{
+       while (tolower(*s1) == tolower(*s2)) {
+               if (*s1 == 0)
+                       return (0);
+               s1++;
+               s2++;
+       }
+       return (tolower(*s1) - tolower(*s2));
+}
+#endif
+
+/*
+ *     set_ct: set CREATOR and TYPE in hfs_ent
+ *
+ *     CREATOR and TYPE are padded with spaces if not CT_SIZE long
+ */
+
+static void
+set_ct(hfsdirent *hfs_ent, char *c, char *t)
+{
+       memset(hfs_ent->u.file.type, ' ', CT_SIZE);
+       memset(hfs_ent->u.file.creator, ' ', CT_SIZE);
+
+       strncpy(hfs_ent->u.file.type, t, MIN(CT_SIZE, strlen(t)));
+       strncpy(hfs_ent->u.file.creator, c, MIN(CT_SIZE, strlen(c)));
+
+       hfs_ent->u.file.type[CT_SIZE] = '\0';
+       hfs_ent->u.file.creator[CT_SIZE] = '\0';
+}
+
+/*
+ *     cstrncopy: Cap Unix name to HFS name
+ *
+ *     ':' is replaced by '%' and string is terminated with '\0'
+ */
+static void
+cstrncpy(char *t, char *f, int c)
+{
+       while (c-- && *f) {
+               switch (*f) {
+               case ':':
+                       *t = '%';
+                       break;
+               default:
+                       *t = *f;
+                       break;
+               }
+               t++;
+               f++;
+       }
+
+       *t = '\0';
+}
+
+/*
+ * dehex()
+ *
+ * Given a hexadecimal digit in ASCII, return the integer representation.
+ *
+ *     Taken from linux/fs/hfs/trans.c by Paul H. Hargrove
+ */
+static unsigned char
+dehex(char c)
+{
+       if ((c >= '0') && (c <= '9')) {
+               return (c - '0');
+       }
+       if ((c >= 'a') && (c <= 'f')) {
+               return (c - 'a' + 10);
+       }
+       if ((c >= 'A') && (c <= 'F')) {
+               return (c - 'A' + 10);
+       }
+/*     return (0xff); */
+       return (0);
+}
+
+static unsigned char
+hex2char(char *s)
+{
+       unsigned char   i1;
+       unsigned char   i2;
+       unsigned char   o;
+
+       if (strlen(++s) < 2)
+               return (0);
+
+       i1 = (unsigned char) s[0];
+       i2 = (unsigned char) s[1];
+
+       if (!isxdigit(i1) || !isxdigit(i2))
+               return (0);
+
+       o = (dehex(i1) << 4) & 0xf0;
+       o |= (dehex(i2) & 0xf);
+
+       return (o);
+}
+
+
+/*
+ *     hstrncpy: Unix name to HFS name with special character
+ *     translation.
+ *
+ *     "%xx" or ":xx" is assumed to be a "special" character and
+ *     replaced by character code given by the hex characters "xx"
+ *
+ *     if "xx" is not a hex number, then it is left alone - except
+ *     that ":" is replaced by "%"
+ *
+ */
+static void
+hstrncpy(unsigned char *t, char *f, int c)
+{
+       unsigned char   o;
+
+       while (c-- && *f) {
+               switch (*f) {
+               case ':':
+               case '%':
+                       if ((o = hex2char(f)) == 0) {
+                               *t = conv_charset('%', in_nls, hfs_onls);
+                       } else {
+                               *t = o;
+                               f += 2;
+                       }
+                       break;
+               default:
+                       *t = conv_charset(*f, in_nls, hfs_onls);
+                       break;
+               }
+               t++;
+               f++;
+       }
+
+       *t = '\0';
+}
+
+/*
+ *     basename: find just the filename with any directory component
+ */
+/*
+       not used at the moment ...
+static char
+basename(a)
+       char    *a;
+{
+       char    *b;
+
+       if ((b = strchr(a, '/')))
+               return (++b);
+       else
+               return (a);
+}
+*/
+
+/*
+ *     set_Dinfo: set directory info
+ */
+static void
+set_Dinfo(byte *ptr, hfsdirent *ent)
+{
+       Dinfo   *dinfo = (Dinfo *)ptr;
+
+       /* finder flags */
+       ent->fdflags = d_getw((unsigned char *) dinfo->frFlags);
+
+       if (icon_pos) {
+               ent->u.dir.rect.top =
+               d_getw((unsigned char *) dinfo->frRect[0]);
+               ent->u.dir.rect.left =
+               d_getw((unsigned char *) dinfo->frRect[1]);
+               ent->u.dir.rect.bottom =
+               d_getw((unsigned char *) dinfo->frRect[2]);
+               ent->u.dir.rect.right =
+               d_getw((unsigned char *) dinfo->frRect[3]);
+
+               ent->fdlocation.v =
+               d_getw((unsigned char *) dinfo->frLocation[0]);
+               ent->fdlocation.h =
+               d_getw((unsigned char *) dinfo->frLocation[1]);
+
+               ent->u.dir.view =
+               d_getw((unsigned char *) dinfo->frView);
+
+               ent->u.dir.frscroll.v =
+               d_getw((unsigned char *) dinfo->frScroll[0]);
+               ent->u.dir.frscroll.h =
+               d_getw((unsigned char *) dinfo->frScroll[1]);
+
+       } else {
+               /*
+                * clear HFS_FNDR_HASBEENINITED to have tidy desktop ??
+                */
+               ent->fdflags &= 0xfeff;
+       }
+}
+
+/*
+ *     set_Finfo: set file info
+ */
+static void
+set_Finfo(byte *ptr, hfsdirent *ent)
+{
+       Finfo   *finfo = (Finfo *)ptr;
+
+       /* type and creator from finder info */
+       set_ct(ent, finfo->fdCreator, finfo->fdType);
+
+       /* finder flags */
+       ent->fdflags = d_getw((unsigned char *) finfo->fdFlags);
+
+       if (icon_pos) {
+               ent->fdlocation.v =
+               d_getw((unsigned char *) finfo->fdLocation[0]);
+               ent->fdlocation.h =
+               d_getw((unsigned char *) finfo->fdLocation[1]);
+       } else {
+               /*
+                * clear HFS_FNDR_HASBEENINITED to have tidy desktop ??
+                */
+               ent->fdflags &= 0xfeff;
+       }
+}
+
+/*
+ *     get_none_dir: ordinary Unix directory
+ */
+static int
+get_none_dir(char *hname, char *dname, dir_ent *s_entry, int ret)
+{
+       /* just copy the given name */
+       hstrncpy((unsigned char *) (s_entry->hfs_ent->name),
+                                                       dname, HFS_MAX_FLEN);
+
+       return (ret);
+}
+
+/*
+ *     get_none_info: ordinary Unix file - try to map extension
+ */
+static int
+get_none_info(char *hname, char *dname, dir_ent *s_entry, int ret)
+{
+       char            *t,
+                       *c;
+       hfsdirent       *hfs_ent = s_entry->hfs_ent;
+
+       map_ext(dname, &t, &c, &s_entry->hfs_ent->fdflags, s_entry->whole_name);
+
+       /* just copy the given name */
+       hstrncpy((unsigned char *) (hfs_ent->name), dname, HFS_MAX_FLEN);
+
+       set_ct(hfs_ent, c, t);
+
+       return (ret);
+}
+
+/*
+ *     read_info_file: open and read a finderinfo file for an HFS file
+ *                     or directory
+ */
+static int
+read_info_file(char *name, /* finderinfo filename */
+                                       void *info, /* info buffer */
+                                       int len         /* length of above */)
+{
+       FILE            *fp;
+       int             num;
+
+       /* clear out any old finderinfo stuf */
+       memset(info, 0, len);
+
+       if ((fp = fopen(name, "rb")) == NULL)
+               return (-1);
+
+       /* read and ignore if the file is short - checked later */
+       num = fread(info, 1, len, fp);
+
+       fclose(fp);
+
+       return (num);
+}
+
+/*
+ *     get_cap_dir: get the CAP name for a directory
+ */
+static int
+get_cap_dir(char *hname, /* whole path */ 
+                               char *dname, /* this dir name */
+                               dir_ent *s_entry, /* directory entry */ 
+                               int ret)
+{
+       FileInfo        info;           /* finderinfo struct */
+       int             num = -1;       /* bytes read */
+       hfsdirent       *hfs_ent = s_entry->hfs_ent;
+
+       num = read_info_file(hname, &info, sizeof (FileInfo));
+
+       /* check finder info is OK */
+       if (num > 0 &&
+               info.fi_magic1 == FI_MAGIC1 &&
+               info.fi_magic == FI_MAGIC &&
+               info.fi_bitmap & FI_BM_MACINTOSHFILENAME) {
+               /* use the finderinfo name if it exists */
+               cstrncpy((char *) (hfs_ent->name),
+                               (char *) (info.fi_macfilename), HFS_MAX_FLEN);
+
+               set_Dinfo(info.finderinfo, hfs_ent);
+
+               return (ret);
+       } else {
+               /* otherwise give it it's Unix name */
+               hstrncpy((unsigned char *) (s_entry->hfs_ent->name),
+                                                       dname, HFS_MAX_FLEN);
+               return (TYPE_NONE);
+       }
+}
+
+/*
+**     get_cap_info:   get CAP finderinfo for a file
+*/
+static int
+get_cap_info(char *hname, /* whole path */
+                                char *dname, /* this dir name */
+                                dir_ent *s_entry, /* directory entry */
+                                int ret)
+{
+       FileInfo        info;           /* finderinfo struct */
+       int             num = -1;       /* bytes read */
+       hfsdirent       *hfs_ent = s_entry->hfs_ent;
+
+       num = read_info_file(hname, &info, sizeof (info));
+
+       /* check finder info is OK */
+       if (num > 0 &&
+               info.fi_magic1 == FI_MAGIC1 &&
+               info.fi_magic == FI_MAGIC) {
+
+               if (info.fi_bitmap & FI_BM_MACINTOSHFILENAME) {
+                       /* use the finderinfo name if it exists */
+                       cstrncpy((char *) (hfs_ent->name),
+                               (char *) (info.fi_macfilename), HFS_MAX_FLEN);
+               } else {
+                       /* use Unix name */
+                       hstrncpy((unsigned char *) (hfs_ent->name), dname,
+                                                               HFS_MAX_FLEN);
+               }
+
+               set_Finfo(info.finderinfo, hfs_ent);
+#ifdef USE_MAC_DATES
+               /*
+                * set created/modified dates - these date should have already
+                * been set from the Unix data fork dates. The finderinfo dates
+                * are in Mac format - but we have to convert them back to Unix
+                * for the time being
+                */
+               if ((info.fi_datemagic & FI_CDATE)) {
+                       /* use libhfs routines to get correct byte order */
+                       hfs_ent->crdate = d_toutime(d_getl(info.fi_ctime));
+               }
+               if (info.fi_datemagic & FI_MDATE) {
+                       hfs_ent->mddate = d_toutime(d_getl(info.fi_mtime));
+               }
+#endif /* USE_MAC_DATES */
+       } else {
+               /* failed to open/read finderinfo - so try afpfile mapping */
+               if (verbose > 2) {
+                       fprintf(stderr,
+                               "warning: %s doesn't appear to be a %s file\n",
+                               s_entry->whole_name, hfs_types[ret].desc);
+               }
+               ret = get_none_info(hname, dname, s_entry, TYPE_NONE);
+       }
+
+       return (ret);
+}
+
+/*
+ *     get_es_dir:     get EtherShare/UShare finderinfo for a directory
+ *
+ *     based on code from Jens-Uwe Mager (jum@helios.de) and Phil Sylvester
+ *     <psylvstr@interaccess.com>
+ */
+static int
+get_es_dir(char *hname, /* whole path */ 
+                         char *dname, /* this dir name */
+                         dir_ent *s_entry, /* directory entry */
+                         int ret)
+{
+       es_FileInfo     *einfo;         /* EtherShare info struct */
+       us_FileInfo     *uinfo;         /* UShare info struct */
+       char            info[ES_INFO_SIZE];     /* finderinfo buffer */
+       int             num = -1;       /* bytes read */
+       hfsdirent       *hfs_ent = s_entry->hfs_ent;
+
+       /*
+        * the EtherShare and UShare file layout is the same, but they store
+        * finderinfo differently
+        */
+       einfo = (es_FileInfo *) info;
+       uinfo = (us_FileInfo *) info;
+
+       num = read_info_file(hname, info, sizeof (info));
+
+       /* check finder info for EtherShare finderinfo */
+       if (num >= (int)sizeof (es_FileInfo) &&
+               d_getl(einfo->magic) == ES_MAGIC &&
+               d_getw(einfo->version) == ES_VERSION) {
+
+               set_Dinfo(einfo->finderinfo, hfs_ent);
+
+       } else if (num >= (int)sizeof (us_FileInfo)) {
+               /*
+                * UShare has no magic number, so we assume that this is a valid
+                * info/resource file ...
+                */
+
+               set_Dinfo(uinfo->finderinfo, hfs_ent);
+
+       } else {
+               /* failed to open/read finderinfo - so try afpfile mapping */
+               if (verbose > 2) {
+                       fprintf(stderr,
+                               "warning: %s doesn't appear to be a %s file\n",
+                               s_entry->whole_name, hfs_types[ret].desc);
+               }
+               ret = get_none_dir(hname, dname, s_entry, TYPE_NONE);
+               return (ret);
+       }
+
+       /* set name */
+       hstrncpy((unsigned char *) (hfs_ent->name), dname, HFS_MAX_FLEN);
+
+       return (ret);
+}
+
+/*
+ *     get_es_info:    get EtherShare/UShare finderinfo for a file
+ *
+ *     based on code from Jens-Uwe Mager (jum@helios.de) and Phil Sylvester
+ *     <psylvstr@interaccess.com>
+ */
+static int
+get_es_info(char *hname, /* whole path */
+                               char *dname, /* this dir name */
+                               dir_ent *s_entry, /* directory entry */
+                               int ret)
+{
+       es_FileInfo     *einfo;         /* EtherShare info struct */
+       us_FileInfo     *uinfo;         /* UShare info struct */
+       char            info[ES_INFO_SIZE];     /* finderinfo buffer */
+       int             num = -1;       /* bytes read */
+       hfsdirent       *hfs_ent = s_entry->hfs_ent;
+       dir_ent         *s_entry1;
+
+       /*
+        * the EtherShare and UShare file layout is the same, but they store
+        * finderinfo differently
+        */
+       einfo = (es_FileInfo *) info;
+       uinfo = (us_FileInfo *) info;
+
+       num = read_info_file(hname, info, sizeof (info));
+
+       /* check finder info for EtherShare finderinfo */
+       if (num >= (int)sizeof (es_FileInfo) &&
+               d_getl(einfo->magic) == ES_MAGIC &&
+               d_getw(einfo->version) == ES_VERSION) {
+
+               set_Finfo(einfo->finderinfo, hfs_ent);
+
+               /*
+                * set create date - modified date set from the Unix
+                * data fork date
+                */
+
+               hfs_ent->crdate = d_getl(einfo->createTime);
+
+       } else if (num >= (int)sizeof (us_FileInfo)) {
+               /*
+                * UShare has no magic number, so we assume that this is a valid
+                * info/resource file ...
+                */
+
+               set_Finfo(uinfo->finderinfo, hfs_ent);
+
+               /* set create and modified date - if they exist */
+               if (uinfo->ctime)
+                       hfs_ent->crdate =
+                               d_getl(uinfo->ctime);
+
+               if (uinfo->mtime)
+                       hfs_ent->mddate =
+                               d_getl(uinfo->mtime);
+       } else {
+               /* failed to open/read finderinfo - so try afpfile mapping */
+               if (verbose > 2) {
+                       fprintf(stderr,
+                               "warning: %s doesn't appear to be a %s file\n",
+                               s_entry->whole_name, hfs_types[ret].desc);
+               }
+               ret = get_none_info(hname, dname, s_entry, TYPE_NONE);
+               return (ret);
+       }
+
+       /* this should exist ... */
+       if ((s_entry1 = s_entry->assoc) == NULL)
+               perr("TYPE_ESH error - shouldn't happen!");
+
+       /* set name */
+       hstrncpy((unsigned char *) (hfs_ent->name), dname, HFS_MAX_FLEN);
+
+       /* real rsrc file starts ES_INFO_SIZE bytes into the file */
+       if (s_entry1->size <= ES_INFO_SIZE) {
+               s_entry1->size = 0;
+               hfs_ent->u.file.rsize = 0;
+       } else {
+               s_entry1->size -= ES_INFO_SIZE;
+               hfs_ent->u.file.rsize = s_entry1->size;
+               s_entry1->hfs_off = ES_INFO_SIZE;
+       }
+
+       set_733((char *) s_entry1->isorec.size, s_entry1->size);
+
+       return (ret);
+}
+
+/*
+ * calc_crc() --
+ *   Compute the MacBinary II-style CRC for the data pointed to by p, with the
+ *   crc seeded to seed.
+ *
+ *   Modified by Jim Van Verth to use the magic array for efficiency.
+ */
+#ifdef __used__
+static unsigned short
+calc_mb_crc(unsigned char *p, long len, unsigned short seed)
+{
+       unsigned short  hold;   /* crc computed so far */
+       long            i;      /* index into data */
+
+       hold = seed;    /* start with seed */
+       for (i = 0; i < len; i++, p++) {
+               hold ^= (*p << 8);
+               hold = (hold << 8) ^ mb_magic[(unsigned char) (hold >> 8)];
+       }
+
+       return (hold);
+}/* calc_mb_crc() */
+
+#endif /* __used__ */
+
+static int
+get_mb_info(char *hname, /* whole path */
+                               char *dname, /* this dir name */
+                               dir_ent *s_entry, /* directory entry */
+                               int ret)
+{
+       mb_info         *info;          /* finderinfo struct */
+       char            *c;
+       char            *t;
+       hfsdirent       *hfs_ent;
+       dir_ent         *s_entry1;
+       int             i;
+
+#ifdef TEST_CODE
+       unsigned short  crc_file,
+                       crc_calc;
+
+#endif
+
+       info = (mb_info *) p_buf;
+
+       /*
+        * routine called twice for each file - first to check that it is a
+        * valid MacBinary file, second to fill in the HFS info. p_buf holds
+        * the required raw data and it *should* remain the same between the
+        * two calls
+        */
+       if (s_entry == 0) {
+               /*
+                * test that the CRC is OK - not set for MacBinary I files (and
+                * incorrect in some MacBinary II files!). If this fails, then
+                * perform some other checks
+                */
+
+#ifdef TEST_CODE
+               /* leave this out for the time being ... */
+               if (p_num >= MB_SIZE && info->version == 0 && info->zero1 == 0) {
+                       crc_calc = calc_mb_crc((unsigned char *) info, 124, 0);
+                       crc_file = d_getw(info->crc);
+#ifdef DEBUG
+                       fprintf(stderr, "%s: file %d, calc %d\n", hname,
+                                                       crc_file, crc_calc);
+#endif /* DEBUG */
+                       if (crc_file == crc_calc)
+                               return (ret);
+               }
+#endif /* TEST_CODE */
+
+               /*
+                * check some of the fields for a valid MacBinary file not
+                * zero1 and zero2 SHOULD be zero - but some files incorrect
+                */
+
+/*         if (p_num < MB_SIZE || info->nlen > 63 || info->zero2 || */
+               if (p_num < MB_SIZE || info->zero1 ||
+                       info->zero2 || info->nlen > 63 ||
+                       info->version || info->nlen == 0 || *info->name == 0)
+                       return (TYPE_NONE);
+
+               /* check that the filename is OKish */
+               for (i = 0; i < (int)info->nlen; i++)
+                       if (info->name[i] == 0)
+                               return (TYPE_NONE);
+
+               /* check CREATOR and TYPE are valid */
+               for (i = 0; i < 4; i++)
+                       if (info->type[i] == 0 || info->auth[i] == 0)
+                               return (TYPE_NONE);
+       } else {
+               /* we have a vaild MacBinary file, so fill in the bits */
+
+               /* this should exist ... */
+               if ((s_entry1 = s_entry->assoc) == NULL)
+                       perr("TYPE_MBIN error - shouldn't happen!");
+
+               hfs_ent = s_entry->hfs_ent;
+
+               /* type and creator from finder info */
+               t = (char *) (info->type);
+               c = (char *) (info->auth);
+
+               set_ct(hfs_ent, c, t);
+
+               /* finder flags */
+               hfs_ent->fdflags = ((info->flags << 8) & 0xff00) | info->flags2;
+
+               if (icon_pos) {
+                       hfs_ent->fdlocation.v =
+                               d_getw((unsigned char *) info->icon_vert);
+                       hfs_ent->fdlocation.h =
+                               d_getw((unsigned char *) info->icon_horiz);
+               } else {
+                       /*
+                        * clear HFS_FNDR_HASBEENINITED to have tidy desktop ??
+                        */
+                       hfs_ent->fdflags &= 0xfeff;
+               }
+
+               /*
+                * set created/modified dates - these date should have already
+                * been set from the Unix data fork dates. The finderinfo dates
+                * are in Mac format - but we have to convert them back to Unix
+                * for the time being
+                */
+               hfs_ent->crdate = d_toutime(d_getl(info->cdate));
+               hfs_ent->mddate = d_toutime(d_getl(info->mdate));
+
+               /* set name */
+               hstrncpy((unsigned char *) (hfs_ent->name),
+                       (char *) (info->name), MIN(HFS_MAX_FLEN, info->nlen));
+
+               /* set correct fork sizes */
+               hfs_ent->u.file.dsize = d_getl(info->dflen);
+               hfs_ent->u.file.rsize = d_getl(info->rflen);
+
+               /* update directory entries for data fork */
+               s_entry->size = hfs_ent->u.file.dsize;
+               s_entry->hfs_off = MB_SIZE;
+               set_733((char *) s_entry->isorec.size, s_entry->size);
+
+               /*
+                * real rsrc file starts after data fork (must be a multiple of
+                * MB_SIZE)
+                */
+               s_entry1->size = hfs_ent->u.file.rsize;
+               s_entry1->hfs_off = MB_SIZE + ROUND_UP(hfs_ent->u.file.dsize, MB_SIZE);
+               set_733((char *) s_entry1->isorec.size, s_entry1->size);
+       }
+
+       return (ret);
+}
+
+/*
+ *     get_dbl_dir:    get Apple double finderinfo for a directory
+ *
+ *     Based on code from cvt2cap.c (c) May 1988, Paul Campbell
+ */
+static int
+get_dbl_dir(char *hname, /* whole path */
+                               char *dname, /* this dir name */
+                               dir_ent *s_entry, /* directory entry */
+                               int ret)
+{
+       FileInfo        info;           /* finderinfo struct */
+       a_hdr           *hp;
+       a_entry         *ep;
+       int             num = -1;       /* bytes read */
+       int             nentries;
+       FILE            *fp;
+       hfsdirent       *hfs_ent = s_entry->hfs_ent;
+       char            name[64];
+       int             i;
+       int             fail = 0;
+       int             len = 0;
+
+       hp = (a_hdr *) p_buf;
+       memset(hp, 0, A_HDR_SIZE);
+
+       memset(name, 0, sizeof (name));
+
+       /* open and read the info/rsrc file (it's the same file) */
+       if ((fp = fopen(hname, "rb")) != NULL)
+               num = fread(hp, 1, A_HDR_SIZE, fp);
+
+       /*
+        * check finder info is OK - some Netatalk files don't have magic
+        * or version set - ignore if it's a netatalk file
+        */
+       if (num == A_HDR_SIZE && ((ret == TYPE_NETA) ||
+                       (d_getl(hp->magic) == APPLE_DOUBLE &&
+                               (d_getl(hp->version) == A_VERSION1 ||
+                                       d_getl(hp->version) == A_VERSION2)))) {
+
+               /* read TOC of the AppleDouble file */
+               nentries = (int) d_getw(hp->nentries);
+               if (fread(hp->entries, A_ENTRY_SIZE, nentries, fp) < 1) {
+                       fail = 1;
+                       nentries = 0;
+               }
+               /* extract what is needed */
+               for (i = 0, ep = hp->entries; i < nentries; i++, ep++) {
+                       switch ((int)d_getl(ep->id)) {
+                       case ID_FINDER:
+                               /* get the finder info */
+                               fseek(fp, (off_t)d_getl(ep->offset), SEEK_SET);
+                               if (fread(&info, d_getl(ep->length), 1, fp) < 1) {
+                                       fail = 1;
+                               }
+                               break;
+                       case ID_NAME:
+                               /* get Mac file name */
+                               fseek(fp, (off_t)d_getl(ep->offset), SEEK_SET);
+                               if (fread(name, d_getl(ep->length), 1, fp) < 1)
+                                       *name = '\0';
+                               len = d_getl(ep->length);
+                               break;
+                       default:
+                               break;
+                       }
+               }
+
+               fclose(fp);
+
+               /* skip this if we had a problem */
+               if (!fail) {
+
+                       set_Dinfo(info.finderinfo, hfs_ent);
+
+                       /* use stored name if it exists */
+                       if (*name) {
+                               /*
+                                * In some cases the name is stored in the
+                                * Pascal string format - first char is the
+                                * length, the rest is the actual string.
+                                * The following *should* be OK
+                                */
+                               if (len == 32 && (int) name[0] < 32) {
+                                       cstrncpy(hfs_ent->name, &name[1],
+                                               MIN(name[0], HFS_MAX_FLEN));
+                               } else {
+                                       cstrncpy(hfs_ent->name, name,
+                                                       HFS_MAX_FLEN);
+                               }
+                       } else {
+                               hstrncpy((unsigned char *) (hfs_ent->name),
+                                                       dname, HFS_MAX_FLEN);
+                       }
+               }
+       } else {
+               /* failed to open/read finderinfo */
+               fail = 1;
+               if (fp)
+                       fclose(fp);
+       }
+
+       if (fail) {
+               /* problem with the file - try mapping/magic */
+               if (verbose > 2) {
+                       fprintf(stderr,
+                               "warning: %s doesn't appear to be a %s file\n",
+                               s_entry->whole_name, hfs_types[ret].desc);
+               }
+               ret = get_none_dir(hname, dname, s_entry, TYPE_NONE);
+       }
+       return (ret);
+}
+
+/*
+ *     Depending on the version, AppleDouble/Single stores dates
+ *     relative to 1st Jan 1904 (v1) or 1st Jan 2000 (v2)
+ *
+ *     The d_toutime() function uses 1st Jan 1904 to convert to
+ *     Unix time (1st Jan 1970).
+ *
+ *     The d_dtoutime() function uses 1st Jan 2000 to convert to
+ *     Unix time (1st Jan 1970).
+ *
+ *     However, NetaTalk files seem to do their own thing - older
+ *     Netatalk files don't have a magic number of version and
+ *     store dates in ID=7 (don't know how). Newer Netatalk files
+ *     claim to be version 1, but store dates in ID=7 as if they
+ *     were version 2 files.
+ */
+
+/*
+ *     get_dbl_info:   get Apple double finderinfo for a file
+ *
+ *     Based on code from cvt2cap.c (c) May 1988, Paul Campbell
+ */
+static int
+get_dbl_info(char *hname, /* whole path */
+                                char *dname, /* this dir name */
+                                dir_ent *s_entry, /* directory entry */
+                                int ret)
+{
+       FileInfo        info;           /* finderinfo struct */
+       a_hdr           *hp;
+       a_entry         *ep;
+       int             num = -1;       /* bytes read */
+       int             nentries;
+       FILE            *fp;
+       hfsdirent       *hfs_ent = s_entry->hfs_ent;
+       dir_ent         *s_entry1;
+       char            name[64];
+       int             i;
+       int             fail = 0;
+       int             len = 0;
+       unsigned char   dates[A_DATE];
+       int             ver = 0, dlen;
+
+       hp = (a_hdr *) p_buf;
+       memset(hp, 0, A_HDR_SIZE);
+
+       memset(name, 0, sizeof (name));
+       memset(dates, 0, sizeof (dates));
+
+       /* get the rsrc file info - should exist ... */
+       if ((s_entry1 = s_entry->assoc) == NULL)
+               perr("TYPE_DBL error - shouldn't happen!");
+
+       /* open and read the info/rsrc file (it's the same file) */
+       if ((fp = fopen(hname, "rb")) != NULL)
+               num = fread(hp, 1, A_HDR_SIZE, fp);
+
+       /*
+        * check finder info is OK - some Netatalk files don't have magic
+        * or version set - ignore if it's a netatalk file
+        */
+
+       ver = d_getl(hp->version);
+       if (num == A_HDR_SIZE && ((ret == TYPE_NETA) ||
+                       (d_getl(hp->magic) == APPLE_DOUBLE &&
+                               (ver == A_VERSION1 || ver == A_VERSION2)))) {
+
+               /* read TOC of the AppleDouble file */
+               nentries = (int) d_getw(hp->nentries);
+               if (fread(hp->entries, A_ENTRY_SIZE, nentries, fp) < 1) {
+                       fail = 1;
+                       nentries = 0;
+               }
+               /* extract what is needed */
+               for (i = 0, ep = hp->entries; i < nentries; i++, ep++) {
+                       switch ((int)d_getl(ep->id)) {
+                       case ID_FINDER:
+                               /* get the finder info */
+                               fseek(fp, (off_t)d_getl(ep->offset), SEEK_SET);
+                               if (fread(&info, d_getl(ep->length), 1, fp) < 1) {
+                                       fail = 1;
+                               }
+                               break;
+                       case ID_RESOURCE:
+                               /* set the offset and correct rsrc fork size */
+                               s_entry1->size = d_getl(ep->length);
+                               hfs_ent->u.file.rsize = s_entry1->size;
+                               /* offset to start of real rsrc fork */
+                               s_entry1->hfs_off = d_getl(ep->offset);
+                               set_733((char *) s_entry1->isorec.size,
+                                                               s_entry1->size);
+                               break;
+                       case ID_NAME:
+                               /* get Mac file name */
+                               fseek(fp, (off_t)d_getl(ep->offset), SEEK_SET);
+                               if (fread(name, d_getl(ep->length), 1, fp) < 1)
+                                       *name = '\0';
+                               len = d_getl(ep->length);
+                               break;
+                       case ID_FILEI:
+                               /* Workround for NetaTalk files ... */
+                               if (ret == TYPE_NETA && ver == A_VERSION1)
+                                       ver = A_VERSION2;
+                               /* fall through */
+                       case ID_FILEDATESI:
+                               /* get file info */
+                               fseek(fp, d_getl(ep->offset), 0);
+                               dlen = MIN(d_getl(ep->length), A_DATE);
+                               if (fread(dates, dlen, 1, fp) < 1) {
+                                       fail = 1;
+                               } else {
+                                       /* get the correct Unix time */
+                                       switch (ver) {
+
+                                       case (A_VERSION1):
+                                               hfs_ent->crdate =
+                                               d_toutime(d_getl(dates));
+                                               hfs_ent->mddate =
+                                               d_toutime(d_getl(dates+4));
+                                               break;
+                                       case (A_VERSION2):
+                                               hfs_ent->crdate =
+                                               d_dtoutime(d_getl(dates));
+                                               hfs_ent->mddate =
+                                               d_dtoutime(d_getl(dates+4));
+                                               break;
+                                       default:
+                                               /* Use Unix dates */
+                                               break;
+                                       }
+                               }
+                               break;
+                       default:
+                               break;
+                       }
+               }
+
+               fclose(fp);
+
+               /* skip this if we had a problem */
+               if (!fail) {
+                       set_Finfo(info.finderinfo, hfs_ent);
+
+                       /* use stored name if it exists */
+                       if (*name) {
+                               /*
+                                * In some cases the name is stored in the
+                                * Pascal string format - first char is the
+                                * length, the rest is the actual string.
+                                * The following *should* be OK
+                                */
+                               if (len == 32 && (int) name[0] < 32) {
+                                       cstrncpy(hfs_ent->name, &name[1],
+                                               MIN(name[0], HFS_MAX_FLEN));
+                               } else {
+                                       cstrncpy(hfs_ent->name, name,
+                                                       HFS_MAX_FLEN);
+                               }
+                       } else {
+                               hstrncpy((unsigned char *) (hfs_ent->name),
+                                                       dname, HFS_MAX_FLEN);
+                       }
+               }
+       } else {
+               /* failed to open/read finderinfo */
+               fail = 1;
+               if (fp)
+                       fclose(fp);
+       }
+
+       if (fail) {
+               /* problem with the file - try mapping/magic */
+               if (verbose > 2) {
+                       fprintf(stderr,
+                               "warning: %s doesn't appear to be a %s file\n",
+                               s_entry->whole_name, hfs_types[ret].desc);
+               }
+               ret = get_none_info(hname, dname, s_entry, TYPE_NONE);
+       }
+       return (ret);
+}
+
+/*
+ *     get_sgl_info:   get Apple single finderinfo for a file
+ *
+ *     Based on code from cvt2cap.c (c) May 1988, Paul Campbell
+ */
+static int
+get_sgl_info(char *hname, /* whole path */
+                                char *dname, /* this dir name */
+                                dir_ent *s_entry, /* directory entry */
+                                int ret)
+{
+       FileInfo        *info = 0;      /* finderinfo struct */
+       a_hdr           *hp;
+       static a_entry  *entries;
+       a_entry         *ep;
+       int             nentries;
+       hfsdirent       *hfs_ent;
+       dir_ent         *s_entry1;
+       char            name[64];
+       int             i;
+       int             len = 0;
+       unsigned char   *dates;
+       int             ver = 0;
+
+       /*
+        * routine called twice for each file
+        * - first to check that it is a valid
+        * AppleSingle file, second to fill in the HFS info.
+        * p_buf holds the required
+        * raw data and it *should* remain the same between the two calls
+        */
+       hp = (a_hdr *) p_buf;
+
+       if (s_entry == 0) {
+               if (p_num < A_HDR_SIZE ||
+                       d_getl(hp->magic) != APPLE_SINGLE ||
+                       (d_getl(hp->version) != A_VERSION1 &&
+                               d_getl(hp->version) != A_VERSION2))
+                       return (TYPE_NONE);
+
+               /* check we have TOC for the AppleSingle file */
+               nentries = (int) d_getw(hp->nentries);
+               if (p_num < (int)(A_HDR_SIZE + nentries * A_ENTRY_SIZE))
+                       return (TYPE_NONE);
+
+               /* save the TOC */
+               entries = (a_entry *) e_malloc(nentries * A_ENTRY_SIZE);
+
+               memcpy(entries, (p_buf + A_HDR_SIZE), nentries * A_ENTRY_SIZE);
+       } else {
+               /* have a vaild AppleSingle File */
+               memset(name, 0, sizeof (name));
+
+               /* get the rsrc file info - should exist ... */
+               if ((s_entry1 = s_entry->assoc) == NULL)
+                       perr("TYPE_SGL error - shouldn't happen!");
+
+               hfs_ent = s_entry->hfs_ent;
+
+               nentries = (int) d_getw(hp->nentries);
+               ver = d_getl(hp->version);
+
+               /* extract what is needed */
+               for (i = 0, ep = entries; i < nentries; i++, ep++) {
+                       switch ((int)d_getl(ep->id)) {
+                       case ID_FINDER:
+                               /* get the finder info */
+                               info = (FileInfo *) (p_buf + d_getl(ep->offset));
+                               break;
+                       case ID_DATA:
+                               /* set the offset and correct data fork size */
+                               hfs_ent->u.file.dsize = s_entry->size =
+                                                       d_getl(ep->length);
+                               /* offset to start of real data fork */
+                               s_entry->hfs_off = d_getl(ep->offset);
+                               set_733((char *) s_entry->isorec.size,
+                                                               s_entry->size);
+                               break;
+                       case ID_RESOURCE:
+                               /* set the offset and correct rsrc fork size */
+                               hfs_ent->u.file.rsize = s_entry1->size =
+                                                       d_getl(ep->length);
+                               /* offset to start of real rsrc fork */
+                               s_entry1->hfs_off = d_getl(ep->offset);
+                               set_733((char *) s_entry1->isorec.size,
+                                                               s_entry1->size);
+                               break;
+                       case ID_NAME:
+                               /* get Mac file name */
+                               strncpy(name, (p_buf + d_getl(ep->offset)),
+                                       d_getl(ep->length));
+                               len = d_getl(ep->length);
+                               break;
+                       case ID_FILEI:
+                               /* get file info - ignore at the moment*/
+                               break;
+                       case ID_FILEDATESI:
+                               /* get file info */
+                               dates = (unsigned char *)p_buf + d_getl(ep->offset);
+                               /* get the correct Unix time */
+                               if (ver == A_VERSION1) {
+                                       hfs_ent->crdate =
+                                               d_toutime(d_getl(dates));
+                                       hfs_ent->mddate =
+                                               d_toutime(d_getl(dates+4));
+                               } else {
+                                       hfs_ent->crdate =
+                                               d_dtoutime(d_getl(dates));
+                                       hfs_ent->mddate =
+                                               d_dtoutime(d_getl(dates+4));
+                               }
+                               break;
+                       default:
+                               break;
+                       }
+               }
+
+               free(entries);
+
+               if (info == NULL) {
+                       /*
+                        * failed to open/read finderinfo
+                        * - so try afpfile mapping
+                        */
+                       if (verbose > 2) {
+                               fprintf(stderr,
+                               "warning: %s doesn't appear to be a %s file\n",
+                                       s_entry->whole_name,
+                                       hfs_types[ret].desc);
+                       }
+                       ret = get_none_info(hname, dname, s_entry, TYPE_NONE);
+                       return (ret);
+               }
+
+               set_Finfo(info->finderinfo, hfs_ent);
+
+               /* use stored name if it exists */
+               if (*name) {
+                       /*
+                        * In some cases the name is stored in the Pascal string
+                        * format - first char is the length, the rest is the
+                        * actual string. The following *should* be OK
+                        */
+                       if (len == 32 && (int) name[0] < 32) {
+                               cstrncpy(hfs_ent->name, &name[1], MIN(name[0],
+                                                               HFS_MAX_FLEN));
+                       } else {
+                               cstrncpy(hfs_ent->name, name, HFS_MAX_FLEN);
+                       }
+               } else {
+                       hstrncpy((unsigned char *) (hfs_ent->name), dname,
+                                                               HFS_MAX_FLEN);
+               }
+       }
+
+       return (ret);
+}
+
+/*
+ *     get_hfs_fe_info: read in the whole finderinfo for a PC Exchange
+ *             directory - saves on reading this many times for each file.
+ *
+ *     Based of information provided by Mark Weinstein <mrwesq@earthlink.net>
+ *
+ *     Note: the FINDER.DAT file layout depends on the FAT cluster size
+ *     therefore, files should only be read directly from the FAT media
+ *
+ *     Only tested with PC Exchange v2.1 - don't know if it will work
+ *     with v2.2 and above.
+ */
+static struct hfs_info *
+get_hfs_fe_info(struct hfs_info *hfs_info, char *name)
+{
+       FILE            *fp;
+       int             fe_num,
+                       fe_pad;
+       fe_info         info;
+       int             c = 0;
+       struct hfs_info *hfs_info1 = NULL;
+       char            keyname[12];
+       char            *s,
+                       *e,
+                       *k;
+       int             i;
+
+       if ((fp = fopen(name, "rb")) == NULL)
+               return (NULL);
+
+       /*
+        * no longer attempt to find out FAT cluster
+        * - rely on command line parameter
+        */
+       if (afe_size <= 0)
+               return (NULL);
+
+       fe_num = afe_size / FE_SIZE;
+       fe_pad = afe_size % FE_SIZE;
+
+       while (fread(&info, 1, FE_SIZE, fp) != 0) {
+
+               /* the Mac name may be NULL - so ignore this entry */
+               if (info.nlen != 0) {
+
+                       hfs_info1 =
+                       (struct hfs_info *)e_malloc(sizeof (struct hfs_info));
+                       /* add this entry to the list */
+                       hfs_info1->next = hfs_info;
+                       hfs_info = hfs_info1;
+
+                       /*
+                        * get the bits we need
+                        * - ignore [cm]time for the moment
+                        */
+                       cstrncpy(hfs_info->name, (char *) (info.name),
+                                       info.nlen);
+
+                       memcpy(hfs_info->finderinfo, info.finderinfo, INFOLEN);
+
+                       s = (char *) (info.sname);
+                       e = (char *) (info.ext);
+                       k = keyname;
+
+                       /*
+                        * short (Unix) name is stored in PC format,
+                        * so needs to be mangled a bit
+                        */
+
+                       /* name part */
+                       for (i = 0; i < 8; i++, s++, k++) {
+                               if (*s == ' ')
+                                       break;
+                               else
+                                       *k = *s;
+                       }
+
+                       /* extension - if it exists */
+                       if (strncmp((const char *) (info.ext), "   ", 3)) {
+                               *k = '.';
+                               k++;
+                               for (i = 0; i < 3; i++, e++, k++) {
+                                       if (*e == ' ')
+                                               break;
+                                       else
+                                               *k = *e;
+                               }
+                       }
+                       *k = '\0';
+
+                       hfs_info1->keyname = strdup(keyname);
+               }
+               /*
+                * each record is FE_SIZE long, and there are FE_NUM
+                * per each "cluster size", so we may need to skip the padding
+                */
+               if (++c == fe_num) {
+                       c = 0;
+                       fseek(fp, (off_t)fe_pad, SEEK_CUR);
+               }
+       }
+       fclose(fp);
+
+       return (hfs_info);
+}
+
+/*
+ *     get_hfs_sgi_info: read in the whole finderinfo for a SGI (XINET)
+ *             directory - saves on reading this many times for each
+ *             file.
+ */
+static struct hfs_info *
+get_hfs_sgi_info(struct hfs_info *hfs_info, char *name)
+{
+       FILE            *fp;
+       sgi_info        info;
+       struct hfs_info *hfs_info1 = NULL;
+
+       if ((fp = fopen(name, "rb")) == NULL)
+               return (NULL);
+
+       while (fread(&info, 1, SGI_SIZE, fp) != 0) {
+
+               hfs_info1 = (struct hfs_info *)e_malloc(sizeof (struct hfs_info));
+               /* add this entry to the list */
+               hfs_info1->next = hfs_info;
+               hfs_info = hfs_info1;
+
+               /* get the bits we need - ignore [cm]time for the moment */
+               cstrncpy(hfs_info->name, (char *)info.name, HFS_MAX_FLEN);
+
+               memcpy(hfs_info->finderinfo, info.finderinfo, INFOLEN);
+
+               /* use the HFS name as the key */
+               hfs_info1->keyname = hfs_info->name;
+
+       }
+       fclose(fp);
+
+       return (hfs_info);
+}
+
+/*
+ *     del_hfs_info: delete the info list and recover memory
+ */
+void
+del_hfs_info(struct hfs_info *hfs_info)
+{
+       struct hfs_info *hfs_info1;
+
+       while (hfs_info) {
+               hfs_info1 = hfs_info;
+               hfs_info = hfs_info->next;
+
+               /* key may be the same as the HFS name - so don't free it */
+               *hfs_info1->name = '\0';
+               if (*hfs_info1->keyname)
+                       free(hfs_info1->keyname);
+               free(hfs_info1);
+       }
+}
+
+/*
+ *     match_key: find the correct hfs_ent using the Unix filename
+ *             as the key
+ */
+static struct hfs_info *
+match_key(struct hfs_info *hfs_info, char *key)
+{
+       while (hfs_info) {
+               if (strcasecmp(key, hfs_info->keyname) == 0)
+                       return (hfs_info);
+               hfs_info = hfs_info->next;
+       }
+
+       return (NULL);
+}
+
+/*
+ *     get_fe_dir: get PC Exchange directory name
+ *
+ *     base on probing with od ...
+ */
+static int
+get_fe_dir(char *hname, /* whole path */
+                         char *dname, /* this dir name */
+                         dir_ent *s_entry, /* directory entry */
+                         int ret)
+{
+       struct hfs_info *hfs_info;
+       hfsdirent       *hfs_ent = s_entry->hfs_ent;
+
+       /* cached finderinfo stored with parent directory */
+       hfs_info = s_entry->filedir->hfs_info;
+
+       /* if we have no cache, then make one and store it */
+       if (hfs_info == NULL) {
+               if ((hfs_info = get_hfs_fe_info(hfs_info, hname)) == NULL)
+                       ret = TYPE_NONE;
+               else
+                       s_entry->filedir->hfs_info = hfs_info;
+       }
+       if (ret != TYPE_NONE) {
+               /* see if we can find the details of this file */
+               if ((hfs_info = match_key(hfs_info, dname)) != NULL) {
+                       strcpy(hfs_ent->name, hfs_info->name);
+
+                       set_Dinfo(hfs_info->finderinfo, hfs_ent);
+
+                       return (ret);
+               }
+       }
+       /* can't find the entry, so use the Unix name */
+       hstrncpy((unsigned char *)(hfs_ent->name), dname, HFS_MAX_FLEN);
+
+       return (TYPE_NONE);
+}
+
+/*
+ *     get_fe_info: get PC Exchange file details.
+ *
+ *     base on probing with od and details from Mark Weinstein
+ *     <mrwesq@earthlink.net>
+ */
+static int
+get_fe_info(char *hname, /* whole path */
+                          char *dname, /* this dir name */
+                          dir_ent *s_entry, /* directory entry */
+                          int ret)
+{
+       struct hfs_info *hfs_info;
+       hfsdirent       *hfs_ent = s_entry->hfs_ent;
+
+       /* cached finderinfo stored with parent directory */
+       hfs_info = s_entry->filedir->hfs_info;
+
+       /* if we have no cache, then make one and store it */
+       if (hfs_info == NULL) {
+               if ((hfs_info = get_hfs_fe_info(hfs_info, hname)) == NULL)
+                       ret = TYPE_NONE;
+               else
+                       s_entry->filedir->hfs_info = hfs_info;
+       }
+       if (ret != TYPE_NONE) {
+               char    *dn = dname;
+
+#ifdef _WIN32_TEST
+               /*
+                * may have a problem here - v2.2 has long filenames,
+                * but we need to key on the short filename,
+                * so we need do go a bit of win32 stuff
+                * ...
+                */
+               char    sname[1024];
+               char    lname[1024];
+
+               cygwin32_conv_to_full_win32_path(s_entry->whole_name, lname);
+
+               if (GetShortPathName(lname, sname, sizeof (sname))) {
+                       if (dn = strrchr(sname, '\\'))
+                               dn++;
+                       else
+                               dn = sname;
+               }
+#endif /* _WIN32 */
+
+               /* see if we can find the details of this file */
+               if ((hfs_info = match_key(hfs_info, dn)) != NULL) {
+
+                       strcpy(hfs_ent->name, hfs_info->name);
+
+                       set_Finfo(hfs_info->finderinfo, hfs_ent);
+
+                       return (ret);
+               }
+       }
+       /* no entry found - use extension mapping */
+       if (verbose > 2) {
+               fprintf(stderr, "warning: %s doesn't appear to be a %s file\n",
+                       s_entry->whole_name, hfs_types[ret].desc);
+       }
+       ret = get_none_info(hname, dname, s_entry, TYPE_NONE);
+
+       return (TYPE_NONE);
+}
+
+/*
+ *     get_sgi_dir: get SGI (XINET) HFS directory name
+ *
+ *     base on probing with od ...
+ */
+static int
+get_sgi_dir(char *hname, /* whole path */
+                          char *dname, /* this dir name */
+                          dir_ent *s_entry, /* directory entry */
+                          int ret)
+{
+       struct hfs_info *hfs_info;
+       hfsdirent       *hfs_ent = s_entry->hfs_ent;
+
+       /* cached finderinfo stored with parent directory */
+       hfs_info = s_entry->filedir->hfs_info;
+
+       /* if we haven't got a cache, then make one */
+       if (hfs_info == NULL) {
+               if ((hfs_info = get_hfs_sgi_info(hfs_info, hname)) == NULL)
+                       ret = TYPE_NONE;
+               else
+                       s_entry->filedir->hfs_info = hfs_info;
+       }
+       /* find the matching entry in the cache */
+       if (ret != TYPE_NONE) {
+               /* key is (hopefully) the real Mac name */
+               cstrncpy(tmp, dname, strlen(dname));
+               if ((hfs_info = match_key(hfs_info, tmp)) != NULL) {
+                       strcpy(hfs_ent->name, hfs_info->name);
+
+                       set_Dinfo(hfs_info->finderinfo, hfs_ent);
+
+                       return (ret);
+               }
+       }
+       /* no entry found - use Unix name */
+       hstrncpy((unsigned char *)(hfs_ent->name), dname, HFS_MAX_FLEN);
+
+       return (TYPE_NONE);
+}
+
+/*
+ *     get_sgi_info: get SGI (XINET) HFS finder info
+ *
+ *     base on probing with od ...
+ */
+static int
+get_sgi_info(char *hname, /* whole path */
+                           char *dname, /* this dir name */
+                           dir_ent *s_entry, /* directory entry */
+                           int ret)
+{
+       struct hfs_info *hfs_info;
+       hfsdirent       *hfs_ent = s_entry->hfs_ent;
+
+       /* cached finderinfo stored with parent directory */
+       hfs_info = s_entry->filedir->hfs_info;
+
+       /* if we haven't got a cache, then make one */
+       if (hfs_info == NULL) {
+               if ((hfs_info = get_hfs_sgi_info(hfs_info, hname)) == NULL)
+                       ret = TYPE_NONE;
+               else
+                       s_entry->filedir->hfs_info = hfs_info;
+       }
+       if (ret != TYPE_NONE) {
+               /*
+                * tmp is the same as hname here, but we don't need hname
+                * anymore in this function  ...  see if we can find the
+                * details of this file using the Unix name as the key
+                */
+               cstrncpy(tmp, dname, strlen(dname));
+               if ((hfs_info = match_key(hfs_info, tmp)) != NULL) {
+
+                       strcpy(hfs_ent->name, hfs_info->name);
+
+                       set_Finfo(hfs_info->finderinfo, hfs_ent);
+
+                       return (ret);
+               }
+       }
+       /* no entry found, so try file extension */
+       if (verbose > 2) {
+               fprintf(stderr, "warning: %s doesn't appear to be a %s file\n",
+                       s_entry->whole_name, hfs_types[ret].desc);
+       }
+       ret = get_none_info(hname, dname, s_entry, TYPE_NONE);
+
+       return (TYPE_NONE);
+}
+
+/*
+ *     get_sfm_info:   get SFM finderinfo for a file
+ */
+
+static byte    sfm_magic[4] = {0x41, 0x46, 0x50, 0x00};
+static byte    sfm_version[4] = {0x00, 0x00, 0x01, 0x00};
+
+static int
+get_sfm_info(char *hname, /* whole path */
+                           char *dname, /* this dir name */
+                           dir_ent *s_entry, /* directory entry */
+                           int ret)
+{
+       sfm_info        info;   /* finderinfo struct */
+       int             num = -1; /* bytes read */
+       hfsdirent       *hfs_ent = s_entry->hfs_ent;
+
+       num = read_info_file(hname, &info, sizeof (info));
+
+       /* check finder info is OK */
+       if (num == sizeof (info) &&
+               !memcmp((char *)info.afpi_Signature, (char *)sfm_magic, 4) &&
+               !memcmp((char *)info.afpi_Version, (char *)sfm_version, 4)) {
+               /* use Unix name */
+               hstrncpy((unsigned char *)(hfs_ent->name), dname, HFS_MAX_FLEN);
+
+               set_Finfo(info.finderinfo, hfs_ent);
+
+       } else {
+               /* failed to open/read finderinfo - so try afpfile mapping */
+               if (verbose > 2) {
+                       fprintf(stderr,
+                               "warning: %s doesn't appear to be a %s file\n",
+                               s_entry->whole_name, hfs_types[ret].desc);
+               }
+               ret = get_none_info(hname, dname, s_entry, TYPE_NONE);
+       }
+
+       return (ret);
+}
+
+#ifdef IS_MACOS_X
+/*
+ *     get_xhfs_dir:   get MacOS X HFS finderinfo for a directory
+ *
+ *     Code ideas from 'hfstar' by Marcel Weiher marcel@metaobject.com
+ *     and another GNU hfstar by Torres Vedras paulotex@yahoo.com
+ *
+ *     Here we are dealing with actual HFS files - not some encoding
+ *     we have to use a system call to get the finderinfo
+ *
+ *     The file name here is the pseudo name for the resource fork
+ */
+static int
+get_xhfs_dir(char *hname, /* whole path */
+                           char *dname, /* this dir name */
+                           dir_ent *s_entry, /* directory entry */
+                           int ret)
+{
+       int             err;
+       hfsdirent       *hfs_ent = s_entry->hfs_ent;
+       attrinfo        ainfo;
+       struct attrlist attrs;
+       int             i;
+
+       memset(&attrs, 0, sizeof (attrs));
+
+       /* set flags we need to get info from getattrlist() */
+       attrs.bitmapcount = ATTR_BIT_MAP_COUNT;
+       attrs.commonattr  = ATTR_CMN_CRTIME | ATTR_CMN_MODTIME |
+                               ATTR_CMN_FNDRINFO;
+
+       /* get the info */
+       err = getattrlist(hname, &attrs, &ainfo, sizeof (ainfo), 0);
+
+       if (err == 0) {
+               /*
+                * If the Finfo is blank then we assume it's not a
+                * 'true' HFS directory ...
+                */
+               err = 1;
+               for (i = 0; i < sizeof (ainfo.info); i++) {
+                       if (ainfo.info[i] != 0) {
+                               err = 0;
+                               break;
+                       }
+               }
+       }
+
+       /* check finder info is OK */
+       if (err == 0) {
+
+               hstrncpy((unsigned char *) (s_entry->hfs_ent->name),
+                                                       dname, HFS_MAX_FLEN);
+
+               set_Dinfo(ainfo.info, hfs_ent);
+
+               return (ret);
+       } else {
+               /* otherwise give it it's Unix name */
+               hstrncpy((unsigned char *) (s_entry->hfs_ent->name),
+                                                       dname, HFS_MAX_FLEN);
+               return (TYPE_NONE);
+       }
+}
+
+/*
+ *     get_xhfs_info:  get MacOS X HFS finderinfo for a file
+ *
+ *     Code ideas from 'hfstar' by Marcel Weiher marcel@metaobject.com,
+ *     another GNU hfstar by Torres Vedras paulotex@yahoo.com and
+ *     hfspax by Howard Oakley howard@quercus.demon.co.uk
+ *
+ *     Here we are dealing with actual HFS files - not some encoding
+ *     we have to use a system call to get the finderinfo
+ *
+ *     The file name here is the pseudo name for the resource fork
+ */
+static int
+get_xhfs_info(char *hname, /* whole path */
+                            char *dname, /* this dir name */
+                            dir_ent *s_entry, /* directory entry */
+                            int ret)
+{
+       int             err;
+       hfsdirent       *hfs_ent = s_entry->hfs_ent;
+       attrinfo        ainfo;
+       struct attrlist attrs;
+       int             i;
+       int             size;
+
+       memset(&attrs, 0, sizeof (attrs));
+
+       /* set flags we need to get info from getattrlist() */
+       attrs.bitmapcount = ATTR_BIT_MAP_COUNT;
+       attrs.commonattr  = ATTR_CMN_CRTIME | ATTR_CMN_MODTIME |
+                               ATTR_CMN_FNDRINFO;
+
+       /* get the info */
+       err = getattrlist(hname, &attrs, &ainfo, sizeof (ainfo), 0);
+
+       /* check finder info is OK */
+       if (err == 0) {
+
+               /*
+                * If the Finfo is blank and the resource file is empty,
+                * then we assume it's not a 'true' HFS file ...
+                * There will be not associated file if the resource fork
+                * is empty
+                */
+
+               if (s_entry->assoc == NULL) {
+                       err = 1;
+                       for (i = 0; i < sizeof (ainfo.info); i++) {
+                               if (ainfo.info[i] != 0) {
+                                       err = 0;
+                                       break;
+                               }
+                       }
+               }
+
+               if (err == 0) {
+
+                       /* use Unix name */
+                       hstrncpy((unsigned char *) (hfs_ent->name), dname,
+                                               HFS_MAX_FLEN);
+
+                       set_Finfo(ainfo.info, hfs_ent);
+
+                       /*
+                        * dates have already been set - but we will
+                        * set them here as well from the HFS info
+                        * shouldn't need to check for byte order, as
+                        * the source is HFS ... but we will just in case
+                        */
+                       hfs_ent->crdate = d_getl((byte *)&ainfo.ctime.tv_sec);
+
+                       hfs_ent->mddate = d_getl((byte *)&ainfo.mtime.tv_sec);
+               }
+
+       }
+
+       if (err) {
+               /* not a 'true' HFS file - so try afpfile mapping */
+#if 0
+               /*
+                * don't print a warning as we will get lots on HFS
+                * file systems ...
+                */
+               if (verbose > 2) {
+                       fprintf(stderr,
+                               "warning: %s doesn't appear to be a %s file\n",
+                               s_entry->whole_name, hfs_types[ret].desc);
+               }
+#endif
+               ret = get_none_info(hname, dname, s_entry, TYPE_NONE);
+       }
+
+       return (ret);
+}
+#endif /* IS_MACOS_X */
+
+/*
+ *     get_hfs_itype: get the type of HFS info for a file
+ */
+static int
+get_hfs_itype(char *wname, char *dname, char *htmp)
+{
+       int     wlen,
+               i;
+       int     no_type = TYPE_NONE;
+
+       wlen = strlen(wname) - strlen(dname);
+
+       /* search through the known types looking for matches */
+       for (i = 1; i < hfs_num; i++) {
+               /* skip the ones that we don't care about */
+               if ((hfs_types[i].flags & PROBE) ||
+                               *(hfs_types[i].info) == TYPE_NONE) {
+                       continue;
+               }
+
+               strcpy(htmp, wname);
+
+               /*
+                * special case - if the info file doesn't exist
+                * for a requested type, then remember the type -
+                * we don't return here, as we _may_ find another type
+                * so we save the type here in case - we will have
+                * problems if more than one of this type ever exists ...
+                */
+               if (hfs_types[i].flags & NOINFO) {
+                       no_type = i;
+               } else {
+
+                       /* append or insert finderinfo filename part */
+                       if (hfs_types[i].flags & APPEND)
+                               strcat(htmp, hfs_types[i].info);
+                       else
+                               sprintf(htmp + wlen, "%s%s", hfs_types[i].info,
+                                       (hfs_types[i].flags & NOPEND) ? "" : dname);
+
+                       /* hack time ... Netatalk is a special case ... */
+                       if (i == TYPE_NETA) {
+                               strcpy(htmp, wname);
+                               strcat(htmp, "/.AppleDouble/.Parent");
+                       }
+
+                       if (!access(htmp, R_OK))
+                               return (hfs_types[i].type);
+               }
+       }
+
+       return (no_type);
+}
+
+/*
+ *     set_root_info: set the root folder hfs_ent from given file
+ */
+void
+set_root_info(char *name)
+{
+       dir_ent         *s_entry;
+       hfsdirent       *hfs_ent;
+       int             i;
+
+       s_entry = root->self;
+
+       hfs_ent = (hfsdirent *) e_malloc(sizeof (hfsdirent));
+       memset(hfs_ent, 0, sizeof (hfsdirent));
+
+       /* make sure root has a valid hfs_ent */
+       s_entry->hfs_ent = root->hfs_ent = hfs_ent;
+
+       /* search for correct type of root info data */
+       for (i = 1; i < hfs_num; i++) {
+               if ((hfs_types[i].flags & PROBE) ||
+                               (hfs_types[i].get_info == get_none_info))
+                       continue;
+
+               if ((*(hfs_types[i].get_dir))(name, "", s_entry, i) == i)
+                       return;
+       }
+}
+
+
+/*
+ *     get_hfs_dir: set the HFS directory name
+ */
+int
+get_hfs_dir(char *wname, char *dname, dir_ent *s_entry)
+{
+       int     type;
+
+       /* get the HFS file type from the info file (if it exists) */
+       type = get_hfs_itype(wname, dname, tmp);
+
+       /* try to get the required info */
+       type = (*(hfs_types[type].get_dir)) (tmp, dname, s_entry, type);
+
+       return (type);
+}
+
+/*
+ *     get_hfs_info: set the HFS info for a file
+ */
+int
+get_hfs_info(char *wname, char *dname, dir_ent *s_entry)
+{
+       int     type,
+               wlen,
+               i;
+
+       wlen = strlen(wname) - strlen(dname);
+
+       /* we may already know the type of Unix/HFS file - so process */
+       if (s_entry->hfs_type != TYPE_NONE) {
+
+               type = s_entry->hfs_type;
+
+               strcpy(tmp, wname);
+
+               /* append or insert finderinfo filename part */
+               if (hfs_types[type].flags & APPEND)
+                       strcat(tmp, hfs_types[type].info);
+               else
+                       sprintf(tmp + wlen, "%s%s", hfs_types[type].info,
+                               (hfs_types[type].flags & NOPEND) ? "" : dname);
+
+               type = (*(hfs_types[type].get_info))(tmp, dname, s_entry, type);
+
+               /* if everything is as expected, then return */
+               if (s_entry->hfs_type == type)
+                       return (type);
+       }
+       /* we don't know what type we have so, find out */
+       for (i = 1; i < hfs_num; i++) {
+               if ((hfs_types[i].flags & PROBE) ||
+                               *(hfs_types[i].info) == TYPE_NONE) {
+                       continue;
+               }
+
+               strcpy(tmp, wname);
+
+               /* append or insert finderinfo filename part */
+               if (hfs_types[i].flags & APPEND) {
+                       strcat(tmp, hfs_types[i].info);
+               } else {
+                       sprintf(tmp + wlen, "%s%s", hfs_types[i].info,
+                               (hfs_types[i].flags & NOPEND) ? "" : dname);
+               }
+
+               /* if the file exists - and not a type we've already tried */
+               if (!access(tmp, R_OK) && i != s_entry->hfs_type) {
+                       type = (*(hfs_types[i].get_info))(tmp, dname,
+                                                       s_entry, i);
+                       s_entry->hfs_type = type;
+                       return (type);
+               }
+       }
+
+       /* nothing found, so just a Unix file */
+       type = (*(hfs_types[TYPE_NONE].get_info))(wname, dname,
+                                                       s_entry, TYPE_NONE);
+
+       return (type);
+}
+
+/*
+ *     get_hfs_rname: set the name of the Unix rsrc file for a file
+ *
+ *     For the time being we ignore the 'NOINFO' flag - the only case
+ *     at the moment is for MacOS X HFS files - for files the resource
+ *     fork exists - so testing the "filename/rsrc" pseudo file as
+ *     the 'info' filename is OK ...
+ */
+int
+get_hfs_rname(char *wname, char *dname, char *rname)
+{
+       int     wlen,
+               type,
+               i;
+       int     p_fd = -1;
+
+       wlen = strlen(wname) - strlen(dname);
+
+       /* try to find what sort of Unix HFS file type we have */
+       for (i = 1; i < hfs_num; i++) {
+               /* skip if don't want to probe the files - (default) */
+               if (hfs_types[i].flags & PROBE)
+                       continue;
+
+               strcpy(rname, wname);
+
+               /* if we have a different info file, the find out it's type */
+               if (*(hfs_types[i].rsrc) && *(hfs_types[i].info)) {
+                       /* first test the Info file */
+
+                       /* append or insert finderinfo filename part */
+                       if (hfs_types[i].flags & APPEND) {
+                               strcat(rname, hfs_types[i].info);
+                       } else {
+                               sprintf(rname + wlen, "%s%s", hfs_types[i].info,
+                                       (hfs_types[i].flags & NOPEND) ?
+                                                               "" : dname);
+                       }
+
+                       /* if it exists, then check the Rsrc file */
+                       if (!access(rname, R_OK)) {
+                               if (hfs_types[i].flags & APPEND) {
+                                       sprintf(rname + wlen, "%s%s", dname,
+                                               hfs_types[i].rsrc);
+                               } else {
+                                       sprintf(rname + wlen, "%s%s",
+                                               hfs_types[i].rsrc, dname);
+                               }
+
+                               /*
+                                * for some types, a rsrc fork may not exist,
+                                * so just return the current type
+                                * in these cases
+                                */
+                               if (hfs_types[i].flags & NORSRC ||
+                                                       !access(rname, R_OK))
+                                       return (hfs_types[i].type);
+                       }
+               } else {
+                       /*
+                        * if we are probing,
+                        * then have a look at the contents to find type
+                        */
+                       if (p_fd < 0) {
+                               /* open file, if not already open */
+                               if ((p_fd = open(wname,
+                                               O_RDONLY | O_BINARY)) < 0) {
+                                       /* can't open it, then give up */
+                                       return (TYPE_NONE);
+                               } else {
+                                       if ((p_num = read(p_fd, p_buf,
+                                                       sizeof (p_buf))) <= 0) {
+                                               /*
+                                                * can't read, or zero length
+                                                * - give up
+                                                */
+                                               close(p_fd);
+                                               return (TYPE_NONE);
+                                       }
+                                       /* get file pointer and close file */
+                                       p_fp = fdopen(p_fd, "rb");
+                                       close(p_fd);
+                                       if (p_fp == NULL)
+                                               return (TYPE_NONE);
+                               }
+                       }
+                       /*
+                        * call routine to do the work
+                        * - use the given dname as this
+                        * is the name we may use on the CD
+                        */
+                       type = (*(hfs_types[i].get_info)) (rname, dname, 0, i);
+                       if (type != 0) {
+                               fclose(p_fp);
+                               return (type);
+                       }
+                       if (p_fp) {
+                               /*
+                                * close file
+                                * - just use contents of buffer next time
+                                */
+                               fclose(p_fp);
+                               p_fp = NULL;
+                       }
+               }
+       }
+
+       return (0);
+}
+
+/*
+ *     hfs_exclude: file/directory names that hold finder/resource
+ *                  information that we want to exclude from the tree.
+ *                  These files/directories are processed later ...
+ */
+int
+hfs_exclude(char *d_name)
+{
+       /* we don't exclude "." and ".." */
+       if (strcmp(d_name, ".") == 0)
+               return (0);
+       if (strcmp(d_name, "..") == 0)
+               return (0);
+
+       /* do not add the following to our list of dir entries */
+       if (DO_CAP & hselect) {
+               /* CAP */
+               if (strcmp(d_name, ".finderinfo") == 0)
+                       return (1);
+               if (strcmp(d_name, ".resource") == 0)
+                       return (1);
+               if (strcmp(d_name, ".ADeskTop") == 0)
+                       return (1);
+               if (strcmp(d_name, ".IDeskTop") == 0)
+                       return (1);
+               if (strcmp(d_name, "Network Trash Folder") == 0)
+                       return (1);
+               /*
+                * special case when HFS volume is mounted using Linux's hfs_fs
+                * Brad Midgley <brad@pht.com>
+                */
+               if (strcmp(d_name, ".rootinfo") == 0)
+                       return (1);
+       }
+       if (DO_ESH & hselect) {
+               /* Helios EtherShare files */
+               if (strcmp(d_name, ".rsrc") == 0)
+                       return (1);
+               if (strcmp(d_name, ".Desktop") == 0)
+                       return (1);
+               if (strcmp(d_name, ".DeskServer") == 0)
+                       return (1);
+               if (strcmp(d_name, ".Label") == 0)
+                       return (1);
+       }
+       if (DO_DBL & hselect) {
+       /* Apple Double */
+               /*
+                * special case when HFS volume is mounted using Linux's hfs_fs
+                */
+               if (strcmp(d_name, "%RootInfo") == 0)
+                       return (1);
+               /*
+                * have to be careful here - a filename starting with '%'
+                * may be vaild if the next two letters are a hex character -
+                * unfortunately '%' 'digit' 'digit' may be a valid resource
+                * file name ...
+                */
+               if (*d_name == '%')
+                       if (hex2char(d_name) == 0)
+                               return (1);
+       }
+       if (DO_NETA & hselect) {
+               if (strcmp(d_name, ".AppleDouble") == 0)
+                       return (1);
+               if (strcmp(d_name, ".AppleDesktop") == 0)
+                       return (1);
+       }
+       if ((DO_FEU & hselect) || (DO_FEL & hselect)) {
+               /* PC Exchange */
+               if (strcmp(d_name, "RESOURCE.FRK") == 0)
+                       return (1);
+               if (strcmp(d_name, "FINDER.DAT") == 0)
+                       return (1);
+               if (strcmp(d_name, "DESKTOP") == 0)
+                       return (1);
+               if (strcmp(d_name, "FILEID.DAT") == 0)
+                       return (1);
+               if (strcmp(d_name, "resource.frk") == 0)
+                       return (1);
+               if (strcmp(d_name, "finder.dat") == 0)
+                       return (1);
+               if (strcmp(d_name, "desktop") == 0)
+                       return (1);
+               if (strcmp(d_name, "fileid.dat") == 0)
+                       return (1);
+       }
+       if (DO_SGI & hselect) {
+               /* SGI */
+               if (strcmp(d_name, ".HSResource") == 0)
+                       return (1);
+               if (strcmp(d_name, ".HSancillary") == 0)
+                       return (1);
+       }
+       if (DO_DAVE & hselect) {
+               /* DAVE */
+               if (strcmp(d_name, "resource.frk") == 0)
+                       return (1);
+               if (strcmp(d_name, "DesktopFolderDB") == 0)
+                       return (1);
+       }
+#ifndef _WIN32
+       /*
+        * NTFS streams are not "seen" as files,
+        * so WinNT will not see these files -
+        * so ignore - used for testing under Unix
+        */
+       if (DO_SFM & hselect) {
+               /* SFM */
+               char    *dn = strrchr(d_name, ':');
+
+               if (dn) {
+                       if (strcmp(dn, ":Afp_Resource") == 0)
+                               return (1);
+                       if (strcmp(dn, ":Comments") == 0)
+                               return (1);
+                       if (strcmp(dn, ":Afp_AfpInfo") == 0)
+                               return (1);
+               }
+       }
+#endif /* _WIN32 */
+
+       if (DO_XDBL & hselect) {
+               /* XDB */
+               if (strncmp(d_name, "._", 2) == 0)
+                       return (1);
+       }
+
+       return (0);
+}
+
+/*
+ *     print_hfs_info: print info about the HFS files.
+ *
+ */
+void
+print_hfs_info(dir_ent *s_entry)
+{
+       fprintf(stderr, "Name: %s\n", s_entry->whole_name);
+       fprintf(stderr, "\tFile type: %s\n", hfs_types[s_entry->hfs_type].desc);
+       fprintf(stderr, "\tHFS Name: %s\n", s_entry->hfs_ent->name);
+       fprintf(stderr, "\tISO Name: %s\n", s_entry->isorec.name);
+       fprintf(stderr, "\tCREATOR: %s\n", s_entry->hfs_ent->u.file.creator);
+       fprintf(stderr, "\tTYPE:        %s\n", s_entry->hfs_ent->u.file.type);
+}
+
+
+/*
+ *     hfs_init: sets up the mapping list from the afpfile as well
+ *              the default mapping (with or without) an afpfile
+ */
+void
+hfs_init(char *name, Ushort fdflags, Uint hfs_select)
+{
+       FILE    *fp;            /* File pointer */
+       int     count = NUMMAP; /* max number of entries */
+       char    buf[PATH_MAX];  /* working buffer */
+       afpmap  *amap;          /* mapping entry */
+       char    *c,
+               *t,
+               *e;
+       int     i;
+
+       /* setup number of Unix/HFS filetype - we may wish to not bother */
+       if (hfs_select) {
+               hfs_num = sizeof (hfs_types) / sizeof (struct hfs_type);
+
+               /*
+                * code below needs to be tidied up
+                * - most can be made redundant
+                */
+               for (i = 0; i < hfs_num; i++)
+                       hfs_types[i].flags &= ~1;       /* 0xfffffffe */
+
+               for (i = 1; i < hfs_num; i++)
+                       if (!((1 << i) & hfs_select))
+                               hfs_types[i].flags |= PROBE;
+
+               hselect = hfs_select;
+       } else
+               hfs_num = hselect = 0;
+
+#ifdef DEBUG
+       for (i = 0; i < hfs_num; i++)
+               fprintf(stderr, "type = %d flags = %d\n",
+                                       i, hfs_types[i].flags);
+#endif /* DEBUG */
+
+       /* min length set to max to start with */
+       mlen = PATH_MAX;
+
+#ifdef USE_MAGIC
+       /* initialise magic state */
+       if (magic_filename) {
+               magic_state = magic_open(MAGIC_ERROR);
+               if (magic_state == NULL)
+                       perr("failed to initialise libmagic");
+               if (magic_load(magic_state, magic_filename) == -1) {
+                       fprintf(stderr, "failed to open magic file: %s\n",
+                               magic_error(magic_state));
+                       exit(1);
+               }
+       }
+#endif /* USE_MAGIC */
+
+       /* set defaults */
+       map_num = last_ent = 0;
+
+       /* allocate memory for the default entry */
+       defmap = (afpmap *) e_malloc(sizeof (afpmap));
+
+       /* set default values */
+       defmap->extn = DEFMATCH;
+
+       /* make sure creator and type are 4 chars long */
+       strcpy(defmap->type, BLANK);
+       strcpy(defmap->creator, BLANK);
+
+       e = deftype;
+       t = defmap->type;
+
+       while (*e && (e - deftype) < CT_SIZE)
+               *t++ = *e++;
+
+       e = defcreator;
+       c = defmap->creator;
+
+       while (*e && (e - defcreator) < CT_SIZE)
+               *c++ = *e++;
+
+       /* length is not important here */
+       defmap->elen = 0;
+
+       /* no flags */
+       defmap->fdflags = fdflags;
+
+       /* no afpfile - no mappings */
+       if (*name == '\0') {
+               map = NULL;
+               return;
+       }
+       if ((fp = fopen(name, "r")) == NULL)
+               perr("unable to open mapping file");
+
+       map = (afpmap **) e_malloc(NUMMAP * sizeof (afpmap *));
+
+       /* read afpfile line by line */
+       while (fgets(buf, PATH_MAX, fp) != NULL) {
+               /* ignore any comment lines */
+               c = tmp;
+               *c = '\0';
+               if (sscanf(buf, "%1s", c) == EOF || *c == '#')
+                       continue;
+
+               /* increase list size if needed */
+               if (map_num == count) {
+                       count += NUMMAP;
+                       map = (afpmap **)realloc(map, count * sizeof (afpmap *));
+                       if (map == NULL)
+                               perr("not enough memory");
+               }
+               /* allocate memory for this entry */
+               amap = (afpmap *) e_malloc(sizeof (afpmap));
+
+               t = amap->type;
+               c = amap->creator;
+
+               /* extract the info */
+               if (sscanf(buf, "%s%*s%*1s%c%c%c%c%*1s%*1s%c%c%c%c%*1s",
+                               tmp, c, c + 1, c + 2, c + 3,
+                               t, t + 1, t + 2, t + 3) != 9) {
+                       fprintf(stderr,
+                               "error scanning afpfile %s - continuing", name);
+                       free(amap);
+                       continue;
+               }
+               /* copy the extension found */
+               if ((amap->extn = (char *) strdup(tmp)) == NULL)
+                       perr("not enough memory");
+
+               /* set end-of-string */
+               *(t + 4) = *(c + 4) = '\0';
+
+               /* find the length of the extension */
+               amap->elen = strlen(amap->extn);
+
+               /* set flags */
+               amap->fdflags = fdflags;
+
+               /* see if we have the default creator/type */
+               if (strcmp(amap->extn, DEFMATCH) == 0) {
+                       /* get rid of the old default */
+                       free(defmap);
+                       /* make this the default */
+                       defmap = amap;
+                       continue;
+               }
+               /* update the smallest extension length */
+               mlen = MIN(mlen, amap->elen);
+
+               /* add entry to the list */
+               map[map_num++] = amap;
+
+       }
+
+       /* free up some memory */
+       if (map_num != count) {
+               map = (afpmap **) realloc(map, map_num * sizeof (afpmap *));
+               if (map == NULL)
+                       perr("not enough memory");
+       }
+}
+
+#ifdef USE_MAGIC
+static int
+try_map_magic(char *whole_name, char **type, /* set type */
+                                 char **creator /* set creator */)
+{
+       const char * ret = magic_file(magic_state, whole_name);
+
+#ifdef DEBUG
+       fprintf(stderr, "magic_file(magic_state, \"%s\"): %s\n",
+               whole_name, ret ? ret : "NULL");
+#endif
+       /*
+        * check that we found a match; ignore results in the
+        * wrong format (probably due to libmagic's built-in rules)
+        */
+       if (ret && strcspn(ret, " ") == CT_SIZE
+           && ret[CT_SIZE] == ' '
+           && strcspn(ret + CT_SIZE + 1, " ") == CT_SIZE) {
+               memcpy(tmp_type, ret, CT_SIZE);
+               tmp_type[CT_SIZE] = 0;
+               memcpy(tmp_creator, ret + CT_SIZE + 1, CT_SIZE);
+               tmp_creator[CT_SIZE] = 0;
+#ifdef DEBUG
+               fprintf(stderr, "tmp_type = \"%s\"; tmp_creator = \"%s\"\n",
+                       tmp_type, tmp_creator);
+#endif
+               *type = tmp_type;
+               *creator = tmp_creator;
+               return (1);
+       }
+
+       return (0);
+}
+#endif /* USE_MAGIC */
+
+/*
+ *     map_ext: map a files extension with the list to get type/creator
+ */
+static void
+map_ext(char *name, /* filename */
+                 char **type, /* set type */
+                 char **creator, /* set creator */
+                 short *fdflags, /* set finder flags */
+                 char *whole_name)
+{
+       int     i;              /* loop counter */
+       int     len;            /* filename length */
+       afpmap  *amap;          /* mapping entry */
+       const char      *ret;
+
+       /* we don't take fdflags from the map or magic file */
+       *fdflags = defmap->fdflags;
+
+#ifdef USE_MAGIC
+       /*
+        * if we have a magic file and we want to search it first,
+        * then try to get a match
+        */
+       if (magic_state && hfs_last == MAP_LAST
+           && try_map_magic(whole_name, type, creator))
+                               return;
+#endif /* USE_MAGIC */
+
+       len = strlen(name);
+
+       /* have an afpfile and filename if long enough */
+       if (map && len >= mlen) {
+               /*
+                * search through the list - we start where we left off
+                * last time in case this file is of the same type as the
+                * last one
+                */
+               for (i = 0; i < map_num; i++) {
+                       amap = map[last_ent];
+
+                       /* compare the end of the filename */
+/*                     if (strcmp((name+len - amap->elen), amap->extn) == 0) { */
+                       if (strcasecmp((name+len - amap->elen), amap->extn) == 0) {
+                               /* set the required info */
+                               *type = amap->type;
+                               *creator = amap->creator;
+                               *fdflags = amap->fdflags;
+                               return;
+                       }
+                       /*
+                        * move on to the next entry - wrapping round
+                        * if neccessary
+                        */
+                       last_ent++;
+                       last_ent %= map_num;
+               }
+       }
+       /*
+        * if no matches are found, file name too short, or no afpfile,
+        * then take defaults
+        */
+       *type = defmap->type;
+       *creator = defmap->creator;
+
+#ifdef USE_MAGIC
+       /*
+        * if we have a magic file and we haven't searched yet,
+        * then try to get a match
+        */
+       if (magic_state && hfs_last == MAG_LAST)
+               try_map_magic(whole_name, type, creator);
+#endif /* USE_MAGIC */
+}
+
+void
+delete_rsrc_ent(dir_ent *s_entry)
+{
+       dir_ent *s_entry1 = s_entry->next;
+
+       if (s_entry1 == NULL)
+               return;
+
+       s_entry->next = s_entry1->next;
+       s_entry->assoc = NULL;
+
+       free(s_entry1->name);
+       free(s_entry1->whole_name);
+
+       free(s_entry1);
+}
+
+void
+clean_hfs()
+{
+       if (map)
+               free(map);
+
+       if (defmap)
+               free(defmap);
+
+#ifdef USE_MAGIC
+       if (magic_state) {
+               magic_close(magic_state);
+               magic_state = NULL;
+       }
+#endif /* USE_MAGIC */
+}
+
+#endif /* APPLE_HYB */
+
+void
+perr(char *a)
+{
+#ifdef USE_LIBSCHILY
+       if (a)
+               comerr("%s\n", a);
+       else
+               comerr("<no error message given>\n");
+#else
+       if (a)
+               fprintf(stderr, "mkhybrid: %s\n", a);
+       perror("mkhybrid");
+       exit(1);
+#endif
+}
diff --git a/genisoimage/apple.h b/genisoimage/apple.h
new file mode 100644 (file)
index 0000000..685a812
--- /dev/null
@@ -0,0 +1,386 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)apple.h 1.7 04/03/02 joerg, Copyright 1997, 1998, 1999, 2000 James Pearson */
+/*
+ *      Copyright (c) 1997, 1998, 1999, 2000 James Pearson
+ *
+ * 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; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * apple.h:    cut down macfile.h from CAP distribution
+ */
+#ifndef        _APPLE_H
+#define        _APPLE_H
+
+#include "mactypes.h"
+
+#ifndef        O_BINARY
+#define        O_BINARY 0
+#endif /* O_BINARY */
+
+#ifdef _WIN32_TEST
+#undef UNICODE
+#include <windows.h>
+#endif /* _WIN32 */
+
+#ifndef        MIN
+#define        MIN(a, b) (((a) < (b)) ? (a):(b))
+#endif /* MIN */
+
+#define        CT_SIZE         4                       /* Size of type/creator */
+#define        NUMMAP          512                     /* initial number of maps */
+#define        BLANK           "    "                  /* blank type/creator */
+#define        DEFMATCH        "*"                     /* default mapping extension */
+
+typedef struct {
+       char            *extn;                  /* filename extension */
+       int             elen;                   /* length of extension */
+       char            type[CT_SIZE+1];        /* extension type */
+       char            creator[CT_SIZE+1];     /* extension creator */
+       unsigned short  fdflags;                /* finder flags */
+} afpmap;
+
+/* from "data.h" - libhfs routines */
+unsigned long d_toutime(unsigned long);
+unsigned long d_dtoutime(long);
+long d_getl(unsigned char *);
+short d_getw(unsigned char *);
+
+/* for libfile routines */
+int init_magic(char *);
+char * get_magic_match(const char *);
+
+typedef unsigned char byte;
+typedef unsigned char word[2];
+typedef unsigned char dword[4];
+
+#define        INFOLEN 32              /* Finder info is 32 bytes */
+
+typedef struct {
+       /* base finder information */
+       char fdType[4];                 /* File type [4] */
+       char fdCreator[4];              /* File creator [8] */
+       word fdFlags;                   /* Finder flags [10] */
+       word fdLocation[2];             /* File's location [14] */
+       word fdFldr;                    /* File's window [16] */
+       /* extended finder information */
+       word fdIconID;                  /* Icon ID [18] */
+       word fdUnused[3];               /* Unused [24] */
+       byte fdScript;                  /* Script system used [25] */
+       byte fdXFlags;                  /* Reserved [26] */
+       word fdComment;                 /* Comment ID [28] */
+       dword fdPutAway;                /* Home directory ID [32] */
+} Finfo;
+
+typedef struct {
+       /* base finder information */
+       word frRect[4];                 /* Folder's rectangle [8] */
+       word frFlags;                   /* Finder flags [10] */
+       word frLocation[2];             /* Folder's location [14] */
+       word frView;                    /* Folder's view [16] */
+       /* extended finder information */
+       word frScroll[2];               /* Folder's scroll position [20] */
+       dword frOpenChain;              /* ID's of open folders [24] */
+       byte frScript;                  /* Script system used [25] */
+       byte frXFlags;                  /* Reserved [26] */
+       word frComment;                 /* Comment ID [28] */
+       dword frPutAway;                /* Home directory ID [32] */
+} Dinfo;
+
+/****** TYPE_CAP ******/
+
+/*
+ * taken from the CAP distribution:
+ * macfile.h - header file with Macintosh file definitions
+ *
+ * AppleTalk package for UNIX (4.2 BSD).
+ *
+ * Copyright (c) 1986, 1987, 1988 by The Trustees of Columbia University in the
+ * City of New York.
+ *
+ * Edit History:
+ *
+ *  Sept 1987  Created by Charlie
+ *
+ */
+
+
+#ifndef        USE_MAC_DATES
+#define        USE_MAC_DATES
+#endif /* USE_MAC_DATES */
+
+#define        MAXCLEN 199             /* max size of a comment string */
+#define        FINFOLEN 32             /* Finder info is 32 bytes */
+#define        MAXMACFLEN 31           /* max Mac file name length */
+
+typedef struct {
+       byte    finderinfo[INFOLEN];    /* Finder info */
+       word    fi_attr;                /* attributes */
+#define        FI_MAGIC1 255
+       byte    fi_magic1;              /* was: length of comment */
+#define        FI_VERSION 0x10                 /* version major 1, minor 0 */
+                                       /* if we have more than 8 versions wer're */
+                                       /* doiong something wrong anyway */
+       byte    fi_version;             /* version number */
+#define        FI_MAGIC 0xda
+       byte    fi_magic;               /* magic word check */
+       byte    fi_bitmap;              /* bitmap of included info */
+#define        FI_BM_SHORTFILENAME 0x1         /* is this included? */
+#define        FI_BM_MACINTOSHFILENAME 0x2     /* is this included? */
+       byte    fi_shortfilename[12+1]; /* possible short file name */
+       byte    fi_macfilename[32+1];   /* possible macintosh file name */
+       byte    fi_comln;               /* comment length */
+       byte    fi_comnt[MAXCLEN+1];    /* comment string */
+#ifdef USE_MAC_DATES
+       byte    fi_datemagic;           /* sanity check */
+#define        FI_MDATE 0x01                   /* mtime & utime are valid */
+#define        FI_CDATE 0x02                   /* ctime is valid */
+       byte    fi_datevalid;           /* validity flags */
+       byte    fi_ctime[4];            /* mac file create time */
+       byte    fi_mtime[4];            /* mac file modify time */
+       byte    fi_utime[4];            /* (real) time mtime was set */
+#endif /* USE_MAC_DATES */
+} FileInfo;
+
+/* Atribute flags */
+#define        FI_ATTR_SETCLEAR 0x8000 /* set-clear attributes */
+#define        FI_ATTR_READONLY 0x20   /* file is read-only */
+#define        FI_ATTR_ROPEN 0x10      /* resource fork in use */
+#define        FI_ATTR_DOPEN 0x80      /* data fork in use */
+#define        FI_ATTR_MUSER 0x2       /* multi-user */
+#define        FI_ATTR_INVISIBLE 0x1   /* invisible */
+
+/**** MAC STUFF *****/
+
+/* Flags */
+#define        FNDR_fOnDesk 0x1
+#define        FNDR_fHasBundle 0x2000
+#define        FNDR_fInvisible 0x4000
+/* locations */
+#define        FNDR_fTrash -3  /* File in Trash */
+#define        FNDR_fDesktop -2        /* File on desktop */
+#define        FNDR_fDisk 0    /* File in disk window */
+
+/****** TYPE_ESHARE ******/
+
+/*
+ *     Information supplied by Jens-Uwe Mager (jum@helios.de)
+ */
+
+#define        ES_VERSION      0x0102
+#define        ES_MAGIC        0x3681093
+#define        ES_INFOLEN      32
+#define        ES_INFO_SIZE    512
+
+typedef struct {
+       dword           magic;
+       dword           serno;                  /* written only, never read */
+       word            version;
+       word            attr;                   /* invisible... */
+       word            openMax;                /* max number of opens */
+       word            filler0;
+       dword           backupCleared;          /* time backup bit cleared */
+       dword           id;                     /* dir/file id */
+       dword           createTime;             /* unix format */
+       dword           backupTime;             /* unix format */
+       byte            finderinfo[INFOLEN];    /* Finder info */
+} es_FileInfo;
+
+/****** TYPE_USHARE ******/
+
+/*
+ * similar to the EtherShare layout, but the finder info stuff is different
+ * info provided by: Phil Sylvester <psylvstr@interaccess.com>
+ */
+
+typedef struct {
+       byte            finderinfo[INFOLEN];    /* Finder info */
+       dword           btime;                  /* mac file backup time [36]*/
+       byte            unknown2[4];            /* ignore [40] */
+       dword           ctime;                  /* mac file create time [44]*/
+       byte            unknown3[8];            /* ignore [52] */
+       dword           mtime;                  /* mac file modify time [56]*/
+       byte            unknown4[456];          /* ignore [512] */
+} us_FileInfo;
+
+/****** TYPE_DOUBLE, TYPE_SINGLE ******/
+
+/*
+ *     Taken from cvt2cap (c) May 1988, Paul Campbell
+ */
+
+typedef struct {
+       dword id;
+       dword offset;
+       dword length;
+} a_entry;
+
+typedef struct {
+       dword   magic;
+       dword   version;
+       char    home[16];
+       word    nentries;
+       a_entry entries[1];
+} a_hdr;
+
+#define        A_HDR_SIZE      26
+#define        A_ENTRY_SIZE    sizeof (a_entry)
+
+#define        A_VERSION1      0x00010000
+#define        A_VERSION2      0x00020000
+#define        APPLE_SINGLE    0x00051600
+#define        APPLE_DOUBLE    0x00051607
+#define        ID_DATA         1
+#define        ID_RESOURCE     2
+#define        ID_NAME         3
+#define        ID_FILEI        7       /* v1 */
+#define        ID_FILEDATESI   8       /* v2 */
+#define        ID_FINDER       9
+
+#define        A_DATE          16
+
+/****** TYPE_MACBIN ******/
+/*
+ *     taken from capit.c by Nigel Perry, np@doc.ic.ac.uk which is adapted
+ *     from unmacbin by John M. Sellens, jmsellens@watdragon.uwaterloo.ca
+ */
+
+
+#define        MB_NAMELEN 63           /* maximum legal Mac file name length */
+#define        MB_SIZE 128
+
+/*
+ * Format of a bin file:
+ * A bin file is composed of 128 byte blocks.  The first block is the
+ * info_header (see below).  Then comes the data fork, null padded to fill the
+ * last block.  Then comes the resource fork, padded to fill the last block.  A
+ * proposal to follow with the text of the Get Info box has not been implemented,
+ * to the best of my knowledge.  Version, zero1 and zero2 are what the receiving
+ * program looks at to determine if a MacBinary transfer is being initiated.
+ */
+typedef struct {               /* info file header (128 bytes). Unfortunately, these */
+                               /* longs don't align to word boundaries */
+       byte version;           /* there is only a version 0 at this time */
+       byte nlen;              /* Length of filename. */
+       byte name[MB_NAMELEN];  /* Filename */
+       byte type[4];           /* File type. */
+       byte auth[4];           /* File creator. */
+       byte flags;             /* file flags: LkIvBnSyBzByChIt */
+       byte zero1;             /* Locked, Invisible,Bundle, System */
+                               /* Bozo, Busy, Changed, Init */
+       byte icon_vert[2];      /* Vertical icon position within window */
+       byte icon_horiz[2];     /* Horizontal icon postion in window */
+       byte window_id[2];      /* Window or folder ID. */
+       byte protect;           /* = 1 for protected file, 0 otherwise */
+       byte zero2;
+       byte dflen[4];          /* Data Fork length (bytes) - most sig.  */
+       byte rflen[4];          /* Resource Fork length byte first */
+       byte cdate[4];          /* File's creation date. */
+       byte mdate[4];          /* File's "last modified" date. */
+       byte ilen[2];           /* GetInfo message length */
+       byte flags2;            /* Finder flags, bits 0-7 */
+       byte unused[14];
+       byte packlen[4];        /* length of total files when unpacked */
+       byte headlen[2];        /* length of secondary header */
+       byte uploadvers;        /* Version of MacBinary II that the uploading program is written for */
+       byte readvers;          /* Minimum MacBinary II version needed to read this file */
+       byte crc[2];            /* CRC of the previous 124 bytes */
+       byte padding[2];        /* two trailing unused bytes */
+} mb_info;
+
+/****** TYPE_FE ******/
+
+/* Information provided by Mark Weinstein <mrwesq@earthlink.net> */
+
+typedef struct {
+       byte    nlen;
+       byte    name[31];
+       byte    finderinfo[INFOLEN];    /* Finder info */
+       byte    cdate[4];
+       byte    mdate[4];
+       byte    bdate[4];
+       byte    fileid[4];
+       byte    sname[8];
+       byte    ext[3];
+       byte    pad;
+} fe_info;
+
+#define        FE_SIZE 92
+
+/****** TYPE_SGI ******/
+
+typedef struct {
+       byte    unknown1[8];
+       byte    finderinfo[INFOLEN];    /* Finder info */
+       byte    unknown2[214];
+       byte    name[32];
+       byte    unknown3[14];
+} sgi_info;
+
+#define        SGI_SIZE 300
+
+/****** TYPE_SFM ******/
+
+/*
+ * Information provided by Lou Rieger <lrieger@meridiancg.com> taken from
+ * an email from Eddie Bowers <eddieb@microsoft.com>
+ */
+
+typedef struct {
+       byte    afpi_Signature[4];      /* Must be 0x00504641 */
+       byte    afpi_Version[4];        /* Must be 0x00010000 */
+       byte    afpi_Reserved1[4];
+       byte    afpi_BackupTime[4];     /* Backup time for the file/dir */
+       byte    finderinfo[INFOLEN];    /* Finder info */
+       byte    afpi_ProDosInfo[6];     /* ProDos Info */
+       byte    afpi_Reserved2[6];
+} sfm_info;
+
+#define        SFM_MAGIC       0x00504641
+#define        SFM_VERSION     0x00010000
+
+/****** TYPE_DHFS ******/
+
+#ifdef IS_MACOS_X
+
+/*
+ *     Code ideas from 'hfstar' by Marcel Weiher marcel@metaobject.com,
+ *     another GNU hfstar by Torres Vedras paulotex@yahoo.com and
+ *     hfspax by Howard Oakley howard@quercus.demon.co.uk
+ */
+
+#include <sys/attr.h>
+
+typedef struct {
+       unsigned long   info_length;
+       struct timespec ctime;
+       struct timespec mtime;
+       byte            info[32];
+} attrinfo;
+
+#endif /* IS_MACOS_X */
+
+#endif /* _APPLE_H */
diff --git a/genisoimage/apple_driver.8 b/genisoimage/apple_driver.8
new file mode 100644 (file)
index 0000000..773a074
--- /dev/null
@@ -0,0 +1,72 @@
+'\" te
+.\" To print, first run through tbl
+.TH APPLE_DRIVER 8 "18 May 1998" "Version 1.0"
+.SH NAME
+apple_driver \- extract Macintosh partition label, maps and boot driver
+.SH SYNOPSIS
+.B apple_driver
+CDROM_device > HFS_driver_file
+.SH DESCRIPTION
+.I Apple_driver
+extracts the information from an Apple (or compatible) CD-ROM required
+for the
+.I \-hfs-boot-file
+option to
+.IR mkhybrid (1). 
+.PP
+The 
+.I CDROM_device
+is the device name used by the CD-ROM (e.g. /dev/cdrom).
+.PP
+The format of the HFS driver file is:
+.PP
+.TS
+l l .
+HFS CD Label Block     512 bytes
+Driver Partition Map (for 2048 byte blocks)    512 bytes
+Driver Partition Map (for 512 byte blocks)     512 bytes
+Empty  512 bytes
+Driver Partition       N x 2048 bytes
+HFS Partition Boot Block       1024 bytes
+.TE
+.PP
+The Perl script
+.I hdisk.pl
+can be used to give a listing of what's on a Mac CD. hdisk.pl is part of
+hfsutils.
+.SH NOTE
+By using a driver from an Apple CD and copying Apple software to your CD,
+you become liable to obey Apple Computer, Inc. Software License Agreements.
+
+.SH SEE\ ALSO
+.IR mkhybrid (1)
+.SH PROGRAMMER
+James Pearson (j.pearson@ge.ucl.ac.uk) 18/5/98
+.PP
+The driver code (both extracting the driver and creating partitions etc.
+is based on code from 
+.I genisoimage 1.05 PLUS
+by Andy Polyakov <appro@fy.chalmers.se>
+(see http://fy.chalmers.se/~appro/genisoimage_plus.html)
+.PP
+This manpage describes the program implementation of
+.B
+apple_driver
+as shipped by the cdrkit distribution. See
+.B
+http://alioth.debian.org/projects/debburn/
+for details. It is a spinof from the original program distributed by the cdrtools project. However, the cdrtools developers are not involved in the development of this spinoff and therefore shall not be made responsible for any problem caused by it. Do not try to get support for this program by contacting the original authors.
+.PP
+If you have support questions, send them to
+.PP
+.B
+debburn-devel@lists.alioth.debian.org
+.br
+.PP
+If you have definitely found a bug, send a mail to this list or to
+.PP
+.B
+submit@bugs.debian.org
+.br
+.PP
+writing at least a short description into the Subject and "Package: cdrkit" into the first line of the mail body.
diff --git a/genisoimage/apple_driver.c b/genisoimage/apple_driver.c
new file mode 100644 (file)
index 0000000..24f8544
--- /dev/null
@@ -0,0 +1,190 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)apple_driver.c  1.6 04/03/04 joerg */
+/*
+ *     apple_driver.c: extract Mac partition label, maps and boot driver
+ *
+ *     Based on Apple_Driver.pl, part of "genisoimage 1.05 PLUS" by Andy Polyakov
+ *     <appro@fy.chalmers.se> (I don't know Perl, so I rewrote it C ...)
+ *     (see http://fy.chalmers.se/~appro/genisoimage_plus.html for details)
+ *
+ *     usage: apple_driver CDROM_device > HFS_driver_file
+ *
+ *     The format of the HFS driver file:
+ *
+ *     HFS CD Label Block                              512 bytes
+ *     Driver Partition Map (for 2048 byte blocks)     512 bytes
+ *     Driver Partition Map (for 512 byte blocks)      512 bytes
+ *     Empty                                           512 bytes
+ *     Driver Partition                                N x 2048 bytes
+ *     HFS Partition Boot Block                        1024 bytes
+ *
+ *     By extracting a driver from an Apple CD, you become liable to obey
+ *     Apple Computer, Inc. Software License Agreements.
+ *
+ *     James Pearson 17/5/98
+ */
+
+#include <mconfig.h>
+#include "genisoimage.h"
+#include <mac_label.h>
+#include <schily.h>
+
+int    get_732(char *p);
+int    get_722(char *p);
+
+int
+get_732(char *p)
+{
+       return ((p[3] & 0xff)
+               | ((p[2] & 0xff) << 8)
+               | ((p[1] & 0xff) << 16)
+               | ((p[0] & 0xff) << 24));
+}
+
+int
+get_722(char *p)
+{
+       return ((p[1] & 0xff)
+               | ((p[0] & 0xff) << 8));
+}
+
+#if 0
+EXPORT int
+main(argc, argv)
+       int     argc;
+       char    **argv;
+{
+       FILE            *fp;
+       MacLabel        *mac_label;
+       MacPart         *mac_part;
+       unsigned char   Block0[HFS_BLOCKSZ];
+       unsigned char   block[SECTOR_SIZE];
+       unsigned char   bootb[2*HFS_BLOCKSZ];
+       unsigned char   pmBlock512[HFS_BLOCKSZ];
+       unsigned int    sbBlkSize;
+       unsigned int    pmPyPartStart;
+       unsigned int    pmPartStatus;
+       unsigned int    pmMapBlkCnt;
+       int             have_boot = 0, have_hfs = 0;
+       int             hfs_start;
+       int             i, j;
+
+
+       save_args(argc, argv);
+
+       if (argc != 2)
+           comerrno(EX_BAD, "Usage: %s device-path", argv[0]);
+
+       if ((fp = fopen(argv[1], "rb")) == NULL)
+           comerr("Can't open '%s'.", argv[1]);
+
+       if (fread(Block0, 1, HFS_BLOCKSZ, fp) != HFS_BLOCKSZ)
+           comerr("Can't read '%s'.", argv[1]);
+
+       mac_label = (MacLabel *)Block0;
+       mac_part = (MacPart *)block;
+
+       sbBlkSize = get_722((char *)mac_label->sbBlkSize);
+
+       if (! IS_MAC_LABEL(mac_label) || sbBlkSize != SECTOR_SIZE)
+           comerrno(EX_BAD, "%s is not a bootable Mac disk", argv[1]);
+
+       i = 1;
+       do {
+               if (fseek(fp, i * HFS_BLOCKSZ, SEEK_SET) != 0)
+                       comerr("Ccan't seek %s", argv[1]);
+
+               if (fread(block, 1, HFS_BLOCKSZ, fp) != HFS_BLOCKSZ)
+                       comerr("Can't read '%s'.", argv[1]);
+
+               pmMapBlkCnt = get_732((char *)mac_part->pmMapBlkCnt);
+
+               if (!have_boot && strncmp((char *)mac_part->pmPartType, pmPartType_2, 12) == 0) {
+                       hfs_start = get_732((char *)mac_part->pmPyPartStart);
+
+                       fprintf(stderr, "%s: found 512 driver partition (at block %d)\n", argv[0], hfs_start);
+                       memcpy(pmBlock512, block, HFS_BLOCKSZ);
+                       have_boot = 1;
+               }
+
+               if (!have_hfs && strncmp((char *)mac_part->pmPartType, pmPartType_4, 9) == 0) {
+
+                       hfs_start = get_732((char *)mac_part->pmPyPartStart);
+
+                       if (fseek(fp, hfs_start*HFS_BLOCKSZ, SEEK_SET) != 0)
+                               comerr("Can't seek '%s'.", argv[1]);
+
+                       if (fread(bootb, 2, HFS_BLOCKSZ, fp) != HFS_BLOCKSZ)
+                               comerr("Can't read '%s'.", argv[1]);
+
+                       if (get_722((char *)bootb) == 0x4c4b) {
+
+                               fprintf(stderr, "%s: found HFS partition (at blk %d)\n", argv[0], hfs_start);
+                               have_hfs = 1;
+                       }
+               }
+       } while (i++ < pmMapBlkCnt);
+
+       if (!have_hfs || !have_boot)
+               comerrno(EX_BAD, "%s is not a bootable Mac disk", argv[1]);
+
+       i = 1;
+
+       do {
+               if (fseek(fp, i*sbBlkSize, SEEK_SET) != 0)
+                       comerr("Can't seek '%s'.", argv[1]);
+
+               if (fread(block, 1, HFS_BLOCKSZ, fp) != HFS_BLOCKSZ)
+                       comerr("Can't read '%s'.", argv[1]);
+
+               pmMapBlkCnt = get_732((char *)mac_part->pmMapBlkCnt);
+
+               if (strncmp((char *)mac_part->pmPartType, pmPartType_2, 12) == 0) {
+
+                       int     start, num;
+
+                       fprintf(stderr, "%s: extracting %s ", argv[0], mac_part->pmPartType);
+                       start = get_732((char *)mac_part->pmPyPartStart);
+                       num = get_732((char *)mac_part->pmPartBlkCnt);
+                       fwrite(Block0, 1, HFS_BLOCKSZ, stdout);
+                       fwrite(block, 1, HFS_BLOCKSZ, stdout);
+                       fwrite(pmBlock512, 1, HFS_BLOCKSZ, stdout);
+                       memset(block, 0, HFS_BLOCKSZ);
+                       fwrite(block, 1, HFS_BLOCKSZ, stdout);
+
+                       if (fseek(fp, start*sbBlkSize, SEEK_SET) != 0)
+                               comerr("Can't seek '%s'.", argv[1]);
+
+                       for (j = 0; j < num; j++) {
+                               if (fread(block, 1, sbBlkSize, fp) != sbBlkSize)
+                                       comerr("Can't read '%s'.", argv[1]);
+
+                               fwrite(block, 1, sbBlkSize, stdout);
+                               fprintf(stderr, ".");
+                       }
+                       fprintf(stderr, "\n");
+
+                       fwrite(bootb, 2, HFS_BLOCKSZ, stdout);
+                       fclose(fp);
+                       exit(0);
+               }
+
+               if (!IS_MAC_PART(mac_part))
+                       comerrno(EX_BAD, "Unable to find boot partition");
+
+       } while (i++ < pmMapBlkCnt);
+
+       return (0);
+}
+#endif
diff --git a/genisoimage/boot-alpha.c b/genisoimage/boot-alpha.c
new file mode 100644 (file)
index 0000000..cfd4862
--- /dev/null
@@ -0,0 +1,137 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/*
+ * Program boot-alpha.c - Handle Linux alpha boot extensions to iso9660.
+ *
+ * Written by Steve McIntyre <steve@einval.com> June 2004
+ *
+ * Heavily inspired by isomarkboot by David Mosberger in 1996.
+ *
+ * Copyright 2004 Steve McIntyre
+ *
+ * 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 <mconfig.h>
+#include "genisoimage.h"
+#include <fctldefs.h>
+#include <utypes.h>
+#include <intcvt.h>
+#include "match.h"
+#include "diskmbr.h"
+#include "bootinfo.h"
+#include <schily.h>
+#include "endianconv.h"
+
+        int     add_boot_alpha_filename(char *filename);
+static  int     boot_alpha_write(FILE *outfile);
+static  int     boot_alpha_hppa_write(FILE *outfile);
+static  char   *boot_file_name = NULL;
+
+unsigned long long alpha_hppa_boot_sector[256]; /* One (ISO) sector */
+int boot_sector_initialized = 0;
+
+#define BOOT_STRING "Linux/Alpha aboot for ISO filesystem."
+
+/* Simple function: store the filename to be used later when we need
+   to find the boot file */
+extern int add_boot_alpha_filename(char *filename)
+{
+    boot_file_name = filename;
+    return 0;
+}
+
+static int boot_alpha_write(FILE *outfile)
+{
+    struct directory_entry     *boot_file;     /* Boot file we need to search for */
+    unsigned long length = 0;
+    unsigned long extent = 0;
+
+    if (!boot_sector_initialized) {
+       memset(alpha_hppa_boot_sector, 0, sizeof(alpha_hppa_boot_sector));
+       boot_sector_initialized = 1;
+    }
+
+    /* Write the text header into the boot sector */
+    strcpy((char *)alpha_hppa_boot_sector, BOOT_STRING);
+
+    /* Find the dir entry for the boot file by walking our file list */
+    boot_file = search_tree_file(root, boot_file_name);
+    if (!boot_file) {
+#ifdef USE_LIBSCHILY
+               comerrno(EX_BAD, "Uh oh, I cant find the Alpha boot file '%s'!\n",
+                                                       boot_file_name);
+#else
+               fprintf(stderr, "Uh oh, I cant find the Alpha boot file '%s'!\n",
+                                                       boot_file_name);
+               exit(1);
+#endif
+    }
+
+    /* Grab the ISO start sector and length from the dir entry. ISO
+       uses 2048-byte sectors, but we convert to 512-byte sectors here
+       for the sake of the firmware */
+    extent = get_733(boot_file->isorec.extent);
+    extent *= 4;
+    
+    length = get_733(boot_file->isorec.size);
+    length /= 512; /* I'm sure we should take account of any overlap
+                      here, but I'm copying what isomarkboot
+                      does. Maybe the boot files are specified to be
+                      exact multiples of 512 bytes? */
+
+    fprintf(stderr, "Found alpha boot image %s: using extent %lu, #blocks %lu\n",
+            boot_file_name, extent, length);
+
+    /* Now write those values into the appropriate area of the boot
+       sector in LITTLE ENDIAN format. */
+    write_le64(length, (unsigned char *)&alpha_hppa_boot_sector[60]);
+    write_le64(extent, (unsigned char *)&alpha_hppa_boot_sector[61]);
+
+    return 0;
+}
+
+static int boot_alpha_hppa_write(FILE *outfile)
+{
+    unsigned long long sum = 0;
+    int i = 0;
+
+    /* Now generate a checksum of the first 504 bytes of the boot
+       sector and place it in alpha_hppa_boot_sector[63]. Isomarkboot currently
+       gets this wrong and will not work on big-endian systems! */
+    for (i = 0; i < 63; i++)
+        sum += read_le64((unsigned char *)&alpha_hppa_boot_sector[i]);
+
+    write_le64(sum, (unsigned char *)&alpha_hppa_boot_sector[63]);
+
+    jtwrite(alpha_hppa_boot_sector, sizeof(alpha_hppa_boot_sector), 1, 0, FALSE);
+    xfwrite(alpha_hppa_boot_sector, sizeof(alpha_hppa_boot_sector), 1, outfile, 0, FALSE);
+    last_extent_written++;
+
+    return 0;
+}
+
+struct output_fragment alphaboot_desc = {NULL, NULL, NULL, boot_alpha_write, "alpha boot block"};
+struct output_fragment alpha_hppa_boot_desc = {NULL, oneblock_size, NULL, boot_alpha_hppa_write, "alpha/hppa boot block"};
diff --git a/genisoimage/boot-hppa.c b/genisoimage/boot-hppa.c
new file mode 100644 (file)
index 0000000..5f3bd1c
--- /dev/null
@@ -0,0 +1,207 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/*
+ * Program boot-hppa.c - Handle HPPA boot extensions to iso9660.
+ *
+ * Written by Steve McIntyre <steve@einval.com> June 2004.
+ *
+ * Heavily inspired by palo:
+ *
+ ****************************************************************************
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) Hewlett-Packard (Paul Bame) paul_bame@hp.com
+ *
+ ****************************************************************************
+ * Copyright 2004 Steve McIntyre
+ *
+ * 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 <mconfig.h>
+#include "genisoimage.h"
+#include <fctldefs.h>
+#include <utypes.h>
+#include <intcvt.h>
+#include "match.h"
+#include "diskmbr.h"
+#include "bootinfo.h"
+#include <schily.h>
+#include "endianconv.h"
+
+extern long long alpha_hppa_boot_sector[256];
+extern int boot_sector_initialized;
+
+int     add_boot_hppa_cmdline(char *cmdline);
+int     add_boot_hppa_kernel_32(char *filename);
+int     add_boot_hppa_kernel_64(char *filename);
+int     add_boot_hppa_bootloader(char *filename);
+int     add_boot_hppa_ramdisk(char *filename);
+
+static  int     boot_hppa_write(FILE *outfile);
+
+static  char   *hppa_cmdline = NULL;
+static  char   *hppa_kernel_32 = NULL;
+static  char   *hppa_kernel_64 = NULL;
+static  char   *hppa_bootloader = NULL;
+static  char   *hppa_ramdisk = NULL;
+
+/* Simple function: store the filename to be used later when we need
+   to find the boot file */
+extern int add_boot_hppa_cmdline(char *cmdline)
+{
+    char *ptr = NULL;
+    hppa_cmdline = strdup(cmdline);
+    ptr = hppa_cmdline;
+    while (*ptr)
+    {
+        if (',' == *ptr)
+            *ptr = ' ';
+        ptr++;
+    }    
+    return 0;
+}
+
+/* Simple function: store the filename to be used later when we need
+   to find the boot file */
+extern int add_boot_hppa_kernel_32(char *filename)
+{
+    hppa_kernel_32 = filename;
+    return 0;
+}
+
+/* Simple function: store the filename to be used later when we need
+   to find the boot file */
+extern int add_boot_hppa_kernel_64(char *filename)
+{
+    hppa_kernel_64 = filename;
+    return 0;
+}
+
+/* Simple function: store the filename to be used later when we need
+   to find the boot file */
+extern int add_boot_hppa_bootloader(char *filename)
+{
+    hppa_bootloader = filename;
+    return 0;
+}
+
+/* Simple function: store the filename to be used later when we need
+   to find the boot file */
+extern int add_boot_hppa_ramdisk(char *filename)
+{
+    hppa_ramdisk = filename;
+    return 0;
+}
+
+static void exit_fatal(char *type, char *filename)
+{
+#ifdef USE_LIBSCHILY
+    comerrno(EX_BAD, "Uh oh, I can't find the %s '%s'!\n",
+             type, filename);
+#else
+    fprintf(stderr, "Uh oh, I can't find the %s '%s'!\n",
+             type, filename);
+    exit(1);
+#endif
+}
+
+static int boot_hppa_write(FILE *outfile)
+{
+    struct directory_entry     *boot_file;     /* Boot file we need to search for */
+    unsigned long length = 0;
+    unsigned long extent = 0;
+    unsigned char *boot_sector = (unsigned char *) alpha_hppa_boot_sector;
+    int i = 0;
+
+    if (!boot_sector_initialized) {
+       memset(alpha_hppa_boot_sector, 0, sizeof(alpha_hppa_boot_sector));
+       boot_sector_initialized = 1;
+    }
+
+    printf("Address is: %p\n",alpha_hppa_boot_sector);
+
+    boot_sector[0] = 0x80;  /* magic */
+    boot_sector[1] = 0x00;  /* magic */
+    boot_sector[2] = 'P';
+    boot_sector[3] = 'A';
+    boot_sector[4] = 'L';
+    boot_sector[5] = 'O';
+    boot_sector[6] = 0x00;
+    boot_sector[7] = 0x04;  /* version */
+
+    /* Find the dir entry for the 32-bit kernel by walking our file list */
+    boot_file = search_tree_file(root, hppa_kernel_32);
+    if (!boot_file)
+        exit_fatal("HPPA 32-bit kernel", hppa_kernel_32);
+    extent = 2048 * get_733(boot_file->isorec.extent);
+    length = get_733(boot_file->isorec.size);
+    fprintf(stderr, "Found hppa 32-bit kernel %s: using extent %lu (0x%lX), size %lu (0x%lX)\n",
+            hppa_kernel_32, extent, extent, length, length);
+    write_be32(extent, &boot_sector[8]);
+    write_be32(length, &boot_sector[12]);
+
+    /* Find the dir entry for the ramdisk by walking our file list */
+    boot_file = search_tree_file(root, hppa_ramdisk);
+    if (!boot_file)
+        exit_fatal("HPPA ramdisk", hppa_ramdisk);
+    extent = 2048 * get_733(boot_file->isorec.extent);
+    length = get_733(boot_file->isorec.size);
+    fprintf(stderr, "Found hppa ramdisk %s: using extent %lu (0x%lX), size %lu (0x%lX)\n",
+            hppa_ramdisk, extent, extent, length, length);
+    write_be32(extent, &boot_sector[16]);
+    write_be32(length, &boot_sector[20]);
+
+    /* Now the commandline */
+    snprintf((char *)&boot_sector[24], 127, "%s", hppa_cmdline);
+
+    /* Find the dir entry for the 64-bit kernel by walking our file list */
+    boot_file = search_tree_file(root, hppa_kernel_64);
+    if (!boot_file)
+        exit_fatal("HPPA 64-bit kernel", hppa_kernel_64);
+    extent = 2048 * get_733(boot_file->isorec.extent);
+    length = get_733(boot_file->isorec.size);
+    fprintf(stderr, "Found hppa 64-bit kernel %s: using extent %lu (0x%lX), size %lu (0x%lX)\n",
+            hppa_kernel_64, extent, extent, length, length);
+    write_be32(extent, &boot_sector[232]);
+    write_be32(length, &boot_sector[236]);
+
+    /* Find the dir entry for the IPL by walking our file list */
+    boot_file = search_tree_file(root, hppa_bootloader);
+    if (!boot_file)
+        exit_fatal("HPPA bootloader", hppa_bootloader);
+    extent = 2048 * get_733(boot_file->isorec.extent);
+    length = get_733(boot_file->isorec.size);
+    fprintf(stderr, "Found hppa bootloader %s: using extent %lu (0x%lX), size %lu (0x%lX)\n",
+            hppa_bootloader, extent, extent, length, length);
+    write_be32(extent, &boot_sector[240]);
+    write_be32(length, &boot_sector[244]);
+
+    return 0;
+}
+
+struct output_fragment hppaboot_desc = {NULL, NULL, NULL, boot_hppa_write, "hppa boot block"};
diff --git a/genisoimage/boot-mips.c b/genisoimage/boot-mips.c
new file mode 100644 (file)
index 0000000..956b94f
--- /dev/null
@@ -0,0 +1,341 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/*
+ * Program boot-mips.c - Handle big-endian boot extensions to iso9660.
+ *
+ * Written by Steve McIntyre <steve@einval.com> June 2004
+ *
+ * Heavily inspired by / borrowed from genisovh:
+ *
+ * Copyright: (C) 2002 by Florian Lohoff <flo@rfc822.org>
+ *            (C) 2004 by Thiemo Seufer <seufer@csv.ica.uni-stuttgart.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, Version 2, as published by the
+ * Free Software Foundation.
+ *
+ * Format for volume header information
+ *
+ * The volume header is a block located at the beginning of all disk
+ * media (sector 0).  It contains information pertaining to physical
+ * device parameters and logical partition information.
+ *
+ * The volume header is manipulated by disk formatters/verifiers,
+ * partition builders (e.g. fx, dvhtool, and mkfs), and disk drivers.
+ *
+ * Previous versions of IRIX wrote a copy of the volume header is
+ * located at sector 0 of each track of cylinder 0.  These copies were
+ * never used, and reduced the capacity of the volume header to hold large
+ * files, so this practice was discontinued.
+ * The volume header is constrained to be less than or equal to 512
+ * bytes long.  A particular copy is assumed valid if no drive errors
+ * are detected, the magic number is correct, and the 32 bit 2's complement
+ * of the volume header is correct.  The checksum is calculated by initially
+ * zeroing vh_csum, summing the entire structure and then storing the
+ * 2's complement of the sum.  Thus a checksum to verify the volume header
+ * should be 0.
+ *
+ * The error summary table, bad sector replacement table, and boot blocks are
+ * located by searching the volume directory within the volume header.
+ *
+ * Tables are sized simply by the integral number of table records that
+ * will fit in the space indicated by the directory entry.
+ *
+ * The amount of space allocated to the volume header, replacement blocks,
+ * and other tables is user defined when the device is formatted.
+ */
+
+#include <inttypes.h>
+#ifndef MIN
+#define MIN(a,b) ( (a<b) ? a : b )
+#endif
+
+/*
+ * device parameters are in the volume header to determine mapping
+ * from logical block numbers to physical device addresses
+ *
+ * Linux doesn't care ...
+ */
+struct device_parameters {
+       uint8_t dp_skew;        /* spiral addressing skew */
+       uint8_t dp_gap1;        /* words of 0 before header */
+       uint8_t dp_gap2;        /* words of 0 between hdr and data */
+       uint8_t dp_spares_cyl;  /* This is for drives (such as SCSI
+               that support zone oriented sparing, where the zone is larger
+               than one track.  It gets subracteded from the cylinder size
+               ( dp_trks0 * dp_sec) when doing partition size calculations */
+       uint16_t dp_cyls;       /* number of usable cylinders (i.e.,
+               doesn't include cylinders reserved by the drive for badblocks,
+               etc.). For drives with variable geometry, this number may be
+               decreased so that:
+               dp_cyls * ((dp_heads * dp_trks0) - dp_spares_cyl) <= actualcapacity
+               This happens on SCSI drives such as the Wren IV and Toshiba 156
+               Also see dp_cylshi below */
+       uint16_t dp_shd0;       /* starting head vol 0 */
+       uint16_t dp_trks0;      /* number of tracks / cylinder vol 0*/
+       uint8_t dp_ctq_depth;   /* Depth of CTQ queue */
+       uint8_t dp_cylshi;      /* high byte of 24 bits of cylinder count */
+       uint16_t dp_unused;     /* not used */
+       uint16_t dp_secs;       /* number of sectors/track */
+       uint16_t dp_secbytes;   /* length of sector in bytes */
+       uint16_t dp_interleave; /* sector interleave */
+       int32_t dp_flags;               /* controller characteristics */
+       int32_t dp_datarate;            /* bytes/sec for kernel stats */
+       int32_t dp_nretries;            /* max num retries on data error */
+       int32_t dp_mspw;                /* ms per word to xfer, for iostat */
+       uint16_t dp_xgap1;      /* Gap 1 for xylogics controllers */
+       uint16_t dp_xsync;    /* sync delay for xylogics controllers */
+       uint16_t dp_xrdly;    /* read delay for xylogics controllers */
+       uint16_t dp_xgap2;    /* gap 2 for xylogics controllers */
+       uint16_t dp_xrgate;   /* read gate for xylogics controllers */
+       uint16_t dp_xwcont;   /* write continuation for xylogics */
+};
+
+/*
+ * Device characterization flags
+ * (dp_flags)
+ */
+#define        DP_SECTSLIP     0x00000001      /* sector slip to spare sector */
+#define        DP_SECTFWD      0x00000002      /* forward to replacement sector */
+#define        DP_TRKFWD       0x00000004      /* forward to replacement track */
+#define        DP_MULTIVOL     0x00000008      /* multiple volumes per spindle */
+#define        DP_IGNOREERRORS 0x00000010      /* transfer data regardless of errors */
+#define DP_RESEEK      0x00000020      /* recalibrate as last resort */
+#define        DP_CTQ_EN       0x00000040      /* enable command tag queueing */
+
+/*
+ * Boot blocks, bad sector tables, and the error summary table, are located
+ * via the volume_directory.
+ */
+#define VDNAMESIZE     8
+
+struct volume_directory {
+       int8_t  vd_name[VDNAMESIZE];    /* name */
+       int32_t vd_lbn;                 /* logical block number */
+       int32_t vd_nbytes;              /* file length in bytes */
+};
+
+/*
+ * partition table describes logical device partitions
+ * (device drivers examine this to determine mapping from logical units
+ * to cylinder groups, device formatters/verifiers examine this to determine
+ * location of replacement tracks/sectors, etc)
+ *
+ * NOTE: pt_firstlbn SHOULD BE CYLINDER ALIGNED
+ */
+struct partition_table {               /* one per logical partition */
+       int32_t pt_nblks;               /* # of logical blks in partition */
+       int32_t pt_firstlbn;            /* first lbn of partition */
+       int32_t pt_type;                /* use of partition */
+};
+
+#define        PTYPE_VOLHDR    0               /* partition is volume header */
+#define        PTYPE_TRKREPL   1               /* partition is used for repl trks */
+#define        PTYPE_SECREPL   2               /* partition is used for repl secs */
+#define        PTYPE_RAW       3               /* partition is used for data */
+#define        PTYPE_BSD42     4               /* partition is 4.2BSD file system */
+#define        PTYPE_BSD       4               /* partition is 4.2BSD file system */
+#define        PTYPE_SYSV      5               /* partition is SysV file system */
+#define        PTYPE_VOLUME    6               /* partition is entire volume */
+#define        PTYPE_EFS       7               /* partition is sgi EFS */
+#define        PTYPE_LVOL      8               /* partition is part of a logical vol */
+#define        PTYPE_RLVOL     9               /* part of a "raw" logical vol */
+#define        PTYPE_XFS       10              /* partition is sgi XFS */
+#define        PTYPE_XFSLOG    11              /* partition is sgi XFS log */
+#define        PTYPE_XLV       12              /* partition is part of an XLV vol */
+#define        PTYPE_XVM       13              /* partition is sgi XVM */
+#define        PTYPE_LSWAP     0x82            /* partition is Linux swap */
+#define        PTYPE_LINUX     0x83            /* partition is Linux native */
+#define NPTYPES                16
+
+#define        VHMAGIC         0xbe5a941       /* randomly chosen value */
+#define        NPARTAB         16              /* 16 unix partitions */
+#define        NVDIR           15              /* max of 15 directory entries */
+#define BFNAMESIZE     16              /* max 16 chars in boot file name */
+
+/* Partition types for ARCS */
+#define NOT_USED        0       /* Not used                            */
+#define FAT_SHORT       1       /* FAT filesystem, 12-bit FAT entries  */
+#define FAT_LONG        4       /* FAT filesystem, 16-bit FAT entries  */
+#define EXTENDED        5       /* extended partition                  */
+#define HUGE            6       /* huge partition- MS/DOS 4.0 and later */
+
+/* Active flags for ARCS */
+#define BOOTABLE        0x00;
+#define NOT_BOOTABLE    0x80;
+
+struct volume_header {
+       int32_t vh_magic; /* identifies volume header */
+       int16_t vh_rootpt; /* root partition number */
+       int16_t vh_swappt; /* swap partition number */
+       int8_t vh_bootfile[BFNAMESIZE]; /* name of file to boot */
+       struct device_parameters vh_dp; /* device parameters */
+       struct volume_directory vh_vd[NVDIR]; /* other vol hdr contents */
+       struct partition_table vh_pt[NPARTAB]; /* device partition layout */
+       int32_t vh_csum; /* volume header checksum */
+       int32_t vh_fill; /* fill out to 512 bytes */
+    char pad[1536];  /* pad out to 2048 */
+};
+
+#include <mconfig.h>
+#include "genisoimage.h"
+#include <fctldefs.h>
+#include <utypes.h>
+#include <intcvt.h>
+#include "match.h"
+#include "diskmbr.h"
+#include "bootinfo.h"
+#include <schily.h>
+#include "endianconv.h"
+
+int     add_boot_mips_filename(char *filename);
+
+static  int     boot_mips_write(FILE *outfile);
+
+#define MAX_NAMES 15
+static char *boot_mips_filename[MAX_NAMES] =
+{
+    NULL, NULL, NULL,
+    NULL, NULL, NULL,
+    NULL, NULL, NULL,
+    NULL, NULL, NULL,
+    NULL, NULL, NULL
+};
+
+static int boot_mips_num_files = 0;
+
+#define SECTORS_PER_TRACK      32
+#define BYTES_PER_SECTOR       512
+
+int add_boot_mips_filename(char *filename)
+{
+    if (boot_mips_num_files < MAX_NAMES)
+    {
+        boot_mips_filename[boot_mips_num_files] = filename;
+        boot_mips_num_files++;
+    }
+
+    else
+    {
+#ifdef USE_LIBSCHILY
+        comerrno(EX_BAD, "Too many MIPS boot files!\n");
+#else
+        fprintf(stderr, "Too many MIPS boot files!\n");
+        exit(1);
+#endif
+    }
+    return 0;
+}
+
+static void vh_calc_checksum(struct volume_header *vh)
+{
+       uint32_t newsum = 0;
+       unsigned char *buffer = (unsigned char *)vh;
+       unsigned int i;
+
+       vh->vh_csum = 0;
+
+       for(i = 0; i < sizeof(struct volume_header); i += 4)
+        newsum -= read_be32(&buffer[i]);
+
+    write_be32(newsum, (unsigned char *)&vh->vh_csum);
+}
+
+static char *file_base_name(char *path)
+{
+    char *endptr = path;
+    char *ptr = path;
+    
+    while (*ptr != '\0')
+    {
+        if ('/' == *ptr)
+            endptr = ++ptr;
+        else
+            ++ptr;
+    }
+    return endptr;
+}
+
+static int boot_mips_write(FILE *outfile)
+{
+       struct directory_entry  *boot_file;     /* Boot file we need to search for */
+    unsigned long length = 0;
+    unsigned long extent = 0;
+       int i;
+       struct volume_header vh;
+    unsigned long long iso_size = 0;
+    char *filename = NULL;
+
+       memset(&vh, 0, sizeof(vh));
+
+    iso_size = last_extent * 2048;
+
+    write_be32(VHMAGIC, (unsigned char *)&vh.vh_magic);
+
+       /* Values from an IRIX cd */
+    write_be16(BYTES_PER_SECTOR, (unsigned char *)&vh.vh_dp.dp_secbytes);
+    write_be16(SECTORS_PER_TRACK, (unsigned char *)&vh.vh_dp.dp_secs);
+    write_be32(DP_RESEEK|DP_IGNOREERRORS|DP_TRKFWD, (unsigned char *)&vh.vh_dp.dp_flags);
+    write_be16(1, (unsigned char *)&vh.vh_dp.dp_trks0);
+
+    write_be16((iso_size + BYTES_PER_SECTOR - 1) / (SECTORS_PER_TRACK * BYTES_PER_SECTOR),
+               (unsigned char *)&vh.vh_dp.dp_cyls);
+
+       for(i = 0; i < boot_mips_num_files; i++)
+    {
+        boot_file = search_tree_file(root, boot_mips_filename[i]);
+        
+        if (!boot_file) {
+#ifdef USE_LIBSCHILY
+            comerrno(EX_BAD, "Uh oh, I cant find the MIPS boot file '%s'!\n",
+                     boot_mips_filename[i]);
+#else
+            fprintf(stderr, "Uh oh, I cant find the MIPS boot file '%s'!\n",
+                    boot_mips_filename[i]);
+            exit(1);
+#endif
+        }
+
+        extent = get_733(boot_file->isorec.extent) * 4;
+        length = ((get_733(boot_file->isorec.size) + 2047) / 2048) * 2048;
+        filename = file_base_name(boot_mips_filename[i]);
+
+        strncpy((char *)vh.vh_vd[i].vd_name, filename, MIN(VDNAMESIZE, strlen(filename)));
+        write_be32(extent, (unsigned char *)&vh.vh_vd[i].vd_lbn);
+        write_be32(length, (unsigned char *)&vh.vh_vd[i].vd_nbytes);
+        
+        fprintf(stderr, "Found mips boot image %s, using extent %lu (0x%lX), #blocks %lu (0x%lX)\n",
+                filename, extent, extent, length, length);
+       }
+
+       /* Create volume partition on whole cd iso */
+    write_be32((iso_size + (BYTES_PER_SECTOR - 1))/ BYTES_PER_SECTOR, (unsigned char *)&vh.vh_pt[10].pt_nblks);
+    write_be32(0, (unsigned char *)&vh.vh_pt[10].pt_firstlbn);
+    write_be32(PTYPE_VOLUME, (unsigned char *)&vh.vh_pt[10].pt_type);
+
+       /* Create volume header partition, also on WHOLE cd iso */
+    write_be32((iso_size + (BYTES_PER_SECTOR - 1))/ BYTES_PER_SECTOR, (unsigned char *)&vh.vh_pt[8].pt_nblks);
+    write_be32(0, (unsigned char *)&vh.vh_pt[8].pt_firstlbn);
+    write_be32(PTYPE_VOLHDR, (unsigned char *)&vh.vh_pt[8].pt_type);
+
+       /* Create checksum */
+       vh_calc_checksum(&vh);
+
+    jtwrite(&vh, sizeof(vh), 1, 0, FALSE);
+    xfwrite(&vh, sizeof(vh), 1, outfile, 0, FALSE);
+    last_extent_written++;
+
+       return 0;
+}
+
+struct output_fragment mipsboot_desc = {NULL, oneblock_size, NULL, boot_mips_write, "MIPS boot block"};
diff --git a/genisoimage/boot-mipsel.c b/genisoimage/boot-mipsel.c
new file mode 100644 (file)
index 0000000..3d8ca65
--- /dev/null
@@ -0,0 +1,259 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/*
+ * Program boot-mipsel.c - Handle Mipsel boot extensions to iso9660.
+ *
+ *  Written by Steve McIntyre <steve@einval.com> (2004).
+ *
+ * Heavily inspired by / borrowed from delo:
+ *
+ * Copyright: (C) 2002 by Florian Lohoff <flo@rfc822.org>
+ *            (C) 2004 by Thiemo Seufer <seufer@csv.ica.uni-stuttgart.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, Version 2, as published by the
+ * Free Software Foundation.
+ *
+ * Format for volume header information
+ *
+ * The volume header is a block located at the beginning of all disk
+ * media (sector 0).  It contains information pertaining to physical
+ * device parameters and logical partition information.
+ *
+ * The volume header is manipulated by disk formatters/verifiers,
+ * partition builders (e.g. fx, dvhtool, and mkfs), and disk drivers.
+ *
+ * Previous versions of IRIX wrote a copy of the volume header is
+ * located at sector 0 of each track of cylinder 0.  These copies were
+ * never used, and reduced the capacity of the volume header to hold large
+ * files, so this practice was discontinued.
+ * The volume header is constrained to be less than or equal to 512
+ * bytes long.  A particular copy is assumed valid if no drive errors
+ * are detected, the magic number is correct, and the 32 bit 2's complement
+ * of the volume header is correct.  The checksum is calculated by initially
+ * zeroing vh_csum, summing the entire structure and then storing the
+ * 2's complement of the sum.  Thus a checksum to verify the volume header
+ * should be 0.
+ *
+ * The error summary table, bad sector replacement table, and boot blocks are
+ * located by searching the volume directory within the volume header.
+ *
+ * Tables are sized simply by the integral number of table records that
+ * will fit in the space indicated by the directory entry.
+ *
+ * The amount of space allocated to the volume header, replacement blocks,
+ * and other tables is user defined when the device is formatted.
+ */
+
+#include <mconfig.h>
+#include "genisoimage.h"
+#include <fctldefs.h>
+#include <utypes.h>
+#include <intcvt.h>
+#include "match.h"
+#include "diskmbr.h"
+#include "bootinfo.h"
+#include <schily.h>
+#include "endianconv.h"
+#include <errno.h>
+#include <glibc_elf.h>
+
+int             add_boot_mipsel_filename(char *filename);
+static  int     boot_mipsel_write(FILE *outfile);
+
+static  char   *boot_file_name = NULL;
+
+#define MAX_MAPS        51
+#define DEC_BOOT_MAGIC  0x02757a
+#define HD_SECTOR_SIZE  512
+
+/* Those were stolen from linux kernel headers. */
+
+struct extent {
+    uint32_t count;
+    uint32_t start;
+}
+#ifdef __GNUC__
+__attribute__((packed))
+#endif
+   ;
+
+struct dec_bootblock {
+    int8_t pad[8];
+    int32_t magic;          /* We are a DEC BootBlock */
+    int32_t mode;           /* 0: Single extent, 1: Multi extent boot */
+    int32_t loadAddr;       /* Load below kernel */
+    int32_t execAddr;       /* And exec there */
+    struct extent bootmap[MAX_MAPS];
+}
+#ifdef __GNUC__
+__attribute__((packed))
+#endif
+   ;
+
+static void swap_in_elf32_ehdr(Elf32_Ehdr *ehdr)
+{
+    ehdr->e_type = read_le16((unsigned char *)&ehdr->e_type);
+    ehdr->e_machine = read_le16((unsigned char *)&ehdr->e_machine);
+    ehdr->e_version = read_le32((unsigned char *)&ehdr->e_version);
+    ehdr->e_entry = read_le32((unsigned char *)&ehdr->e_entry);
+    ehdr->e_phoff = read_le32((unsigned char *)&ehdr->e_phoff);
+    ehdr->e_shoff = read_le32((unsigned char *)&ehdr->e_shoff);
+    ehdr->e_flags = read_le32((unsigned char *)&ehdr->e_flags);
+    ehdr->e_ehsize = read_le16((unsigned char *)&ehdr->e_ehsize);
+    ehdr->e_phentsize = read_le16((unsigned char *)&ehdr->e_phentsize);
+    ehdr->e_phnum = read_le16((unsigned char *)&ehdr->e_phnum);
+    ehdr->e_shentsize = read_le16((unsigned char *)&ehdr->e_shentsize);
+    ehdr->e_shnum = read_le16((unsigned char *)&ehdr->e_shnum);
+    ehdr->e_shstrndx = read_le16((unsigned char *)&ehdr->e_shstrndx);
+}
+
+static void swap_in_elf32_phdr(Elf32_Phdr *phdr)
+{
+    phdr->p_type = read_le32((unsigned char *)&phdr->p_type);
+    phdr->p_offset = read_le32((unsigned char *)&phdr->p_offset);
+    phdr->p_vaddr = read_le32((unsigned char *)&phdr->p_vaddr);
+    phdr->p_paddr = read_le32((unsigned char *)&phdr->p_paddr);
+    phdr->p_filesz = read_le32((unsigned char *)&phdr->p_filesz);
+    phdr->p_memsz = read_le32((unsigned char *)&phdr->p_memsz);
+    phdr->p_flags = read_le32((unsigned char *)&phdr->p_flags);
+    phdr->p_align = read_le32((unsigned char *)&phdr->p_align);
+}
+
+/* Simple function: store the filename to be used later when we need
+   to find the boot file */
+extern int add_boot_mipsel_filename(char *filename)
+{
+    boot_file_name = filename;
+    return 0;
+}
+
+/* Parse the ELF header of the boot loaded to work out the load
+   address and exec address */
+static int parse_boot_file(char *filename, int32_t *loadaddr, int32_t *execaddr, int32_t *offset, int32_t *count)
+{
+    int error = 0;
+    FILE *loader = NULL;
+    Elf32_Ehdr ehdr;
+    Elf32_Phdr phdr;
+    
+    loader = fopen(filename, "rb");
+    if (!loader)
+        return errno;
+    
+    error = fread(&ehdr, sizeof(ehdr), 1, loader);
+    if (1 != error)
+        return EIO;
+
+    swap_in_elf32_ehdr(&ehdr);
+    if (!(ehdr.e_ident[EI_MAG0] == ELFMAG0
+          && ehdr.e_ident[EI_MAG1] == ELFMAG1
+          && ehdr.e_ident[EI_MAG2] == ELFMAG2
+          && ehdr.e_ident[EI_MAG3] == ELFMAG3
+          && ehdr.e_ident[EI_CLASS] == ELFCLASS32
+          && ehdr.e_ident[EI_DATA] == ELFDATA2LSB
+          && ehdr.e_ident[EI_VERSION] == EV_CURRENT
+          && ehdr.e_type == ET_EXEC
+          && ehdr.e_machine == EM_MIPS
+          && ehdr.e_version == EV_CURRENT))
+    {
+        fprintf(stderr, "Sorry, %s is not a MIPS ELF32 little endian file", filename);        
+        return EINVAL;
+    }
+    if (ehdr.e_phnum != 1)
+    {
+        fprintf(stderr, "Sorry, %s has more than one ELF segment", filename);
+        return EINVAL;
+    }
+    fseek(loader, ehdr.e_phoff, SEEK_SET);
+    error = fread(&phdr, sizeof(phdr), 1, loader);
+    if (1 != error)
+        return EIO;
+
+    *loadaddr = phdr.p_vaddr;
+    *execaddr = ehdr.e_entry;
+       *offset = (phdr.p_offset + HD_SECTOR_SIZE - 1) / HD_SECTOR_SIZE;
+       *count = (phdr.p_filesz + HD_SECTOR_SIZE - 1) / HD_SECTOR_SIZE;
+
+    fprintf(stderr, "Parsed mipsel boot image %s: using loadaddr 0x%X, execaddr 0x%X, offset 0x%X, count 0x%X\n",
+            filename, *loadaddr, *execaddr, *offset, *count);
+
+    fclose(loader);
+    return 0;
+}
+
+static int boot_mipsel_write(FILE *outfile)
+{
+    char sector[2048];
+    struct dec_bootblock *bb = (struct dec_bootblock *)sector;
+    int error = 0;
+    int offset = 0;
+    int count = 0;
+    struct directory_entry     *boot_file;     /* Boot file we need to search for in the image */
+    unsigned long length = 0;
+    unsigned long extent = 0;
+    int loadaddr = 0;
+    int execaddr = 0;
+
+    memset(sector, 0, sizeof(sector));
+
+    /* Fill in our values we care on */
+    write_le32(DEC_BOOT_MAGIC, (unsigned char *)&bb->magic);
+    write_le32(1, (unsigned char *)&bb->mode);
+
+    /* Find the file entry in the CD image */
+    boot_file = search_tree_file(root, boot_file_name);
+    if (!boot_file)
+    {
+#ifdef USE_LIBSCHILY
+               comerrno(EX_BAD, "Uh oh, unable to find the mipsel boot file '%s'!\n",
+                 boot_file_name);
+#else
+               fprintf(stderr, "Uh oh, unable to find the mipsel boot file '%s'!\n",
+                boot_file_name);
+               exit(1);
+#endif
+    }
+
+    extent = get_733(boot_file->isorec.extent);
+    length = get_733(boot_file->isorec.size);
+    fprintf(stderr, "Found mipsel boot loader %s: using extent %lu, #blocks %lu\n",
+            boot_file_name, extent, length);
+
+    /* Parse the ELF headers on the boot file */
+    error = parse_boot_file(boot_file->whole_name, &loadaddr, &execaddr, &offset, &count);
+    if (error)
+    {
+#ifdef USE_LIBSCHILY
+               comerrno(EX_BAD, "Uh oh, unable to parse the mipsel boot file '%s'!\n",
+                 boot_file->whole_name);
+#else
+               fprintf(stderr, "Uh oh, unable to parse the mipsel boot file '%s'!\n",
+                boot_file->whole_name);
+               exit(1);
+#endif
+    }
+
+    write_le32(loadaddr, (unsigned char *)&bb->loadAddr);
+    write_le32(execaddr, (unsigned char *)&bb->execAddr);
+    write_le32((extent * 4) + offset, (unsigned char *)&bb->bootmap[0].start);
+    write_le32(count, (unsigned char *)&bb->bootmap[0].count);
+    
+    jtwrite(sector, sizeof(sector), 1, 0, FALSE);
+    xfwrite(sector, sizeof(sector), 1, outfile, 0, FALSE);
+    last_extent_written++;
+
+    return 0;
+}
+
+struct output_fragment mipselboot_desc = {NULL, oneblock_size, NULL, boot_mipsel_write, "mipsel boot block"};
diff --git a/genisoimage/boot.c b/genisoimage/boot.c
new file mode 100644 (file)
index 0000000..51b6fb7
--- /dev/null
@@ -0,0 +1,537 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)boot.c  1.13 04/02/22 Copyright 1999-2003 J. Schilling */
+/*
+ *     Support for generic boot (sector 0..16)
+ *     and to boot Sun sparc and Sun x86 systems.
+ *
+ *     Copyright (c) 1999-2003 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <mconfig.h>
+#include "genisoimage.h"
+#include <fctldefs.h>
+#include <utypes.h>
+#include <intcvt.h>
+#include <schily.h>
+#include "sunlabel.h"
+
+extern int     use_sunx86boot;
+
+static struct sun_label cd_label;
+static struct x86_label sx86_label;
+static struct pc_part  fdisk_part;
+static char    *boot_files[NDKMAP];    /* Change this for > 8 x86 parts */
+
+static void    init_sparc_label(void);
+static void    init_sunx86_label(void);
+void   sparc_boot_label(char *label);
+void   sunx86_boot_label(char *label);
+void   scan_sparc_boot(char *files);
+void   scan_sunx86_boot(char *files);
+int    make_sun_label(void);
+int    make_sunx86_label(void);
+static void    dup_sun_label(int part);
+static int     sunboot_write(FILE *outfile);
+static int     sunlabel_size(int starting_extent);
+static int     sunlabel_write(FILE * outfile);
+static int     genboot_size(int starting_extent);
+static int     genboot_write(FILE * outfile);
+
+/*
+ * Set the virtual geometry in the disk label.
+ * If we like to make the geometry variable, we may change
+ * dkl_ncyl and dkl_pcyl later.
+ */
+static void
+init_sparc_label()
+{
+       i_to_4_byte(cd_label.dkl_vtoc.v_version, V_VERSION);
+       i_to_2_byte(cd_label.dkl_vtoc.v_nparts, NDKMAP);
+       i_to_4_byte(cd_label.dkl_vtoc.v_sanity, VTOC_SANE);
+
+       i_to_2_byte(cd_label.dkl_rpm, CD_RPM);
+       i_to_2_byte(cd_label.dkl_pcyl, CD_PCYL);
+       i_to_2_byte(cd_label.dkl_apc, CD_APC);
+       i_to_2_byte(cd_label.dkl_intrlv, CD_INTRLV);
+       i_to_2_byte(cd_label.dkl_ncyl, CD_NCYL);
+       i_to_2_byte(cd_label.dkl_acyl, CD_ACYL);
+       i_to_2_byte(cd_label.dkl_nhead, CD_NHEAD);
+       i_to_2_byte(cd_label.dkl_nsect, CD_NSECT);
+
+       cd_label.dkl_magic[0] = DKL_MAGIC_0;
+       cd_label.dkl_magic[1] = DKL_MAGIC_1;
+}
+
+static void
+init_sunx86_label()
+{
+       li_to_4_byte(sx86_label.dkl_vtoc.v_sanity, VTOC_SANE);
+       li_to_4_byte(sx86_label.dkl_vtoc.v_version, V_VERSION);
+       li_to_2_byte(sx86_label.dkl_vtoc.v_sectorsz, 512);
+       li_to_2_byte(sx86_label.dkl_vtoc.v_nparts, NX86MAP);
+
+       li_to_4_byte(sx86_label.dkl_pcyl, CD_PCYL);
+       li_to_4_byte(sx86_label.dkl_ncyl, CD_NCYL);
+       li_to_2_byte(sx86_label.dkl_acyl, CD_ACYL);
+       li_to_2_byte(sx86_label.dkl_bcyl, 0);
+
+       li_to_4_byte(sx86_label.dkl_nhead, CD_NHEAD);
+       li_to_4_byte(sx86_label.dkl_nsect, CD_NSECT);
+       li_to_2_byte(sx86_label.dkl_intrlv, CD_INTRLV);
+       li_to_2_byte(sx86_label.dkl_skew, 0);
+       li_to_2_byte(sx86_label.dkl_apc, CD_APC);
+       li_to_2_byte(sx86_label.dkl_rpm, CD_RPM);
+
+       li_to_2_byte(sx86_label.dkl_write_reinstruct, 0);
+       li_to_2_byte(sx86_label.dkl_read_reinstruct, 0);
+
+       li_to_2_byte(sx86_label.dkl_magic, DKL_MAGIC);
+}
+
+/*
+ * For command line parser: set ASCII label.
+ */
+void
+sparc_boot_label(char *label)
+{
+       strncpy(cd_label.dkl_ascilabel, label, 127);
+       cd_label.dkl_ascilabel[127] = '\0';
+}
+
+void
+sunx86_boot_label(char *label)
+{
+       strncpy(sx86_label.dkl_vtoc.v_asciilabel, label, 127);
+       sx86_label.dkl_vtoc.v_asciilabel[127] = '\0';
+}
+
+/*
+ * Parse the command line argument for boot images.
+ */
+void
+scan_sparc_boot(char *files)
+{
+       char            *p;
+       int             i = 1;
+       struct stat     statbuf;
+       int             status;
+
+       init_sparc_label();
+
+       do {
+               if (i >= NDKMAP)
+                       comerrno(EX_BAD, "Too many boot partitions.\n");
+               boot_files[i++] = files;
+               if ((p = strchr(files, ',')) != NULL)
+                       *p++ = '\0';
+               files = p;
+       } while (p);
+
+       i_to_2_byte(cd_label.dkl_vtoc.v_part[0].p_tag,  V_USR);
+       i_to_2_byte(cd_label.dkl_vtoc.v_part[0].p_flag, V_RONLY);
+       for (i = 0; i < NDKMAP; i++) {
+               p = boot_files[i];
+               if (p == NULL || *p == '\0')
+                       continue;
+               if (strcmp(p, "...") == '\0')
+                       break;
+
+               status = stat_filter(p, &statbuf);
+               if (status < 0 || access(p, R_OK) < 0)
+                       comerr("Cannot access '%s'.\n", p);
+
+               i_to_4_byte(cd_label.dkl_map[i].dkl_nblk,
+                       roundup(statbuf.st_size, CD_CYLSIZE)/512);
+
+               i_to_2_byte(cd_label.dkl_vtoc.v_part[i].p_tag,  V_ROOT);
+               i_to_2_byte(cd_label.dkl_vtoc.v_part[i].p_flag, V_RONLY);
+       }
+}
+
+void
+scan_sunx86_boot(char *files)
+{
+       char            *p;
+       int             i = 0;
+       struct stat     statbuf;
+       int             status;
+
+       init_sunx86_label();
+
+       do {
+               if (i >= NDKMAP)
+                       comerrno(EX_BAD, "Too many boot partitions.\n");
+               boot_files[i++] = files;
+               if ((p = strchr(files, ',')) != NULL)
+                       *p++ = '\0';
+               files = p;
+       } while (p);
+
+       li_to_2_byte(sx86_label.dkl_vtoc.v_part[0].p_tag,  V_ROOT);  /* UFS */
+       li_to_2_byte(sx86_label.dkl_vtoc.v_part[0].p_flag, V_RONLY);
+       li_to_2_byte(sx86_label.dkl_vtoc.v_part[1].p_tag,  V_USR);   /* ISO */
+       li_to_2_byte(sx86_label.dkl_vtoc.v_part[1].p_flag, V_RONLY);
+       li_to_2_byte(sx86_label.dkl_vtoc.v_part[2].p_tag,  0);      /* ALL */
+       li_to_2_byte(sx86_label.dkl_vtoc.v_part[2].p_flag, 0);
+       for (i = 0; i < NDKMAP; i++) {
+               p = boot_files[i];
+               if (p == NULL || *p == '\0')
+                       continue;
+               if (i == 1 || i == 2) {
+                       comerrno(EX_BAD,
+                       "Partition %d may not have a filename.\n", i);
+               }
+
+               status = stat_filter(p, &statbuf);
+               if (status < 0 || access(p, R_OK) < 0)
+                       comerr("Cannot access '%s'.\n", p);
+
+               li_to_4_byte(sx86_label.dkl_vtoc.v_part[i].p_size,
+                       roundup(statbuf.st_size, CD_CYLSIZE)/512);
+
+               if (i > 2) {
+                       li_to_2_byte(sx86_label.dkl_vtoc.v_part[i].p_tag,  V_USR);
+                       li_to_2_byte(sx86_label.dkl_vtoc.v_part[i].p_flag, V_RONLY);
+               }
+       }
+}
+
+/*
+ * Finish the Sun disk label and compute the size of the additional data.
+ */
+int
+make_sun_label()
+{
+       int     last;
+       int     cyl = 0;
+       int     nblk;
+       int     bsize;
+       int     i;
+       char    *p;
+
+       /*
+        * Compute the size of the padding for the iso9660 image
+        * to allow the next partition to start on a cylinder boundary.
+        */
+       last = roundup(last_extent, (CD_CYLSIZE/SECTOR_SIZE));
+
+       i_to_4_byte(cd_label.dkl_map[0].dkl_nblk, last*4);
+       bsize = 0;
+       for (i = 0; i < NDKMAP; i++) {
+               p = boot_files[i];
+               if (p != NULL && strcmp(p, "...") == '\0') {
+                       dup_sun_label(i);
+                       break;
+               }
+               if ((nblk = a_to_4_byte(cd_label.dkl_map[i].dkl_nblk)) == 0)
+                       continue;
+
+               i_to_4_byte(cd_label.dkl_map[i].dkl_cylno, cyl);
+               cyl += nblk / (CD_CYLSIZE/512);
+               if (i > 0)
+                       bsize += nblk;
+       }
+       bsize /= 4;
+       return (last-last_extent+bsize);
+}
+
+/*
+ * A typical Solaris boot/install CD from a Sun CD set looks
+ * this way:
+ *
+ * UFS Part 0 tag 2 flag 10 start 3839 size 1314560
+ * ISO Part 1 tag 4 flag 10 start    0 size    3839
+ * ALL Part 2 tag 0 flag  0 start    0 size 1318400
+ */
+int
+make_sunx86_label()
+{
+       int     last;
+       int     cyl = 0;
+       int     nblk;
+       int     bsize;
+       int     i;
+       int     partoff = 1;    /* The offset of the Solaris 0x82 partition */
+       char    *p;
+
+       /*
+        * Compute the size of the padding for the iso9660 image
+        * to allow the next partition to start on a cylinder boundary.
+        */
+       last = roundup(last_extent, (CD_CYLSIZE/SECTOR_SIZE));
+
+       li_to_4_byte(sx86_label.dkl_vtoc.v_part[1].p_size, last*4);
+
+       /*
+        * Note that the Solaris fdisk partition with fdisk signature 0x82
+        * is created at fixed offset 1 sector == 512 Bytes by this
+        * implementation.
+        * We need subtract this partition offset from all absolute
+        * partition offsets in order to get offsets relative to the
+        * Solaris primary partition.
+        */
+       bsize = 0;
+       for (i = 0; i < NDKMAP; i++) {
+               if (i == 2)             /* Never include the whole disk in */
+                       continue;       /* size/offset computations        */
+               p = boot_files[i];
+
+               if ((nblk = la_to_4_byte(sx86_label.dkl_vtoc.v_part[i].p_size)) == 0)
+                       continue;
+
+               li_to_4_byte(sx86_label.dkl_vtoc.v_part[i].p_start,
+                                               cyl*(CD_CYLSIZE/512)-partoff);
+               cyl += nblk / (CD_CYLSIZE/512);
+               if (i == 0 || i > 2)
+                       bsize += nblk;
+       }
+       li_to_4_byte(sx86_label.dkl_vtoc.v_part[0].p_start, last*4-partoff);
+       li_to_4_byte(sx86_label.dkl_vtoc.v_part[1].p_start, 0);
+       li_to_4_byte(sx86_label.dkl_vtoc.v_part[1].p_size, last*4-partoff);
+       li_to_4_byte(sx86_label.dkl_vtoc.v_part[2].p_start, 0);
+       li_to_4_byte(sx86_label.dkl_vtoc.v_part[2].p_size, last*4+bsize);
+
+       fdisk_part.part[0].pr_status = STATUS_ACTIVE;
+       fdisk_part.part[0].pr_type   = TYPE_SOLARIS;
+       li_to_4_byte(fdisk_part.part[0].pr_partoff, partoff);
+       li_to_4_byte(fdisk_part.part[0].pr_nsect, last*4+bsize-partoff);
+       fdisk_part.magic[0] = 0x55;
+       fdisk_part.magic[1] = 0xAA;
+
+       bsize /= 4;
+       return (last-last_extent+bsize);
+}
+
+/*
+ * Duplicate a partition of the Sun disk label until all partitions are filled up.
+ */
+static void
+dup_sun_label(int part)
+{
+       int     cyl;
+       int     nblk;
+       int     i;
+
+
+       if (part < 1 || part >= NDKMAP)
+               part = 1;
+       cyl = a_to_4_byte(cd_label.dkl_map[part-1].dkl_cylno);
+       nblk = a_to_4_byte(cd_label.dkl_map[part-1].dkl_nblk);
+
+       for (i = part; i < NDKMAP; i++) {
+               i_to_4_byte(cd_label.dkl_map[i].dkl_cylno, cyl);
+               i_to_4_byte(cd_label.dkl_map[i].dkl_nblk, nblk);
+
+               i_to_2_byte(cd_label.dkl_vtoc.v_part[i].p_tag,  V_ROOT);
+               i_to_2_byte(cd_label.dkl_vtoc.v_part[i].p_flag, V_RONLY);
+       }
+}
+
+/*
+ * Write out Sun boot partitions.
+ */
+static int
+sunboot_write(FILE *outfile)
+{
+       char    buffer[SECTOR_SIZE];
+       int     i;
+       int     n;
+       int     nblk;
+       int     amt;
+       int     f;
+       char    *p;
+
+       memset(buffer, 0, sizeof (buffer));
+
+       /*
+        * Write padding to the iso9660 image to allow the
+        * boot partitions to start on a cylinder boundary.
+        */
+       amt = roundup(last_extent_written, (CD_CYLSIZE/SECTOR_SIZE)) - last_extent_written;
+       for (n = 0; n < amt; n++) {
+               jtwrite(buffer, SECTOR_SIZE, 1, 0, FALSE);
+               xfwrite(buffer, SECTOR_SIZE, 1, outfile, 0, FALSE);
+               last_extent_written++;
+       }
+       if (use_sunx86boot)
+               i = 0;
+       else
+               i = 1;
+       for (; i < NDKMAP; i++) {
+               if (use_sunx86boot && (i == 1 || i == 2))
+                       continue;
+               p = boot_files[i];
+               if (p == NULL || *p == '\0')
+                       continue;
+               if (p != NULL && strcmp(p, "...") == '\0')
+                       break;
+               if (use_sunx86boot) {
+                       if ((nblk = la_to_4_byte(sx86_label.dkl_vtoc.v_part[i].p_size)) == 0)
+                               continue;
+               } else {
+                       if ((nblk = a_to_4_byte(cd_label.dkl_map[i].dkl_nblk)) == 0)
+                               continue;
+               }
+               if ((f = open(boot_files[i], O_RDONLY| O_BINARY)) < 0)
+                       comerr("Cannot open '%s'.\n", boot_files[i]);
+
+               amt = nblk / 4;
+               for (n = 0; n < amt; n++) {
+                       memset(buffer, 0, sizeof (buffer));
+                       if (read(f, buffer, SECTOR_SIZE) < 0)
+                               comerr("Read error on '%s'.\n", boot_files[i]);
+                       jtwrite(buffer, SECTOR_SIZE, 1, 0, FALSE);
+                       xfwrite(buffer, SECTOR_SIZE, 1, outfile, 0, FALSE);
+                       last_extent_written++;
+               }
+               close(f);
+       }
+       fprintf(stderr, "Total extents including %s boot = %u\n",
+                               use_sunx86boot ? "Solaris x86":"sparc",
+                               last_extent_written - session_start);
+       return (0);
+}
+
+/*
+ * Do size management for the Sun disk label that is located in the first
+ * sector of a disk.
+ */
+static int
+sunlabel_size(int starting_extent)
+{
+       if (last_extent != session_start)
+               comerrno(EX_BAD, "Cannot create sparc boot on offset != 0.\n");
+       last_extent++;
+       return (0);
+}
+
+/*
+ * Cumpute the checksum and write a Sun disk label to the first sector
+ * of the disk.
+ * If the -generic-boot option has been specified too, overlay the
+ * Sun disk label on the firs 512 bytes of the generic boot code.
+ */
+static int
+sunlabel_write(FILE *outfile)
+{
+               char    buffer[SECTOR_SIZE];
+       register char   *p;
+       register short  count = (512/2) - 1;
+               int     f;
+
+       memset(buffer, 0, sizeof (buffer));
+       if (genboot_image) {
+               if ((f = open(genboot_image, O_RDONLY| O_BINARY)) < 0)
+                       comerr("Cannot open '%s'.\n", genboot_image);
+
+               if (read(f, buffer, SECTOR_SIZE) < 0)
+                       comerr("Read error on '%s'.\n", genboot_image);
+               close(f);
+       }
+
+       if (use_sunx86boot) {
+               if (sx86_label.dkl_vtoc.v_asciilabel[0] == '\0')
+                       strcpy(sx86_label.dkl_vtoc.v_asciilabel, CD_X86LABEL);
+
+               p = (char *)&sx86_label;
+               sx86_label.dkl_cksum[0] = 0;
+               sx86_label.dkl_cksum[1] = 0;
+               while (count-- > 0) {
+                       sx86_label.dkl_cksum[0] ^= *p++;
+                       sx86_label.dkl_cksum[1] ^= *p++;
+               }
+               memcpy(&buffer[0x1BE], &fdisk_part.part, 512-0x1BE);
+               memcpy(&buffer[1024], &sx86_label, 512);
+       } else {
+               /*
+                * If we don't already have a Sun disk label text
+                * set up the default.
+                */
+               if (cd_label.dkl_ascilabel[0] == '\0')
+                       strcpy(cd_label.dkl_ascilabel, CD_DEFLABEL);
+
+               p = (char *)&cd_label;
+               cd_label.dkl_cksum[0] = 0;
+               cd_label.dkl_cksum[1] = 0;
+               while (count--) {
+                       cd_label.dkl_cksum[0] ^= *p++;
+                       cd_label.dkl_cksum[1] ^= *p++;
+               }
+               memcpy(buffer, &cd_label, 512);
+       }
+
+       jtwrite(buffer, SECTOR_SIZE, 1, 0, FALSE);
+       xfwrite(buffer, SECTOR_SIZE, 1, outfile, 0, FALSE);
+       last_extent_written++;
+       return (0);
+}
+
+/*
+ * Do size management for the generic boot code on sectors 0..16.
+ */
+static int
+genboot_size(int starting_extent)
+{
+       if (last_extent > (session_start + 1))
+               comerrno(EX_BAD, "Cannot create generic boot on offset != 0.\n");
+       last_extent = session_start + 16;
+       return (0);
+}
+
+/*
+ * Write the generic boot code to sectors 0..16.
+ * If there is a Sun disk label, start writing at sector 1.
+ */
+static int
+genboot_write(FILE *outfile)
+{
+       char    buffer[SECTOR_SIZE];
+       int     i;
+       int     f;
+
+       if ((f = open(genboot_image, O_RDONLY| O_BINARY)) < 0)
+               comerr("Cannot open '%s'.\n", genboot_image);
+
+       for (i = 0; i < 16; i++) {
+               memset(buffer, 0, sizeof (buffer));
+               if (read(f, buffer, SECTOR_SIZE) < 0)
+                       comerr("Read error on '%s'.\n", genboot_image);
+
+               if (i != 0 || last_extent_written == session_start) {
+                       jtwrite(buffer, SECTOR_SIZE, 1, 0, FALSE);
+                       xfwrite(buffer, SECTOR_SIZE, 1, outfile, 0, FALSE);
+                       last_extent_written++;
+               }
+       }
+       close(f);
+       return (0);
+}
+
+struct output_fragment sunboot_desc    = {NULL, NULL,          NULL,   sunboot_write,  "Sun Boot" };
+struct output_fragment sunlabel_desc   = {NULL, sunlabel_size, NULL,   sunlabel_write, "Sun Disk Label" };
+struct output_fragment genboot_desc    = {NULL, genboot_size,  NULL,   genboot_write,  "Generic Boot" };
diff --git a/genisoimage/bootinfo.h b/genisoimage/bootinfo.h
new file mode 100644 (file)
index 0000000..a02bd65
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)bootinfo.h      1.3 04/03/02 Copyright 1999, 2004 J. Schilling */
+/*
+ *     Header file bootinfo.h - genisoimage-defined boot information table
+ *     useful for an El Torito-loaded disk image.
+ *
+ *     Copyright (c) 1999, 2004 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef        _BOOTINFO_H
+#define        _BOOTINFO_H
+
+struct genisoimage_boot_info {
+       char bi_pvd      [ISODCL(1,   4)]; /* LBA of PVD */
+       char bi_file     [ISODCL(5,   8)]; /* LBA of boot image */
+       char bi_length   [ISODCL(9,  12)]; /* Length of boot image */
+       char bi_csum     [ISODCL(13, 16)]; /* Checksum of boot image */
+       char bi_reserved [ISODCL(17, 56)]; /* Reserved */
+};
+
+#endif /* _BOOTINFO_H */
diff --git a/genisoimage/bswap.h b/genisoimage/bswap.h
new file mode 100644 (file)
index 0000000..5f3fd9d
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)bswap.h 1.2 03/03/25 Copyright 2002 J. Schilling */
+#ifndef _BSWAP_H
+#define        _BSWAP_H
+
+/*
+ *     Allow to use B2N_* macros found in libdvdread in a portable way.
+ *     These macros should better be avoided as in place conversion in
+ *     general only works on processors like Motorola 68000 and Intel x86.
+ *     Modern processors usually have alignement restrictions that may
+ *     cause problems. The stripped down libdvdread for genisoimage is known
+ *     not to have these alignement problems, so we may use the macros
+ *     as they have been introduced by the authors of libdvdread.
+ *
+ *     Copyright (c) 2002 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <mconfig.h>
+#include <btorder.h>
+#include <intcvt.h>
+
+#if defined(WORDS_BIGENDIAN)
+
+/* All bigendian systems are fine, just ignore the swaps. */
+#define        B2N_16(x) (void)(x)
+#define        B2N_32(x) (void)(x)
+#define        B2N_64(x) (void)(x)
+
+#else
+
+/*
+ * It is a bad idea to convert numbers in place.
+ * In protocols, there is usually the additional problem that the
+ * data is not properly aligned.
+ */
+#define        B2N_16(x) (x) = a_to_u_2_byte(&(x))
+#define        B2N_32(x) (x) = a_to_u_4_byte(&(x))
+#define        B2N_64(x) (x) = a_to_u_8_byte(&(x))
+
+#endif
+
+#endif /* _BSWAP_H */
diff --git a/genisoimage/checksum.c b/genisoimage/checksum.c
new file mode 100644 (file)
index 0000000..704167c
--- /dev/null
@@ -0,0 +1,583 @@
+/*
+ * checksum.c
+ *
+ * Copyright (c) 2008- Steve McIntyre <steve@einval.com>
+ *
+ * Implementation of a generic checksum interface, used in JTE.
+ *
+ * GNU GPL v2
+ */
+
+#include <mconfig.h>
+#include "genisoimage.h"
+#include <timedefs.h>
+#include <fctldefs.h>
+#include <regex.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include "md5.h"
+#include "sha1.h"
+#include "sha256.h"
+#include "sha512.h"
+#include "checksum.h"
+
+#ifdef THREADED_CHECKSUMS
+#   include <pthread.h>
+#endif
+
+static void md5_init(void *context)
+{
+    mk_MD5Init(context);
+}
+static void md5_update(void *context, unsigned char const *buf, unsigned int len)
+{
+    mk_MD5Update(context, buf, len);
+}
+static void md5_final(unsigned char *digest, void *context)
+{
+    mk_MD5Final(digest, context);
+}
+
+static void sha1_init(void *context)
+{
+    sha1_init_ctx(context);
+}
+static void sha1_update(void *context, unsigned char const *buf, unsigned int len)
+{
+    sha1_process_bytes(buf, len, context);
+}
+static void sha1_final(unsigned char *digest, void *context)
+{
+    sha1_finish_ctx(context, digest);
+}
+
+static void sha256_init(void *context)
+{
+    sha256_init_ctx(context);
+}
+static void sha256_update(void *context, unsigned char const *buf, unsigned int len)
+{
+    sha256_process_bytes(buf, len, context);
+}
+static void sha256_final(unsigned char *digest, void *context)
+{
+    sha256_finish_ctx(context, digest);
+}
+
+static void sha512_init(void *context)
+{
+    sha512_init_ctx(context);
+}
+static void sha512_update(void *context, unsigned char const *buf, unsigned int len)
+{
+    sha512_process_bytes(buf, len, context);
+}
+static void sha512_final(unsigned char *digest, void *context)
+{
+    sha512_finish_ctx(context, digest);
+}
+
+struct checksum_details
+{
+    char          *name;
+    char          *prog;
+    int            digest_size;
+    int            context_size;
+    void          (*init)(void *context);
+    void          (*update)(void *context, unsigned char const *buf, unsigned int len);
+    void          (*final)(unsigned char *digest, void *context);
+};
+
+static const struct checksum_details algorithms[] = 
+{
+    {
+        "MD5",
+        "md5sum",
+        16,
+        sizeof(struct mk_MD5Context),
+        md5_init,
+        md5_update,
+        md5_final
+    },
+    {
+        "SHA1",
+        "sha1sum",
+        20,
+        sizeof(struct sha1_ctx),
+        sha1_init,
+        sha1_update,
+        sha1_final
+    },
+    {
+        "SHA256",
+        "sha256sum",
+        32,
+        sizeof(struct sha256_ctx),
+        sha256_init,
+        sha256_update,
+        sha256_final
+    },
+    {
+        "SHA512",
+        "sha512sum",
+        64,
+        sizeof(struct sha512_ctx),
+        sha512_init,
+        sha512_update,
+        sha512_final
+    }
+};
+
+struct algo_context
+{
+    void                     *context;
+    unsigned char            *digest;
+    int                       enabled;
+    int                       finalised;
+    char                     *hexdump;
+#ifdef THREADED_CHECKSUMS
+    unsigned char const      *buf;
+    unsigned int              len;
+    int                       which;
+    pthread_t                 thread;
+    struct _checksum_context *parent;
+    pthread_mutex_t           start_mutex;
+    pthread_cond_t            start_cv;
+#endif
+};
+
+struct _checksum_context
+{
+#ifdef THREADED_CHECKSUMS
+    unsigned int           index;
+    unsigned int           threads_running;
+    unsigned int           threads_desired;
+    pthread_mutex_t        done_mutex;
+    pthread_cond_t         done_cv;
+#endif
+    char                  *owner;
+    struct algo_context    algo[NUM_CHECKSUMS];
+};
+
+struct checksum_info *checksum_information(enum checksum_types which)
+{
+    return (struct checksum_info *)&algorithms[which];
+}
+
+/* Dump a buffer in hex */
+static void hex_dump_to_buffer(char *output_buffer, unsigned char *buf, size_t buf_size)
+{
+    unsigned int i;
+    char *p = output_buffer;
+
+    memset(output_buffer, 0, 1 + (2*buf_size));
+    for (i = 0; i < buf_size ; i++)
+        p += sprintf(p, "%2.2x", buf[i]);
+}
+
+#ifdef THREADED_CHECKSUMS
+static void *checksum_thread(void *arg)
+{
+    struct algo_context *a = arg;
+    struct _checksum_context *c = a->parent;
+    int num_blocks_summed = 0;
+
+    while (1)
+    {
+        /* wait to be given some work to do */
+        pthread_mutex_lock(&a->start_mutex);
+        while (a->buf == NULL)
+        {
+            pthread_cond_wait(&a->start_cv, &a->start_mutex);
+        }
+        pthread_mutex_unlock(&a->start_mutex);
+
+        /* if we're given a zero-length buffer, then that means we're
+         * done */
+        if (a->len == 0)
+            break;
+
+        /* actually do the checksum on the supplied buffer */
+        algorithms[a->which].update(a->context, a->buf, a->len);
+        num_blocks_summed++;
+        a->buf = NULL;
+
+        /* and tell the main thread that we're done with that
+         * buffer */
+        pthread_mutex_lock(&c->done_mutex);
+        c->threads_running--;
+        if (c->threads_running == 0)
+            pthread_cond_signal(&c->done_cv);
+        pthread_mutex_unlock(&c->done_mutex);
+    }
+
+    pthread_exit(0);
+}
+#endif
+
+checksum_context_t *checksum_init_context(int checksums, const char *owner)
+{
+    int i = 0;
+    int ret = 0;
+    struct _checksum_context *context = calloc(1, sizeof(struct _checksum_context));
+
+    if (!context)
+        return NULL;
+
+    context->owner = strdup(owner);
+    if (!context->owner)
+    {
+        free(context);
+        return NULL;
+    }   
+
+#ifdef THREADED_CHECKSUMS
+    pthread_mutex_init(&context->done_mutex, NULL);
+    pthread_cond_init(&context->done_cv, NULL);
+    context->index = 0;
+    context->threads_running = 0;
+    context->threads_desired = 0;
+
+    for (i = 0; i < NUM_CHECKSUMS; i++)
+        if ( (1 << i) & checksums)
+            context->threads_desired++;    
+#endif
+
+    for (i = 0; i < NUM_CHECKSUMS; i++)
+    {
+        struct algo_context *a = &context->algo[i];
+        if ( (1 << i) & checksums)
+        {
+            a->context = malloc(algorithms[i].context_size);
+            if (!a->context)
+            {
+                checksum_free_context(context);
+                return NULL;
+            }
+            a->digest = malloc(algorithms[i].digest_size);
+            if (!a->digest)
+            {
+                checksum_free_context(context);
+                return NULL;
+            }
+            a->hexdump = malloc(1 + (2*algorithms[i].digest_size));
+            if (!a->hexdump)
+            {
+                checksum_free_context(context);
+                return NULL;
+            }
+            algorithms[i].init(a->context);
+            a->enabled = 1;
+            a->finalised = 0;
+#ifdef THREADED_CHECKSUMS
+            a->which = i;
+            a->parent = context;
+            a->buf = NULL;
+            a->len = 0;
+            pthread_mutex_init(&a->start_mutex, NULL);
+            pthread_cond_init(&a->start_cv, NULL);
+            ret = pthread_create(&a->thread, NULL, checksum_thread, a);
+            if (ret != 0)
+            {
+                fprintf(stderr, "failed to create new thread: %d\n", ret);
+                checksum_free_context(context);
+                return NULL;
+            }
+#endif
+        }
+        else
+            a->enabled = 0;
+    }
+    
+    return context;
+}
+
+void checksum_free_context(checksum_context_t *context)
+{
+    int i = 0;
+    struct _checksum_context *c = context;
+
+    for (i = 0; i < NUM_CHECKSUMS; i++)
+    {
+        struct algo_context *a = &c->algo[i];
+
+#ifdef THREADED_CHECKSUMS
+        if (a->thread)
+        {
+            void *ret;
+            pthread_cancel(a->thread);
+            pthread_join(a->thread, &ret);
+            a->thread = 0;
+        }
+#endif
+        free(a->context);
+        free(a->digest);
+        free(a->hexdump);
+    }
+    free(c->owner);
+    free(c);
+}
+
+#ifdef THREADED_CHECKSUMS
+void checksum_update(checksum_context_t *context,
+                     unsigned char const *buf, unsigned int len)
+{
+    int i = 0;
+    struct _checksum_context *c = context;
+    static int index = 0;
+
+    index++;
+
+    c->threads_running = c->threads_desired;    
+    for (i = 0; i < NUM_CHECKSUMS; i++)
+    {
+        if (c->algo[i].enabled)
+        {
+            struct algo_context *a = &c->algo[i];
+            pthread_mutex_lock(&a->start_mutex);
+            a->len = len;
+            a->buf = buf;
+            pthread_cond_signal(&a->start_cv);
+            pthread_mutex_unlock(&a->start_mutex);
+        }
+    }
+
+    /* Should now all be running, wait on them all to return */
+    pthread_mutex_lock(&c->done_mutex);
+    while (c->threads_running > 0)
+    {
+        pthread_cond_wait(&c->done_cv, &c->done_mutex);
+    }
+    pthread_mutex_unlock(&c->done_mutex);
+}
+
+#else // THREADED_CHECKSUMS
+
+void checksum_update(checksum_context_t *context,
+                     unsigned char const *buf, unsigned int len)
+{
+    int i = 0;
+    struct _checksum_context *c = context;
+    
+    for (i = 0; i < NUM_CHECKSUMS; i++)
+    {
+        if (c->algo[i].enabled)
+        {
+            struct algo_context *a = &c->algo[i];
+            algorithms[i].update(a->context, buf, len);
+        }
+    }
+}
+
+#endif // THREADED_CHECKSUMS
+
+void checksum_final(checksum_context_t *context)
+{
+    int i = 0;
+    struct _checksum_context *c = context;
+    
+#ifdef THREADED_CHECKSUMS
+    void *thread_ret;
+    /* Clean up the threads */
+    c->threads_running = c->threads_desired;    
+
+    for (i = 0; i < NUM_CHECKSUMS; i++)
+    {
+        if (c->algo[i].enabled)
+        {
+            void *ret = 0;
+            struct algo_context *a = &c->algo[i];
+
+            pthread_mutex_lock(&a->start_mutex);
+            a->len = 0;
+            a->buf = (unsigned char *)-1;
+            pthread_cond_signal(&a->start_cv);
+            pthread_mutex_unlock(&a->start_mutex);
+            pthread_join(a->thread, &ret);
+            a->thread = 0;
+        }
+    }
+#endif
+
+    for (i = 0; i < NUM_CHECKSUMS; i++)
+    {
+        struct algo_context *a = &c->algo[i];
+        if (a->enabled)
+        {
+            algorithms[i].final(a->digest, a->context);
+            hex_dump_to_buffer(a->hexdump, a->digest, algorithms[i].digest_size);
+            a->finalised = 1;
+        }
+    }
+}
+
+void checksum_copy(checksum_context_t *context,
+                   enum checksum_types which,
+                   unsigned char *digest)
+{
+    struct _checksum_context *c = context;
+
+    if (c->algo[which].enabled)
+    {
+        if (c->algo[which].finalised)
+            memcpy(digest, c->algo[which].digest, algorithms[which].digest_size);
+        else
+            memset(digest, 0, algorithms[which].digest_size);
+    }
+    else
+        fprintf(stderr, "Asked for %s checksum, not enabled!\n",
+                algorithms[which].name);
+}
+
+const char *checksum_hex(checksum_context_t *context,
+                         enum checksum_types which)
+{
+    struct _checksum_context *c = context;
+
+    if (c->algo[which].enabled && c->algo[which].finalised)
+        return c->algo[which].hexdump;
+
+    /* else */
+    return NULL;
+}
+
+
+/* Parse the command line options for which checksums to use */
+int parse_checksum_algo(char *arg, int *algo)
+{
+    int error = 0;
+    int i = 0;
+    char *start_ptr = arg;
+    int len = 0;
+
+    *algo = 0;
+
+    if (!strcasecmp(arg, "all"))
+    {
+        *algo = 0xFF;
+        return 0;
+    }
+    
+    while (*start_ptr != 0)
+    {
+        int match = 0;
+        len = 0;
+
+        while (start_ptr[len] != ',' && start_ptr[len] != 0)
+            len++;
+        
+        if (len)
+        {
+            for (i = 0; i < NUM_CHECKSUMS; i++)
+            {
+                if (len == strlen(algorithms[i].name) &&
+                    !strncasecmp(start_ptr, algorithms[i].name, len))
+                {
+                    match = 1;
+                    *algo |= (1 << i);
+                }
+            }
+        
+            if (!match)
+            {
+                fprintf(stderr, "invalid algorithm name found in %s\n", arg);
+                return EINVAL;
+            }
+        }
+        
+        if (start_ptr[len] == 0)
+            break;
+            
+        start_ptr += len + 1;
+    }
+    
+    if (! (*algo & CHECK_MD5_USED))
+    {
+        fprintf(stderr, "invalid choices: algorithms *must* include MD5\n");
+        return EINVAL;
+    }
+    
+    return 0;
+}
+
+#ifdef CHECKSUM_SELF_TEST
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+
+int main(int argc, char **argv)
+{
+    char buf[1024];
+    int fd = -1;
+    char *filename;
+    int err = 0;
+    static checksum_context_t *test_context = NULL;
+    int i = 0;
+
+    if (argc != 2)
+    {
+        fprintf(stderr, "Need a filename to act on!\n");
+        return 1;
+    }
+
+    filename = argv[1];
+    fd = open(filename, O_RDONLY);
+    if (fd < 0)
+    {
+        fprintf(stderr, "Unable to open file %s, errno %d\n", filename, errno);
+        return 1;
+    }
+
+    test_context = checksum_init_context(CHECK_ALL_USED, "test");
+    if (!test_context)
+    {
+        fprintf(stderr, "Unable to initialise checksum context\n");
+        return 1;
+    }
+
+    while(1)
+    {
+        err = read(fd, buf, sizeof(buf));
+        if (err < 0)
+        {
+            fprintf(stderr, "Failed to read from file, errno %d\n", errno);
+            return 1;
+        }
+
+        if (err == 0)
+            break; // EOF
+
+        /* else */
+        checksum_update(test_context, buf, err);
+    }
+    close(fd);
+    checksum_final(test_context);
+
+    for (i = 0; i < NUM_CHECKSUMS; i++)
+    {
+        struct checksum_info *info;
+        unsigned char r[64];
+        int j = 0;
+
+        info = checksum_information(i);
+        memset(r, 0, sizeof(r));
+
+        checksum_copy(test_context, i, r);
+
+        printf("OUR %s:\n", info->name);
+        for (j = 0; j < info->digest_size; j++)
+            printf("%2.2x", r[j]);
+        printf("  %s\n", filename);
+        printf("system checksum program (%s):\n", info->prog);
+        sprintf(buf, "%s %s", info->prog, filename);
+        system(buf);
+        printf("\n");
+    }
+    return 0;
+}
+#endif /* CHECKSUM_SELF_TEST */
+
diff --git a/genisoimage/checksum.h b/genisoimage/checksum.h
new file mode 100644 (file)
index 0000000..367fae2
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * checksum.h
+ *
+ * Copyright (c) 2008- Steve McIntyre <steve@einval.com>
+ *
+ * Definitions and prototypes for a generic checksum interface, used
+ * in JTE. Inspired heavily by the interface to the MD5 code we're
+ * using already.
+ *
+ * GNU GPL v2
+ */
+
+enum checksum_types
+{
+    CHECK_MD5 = 0,
+    CHECK_SHA1,
+    CHECK_SHA256,
+    CHECK_SHA512,
+    NUM_CHECKSUMS
+};
+
+#define CHECK_MD5_USED     (1 << CHECK_MD5)
+#define CHECK_SHA1_USED    (1 << CHECK_SHA1)
+#define CHECK_SHA256_USED  (1 << CHECK_SHA256)
+#define CHECK_SHA512_USED  (1 << CHECK_SHA512)
+#define CHECK_ALL_USED     0xFFFFFFFF
+
+typedef void checksum_context_t;
+
+struct checksum_info
+{
+    char          *name;
+    char          *prog;
+    int            digest_size;
+};
+
+/* Ask the library for information about a particular checksum
+ * algorithm. Returns a pointer to internal memory - DO NOT
+ * MODIFY/FREE! */
+struct checksum_info *checksum_information(enum checksum_types which);
+
+/* Allocate / initialise a context for the chosen checksums. OR
+ * together the desired checksums as the parameter */
+checksum_context_t   *checksum_init_context(int checksums, const char *owner);
+
+/* Cleanup and free a context when it's finished with */
+void                  checksum_free_context(checksum_context_t *context);
+
+/* Pass a new buffer full of data through the checksum code */
+void                  checksum_update(checksum_context_t *context,
+                                      unsigned char const *buf,
+                                      unsigned int len);
+
+/* Finish the current set of checksums */
+void                  checksum_final(checksum_context_t *context);
+
+/* Extract a particular algorithm's checksum once checksum_final() has
+ * been called. Use the details in checksum_information() above first
+ * to see how big the digest will be. Only valid once checksum_final()
+ * has been called, otherwise the digest returned will be all
+ * zeroes. */
+void                  checksum_copy(checksum_context_t *context,
+                                    enum checksum_types which,
+                                    unsigned char *digest);
+
+/* Helper function: return a pointer to a string containing the ASCII
+ * hexadecimal dump of a checksum. Only valid once checksum_final()
+ * has been called, otherwise will return NULL */
+const char *          checksum_hex(checksum_context_t *context,
+                                   enum checksum_types which);
+
+
+extern int            parse_checksum_algo(char *arg,
+                                          int *algo);
diff --git a/genisoimage/config.h b/genisoimage/config.h
new file mode 100644 (file)
index 0000000..b0f49ce
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)config.h        1.1 97/05/16 Copyright 1997 J. Schilling */
+/*
+ *     Adaption for mconfig.h from make file system.
+ *
+ *     Copyright (c) 1997 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <mconfig.h>
diff --git a/genisoimage/defaults.h b/genisoimage/defaults.h
new file mode 100644 (file)
index 0000000..60fea33
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)defaults.h      1.19 06/01/30 joerg */
+/*
+ * Header file defaults.h - assorted default values for character strings in
+ * the volume descriptor.
+ *
+ * Copyright (c) 1999-2004 J. Schilling
+ */
+
+#define        PREPARER_DEFAULT        NULL
+#define        PUBLISHER_DEFAULT       NULL
+/*
+ * Define me when it's needed again
+#ifndef        APPID_DEFAULT
+#ifdef APPLE_HYB
+#define        APPID_DEFAULT           "MKISOFS ISO 9660/HFS FILESYSTEM BUILDER (C) 1993 E.YOUNGDALE (C) 1997 J.PEARSON/J.SCHILLING"
+#else
+#define        APPID_DEFAULT           "MKISOFS ISO 9660 FILESYSTEM BUILDER (C) 1993 E.YOUNGDALE (C) 1997 J.PEARSON/J.SCHILLING"
+#endif / * APPLE_HYB * /
+#endif */
+#define        COPYRIGHT_DEFAULT       NULL
+#define        BIBLIO_DEFAULT          NULL
+#define        ABSTRACT_DEFAULT        NULL
+#define        VOLSET_ID_DEFAULT       NULL
+#define        VOLUME_ID_DEFAULT       "CDROM"
+#define        BOOT_CATALOG_DEFAULT    "boot.catalog"
+#define        BOOT_IMAGE_DEFAULT      NULL
+#define  SILO_BOOT_IMAGE_DEFAULT "boot/second.b"
+#define  SILO_BOOTBLOCK_DEFAULT        "boot/cd.b"
+#define  SILO_CONF_FILE_DEFAULT        "/etc/silo.conf"
+#ifdef APPLE_HYB
+#define        APPLE_TYPE_DEFAULT      "TEXT"
+#define        APPLE_CREATOR_DEFAULT   "unix"
+#endif /* APPLE_HYB */
+
+#ifdef __QNX__
+#define        SYSTEM_ID_DEFAULT       "QNX"
+#endif
+
+#ifdef __osf__
+#define        SYSTEM_ID_DEFAULT       "OSF"
+#endif
+
+#ifdef __sun
+#ifdef __SVR4
+#define        SYSTEM_ID_DEFAULT       "Solaris"
+#else
+#define        SYSTEM_ID_DEFAULT       "SunOS"
+#endif
+#endif
+
+#ifdef __hpux
+#define        SYSTEM_ID_DEFAULT       "HP-UX"
+#endif
+
+#ifdef __sgi
+#define        SYSTEM_ID_DEFAULT       "SGI"
+#endif
+
+#if    defined(_IBMR2) || defined(_AIX)
+#define        SYSTEM_ID_DEFAULT       "AIX"
+#endif
+
+#if    defined(_WIN) || defined(__CYGWIN32__) || defined(__CYGWIN__)
+#define        SYSTEM_ID_DEFAULT       "Win32"
+#endif /* _WIN */
+
+#ifdef __EMX__
+#define        SYSTEM_ID_DEFAULT       "OS/2"
+#endif
+
+#ifdef __FreeBSD__
+#define        SYSTEM_ID_DEFAULT       "FreeBSD"
+#endif
+
+#ifdef __DragonFly__
+#define        SYSTEM_ID_DEFAULT       "DragonFly"
+#endif
+
+#ifdef __NetBSD__
+#define        SYSTEM_ID_DEFAULT       "NetBSD"
+#endif
+
+#ifdef __OpenBSD__
+#define        SYSTEM_ID_DEFAULT       "OpenBSD"
+#endif
+
+#ifdef __bsdi__
+#define        SYSTEM_ID_DEFAULT       "BSD/OS"
+#endif
+
+#ifdef __NeXT__
+#define        SYSTEM_ID_DEFAULT       "NeXT"
+#endif
+
+#if defined(__NeXT__) && defined(__TARGET_OSNAME) && __TARGET_OSNAME == rhapsody
+#undef SYSTEM_ID_DEFAULT
+#define        SYSTEM_ID_DEFAULT       "Rhapsody"
+#endif
+
+#if defined(__APPLE__) && defined(__MACH__)
+#undef SYSTEM_ID_DEFAULT
+#define        SYSTEM_ID_DEFAULT       "Mac OS X"
+#endif
+
+#ifdef __BEOS__
+#define        SYSTEM_ID_DEFAULT       "BeOS"
+#endif
+
+#ifdef __OS2
+#define        SYSTEM_ID_DEFAULT       "OS/2"
+#endif
+
+#ifdef VMS
+#define        SYSTEM_ID_DEFAULT       "VMS"
+#endif
+
+#ifdef OPENSERVER
+#define        SYSTEM_ID_DEFAULT       "SCO-OPENSERVER"
+#endif
+
+#ifdef UNIXWARE
+#define        SYSTEM_ID_DEFAULT       "SCO-UNIXWARE"
+#endif
+
+#ifdef linux
+#define        SYSTEM_ID_DEFAULT       "LINUX"
+#endif
+
+#ifdef __DJGPP__
+#define        SYSTEM_ID_DEFAULT       "DOS"
+#endif
+
+#ifndef SYSTEM_ID_DEFAULT
+#define        SYSTEM_ID_DEFAULT       "UNIX"
+#endif
diff --git a/genisoimage/desktop.c b/genisoimage/desktop.c
new file mode 100644 (file)
index 0000000..51b0269
--- /dev/null
@@ -0,0 +1,180 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)desktop.c       1.6 04/03/04 joerg, Copyright 1997, 1998, 1999, 2000 James Pearson */
+/*
+ *      Copyright (c) 1997, 1998, 1999, 2000 James Pearson
+ *
+ * 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; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ *     make_desktop: create "Desktop DB" and "Desktop DF" files.
+ *
+ *     These are set up to prevent the Mac "rebuilding the desktop"
+ *     when the CD is inserted ???
+ *
+ *     I don't know if these files should be populated, but I've just
+ *     created these files in their initial states:
+ *
+ *     Desktop DB:     Initial size == volume's clump size
+ *                     first block contents found by using od ...
+ *                     rest of file seems to be padding
+ *                     No resource fork
+ *
+ *     Desktop DF:     Empty
+ *
+ *     If the files already exist, then set correct type/creator/flags
+ *
+ *     James Pearson 11/8/97
+ *     Adapted from mkhfs routines for mkhybrid
+ */
+
+#ifdef APPLE_HYB
+
+#include <mconfig.h>
+#include "genisoimage.h"
+
+#define        DB      "Desktop DB"
+#define        DBFC    "DMGR"
+#define        DBT     "BTFL"
+
+#define        DF      "Desktop DF"
+#define        DFT     "DTFL"
+
+/*
+ * from "data.h" - libhfs routines
+ */
+extern void d_putw(unsigned char *, short);
+extern void d_putl(unsigned char *, long);
+
+int    make_desktop(hfsvol *vol, int end);
+
+
+extern hce_mem *hce;   /* libhfs/genisoimage extras */
+
+int
+make_desktop(hfsvol *vol, int end)
+{
+       hfsfile         *hfp;                   /* Mac file */
+       hfsdirent       ent;                    /* Mac finderinfo */
+       unsigned long   clps;                   /* clump size */
+       unsigned short  blks;                   /* blocks in a clump */
+       unsigned char   *blk;                   /* user data */
+
+       /*
+        * set up default directory entries - not all these fields are needed,
+        * but we'll set them up anyway ...
+        * First do a memset because there was a report about randomly
+        * changing Desktop DB/DF entries...
+        */
+       memset(&ent, 0, sizeof (hfsdirent));    /* First clear all ... */
+       ent.u.file.rsize = 0;                   /* resource size == 0 */
+       strcpy(ent.u.file.creator, DBFC);       /* creator */
+       strcpy(ent.u.file.type, DBT);           /* type */
+       ent.crdate = ent.mddate = time(0);      /* date is now */
+       ent.fdflags = HFS_FNDR_ISINVISIBLE;     /* invisible files */
+
+       /*
+        * clear the DB file
+        */
+       blk = hce->hfs_ce + hce->hfs_ce_size * HFS_BLOCKSZ;
+       blks = hce->hfs_dt_size;
+       clps = blks * HFS_BLOCKSZ;
+
+       memset(blk, 0, clps);
+
+       /*
+        * create "Desktop DB" (if it doesn't exist)
+        */
+       if (hfs_create(vol, DB, ent.u.file.type, ent.u.file.creator) == 0) {
+               /*
+                * DB file size from hce_mem info
+                * set up "Desktop DB" data - following found by od'ing the
+                * "Desktop DB" file
+                */
+               d_putw(blk + 8, 0x100);
+               d_putw(blk + 10, 0x3);
+
+               d_putw(blk + 32, 0x200);
+               d_putw(blk + 34, 0x25);
+
+               d_putl(blk + 36, blks);
+               d_putl(blk + 40, blks - 1);
+
+               d_putl(blk + 46, clps);
+               d_putw(blk + 50, 0xff);
+
+               d_putw(blk + 120, 0x20a);
+               d_putw(blk + 122, 0x100);
+
+               d_putw(blk + 248, 0x8000);
+
+               d_putl(blk + 504, 0x1f800f8);
+               d_putl(blk + 508, 0x78000e);
+
+               /* entries for "Desktop DB" */
+               ent.u.file.dsize = clps;        /* size = clump size */
+
+               /* open file */
+               if ((hfp = hfs_open(vol, DB)) == 0)
+                       perr(hfs_error);
+
+               /* "write" file */
+               write_fork(hfp, clps);
+
+               /* set DB file attributes */
+               if (hfs_fsetattr(hfp, &ent) < 0)
+                       perr(hfs_error);
+
+               /* find the real start of the file */
+               end += hce->hfs_ce_size;
+
+               /* close DB file */
+               if (hfs_close(hfp, end, 0) < 0)
+                       perr(hfs_error);
+       } else {
+               /*
+                * if it already exists, then make sure it has the correct
+                * type/creator and flags
+                */
+               if (hfs_setattr(vol, DB, &ent) < 0)
+                       perr(hfs_error);
+       }
+
+       /* setup "Desktop DF" file as an empty file */
+       strcpy(ent.u.file.type, DFT);           /* type */
+       ent.u.file.dsize = 0;                   /* empty */
+
+       /* create DF file (if it doesn't exist) - no need to open it */
+       hfs_create(vol, DF, ent.u.file.type, ent.u.file.creator);
+
+       /* set DB file attributes */
+       if (hfs_setattr(vol, DF, &ent) < 0)
+               perr(hfs_error);
+
+       return (0);
+}
+
+#endif /* APPLE_HYB */
diff --git a/genisoimage/diag/README b/genisoimage/diag/README
new file mode 100644 (file)
index 0000000..26851f2
--- /dev/null
@@ -0,0 +1,76 @@
+# @(#)README   1.1 97/02/23 eric
+#
+       I am enclosing 3 test programs that I use to verify the
+integrity of an iso9660 disc.  The first one (isodump) is pretty
+simple - it dumps to the screen the contents of the various
+directories.  The second one (isovfy) goes through and looks for
+problems of one kind or another.
+
+       To use, type something like "./isodump /dev/ramdisk" or
+"./isodump /dev/scd0", depending upon where the iso9660 disc is.  It
+starts by displaying the files in the first sector of the root
+directory.  It has some pretty simple one letter commands that you
+can use to traverse the directory tree.
+
+       a - move back one sector.
+       b - move forward one sector.
+       g - go to new logical sector.
+       q - quit
+
+The a and b commands do not try and stop you from going past the
+beginning or end of a sector, and the g command does not have any way
+of knowing whether the sector you request is actually a directory or
+not.
+
+       The output is displayed in several columns.  The first column
+is the total length of the directory record for the file.  The second
+column (in [] brackets) is the volume number.  Next comes the starting
+extent number (in hex), and then comes the file size in bytes.  Then
+cones the filename (not the Rock Ridge version), and this is preceeded
+by an "*" if the file is a directory.  After this is a summary of the
+Rock Ridge fields present along with a display of the translation of
+the symbolic link name if the SL Rock Ridge record is present.
+
+       I tailored this program for debugging some of the problems
+that I was having earlier.  The idea is that you can tailor it
+to test for problems that you might be having, so it is not intended
+as a be-all and end-all dump program.
+
+       If you move to a sector that does not contain directory
+information, the results are unpredictable.
+
+       The second program, isovfy, is run in the same way as isodump,
+except that you do not have to do much except let it run.  I have it
+written to verify all kinds of different things, and as people find
+other sorts of problems other tests could be added.
+
+       The third program, dump.c, basically does a hexdump of the cd.
+This is screen oriented, and there are some simple commands:
+
+       a - move back one sector.
+       b - move forward one sector.
+       f - enter new search string.
+       + - search forward for search string.
+       g - go to new logical sector.
+       q - quit
+
+
+       Note that with the 'g' command, sectors are always given in
+hex, and represent 2048 byte sectors (as on the cdrom).  If you know
+how to decode a raw iso9660 directory, you can pick out the starting
+extent number from the hexdump and know where to go from there.  The
+starting extent appears something like 30 bytes prior to the start of
+the iso9660 (not Rock Ridge) filename, and it appears in a 7.3.3
+format (meaning that it occupies 8 bytes, 4 in little endian format,
+and 4 in big endian format).  Thus you should see a mirror image of
+the bytes when looking at the extent number.
+
+       The isovfy program can also dump the contents of the path
+tables, but this capability is commented out right now.  Feel free
+to enable this to see what is in the tables.  Ultimately I may fix
+it so that this checks the integrity of the tables as well.
+
+       The isovfy program gives warnings about things like files that
+have a size of 0 but have an extent number assigned.  The genisoimage program
+should never do this, but the YM software does leave these around.
+I think it is probably harmless in the YM case.~
diff --git a/genisoimage/diag/devdump.1 b/genisoimage/diag/devdump.1
new file mode 100644 (file)
index 0000000..b170c59
--- /dev/null
@@ -0,0 +1,2 @@
+.so man1/isoinfo.1
+.\" %Z%%M%     %I% %E% joerg
diff --git a/genisoimage/diag/dump.c b/genisoimage/diag/dump.c
new file mode 100644 (file)
index 0000000..b853c4e
--- /dev/null
@@ -0,0 +1,428 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)dump.c  1.24 05/05/15 joerg */
+/*
+ * File dump.c - dump a file/device both in hex and in ASCII.
+ *
+ * Written by Eric Youngdale (1993).
+ *
+ * Copyright 1993 Yggdrasil Computing, Incorporated
+ * Copyright (c) 1999-2004 J. Schilling
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <mconfig.h>
+#include <stdxlib.h>
+#include <unixstd.h>
+#include <strdefs.h>
+#include <utypes.h>
+
+#include <stdio.h>
+#include <standard.h>
+#include <ttydefs.h>
+#include <signal.h>
+#include <schily.h>
+
+#include "../scsi.h"
+#include "../../wodim/defaults.h"
+
+/*
+ * Note: always use these macros to avoid problems.
+ *
+ * ISO_ROUND_UP(X)     may cause an integer overflow and thus give
+ *                     incorrect results. So avoid it if possible.
+ *
+ * ISO_BLOCKS(X)       is overflow safe. Prefer this when ever it is possible.
+ */
+#define        SECTOR_SIZE     (2048)
+#define        ISO_ROUND_UP(X) (((X) + (SECTOR_SIZE - 1)) & ~(SECTOR_SIZE - 1))
+#define        ISO_BLOCKS(X)   (((X) / SECTOR_SIZE) + (((X)%SECTOR_SIZE)?1:0))
+
+#define        infile  in_image
+FILE           *infile = NULL;
+static off_t           file_addr;
+static off_t           sec_addr = (off_t)-1;
+static Uchar           sector[2048];
+#define        PAGE    256
+static Uchar           buffer[PAGE];
+static Uchar           search[64];
+
+#ifdef USE_V7_TTY
+static struct sgttyb   savetty;
+static struct sgttyb   newtty;
+#else
+static struct termios  savetty;
+static struct termios  newtty;
+#endif
+
+static void    reset_tty(void);
+static void    set_tty(void);
+static void    onsusp(int sig);
+static void    crsr2(int row, int col);
+static void    readblock(void);
+static void    showblock(int flag);
+static int     getbyte(void);
+static void    usage(int excode);
+
+static void
+reset_tty()
+{
+#ifdef USE_V7_TTY
+       if (ioctl(STDIN_FILENO, TIOCSETN, &savetty) == -1) {
+#else
+#ifdef TCSANOW
+       if (tcsetattr(STDIN_FILENO, TCSANOW, &savetty) == -1) {
+#else
+       if (ioctl(STDIN_FILENO, TCSETAF, &savetty) == -1) {
+#endif
+#endif
+#ifdef USE_LIBSCHILY
+               comerr("Cannot put tty into normal mode\n");
+#else
+               printf("Cannot put tty into normal mode\n");
+               exit(1);
+#endif
+       }
+}
+
+static void
+set_tty()
+{
+#ifdef USE_V7_TTY
+       if (ioctl(STDIN_FILENO, TIOCSETN, &newtty) == -1) {
+#else
+#ifdef TCSANOW
+       if (tcsetattr(STDIN_FILENO, TCSANOW, &newtty) == -1) {
+#else
+       if (ioctl(STDIN_FILENO, TCSETAF, &newtty) == -1) {
+#endif
+#endif
+#ifdef USE_LIBSCHILY
+               comerr("Cannot put tty into raw mode\n");
+#else
+               printf("Cannot put tty into raw mode\n");
+               exit(1);
+#endif
+       }
+}
+
+
+/*
+ * Come here when we get a suspend signal from the terminal
+ */
+static void
+onsusp(int sig)
+{
+#ifdef SIGTTOU
+       /* ignore SIGTTOU so we don't get stopped if csh grabs the tty */
+       signal(SIGTTOU, SIG_IGN);
+#endif
+       reset_tty();
+       fflush(stdout);
+#ifdef SIGTTOU
+       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);
+#endif
+       set_tty();
+}
+
+
+static void
+crsr2(int row, int col)
+{
+       printf("\033[%d;%dH", row, col);
+}
+
+static void
+readblock()
+{
+       off_t   dpos = file_addr - sec_addr;
+
+       if (sec_addr < 0 ||
+           dpos < 0 || (dpos + sizeof (buffer)) > sizeof (sector)) {
+               sec_addr = file_addr & ~2047;
+#ifdef USE_SCG
+               readsecs(sec_addr/2048, sector, ISO_BLOCKS(sizeof (sector)));
+#else
+               lseek(fileno(infile), sec_addr, SEEK_SET);
+               read(fileno(infile), sector, sizeof (sector));
+#endif
+               dpos = file_addr - sec_addr;
+       }
+       movebytes(&sector[dpos], buffer, sizeof (buffer));
+}
+
+static void
+showblock(int flag)
+{
+       unsigned int    k;
+       int             i;
+       int             j;
+
+       readblock();
+       if (flag) {
+               for (i = 0; i < 16; i++) {
+                       crsr2(i+3, 1);
+                       if (sizeof (file_addr) > sizeof (long)) {
+                               printf("%16.16llx ", (Llong)file_addr+(i<<4));
+                       } else {
+                               printf("%8.8lx ", (long)file_addr+(i<<4));
+                       }
+                       for (j = 15; j >= 0; j--) {
+                               printf("%2.2x", buffer[(i<<4)+j]);
+                               if (!(j & 0x3))
+                                       printf(" ");
+                       }
+                       for (j = 0; j < 16; j++) {
+                               k = buffer[(i << 4) + j];
+                               if (k >= ' ' && k < 0x80)
+                                       printf("%c", k);
+                               else
+                                       printf(".");
+                       }
+               }
+       }
+       crsr2(20, 1);
+       if (sizeof (file_addr) > sizeof (long)) {
+               printf(" Zone, zone offset: %14llx %12.12llx  ",
+                       (Llong)file_addr>>11, (Llong)file_addr & 0x7ff);
+       } else {
+               printf(" Zone, zone offset: %6lx %4.4lx  ",
+                       (long)(file_addr>>11), (long)(file_addr & 0x7ff));
+       }
+       fflush(stdout);
+}
+
+static int
+getbyte()
+{
+       char    c1;
+
+       c1 = buffer[file_addr & (PAGE-1)];
+       file_addr++;
+       if ((file_addr & (PAGE-1)) == 0)
+               showblock(0);
+       return (c1);
+}
+
+static void
+usage(int excode)
+{
+       errmsgno(EX_BAD, "Usage: %s [options] [image]\n",
+                                               get_progname());
+
+       fprintf(stderr, "Options:\n");
+       fprintf(stderr, "\t-help, -h    Print this help\n");
+       fprintf(stderr, "\t-version     Print version info and exit\n");
+       fprintf(stderr, "\t-i filename  Filename to read ISO-9660 image from\n");
+       fprintf(stderr, "\tdev=target   SCSI target to use as CD/DVD-Recorder\n");
+       fprintf(stderr, "\nIf neither -i nor dev= are speficied, <image> is needed.\n");
+       exit(excode);
+}
+
+int
+main(int argc, char *argv[])
+{
+       int     cac;
+       char    * const *cav;
+       char    *opts = "help,h,version,i*,dev*";
+       BOOL    help = FALSE;
+       BOOL    prvers = FALSE;
+       char    *filename = NULL;
+       char    *devname = NULL;
+       char    c;
+       int     i;
+       int     j;
+
+       save_args(argc, argv);
+
+       cac = argc - 1;
+       cav = argv + 1;
+       if (getallargs(&cac, &cav, opts, &help, &help, &prvers,
+                       &filename, &devname) < 0) {
+               errmsgno(EX_BAD, "Bad Option: '%s'\n", cav[0]);
+               usage(EX_BAD);
+       }
+       if (help)
+               usage(0);
+       if (prvers) {
+               printf("devdump %s (%s)\n", CDRKIT_VERSION, HOST_SYSTEM);
+               exit(0);
+       }
+       cac = argc - 1;
+       cav = argv + 1;
+       if (filename == NULL && devname == NULL) {
+               if (getfiles(&cac, &cav, opts) != 0) {
+                       filename = cav[0];
+                       cac--, cav++;
+               }
+       }
+       if (getfiles(&cac, &cav, opts) != 0) {
+               errmsgno(EX_BAD, "Bad Argument: '%s'\n", cav[0]);
+               usage(EX_BAD);
+       }
+       if (filename != NULL && devname != NULL) {
+               errmsgno(EX_BAD, "Only one of -i or dev= allowed\n");
+               usage(EX_BAD);
+       }
+#ifdef USE_SCG
+       if (filename == NULL && devname == NULL)
+               cdr_defaults(&devname, NULL, NULL, NULL);
+#endif
+       if (filename == NULL && devname == NULL) {
+#ifdef USE_LIBSCHILY
+               errmsgno(EX_BAD, "ISO-9660 image not specified\n");
+#else
+               fprintf(stderr, "ISO-9660 image not specified\n");
+#endif
+               usage(EX_BAD);
+       }
+
+       if (filename != NULL)
+               infile = fopen(filename, "rb");
+       else
+               filename = devname;
+
+       if (infile != NULL) {
+               /* EMPTY */;
+#ifdef USE_SCG
+       } else if (scsidev_open(filename) < 0) {
+#else
+       } else {
+#endif
+#ifdef USE_LIBSCHILY
+               comerr("Cannot open '%s'\n", filename);
+#else
+               fprintf(stderr, "Cannot open '%s'\n", filename);
+               exit(1);
+#endif
+       }
+
+       for (i = 0; i < 30; i++)
+               printf("\n");
+       file_addr = (off_t)0;
+
+       /*
+        * Now setup the keyboard for single character input.
+        */
+#ifdef USE_V7_TTY
+       if (ioctl(STDIN_FILENO, TIOCGETP, &savetty) == -1) {
+#else
+#ifdef TCSANOW
+       if (tcgetattr(STDIN_FILENO, &savetty) == -1) {
+#else
+       if (ioctl(STDIN_FILENO, TCGETA, &savetty) == -1) {
+#endif
+#endif
+#ifdef USE_LIBSCHILY
+               comerr("Stdin must be a tty\n");
+#else
+               printf("Stdin must be a tty\n");
+               exit(1);
+#endif
+       }
+       newtty = savetty;
+#ifdef USE_V7_TTY
+       newtty.sg_flags  &= ~(ECHO|CRMOD);
+       newtty.sg_flags  |= CBREAK;
+#else
+       newtty.c_lflag   &= ~ICANON;
+       newtty.c_lflag   &= ~ECHO;
+       newtty.c_cc[VMIN] = 1;
+#endif
+       set_tty();
+#ifdef SIGTSTP
+       signal(SIGTSTP, onsusp);
+#endif
+       on_comerr((void(*)(int, void *))reset_tty, NULL);
+
+       do {
+               if (file_addr < (off_t)0) file_addr = (off_t)0;
+               showblock(1);
+               read(STDIN_FILENO, &c, 1); /* FIXME: check return value */
+               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):");
+                       if (sizeof (file_addr) > sizeof (long)) {
+                               Llong   ll;
+                               scanf("%llx", &ll); /* FIXME: check return value */
+                               file_addr = (off_t)ll;
+                       } else {
+                               long    l;
+                               scanf("%lx", &l); /* FIXME: check return value */
+                               file_addr = (off_t)l;
+                       }
+                       file_addr = file_addr << 11;
+                       crsr2(20, 1);
+                       printf("                                     ");
+               }
+               if (c == 'f') {
+                       crsr2(20, 1);
+                       printf("Enter new search string:");
+                       fgets((char *)search, sizeof (search), stdin); /* FIXME: check return value */
+                       while (search[strlen((char *)search)-1] == '\n')
+                               search[strlen((char *)search)-1] = 0;
+                       crsr2(20, 1);
+                       printf("                                     ");
+               }
+               if (c == '+') {
+                       while (1 == 1) {
+                               int     slen;
+
+                               while (1 == 1) {
+                                       c = getbyte();
+                                       if (c == search[0])
+                                               break;
+                               }
+                               slen = (int)strlen((char *)search);
+                               for (j = 1; j < slen; j++) {
+                                       if (search[j] != getbyte())
+                                               break;
+                               }
+                               if (j == slen)
+                                       break;
+                       }
+                       file_addr &= ~(PAGE-1);
+                       showblock(1);
+               }
+               if (c == 'q')
+                       break;
+       } while (1 == 1);
+       reset_tty();
+       if (infile != NULL)
+               fclose(infile);
+       return (0);
+}
diff --git a/genisoimage/diag/isodebug.1 b/genisoimage/diag/isodebug.1
new file mode 100644 (file)
index 0000000..58f0d9d
--- /dev/null
@@ -0,0 +1,108 @@
+.\" @(#)isodebug.8     1.1 06/02/08 Copyr 2006 J. Schilling
+.\" Manual page for isodebug
+.\" Modified for cdrkit distribution by E.Bloch
+.\"
+.if t .ds a \v'-0.55m'\h'0.00n'\z.\h'0.40n'\z.\v'0.55m'\h'-0.40n'a
+.if t .ds o \v'-0.55m'\h'0.00n'\z.\h'0.45n'\z.\v'0.55m'\h'-0.45n'o
+.if t .ds u \v'-0.55m'\h'0.00n'\z.\h'0.40n'\z.\v'0.55m'\h'-0.40n'u
+.if t .ds A \v'-0.77m'\h'0.25n'\z.\h'0.45n'\z.\v'0.77m'\h'-0.70n'A
+.if t .ds O \v'-0.77m'\h'0.25n'\z.\h'0.45n'\z.\v'0.77m'\h'-0.70n'O
+.if t .ds U \v'-0.77m'\h'0.30n'\z.\h'0.45n'\z.\v'0.77m'\h'-0.75n'U
+.if t .ds s \\(*b
+.if t .ds S SS
+.if n .ds a ae
+.if n .ds o oe
+.if n .ds u ue
+.if n .ds s sz
+.TH ISODEBUG 1 "06/02/08" "J\*org Schilling" "Schily\'s USER COMMANDS"
+.SH NAME
+isodebug \- print genisoimage debug info from ISO-9660 image
+.SH SYNOPSIS
+.B
+isodebug
+[
+.I options
+]
+[
+.I file
+]
+.SH DESCRIPTION
+.B Isodebug
+reads the debug info written by 
+.BR genisoimage (8)
+from within a ISO-9660 file system image and prints them.
+. \" .SH RETURNS
+. \" .SH ERRORS
+.SH OPTIONS
+.TP
+.B \-help
+Prints a short summary of the 
+.B isodebug
+options and exists.
+.TP
+.B \-version
+Prints the 
+.B isodebug
+version number string and exists.
+.TP
+.BI \-i " filename
+Filename to read ISO-9660 image from.
+.TP
+.BI dev= target
+SCSI target to use as CD/DVD-Recorder.
+See
+.BR wodim (1)
+for more information on now to use this option.
+.SH FILES
+.SH "SEE ALSO"
+.BR wodim (1),
+.BR genisoimage (1).
+.SH AUTHOR
+.nf
+J\*org Schilling
+Seestr. 110
+D-13353 Berlin
+Germany
+.fi
+.PP
+
+
+.SH AUTHOR
+.nf
+J\*org Schilling
+Seestr. 110
+D-13353 Berlin
+Germany
+.fi
+
+.PP
+This manpage describes the program implementation of
+.B
+isodebug
+as shipped by the cdrkit distribution. See
+.B
+http://alioth.debian.org/projects/debburn/
+for details. It is a spinoff from the original program distributed in the
+cdrtools package [1]. However, the cdrtools developers are not
+involved in the development of this spinoff and therefore shall not be made
+responsible for any problem caused by it. Do not try to get support for this
+program by contacting the original author(s).
+.PP
+If you have support questions, send them to
+.PP
+.B
+debburn-devel@lists.alioth.debian.org
+.br
+.PP
+If you have definitely found a bug, send a mail to this list or to
+.PP
+.B
+submit@bugs.debian.org
+.br
+.PP
+writing at least a short description into the Subject and "Package: cdrkit" into the first line of the mail body.
+.PP
+.br
+[1] Cdrtools 2.01.01a08 from May 2006, http://cdrecord.berlios.de
+
+
diff --git a/genisoimage/diag/isodebug.c b/genisoimage/diag/isodebug.c
new file mode 100644 (file)
index 0000000..f322021
--- /dev/null
@@ -0,0 +1,281 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)isodebug.c      1.10 05/05/01 Copyright 1996-2004 J. Schilling */
+/*
+ *     Copyright (c) 1996-2004 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <mconfig.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <statdefs.h>
+#include <stdxlib.h>
+#include <unixstd.h>
+#include <strdefs.h>
+#include <standard.h>
+#include <utypes.h>
+#include <intcvt.h>
+#include <schily.h>
+
+#include "../scsi.h"
+#include "../../wodim/defaults.h"
+
+#define        _delta(from, to)        ((to) - (from) + 1)
+
+#define        VD_BOOT         0
+#define        VD_PRIMARY      1
+#define        VD_SUPPLEMENT   2
+#define        VD_PARTITION    3
+#define        VD_TERM         255
+
+#define        VD_ID           "CD001"
+
+struct iso9660_voldesc {
+       char    vd_type         [_delta(1, 1)];
+       char    vd_id           [_delta(2, 6)];
+       char    vd_version      [_delta(7, 7)];
+       char    vd_fill         [_delta(8, 2048)];
+};
+
+struct iso9660_boot_voldesc {
+       char    vd_type         [_delta(1, 1)];
+       char    vd_id           [_delta(2, 6)];
+       char    vd_version      [_delta(7, 7)];
+       char    vd_bootsys      [_delta(8, 39)];
+       char    vd_bootid       [_delta(40, 71)];
+       char    vd_bootcode     [_delta(72, 2048)];
+};
+
+struct iso9660_pr_voldesc {
+       char    vd_type                 [_delta(1,      1)];
+       char    vd_id                   [_delta(2,      6)];
+       char    vd_version              [_delta(7,      7)];
+       char    vd_unused1              [_delta(8,      8)];
+       char    vd_system_id            [_delta(9,      40)];
+       char    vd_volume_id            [_delta(41,     72)];
+       char    vd_unused2              [_delta(73,     80)];
+       char    vd_volume_space_size    [_delta(81,     88)];
+       char    vd_unused3              [_delta(89,     120)];
+       char    vd_volume_set_size      [_delta(121,    124)];
+       char    vd_volume_seq_number    [_delta(125,    128)];
+       char    vd_lbsize               [_delta(129,    132)];
+       char    vd_path_table_size      [_delta(133,    140)];
+       char    vd_pos_path_table_l     [_delta(141,    144)];
+       char    vd_opt_pos_path_table_l [_delta(145,    148)];
+       char    vd_pos_path_table_m     [_delta(149,    152)];
+       char    vd_opt_pos_path_table_m [_delta(153,    156)];
+       char    vd_root_dir             [_delta(157,    190)];
+       char    vd_volume_set_id        [_delta(191,    318)];
+       char    vd_publisher_id         [_delta(319,    446)];
+       char    vd_data_preparer_id     [_delta(447,    574)];
+       char    vd_application_id       [_delta(575,    702)];
+       char    vd_copyr_file_id        [_delta(703,    739)];
+       char    vd_abstr_file_id        [_delta(740,    776)];
+       char    vd_bibl_file_id         [_delta(777,    813)];
+       char    vd_create_time          [_delta(814,    830)];
+       char    vd_mod_time             [_delta(831,    847)];
+       char    vd_expiry_time          [_delta(848,    864)];
+       char    vd_effective_time       [_delta(865,    881)];
+       char    vd_file_struct_vers     [_delta(882,    882)];
+       char    vd_reserved1            [_delta(883,    883)];
+       char    vd_application_use      [_delta(884,    1395)];
+       char    vd_fill                 [_delta(1396,   2048)];
+};
+
+#define        GET_UBYTE(a)    a_to_u_byte(a)
+#define        GET_SBYTE(a)    a_to_byte(a)
+#define        GET_SHORT(a)    a_to_u_2_byte(&((unsigned char *) (a))[0])
+#define        GET_BSHORT(a)   a_to_u_2_byte(&((unsigned char *) (a))[2])
+#define        GET_INT(a)      a_to_4_byte(&((unsigned char *) (a))[0])
+#define        GET_LINT(a)     la_to_4_byte(&((unsigned char *) (a))[0])
+#define        GET_BINT(a)     a_to_4_byte(&((unsigned char *) (a))[4])
+
+#define        infile  in_image
+FILE           *infile = NULL;
+
+static void    usage(int excode);
+static char    *isodinfo(FILE *f);
+
+static void
+usage(int excode)
+{
+       errmsgno(EX_BAD, "Usage: %s [options] image\n",
+                                               get_progname());
+
+       fprintf(stderr, "Options:\n");
+       fprintf(stderr, "\t-help,-h     Print this help\n");
+       fprintf(stderr, "\t-version     Print version info and exit\n");
+       fprintf(stderr, "\t-i filename  Filename to read ISO-9660 image from\n");
+       fprintf(stderr, "\tdev=target   SCSI target to use as CD/DVD-Recorder\n");
+       fprintf(stderr, "\nIf neither -i nor dev= are speficied, <image> is needed.\n");
+       exit(excode);
+}
+
+static char *
+isodinfo(FILE *f)
+{
+static struct iso9660_voldesc          vd;
+       struct iso9660_pr_voldesc       *vp;
+#ifndef        USE_SCG
+       struct stat                     sb;
+       mode_t                          mode;
+#endif
+       BOOL                            found = FALSE;
+       off_t                           sec_off = 16L;
+
+#ifndef        USE_SCG
+       /*
+        * First check if a bad guy tries to call isosize()
+        * with an unappropriate file descriptor.
+        * return -1 in this case.
+        */
+       if (isatty(fileno(f)))
+               return (NULL);
+       if (fstat(fileno(f), &sb) < 0)
+               return (NULL);
+       mode = sb.st_mode & S_IFMT;
+       if (!S_ISREG(mode) && !S_ISBLK(mode) && !S_ISCHR(mode))
+               return (NULL);
+#endif
+
+       vp = (struct iso9660_pr_voldesc *) &vd;
+
+       do {
+#ifdef USE_SCG
+               readsecs(sec_off, &vd, 1);
+#else
+               if (lseek(fileno(f), (off_t)(sec_off * 2048L), SEEK_SET) == -1)
+                       return (NULL);
+               read(fileno(f), &vd, sizeof (vd));
+#endif
+               sec_off++;
+
+               if (GET_UBYTE(vd.vd_type) == VD_PRIMARY) {
+                       found = TRUE;
+/*                     break;*/
+               }
+
+       } while (GET_UBYTE(vd.vd_type) != VD_TERM);
+
+       if (GET_UBYTE(vd.vd_type) != VD_TERM)
+               return (NULL);
+
+#ifdef USE_SCG
+       readsecs(sec_off, &vd, 1);
+#else
+       if (lseek(fileno(f), (off_t)(sec_off * 2048L), SEEK_SET) == -1)
+               return (NULL);
+       read(fileno(f), &vd, sizeof (vd));
+#endif
+       sec_off++;
+
+       return ((char *)&vd);
+}
+
+int
+main(int argc, char *argv[])
+{
+       int     cac;
+       char    * const *cav;
+       char    *opts = "help,h,version,i*,dev*";
+       BOOL    help = FALSE;
+       BOOL    prvers = FALSE;
+       char    *filename = NULL;
+       char    *devname = NULL;
+       char    *p;
+       char    *eol;
+
+       save_args(argc, argv);
+
+       cac = argc - 1;
+       cav = argv + 1;
+       if (getallargs(&cac, &cav, opts, &help, &help, &prvers,
+                       &filename, &devname) < 0) {
+               errmsgno(EX_BAD, "Bad Option: '%s'\n", cav[0]);
+               usage(EX_BAD);
+       }
+       if (help)
+               usage(0);
+       if (prvers) {
+               printf("isodebug %s (%s)\n", CDRKIT_VERSION, HOST_SYSTEM);
+               exit(0);
+       }
+       cac = argc - 1;
+       cav = argv + 1;
+       if (filename == NULL && devname == NULL) {
+               if (getfiles(&cac, &cav, opts) != 0) {
+                       filename = cav[0];
+                       cac--, cav++;
+               }
+       }
+       if (getfiles(&cac, &cav, opts) != 0) {
+               errmsgno(EX_BAD, "Bad Argument: '%s'\n", cav[0]);
+               usage(EX_BAD);
+       }
+       if (filename != NULL && devname != NULL) {
+               errmsgno(EX_BAD, "Only one of -i or dev= allowed\n");
+               usage(EX_BAD);
+       }
+#ifdef USE_SCG
+       if (filename == NULL && devname == NULL)
+               cdr_defaults(&devname, NULL, NULL, NULL);
+#endif
+       if (filename == NULL && devname == NULL) {
+               errmsgno(EX_BAD, "ISO-9660 image not specified\n");
+               usage(EX_BAD);
+       }
+
+       if (filename != NULL)
+               infile = fopen(filename, "rb");
+       else
+               filename = devname;
+
+       if (infile != NULL) {
+               /* EMPTY */;
+#ifdef USE_SCG
+       } else if (scsidev_open(filename) < 0) {
+#else
+       } else {
+#endif
+               comerr("Cannot open '%s'\n", filename);
+       }
+
+       p = isodinfo(infile);
+       if (p == NULL) {
+               printf("No ISO-9660 image debug info.\n");
+       } else if (strncmp(p, "MKI ", 4) == 0) {
+               eol = strchr(p, '\n');
+               if (eol)
+                       *eol = '\0';
+               printf("ISO-9660 image created at %s\n", &p[4]);
+               if (eol) {
+                       printf("\nCmdline: '%s'\n", &eol[1]);
+               }
+       }
+       return (0);
+}
diff --git a/genisoimage/diag/isodump.1 b/genisoimage/diag/isodump.1
new file mode 100644 (file)
index 0000000..b170c59
--- /dev/null
@@ -0,0 +1,2 @@
+.so man1/isoinfo.1
+.\" %Z%%M%     %I% %E% joerg
diff --git a/genisoimage/diag/isodump.c b/genisoimage/diag/isodump.c
new file mode 100644 (file)
index 0000000..34fa8f1
--- /dev/null
@@ -0,0 +1,715 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)isodump.c       1.27 05/05/15 joerg */
+/*
+ * File isodump.c - dump iso9660 directory information.
+ *
+ *
+ * Written by Eric Youngdale (1993).
+ *
+ * Copyright 1993 Yggdrasil Computing, Incorporated
+ * Copyright (c) 1999-2004 J. Schilling
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <mconfig.h>
+#include <stdxlib.h>
+#include <unixstd.h>
+#include <strdefs.h>
+#include <utypes.h>
+
+#include <stdio.h>
+#include <standard.h>
+#include <ttydefs.h>
+#include <signal.h>
+#include <schily.h>
+
+#include "../scsi.h"
+#include "../../wodim/defaults.h"
+
+/*
+ * XXX JS: Some structures have odd lengths!
+ * Some compilers (e.g. on Sun3/mc68020) padd the structures to even length.
+ * For this reason, we cannot use sizeof (struct iso_path_table) or
+ * sizeof (struct iso_directory_record) to compute on disk sizes.
+ * Instead, we use offsetof(..., name) and add the name size.
+ * See iso9660.h
+ */
+#ifndef        offsetof
+#define        offsetof(TYPE, MEMBER)  ((size_t) &((TYPE *)0)->MEMBER)
+#endif
+
+/*
+ * Note: always use these macros to avoid problems.
+ *
+ * ISO_ROUND_UP(X)     may cause an integer overflow and thus give
+ *                     incorrect results. So avoid it if possible.
+ *
+ * ISO_BLOCKS(X)       is overflow safe. Prefer this when ever it is possible.
+ */
+#define        SECTOR_SIZE     (2048)
+#define        ISO_ROUND_UP(X) (((X) + (SECTOR_SIZE - 1)) & ~(SECTOR_SIZE - 1))
+#define        ISO_BLOCKS(X)   (((X) / SECTOR_SIZE) + (((X)%SECTOR_SIZE)?1:0))
+
+#define        infile  in_image
+FILE   *infile = NULL;
+off_t  file_addr;
+unsigned char buffer[2048];
+unsigned char search[64];
+int blocksize;
+
+#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                      [1];
+};
+
+static int     isonum_731(char * p);
+static int     isonum_72(char * p);
+static int     isonum_723(char * p);
+static int     isonum_733(unsigned char * p);
+static void    reset_tty(void);
+static void    set_tty(void);
+static void    onsusp(int signo);
+static void    crsr2(int row, int col);
+static int     parse_rr(unsigned char * pnt, int len, int cont_flag);
+static void    dump_rr(struct iso_directory_record * idr);
+static void    showblock(int flag);
+static int     getbyte(void);
+static void    usage(int excode);
+
+static int
+isonum_731(char *p)
+{
+       return ((p[0] & 0xff)
+               | ((p[1] & 0xff) << 8)
+               | ((p[2] & 0xff) << 16)
+               | ((p[3] & 0xff) << 24));
+}
+
+static int
+isonum_721(char *p)
+{
+       return ((p[0] & 0xff) | ((p[1] & 0xff) << 8));
+}
+
+static int
+isonum_723(char *p)
+{
+#if 0
+       if (p[0] != p[3] || p[1] != p[2]) {
+#ifdef USE_LIBSCHILY
+               comerrno(EX_BAD, "invalid format 7.2.3 number\n");
+#else
+               fprintf(stderr, "invalid format 7.2.3 number\n");
+               exit(1);
+#endif
+       }
+#endif
+       return (isonum_721(p));
+}
+
+
+static int
+isonum_733(unsigned char *p)
+{
+       return (isonum_731((char *)p));
+}
+
+#ifdef USE_V7_TTY
+static struct sgttyb   savetty;
+static struct sgttyb   newtty;
+#else
+static struct termios savetty;
+static struct termios newtty;
+#endif
+
+static void
+reset_tty()
+{
+#ifdef USE_V7_TTY
+       if (ioctl(STDIN_FILENO, TIOCSETN, &savetty) == -1) {
+#else
+#ifdef TCSANOW
+       if (tcsetattr(STDIN_FILENO, TCSANOW, &savetty) == -1)  {
+#else
+       if (ioctl(STDIN_FILENO, TCSETAF, &savetty) == -1) {
+#endif
+#endif
+#ifdef USE_LIBSCHILY
+               comerr("Cannot put tty into normal mode\n");
+#else
+               printf("Cannot put tty into normal mode\n");
+               exit(1);
+#endif
+       }
+}
+
+static void
+set_tty()
+{
+#ifdef USE_V7_TTY
+       if (ioctl(STDIN_FILENO, TIOCSETN, &newtty) == -1) {
+#else
+#ifdef TCSANOW
+       if (tcsetattr(STDIN_FILENO, TCSANOW, &newtty) == -1) {
+#else
+       if (ioctl(STDIN_FILENO, TCSETAF, &newtty) == -1) {
+#endif
+#endif
+#ifdef USE_LIBSCHILY
+               comerr("Cannot put tty into raw mode\n");
+#else
+               printf("Cannot put tty into raw mode\n");
+               exit(1);
+#endif
+       }
+}
+
+/* Come here when we get a suspend signal from the terminal */
+
+static void
+onsusp(int signo)
+{
+#ifdef SIGTTOU
+       /* ignore SIGTTOU so we don't get stopped if csh grabs the tty */
+       signal(SIGTTOU, SIG_IGN);
+#endif
+       reset_tty();
+       fflush(stdout);
+#ifdef SIGTTOU
+       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);
+#endif
+       set_tty();
+}
+
+
+
+static void
+crsr2(int row, int col)
+{
+       printf("\033[%d;%dH", row, col);
+}
+
+static int
+parse_rr(unsigned char *pnt, int len, int cont_flag)
+{
+       int             slen;
+       int             ncount;
+       int             extent;
+       off_t           cont_extent;
+       int             cont_offset;
+       int             cont_size;
+       int             flag1;
+       int             flag2;
+       unsigned char   *pnts;
+       char            symlinkname[1024];
+       char            name[1024];
+       int             goof;
+
+/*     printf(" RRlen=%d ", len); */
+
+       symlinkname[0] = 0;
+
+       cont_extent = (off_t)0;
+       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 && pnt[3] != 2) {
+                       printf("**BAD RRVERSION (%d) for %c%c\n", pnt[3], pnt[0], pnt[1]);
+                       return (0);     /* JS ??? Is this right ??? */
+               } else if (pnt[0] == 'R' && pnt[1] == 'R') {
+                       printf("=%d", pnt[3]);
+               }
+               ncount++;
+               if (pnt[0] == 'R' && pnt[1] == 'R') flag1 = pnt[4] & 0xff;
+               if (strncmp((char *)pnt, "PX", 2) == 0) flag2 |= 1;
+               if (strncmp((char *)pnt, "PN", 2) == 0) flag2 |= 2;
+               if (strncmp((char *)pnt, "SL", 2) == 0) flag2 |= 4;
+               if (strncmp((char *)pnt, "NM", 2) == 0) {
+                       slen = pnt[2] - 5;
+                       pnts = pnt+5;
+                       if ((pnt[4] & 6) != 0) {
+                               printf("*");
+                       }
+                       memset(name, 0, sizeof (name));
+                       memcpy(name, pnts, slen);
+                       printf("=%s", name);
+                       flag2 |= 8;
+               }
+               if (strncmp((char *)pnt, "CL", 2) == 0) flag2 |= 16;
+               if (strncmp((char *)pnt, "PL", 2) == 0) flag2 |= 32;
+               if (strncmp((char *)pnt, "RE", 2) == 0) flag2 |= 64;
+               if (strncmp((char *)pnt, "TF", 2) == 0) flag2 |= 128;
+
+               if (strncmp((char *)pnt, "PX", 2) == 0) {
+                       extent = isonum_733(pnt+12);
+                       printf("=%x", extent);
+               }
+
+               if (strncmp((char *)pnt, "CE", 2) == 0) {
+                       cont_extent = (off_t)isonum_733(pnt+4);
+                       cont_offset = isonum_733(pnt+12);
+                       cont_size = isonum_733(pnt+20);
+                       printf("=[%x,%x,%d]", (int)cont_extent, cont_offset,
+                                                               cont_size);
+               }
+
+               if (strncmp((char *)pnt, "PL", 2) == 0 || strncmp((char *)pnt, "CL", 2) == 0) {
+                       extent = isonum_733(pnt+4);
+                       printf("=%x", extent);
+               }
+
+               if (strncmp((char *)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(symlinkname, (char *)(pnts+2), pnts[1]);
+                                       break;
+                               case 2:
+                                       strcat(symlinkname, ".");
+                                       break;
+                               case 4:
+                                       strcat(symlinkname, "..");
+                                       break;
+                               case 8:
+                                       if ((pnts[0] & 1) == 0)
+                                               strcat(symlinkname, "/");
+                                       break;
+                               case 16:
+                                       strcat(symlinkname, "/mnt");
+                                       printf("Warning - mount point requested");
+                                       break;
+                               case 32:
+                                       strcat(symlinkname, "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(symlinkname, "/");
+
+                               slen -= (pnts[1] + 2);
+                               pnts += (pnts[1] + 2);
+                       }
+                       if (cflag)
+                               strcat(symlinkname, "+");
+                       printf("=%s", symlinkname);
+                       symlinkname[0] = 0;
+               }
+
+               len -= pnt[2];
+               pnt += pnt[2];
+               if (len <= 3 && cont_extent) {
+                       unsigned char sector[2048];
+
+#ifdef USE_SCG
+                       readsecs(cont_extent * blocksize / 2048, sector, ISO_BLOCKS(sizeof (sector)));
+#else
+                       lseek(fileno(infile), cont_extent * blocksize, SEEK_SET);
+                       read(fileno(infile), sector, sizeof (sector));
+#endif
+                       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);
+}
+
+static void
+dump_rr(struct iso_directory_record *idr)
+{
+       int             len;
+       unsigned char   *pnt;
+
+       len = idr->length[0] & 0xff;
+       len -= offsetof(struct iso_directory_record, name[0]);
+       len -= idr->name_len[0];
+       pnt = (unsigned char *) idr;
+       pnt += offsetof(struct iso_directory_record, name[0]);
+       pnt += idr->name_len[0];
+       if ((idr->name_len[0] & 1) == 0) {
+               pnt++;
+               len--;
+       }
+       parse_rr(pnt, len, 0);
+}
+
+
+static void
+showblock(int flag)
+{
+       int     i;
+       int     j;
+       int     line;
+       struct iso_directory_record     *idr;
+
+#ifdef USE_SCG
+       readsecs(file_addr / 2048, buffer, ISO_BLOCKS(sizeof (buffer)));
+#else
+       lseek(fileno(infile), file_addr, SEEK_SET);
+       read(fileno(infile), buffer, sizeof (buffer));
+#endif
+       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("%02x/", idr->flags[0]);
+                       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 < (int)idr->name_len[0]; j++) printf("%c", idr->name[j]);
+                               for (j = 0; j < (14 - (int)idr->name_len[0]); j++) printf(" ");
+                       }
+                       dump_rr(idr);
+                       printf("\n");
+                       i += buffer[i];
+                       if (i > 2048 - offsetof(struct iso_directory_record, name[0]))
+                               break;
+                       line++;
+               }
+       }
+       printf("\n");
+       if (sizeof (file_addr) > sizeof (long)) {
+               printf(" Zone, zone offset: %14llx %12.12llx  ",
+                       (Llong)file_addr / blocksize,
+                       (Llong)file_addr & (Llong)(blocksize - 1));
+       } else {
+               printf(" Zone, zone offset: %6lx %4.4lx  ",
+                       (long) (file_addr / blocksize),
+                       (long) file_addr & (blocksize - 1));
+       }
+       fflush(stdout);
+}
+
+static int
+getbyte()
+{
+       char    c1;
+
+       c1 = buffer[file_addr & (blocksize-1)];
+       file_addr++;
+       if ((file_addr & (blocksize-1)) == 0)
+               showblock(0);
+       return (c1);
+}
+
+static void
+usage(int excode)
+{
+       errmsgno(EX_BAD, "Usage: %s [options] image\n",
+                                               get_progname());
+
+       fprintf(stderr, "Options:\n");
+       fprintf(stderr, "\t-help, -h    Print this help\n");
+       fprintf(stderr, "\t-version     Print version info and exit\n");
+       fprintf(stderr, "\t-i filename  Filename to read ISO-9660 image from\n");
+       fprintf(stderr, "\tdev=target   SCSI target to use as CD/DVD-Recorder\n");
+       fprintf(stderr, "\nIf neither -i nor dev= are speficied, <image> is needed.\n");
+       exit(excode);
+}
+
+int
+main(int argc, char *argv[])
+{
+       int     cac;
+       char    * const *cav;
+       char    *opts = "help,h,version,i*,dev*";
+       BOOL    help = FALSE;
+       BOOL    prvers = FALSE;
+       char    *filename = NULL;
+       char    *devname = NULL;
+       char    c;
+       int     i;
+       struct iso_primary_descriptor   ipd;
+       struct iso_directory_record     *idr;
+
+       save_args(argc, argv);
+
+       cac = argc - 1;
+       cav = argv + 1;
+       if (getallargs(&cac, &cav, opts, &help, &help, &prvers,
+                       &filename, &devname) < 0) {
+               errmsgno(EX_BAD, "Bad Option: '%s'\n", cav[0]);
+               usage(EX_BAD);
+       }
+       if (help)
+               usage(0);
+       if (prvers) {
+               printf("isodump %s (%s)\n", CDRKIT_VERSION, HOST_SYSTEM);
+               exit(0);
+       }
+       cac = argc - 1;
+       cav = argv + 1;
+       if (filename == NULL && devname == NULL) {
+               if (getfiles(&cac, &cav, opts) != 0) {
+                       filename = cav[0];
+                       cac--, cav++;
+               }
+       }
+       if (getfiles(&cac, &cav, opts) != 0) {
+               errmsgno(EX_BAD, "Bad Argument: '%s'\n", cav[0]);
+               usage(EX_BAD);
+       }
+       if (filename != NULL && devname != NULL) {
+               errmsgno(EX_BAD, "Only one of -i or dev= allowed\n");
+               usage(EX_BAD);
+       }
+#ifdef USE_SCG
+       if (filename == NULL && devname == NULL)
+               cdr_defaults(&devname, NULL, NULL, NULL);
+#endif
+       if (filename == NULL && devname == NULL) {
+#ifdef USE_LIBSCHILY
+               errmsgno(EX_BAD, "ISO-9660 image not specified\n");
+#else
+               fprintf(stderr, "ISO-9660 image not specified\n");
+#endif
+               usage(EX_BAD);
+       }
+
+       if (filename != NULL)
+               infile = fopen(filename, "rb");
+       else
+               filename = devname;
+
+       if (infile != NULL) {
+               /* EMPTY */;
+#ifdef USE_SCG
+       } else if (scsidev_open(filename) < 0) {
+#else
+       } else {
+#endif
+#ifdef USE_LIBSCHILY
+               comerr("Cannot open '%s'\n", filename);
+#else
+               fprintf(stderr, "Cannot open '%s'\n", filename);
+               exit(1);
+#endif
+       }
+
+       file_addr = (off_t) (16 << 11);
+#ifdef USE_SCG
+       readsecs(file_addr / 2048, &ipd, ISO_BLOCKS(sizeof (ipd)));
+#else
+       lseek(fileno(infile), file_addr, SEEK_SET);
+       read(fileno(infile), &ipd, sizeof (ipd));
+#endif
+       idr = (struct iso_directory_record *)ipd.root_directory_record;
+
+       blocksize = isonum_723((char *)ipd.logical_block_size);
+       if (blocksize != 512 && blocksize != 1024 && blocksize != 2048) {
+               blocksize = 2048;
+       }
+
+       file_addr = (off_t)isonum_733(idr->extent);
+       file_addr = file_addr * blocksize;
+
+/* Now setup the keyboard for single character input. */
+#ifdef USE_V7_TTY
+       if (ioctl(STDIN_FILENO, TIOCGETP, &savetty) == -1) {
+#else
+#ifdef TCSANOW
+       if (tcgetattr(STDIN_FILENO, &savetty) == -1) {
+#else
+       if (ioctl(STDIN_FILENO, TCGETA, &savetty) == -1) {
+#endif
+#endif
+#ifdef USE_LIBSCHILY
+               comerr("Stdin must be a tty\n");
+#else
+               printf("Stdin must be a tty\n");
+               exit(1);
+#endif
+       }
+       newtty = savetty;
+#ifdef USE_V7_TTY
+       newtty.sg_flags  &= ~(ECHO|CRMOD);
+       newtty.sg_flags  |= CBREAK;
+#else
+       newtty.c_lflag   &= ~ICANON;
+       newtty.c_lflag   &= ~ECHO;
+       newtty.c_cc[VMIN] = 1;
+#endif
+       set_tty();
+#ifdef SIGTSTP
+       signal(SIGTSTP, onsusp);
+#endif
+       on_comerr((void(*)(int, void *))reset_tty, NULL);
+
+       do {
+               if (file_addr < 0)
+                       file_addr = (off_t)0;
+               showblock(1);
+               read(STDIN_FILENO, &c, 1); /* FIXME: check return value */
+               if (c == 'a')
+                       file_addr -= blocksize;
+               if (c == 'b')
+                       file_addr += blocksize;
+               if (c == 'g') {
+                       crsr2(20, 1);
+                       printf("Enter new starting block (in hex):");
+                       if (sizeof (file_addr) > sizeof (long)) {
+                               Llong   ll;
+                               scanf("%llx", &ll); /* FIXME: check return value */
+                               file_addr = (off_t)ll;
+                       } else {
+                               long    l;
+                               scanf("%lx", &l); /* FIXME: check return value */
+                               file_addr = (off_t)l;
+                       }
+                       file_addr = file_addr * blocksize;
+                       crsr2(20, 1);
+                       printf("                                     ");
+               }
+               if (c == 'f') {
+                       crsr2(20, 1);
+                       printf("Enter new search string:");
+                       fgets((char *)search, sizeof (search), stdin); /* FIXME: check return value */
+                       while (search[strlen((char *)search)-1] == '\n')
+                               search[strlen((char *)search)-1] = 0;
+                       crsr2(20, 1);
+                       printf("                                     ");
+               }
+               if (c == '+') {
+                       while (1 == 1) {
+                               int     slen;
+
+                               while (1 == 1) {
+                                       c = getbyte();
+                                       if (c == search[0])
+                                               break;
+                               }
+                               slen = (int)strlen((char *)search);
+                               for (i = 1; i < slen; i++) {
+                                       if (search[i] != getbyte())
+                                               break;
+                               }
+                               if (i == slen)
+                                       break;
+                       }
+                       file_addr &= ~(blocksize-1);
+                       showblock(1);
+               }
+               if (c == 'q')
+                       break;
+       } while (1 == 1);
+       reset_tty();
+       if (infile != NULL)
+               fclose(infile);
+       return (0);
+}
diff --git a/genisoimage/diag/isoinfo.1 b/genisoimage/diag/isoinfo.1
new file mode 100644 (file)
index 0000000..1a00540
--- /dev/null
@@ -0,0 +1,365 @@
+.\"
+.\" @(#)isoinfo.8      1.7 04/06/01 joerg
+.\" 
+.\" Modified for cdrkit in 12/2006
+.\"
+.\" -*- nroff -*-
+.if t .ds a \v'-0.55m'\h'0.00n'\z.\h'0.40n'\z.\v'0.55m'\h'-0.40n'a
+.if t .ds o \v'-0.55m'\h'0.00n'\z.\h'0.45n'\z.\v'0.55m'\h'-0.45n'o
+.if t .ds u \v'-0.55m'\h'0.00n'\z.\h'0.40n'\z.\v'0.55m'\h'-0.40n'u
+.if t .ds A \v'-0.77m'\h'0.25n'\z.\h'0.45n'\z.\v'0.77m'\h'-0.70n'A
+.if t .ds O \v'-0.77m'\h'0.25n'\z.\h'0.45n'\z.\v'0.77m'\h'-0.70n'O
+.if t .ds U \v'-0.77m'\h'0.30n'\z.\h'0.45n'\z.\v'0.77m'\h'-0.75n'U
+.if t .ds s \\(*b
+.if t .ds S SS
+.if n .ds a ae
+.if n .ds o oe
+.if n .ds u ue
+.if n .ds s sz
+.TH ISOINFO 1 "04/06/01" "Version 2.0"
+.SH NAME
+devdump, isoinfo, isovfy, isodump \- Utility programs for dumping and verifying iso9660
+images.
+.SH SYNOPSIS
+.B devdump 
+.I isoimage
+.PP
+.B isodump 
+.I isoimage
+.PP
+.B isoinfo
+[
+.B \-d
+]
+[
+.B \-h
+]
+[
+.B \-R
+]
+[
+.B \-J
+]
+[
+.B \-j
+.I charset
+]
+[
+.B \-f
+]
+[
+.B \-l
+]
+[
+.B \-p
+]
+[
+.B \-T
+.I sector
+]
+[
+.B \-N
+.I sector
+]
+[
+.B \-i
+.I isoimage
+]
+[
+.B \-x
+.I path
+]
+.PP
+.B isovfy 
+.I isoimage
+.SH DESCRIPTION
+.B devdump
+is a crude utility to interactively display the contents of device or
+filesystem images.
+The initial screen is a display of the first 256 bytes of the first 2048 byte
+sector.
+The commands are the same as with 
+.BR isodump .
+.PP
+.B isodump
+is a crude utility to interactively display the contents of iso9660 images
+in order to verify directory integrity.
+The initial screen is a display of the first part of the root directory,
+and the prompt shows you the extent number and offset in the extent.
+.RS
+.PP
+You can use the 'a' and 'b'
+commands to move backwards and forwards within the image. The 'g' command
+allows you to goto an arbitrary extent, and the 'f' command specifies
+a search string to be used. The '+' command searches forward for the next
+instance of the search string, and the 'q' command exits
+.B devdump
+or
+.BR isodump .
+.RE
+.PP
+.B isoinfo
+is a utility to perform directory like listings of iso9660 images.
+.PP
+.B isovfy
+is a utility to verify the integrity of an iso9660 image. Most of the tests
+in
+.B isovfy
+were added after bugs were discovered in early versions of
+.B genisoimage.
+It isn't all that clear how useful this is anymore, but it doesn't hurt to
+have this around.
+
+.SH OPTIONS
+The options common to all programs are
+.BR \-help , \-h , \-version ,
+.BI i =name, dev =name.
+The
+.B isoinfo
+program has additional command line options. The options are:
+.TP
+.B \-help
+.TP
+.B \-h
+print a summary of all options.
+.TP
+.B \-d
+Print information from the primary volume descriptor (PVD) of the iso9660
+image. This includes information about Rock Ridge, Joliet extensions
+and Eltorito boot information
+if present.
+.TP
+.B \-f
+generate output as if a 'find . -print' command had been run on the iso9660
+image. You should not use the
+.B -l
+image with the
+.B -f
+option.
+.TP
+.B \-i iso_image
+Specifies the path of the iso9660 image that we wish to examine.
+The options
+.B \-i
+and 
+.BI dev= target
+are mutual exclusive.
+.TP
+.BI dev= target
+Sets the SCSI target for the drive, see notes above.
+A typical device specification is
+.BI dev= 6,0
+\&.
+If a filename must be provided together with the numerical target 
+specification, the filename is implementation specific.
+The correct filename in this case can be found in the system specific
+manuals of the target operating system.
+On a 
+.I FreeBSD
+system without 
+.I CAM
+support, you need to use the control device (e.g.
+.IR /dev/rcd0.ctl ).
+A correct device specification in this case may be
+.BI dev= /dev/rcd0.ctl:@
+\&.
+.sp
+On Linux, drives connected to a parallel port adapter are mapped
+to a virtual SCSI bus. Different adapters are mapped to different
+targets on this virtual SCSI bus.
+.sp
+If no 
+.I dev
+option is present, the program
+will try to get the device from the 
+.B CDR_DEVICE
+environment.
+.sp
+If the argument to the
+.B dev=
+option does not contain the characters ',', '/', '@' or ':',
+it is interpreted as an label name that may be found in the file
+/etc/wodim.conf (see FILES section).
+.sp
+The options
+.B \-i
+and 
+.BI dev= target
+are mutual exclusive.
+.TP
+.B \-l
+generate output as if a 'ls -lR' command had been run on the iso9660 image.
+You should not use the
+.B -f
+image with the
+.B -l
+option.
+.TP
+.B \-N sector
+Quick hack to help examine single session disc files that are to be written to
+a multi-session disc. The sector number specified is the sector number at
+which the iso9660 image should be written when send to the cd-writer. Not
+used for the first session on the disc.
+.TP
+.B \-p
+Print path table information.
+.TP
+.B \-R
+Extract information from Rock Ridge extensions (if present) for permissions,
+file names and ownerships.
+.TP
+.B \-J
+Extract information from Joliet extensions (if present) for file names.
+.TP
+.B \-j charset
+Convert Joliet file names (if present) to the supplied charset. See
+.BR genisoimage (8)
+for details.
+.TP
+.B \-T sector
+Quick hack to help examine multi-session images that have already been burned
+to a multi-session disc. The sector number specified is the sector number for
+the start of the session we wish to display.
+.TP
+.B \-x pathname
+Extract specified file to stdout.
+.SH AUTHOR
+The author of the original sources (1993 .\|.\|. 1998) is
+Eric Youngdale <ericy@gnu.ai.mit.edu> or <eric@andante.jic.com> is to blame
+for these shoddy hacks.
+J\*org Schilling wrote the SCSI transport library and its adaptation layer to
+the programs and newer parts (starting from 1999) of the utilities, this makes
+them
+Copyright (C) 1999-2004 J\*org Schilling.
+Patches to improve general usability would be gladly accepted.
+.PP
+This manpage describes the program implementation of
+.B
+isoinfo
+as shipped by the cdrkit distribution. See
+.B
+http://alioth.debian.org/projects/debburn/
+for details. It is a spinoff from the original program distributed in the
+cdrtools package [1]. However, the cdrtools
+developers are not involved in the development of this spinoff and therefore
+shall not be made responsible for any problem caused by it. Do not try to get
+support for this program by contacting the original author(s).
+.PP
+If you have support questions, send them to
+.PP
+.B
+debburn-devel@lists.alioth.debian.org
+.br
+.PP
+If you have definitely found a bug, send a mail to this list or to
+.PP
+.B
+submit@bugs.debian.org
+.br
+.PP
+writing at least a short description into the Subject and "Package: cdrkit" into the first line of the mail body.
+.SH BUGS
+The user interface really sucks.
+.SH FUTURE IMPROVEMENTS
+These utilities are really quick hacks, which are very useful for debugging
+problems in genisoimage or in an iso9660 filesystem. In the long run, it would
+be nice to have a daemon that would NFS export a iso9660 image.
+.PP
+The isoinfo program is probably the program that is of the most use to
+the general user.
+.SH AVAILABILITY
+These utilities come with the 
+.B cdrkit
+package, and the primary download site
+is http://debburn.alioth.debian.org/ and FTP mirrors of distributions.
+Despite the name, the software is not beta.
+
+.SH ENVIRONMENT
+.TP
+.B CDR_DEVICE
+This may either hold a device identifier that is suitable to the open
+call of the SCSI transport library or a label in the file /etc/wodim.conf.
+.TP
+.B RSH
+If the 
+.B RSH
+environment is present, the remote connection will not be created via
+.BR rcmd (3)
+but by calling the program pointed to by
+.BR RSH .
+Use e.g. 
+.BR RSH= /usr/bin/ssh
+to create a secure shell connection.
+.sp
+Note that this forces the program
+to create a pipe to the 
+.B rsh(1)
+program and disallows the program
+to directly access the network socket to the remote server.
+This makes it impossible to set up performance parameters and slows down
+the connection compared to a 
+.B root
+initiated
+.B rcmd(3)
+connection.
+.TP
+.B RSCSI
+If the 
+.B RSCSI
+environment is present, the remote SCSI server will not be the program
+.B /opt/schily/sbin/rscsi
+but the program pointed to by
+.BR RSCSI .
+Note that the remote SCSI server program name will be ignored if you log in
+using an account that has been created with a remote SCSI server program as
+login shell.
+
+.SH FILES
+.TP
+/etc/wodim.conf
+Default values can be set for the following options in /etc/wodim.conf.
+.RS
+.TP
+CDR_DEVICE
+This may either hold a device identifier that is suitable to the open
+call of the SCSI transport library or a label in the file /etc/wodim.conf
+that allows to identify a specific drive on the system.
+.TP
+Any other label
+is an identifier for a specific drive on the system.
+Such an identifier may not contain the characters ',', '/', '@' or ':'.
+.sp
+Each line that follows a label contains a TAB separated list of items.
+Currently, four items are recognized: the SCSI ID of the drive, the
+default speed that should be used for this drive, the default FIFO size
+that should be used for this drive and drive specific options. The values for 
+.I speed
+and
+.I fifosize
+may be set to -1 to tell the program to use the global defaults.
+The value for driveropts may be set to "" if no driveropts are used.
+A typical line may look this way:
+.sp
+teac1= 0,5,0   4       8m      ""
+.sp
+yamaha= 1,6,0  -1      -1      burnfree
+.sp
+This tells the program
+that a drive named
+.I teac1
+is at scsibus 0, target 5, lun 0 and should be used with speed 4 and
+a FIFO size of 8 MB.
+A second drive may be found at scsibus 1, target 6, lun 0 and uses the
+default speed and the default FIFO size.
+.RE
+.SH SEE ALSO
+.BR genisoimage (1),
+.BR wodim (1),
+.BR readcd (1),
+.BR ssh (1).
+.RE
+.SH SOURCES
+.PP
+.br
+[1] Cdrtools 2.01.01a08 from May 2006, http://cdrecord.berlios.de
+
diff --git a/genisoimage/diag/isoinfo.c b/genisoimage/diag/isoinfo.c
new file mode 100644 (file)
index 0000000..55396c2
--- /dev/null
@@ -0,0 +1,1321 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)isoinfo.c       1.50 05/05/15 joerg */
+/*
+ * File isodump.c - dump iso9660 directory information.
+ *
+ *
+ * Written by Eric Youngdale (1993).
+ *
+ * Copyright 1993 Yggdrasil Computing, Incorporated
+ * Copyright (c) 1999-2004 J. Schilling
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 <mconfig.h>
+#include <stdxlib.h>
+#include <unixstd.h>
+#include <strdefs.h>
+
+#include <stdio.h>
+#include <utypes.h>
+#include <standard.h>
+#include <signal.h>
+#include <sys/stat.h>
+#include <statdefs.h>
+#include <fctldefs.h>
+#include <schily.h>
+
+#include "../iso9660.h"
+#include "../scsi.h"
+#include "../../wodim/defaults.h"
+
+#include <unls.h>
+
+#if    defined(__CYGWIN32__) || defined(__EMX__) || defined(__DJGPP__)
+#include <io.h>                                        /* for setmode() prototype */
+#endif
+
+/*
+ * Make sure we have a definition for this.  If not, take a very conservative
+ * guess.
+ * POSIX requires the max pathname component lenght to be defined in limits.h
+ * If variable, it may be undefined. If undefined, there should be
+ * a definition for _POSIX_NAME_MAX in limits.h or in unistd.h
+ * As _POSIX_NAME_MAX is defined to 14, we cannot use it.
+ * XXX Eric's wrong comment:
+ * XXX From what I can tell SunOS is the only one with this trouble.
+ */
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+#ifndef        NAME_MAX
+#ifdef FILENAME_MAX
+#define        NAME_MAX        FILENAME_MAX
+#else
+#define        NAME_MAX        256
+#endif
+#endif
+
+#ifndef        PATH_MAX
+#ifdef FILENAME_MAX
+#define        PATH_MAX        FILENAME_MAX
+#else
+#define        PATH_MAX        1024
+#endif
+#endif
+
+/*
+ * XXX JS: Some structures have odd lengths!
+ * Some compilers (e.g. on Sun3/mc68020) padd the structures to even length.
+ * For this reason, we cannot use sizeof (struct iso_path_table) or
+ * sizeof (struct iso_directory_record) to compute on disk sizes.
+ * Instead, we use offsetof(..., name) and add the name size.
+ * See iso9660.h
+ */
+#ifndef        offsetof
+#define        offsetof(TYPE, MEMBER)  ((size_t) &((TYPE *)0)->MEMBER)
+#endif
+
+#ifndef        S_ISLNK
+#define        S_ISLNK(m)      (((m) & S_IFMT) == S_IFLNK)
+#endif
+#ifndef        S_ISSOCK
+#ifdef S_IFSOCK
+#      define  S_ISSOCK(m)     (((m) & S_IFMT) == S_IFSOCK)
+#else
+#      define  S_ISSOCK(m)     (0)
+#endif
+#endif
+
+/*
+ * Note: always use these macros to avoid problems.
+ *
+ * ISO_ROUND_UP(X)     may cause an integer overflow and thus give
+ *                     incorrect results. So avoid it if possible.
+ *
+ * ISO_BLOCKS(X)       is overflow safe. Prefer this when ever it is possible.
+ */
+#define        SECTOR_SIZE     (2048)
+#define        ISO_ROUND_UP(X) (((X) + (SECTOR_SIZE - 1)) & ~(SECTOR_SIZE - 1))
+#define        ISO_BLOCKS(X)   (((X) / SECTOR_SIZE) + (((X)%SECTOR_SIZE)?1:0))
+
+#define        infile  in_image
+FILE   *infile = NULL;
+int    use_rock = 0;
+int    use_joliet = 0;
+int    do_listing = 0;
+int    do_find = 0;
+int    do_sectors = 0;
+int    do_pathtab = 0;
+int    do_pvd = 0;
+BOOL   debug = FALSE;
+char   *xtract = 0;
+int    su_version = 0;
+int    aa_version = 0;
+int    ucs_level = 0;
+
+struct stat    fstat_buf;
+int            found_rr;
+char           name_buf[256];
+char           xname[2048];
+unsigned char  date_buf[9];
+/*
+ * Use sector_offset != 0 (-N #) if we have an image file
+ * of a single session and we need to list the directory contents.
+ * This is the session block (sector) number of the start
+ * of the session when it would be on disk.
+ */
+unsigned int   sector_offset = 0;
+
+unsigned char  buffer[2048];
+
+struct unls_table *unls;
+
+#define        PAGE sizeof (buffer)
+
+#define        ISODCL(from, to) (to - from + 1)
+
+
+int    isonum_721(char * p);
+int    isonum_723(char * p);
+int    isonum_731(char * p);
+int    isonum_732(char * p);
+int    isonum_733(unsigned char * p);
+void   printchars(char *s, int n);
+char   *sdate(char *dp);
+void   dump_pathtab(int block, int size);
+int    parse_rr(unsigned char * pnt, int len, int cont_flag);
+void   find_rr(struct iso_directory_record * idr, Uchar **pntp, int *lenp);
+int    dump_rr(struct iso_directory_record * idr);
+void   dump_stat(struct iso_directory_record * idr, int extent);
+void   extract_file(struct iso_directory_record * idr);
+void   parse_dir(char * rootname, int extent, int len);
+void   usage(int excode);
+
+static void    printf_bootinfo(FILE *f, int bootcat_offset);
+static char    *arch_name(int val);
+static char    *boot_name(int val);
+static char    *bootmedia_name(int val);
+
+
+int
+isonum_721(char *p)
+{
+       return ((p[0] & 0xff)
+               | ((p[1] & 0xff) << 8));
+}
+
+int
+isonum_723(char *p)
+{
+#if 0
+       if (p[0] != p[3] || p[1] != p[2]) {
+#ifdef USE_LIBSCHILY
+               comerrno(EX_BAD, "invalid format 7.2.3 number\n");
+#else
+               fprintf(stderr, "invalid format 7.2.3 number\n");
+               exit(1);
+#endif
+       }
+#endif
+       return (isonum_721(p));
+}
+
+int
+isonum_731(char *p)
+{
+       return ((p[0] & 0xff)
+               | ((p[1] & 0xff) << 8)
+               | ((p[2] & 0xff) << 16)
+               | ((p[3] & 0xff) << 24));
+}
+
+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((char *)p));
+}
+
+void
+printchars(char *s, int n)
+{
+       int     i;
+       char    *p;
+
+       for (; n > 0 && *s; n--) {
+               if (*s == ' ') {
+                       p = s;
+                       i = n;
+                       while (--i >= 0 && *p++ == ' ')
+                               ;
+                       if (i <= 0)
+                               break;
+               }
+               putchar(*s++);
+       }
+}
+
+/*
+ * Print date info from PVD
+ */
+char *
+sdate(char *dp)
+{
+       static  char    d[30];
+
+       sprintf(d, "%4.4s %2.2s %2.2s %2.2s:%2.2s:%2.2s.%2.2s",
+                       &dp[0],         /* Year */
+                       &dp[4],         /* Month */
+                       &dp[6],         /* Monthday */
+                       &dp[8],         /* Hour */
+                       &dp[10],        /* Minute */
+                       &dp[12],        /* Seconds */
+                       &dp[14]);       /* Hunreds of a Seconds */
+
+       /*
+        * dp[16] contains minute offset from Greenwich
+        * Positive values are to the east of Greenwich.
+        */
+       return (d);
+}
+
+void
+dump_pathtab(int block, int size)
+{
+       unsigned char   *buf;
+       int             offset;
+       int             idx;
+       int             extent;
+       int             pindex;
+       int             j;
+       int             len;
+       int             jlen;
+       char            namebuf[255];
+       unsigned char   uh, ul, uc, *up;
+
+
+       printf("Path table starts at block %d, size %d\n", block, size);
+
+       buf = (unsigned char *) malloc(ISO_ROUND_UP(size));
+
+#ifdef USE_SCG
+       readsecs(block - sector_offset, buf, ISO_BLOCKS(size));
+#else
+       lseek(fileno(infile), ((off_t)(block - sector_offset)) << 11, SEEK_SET);
+       read(fileno(infile), buf, size);
+#endif
+
+       offset = 0;
+       idx = 1;
+       while (offset < size) {
+               len    = buf[offset];
+               extent = isonum_731((char *)buf + offset + 2);
+               pindex  = isonum_721((char *)buf + offset + 6);
+               switch (ucs_level) {
+               case 3:
+               case 2:
+               case 1:
+                       jlen = len/2;
+                       namebuf[0] = '\0';
+                       for (j = 0; j < jlen; j++) {
+                               uh = buf[offset + 8 + j*2];
+                               ul = buf[offset + 8 + j*2+1];
+
+                               up = unls->unls_uni2cs[uh];
+
+                               if (up == NULL)
+                                       uc = '\0';
+                               else
+                                       uc = up[ul];
+
+                               namebuf[j] = uc ? uc : '_';
+                       }
+                       printf("%4d: %4d %x %.*s\n",
+                               idx, pindex, extent, jlen, namebuf);
+                       break;
+               case 0:
+                       printf("%4d: %4d %x %.*s\n",
+                               idx, pindex, extent, len, buf + offset + 8);
+               }
+
+               idx++;
+               offset += 8 + len;
+               if (offset & 1)
+                       offset++;
+       }
+
+       free(buf);
+}
+
+int
+parse_rr(unsigned char *pnt, int len, int cont_flag)
+{
+       int slen;
+       int xlen;
+       int ncount;
+       int extent;
+       int cont_extent, cont_offset, cont_size;
+       int flag1, flag2;
+       unsigned char *pnts;
+       char symlinkname[1024];
+       int goof;
+
+       symlinkname[0] = 0;
+
+       cont_extent = cont_offset = cont_size = 0;
+
+       ncount = 0;
+       flag1 = flag2 = 0;
+       while (len >= 4) {
+               if (pnt[3] != 1 && pnt[3] != 2) {
+                       printf("**BAD RRVERSION (%d)\n", pnt[3]);
+                       return (0);             /* JS ??? Is this right ??? */
+               }
+               ncount++;
+               if (pnt[0] == 'R' && pnt[1] == 'R') flag1 = pnt[4] & 0xff;
+               if (strncmp((char *)pnt, "PX", 2) == 0) flag2 |= 1;     /* POSIX attributes */
+               if (strncmp((char *)pnt, "PN", 2) == 0) flag2 |= 2;     /* POSIX device number */
+               if (strncmp((char *)pnt, "SL", 2) == 0) flag2 |= 4;     /* Symlink */
+               if (strncmp((char *)pnt, "NM", 2) == 0) flag2 |= 8;     /* Alternate Name */
+               if (strncmp((char *)pnt, "CL", 2) == 0) flag2 |= 16;    /* Child link */
+               if (strncmp((char *)pnt, "PL", 2) == 0) flag2 |= 32;    /* Parent link */
+               if (strncmp((char *)pnt, "RE", 2) == 0) flag2 |= 64;    /* Relocated Direcotry */
+               if (strncmp((char *)pnt, "TF", 2) == 0) flag2 |= 128;   /* Time stamp */
+               if (strncmp((char *)pnt, "SP", 2) == 0) {
+                       flag2 |= 1024;                                  /* SUSP record */
+                       su_version = pnt[3] & 0xff;
+               }
+               if (strncmp((char *)pnt, "AA", 2) == 0) {
+                       flag2 |= 2048;                                  /* Apple Signature record */
+                       aa_version = pnt[3] & 0xff;
+               }
+
+               if (strncmp((char *)pnt, "PX", 2) == 0) {               /* POSIX attributes */
+                       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((char *)pnt, "NM", 2) == 0) {               /* Alternate Name */
+                       int     l = strlen(name_buf);
+
+                       if (!found_rr)
+                               l = 0;
+                       strncpy(&name_buf[l], (char *)(pnt+5), pnt[2] - 5);
+                       name_buf[l + pnt[2] - 5] = 0;
+                       found_rr = 1;
+               }
+
+               if (strncmp((char *)pnt, "CE", 2) == 0) {               /* Continuation Area */
+                       cont_extent = isonum_733(pnt+4);
+                       cont_offset = isonum_733(pnt+12);
+                       cont_size = isonum_733(pnt+20);
+               }
+
+               if (strncmp((char *)pnt, "PL", 2) == 0 || strncmp((char *)pnt, "CL", 2) == 0) {
+                       extent = isonum_733(pnt+4);
+               }
+
+               if (strncmp((char *)pnt, "SL", 2) == 0) {               /* Symlink */
+                       int     cflag;
+
+                       cflag = pnt[4];
+                       pnts = pnt+5;
+                       slen = pnt[2] - 5;
+                       while (slen >= 1) {
+                               switch (pnts[0] & 0xfe) {
+                               case 0:
+                                       strncat(symlinkname, (char *)(pnts+2), pnts[1]);
+                                       symlinkname[pnts[1]] = 0;
+                                       break;
+                               case 2:
+                                       strcat(symlinkname, ".");
+                                       break;
+                               case 4:
+                                       strcat(symlinkname, "..");
+                                       break;
+                               case 8:
+                                       strcat(symlinkname, "/");
+                                       break;
+                               case 16:
+                                       strcat(symlinkname, "/mnt");
+                                       printf("Warning - mount point requested");
+                                       break;
+                               case 32:
+                                       strcat(symlinkname, "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 (xname[0] == 0) strcpy(xname, "-> ");
+                               strcat(xname, symlinkname);
+                               symlinkname[0] = 0;
+                               xlen = strlen(xname);
+                               if ((pnts[0] & 1) == 0 && xname[xlen-1] != '/') strcat(xname, "/");
+
+                               slen -= (pnts[1] + 2);
+                               pnts += (pnts[1] + 2);
+                       }
+                       symlinkname[0] = 0;
+               }
+
+               len -= pnt[2];
+               pnt += pnt[2];
+               if (len <= 3 && cont_extent) {
+                       unsigned char   sector[2048];
+
+#ifdef USE_SCG
+                       readsecs(cont_extent - sector_offset, sector, ISO_BLOCKS(sizeof (sector)));
+#else
+                       lseek(fileno(infile), ((off_t)(cont_extent - sector_offset)) << 11, SEEK_SET);
+                       read(fileno(infile), sector, sizeof (sector));
+#endif
+                       flag2 |= parse_rr(&sector[cont_offset], cont_size, 1);
+               }
+       }
+       /*
+        * for symbolic links, strip out the last '/'
+        */
+       if (xname[0] != 0 && xname[strlen(xname)-1] == '/') {
+               xname[strlen(xname)-1] = '\0';
+       }
+       return (flag2);
+}
+
+void
+find_rr(struct iso_directory_record *idr, Uchar **pntp, int *lenp)
+{
+       struct iso_xa_dir_record *xadp;
+       int len;
+       unsigned char * pnt;
+
+       len = idr->length[0] & 0xff;
+       len -= offsetof(struct iso_directory_record, name[0]);
+       len -= idr->name_len[0];
+
+       pnt = (unsigned char *) idr;
+       pnt += offsetof(struct iso_directory_record, name[0]);
+       pnt += idr->name_len[0];
+       if ((idr->name_len[0] & 1) == 0) {
+               pnt++;
+               len--;
+       }
+       if (len >= 14) {
+               xadp = (struct iso_xa_dir_record *)pnt;
+
+               if (xadp->signature[0] == 'X' && xadp->signature[1] == 'A' &&
+                   xadp->reserved[0] == '\0') {
+                       len -= 14;
+                       pnt += 14;
+               }
+       }
+       *pntp = pnt;
+       *lenp = len;
+}
+
+int
+dump_rr(struct iso_directory_record *idr)
+{
+       int len;
+       unsigned char * pnt;
+
+       find_rr(idr, &pnt, &len);
+       return (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"};
+
+void
+dump_stat(struct iso_directory_record *idr, int extent)
+{
+       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';
+
+       /*
+        * XXX This is totally ugly code from Eric.
+        * XXX If one field is wider than expected then it is truncated.
+        */
+       sprintf(outline+11, "%3ld", (long)fstat_buf.st_nlink);
+       sprintf(outline+15, "%4lo", (unsigned long)fstat_buf.st_uid);
+       sprintf(outline+20, "%4lo", (unsigned long)fstat_buf.st_gid);
+       sprintf(outline+30, "%10lld", (Llong)fstat_buf.st_size);
+
+       if (do_sectors == 0) {
+               sprintf(outline+30, "%10lld", (Llong)fstat_buf.st_size);
+       } else {
+               sprintf(outline+30, "%10lld", (Llong)((fstat_buf.st_size+PAGE-1)/PAGE));
+       }
+
+       if (date_buf[1] >= 1 && date_buf[1] <= 12) {
+               memcpy(outline+41, months[date_buf[1]-1], 3);
+       }
+
+       sprintf(outline+45, "%2d", date_buf[2]);
+               outline[63] = 0;
+       sprintf(outline+48, "%4d", date_buf[0]+1900);
+
+       sprintf(outline+53, "[%7d", extent);    /* XXX up to 20 GB */
+       sprintf(outline+61, " %02X]", idr->flags[0]);
+
+       for (i = 0; i < 66; i++) {
+               if (outline[i] == 0) outline[i] = ' ';
+       }
+       outline[66] = 0;
+       printf("%s %s %s\n", outline, name_buf, xname);
+}
+
+void
+extract_file(struct iso_directory_record *idr)
+{
+       int             extent, len, tlen;
+       unsigned char   buff[2048];
+
+#if    defined(__CYGWIN32__) || defined(__CYGWIN__) || defined(__EMX__) || defined(__DJGPP__)
+       setmode(fileno(stdout), O_BINARY);
+#endif
+
+       extent = isonum_733((unsigned char *)idr->extent);
+       len = isonum_733((unsigned char *)idr->size);
+
+       while (len > 0) {
+#ifdef USE_SCG
+               readsecs(extent - sector_offset, buff, ISO_BLOCKS(sizeof (buff)));
+               tlen = (len > sizeof (buff) ? sizeof (buff) : len);
+#else
+               lseek(fileno(infile), ((off_t)(extent - sector_offset)) << 11, SEEK_SET);
+               tlen = (len > sizeof (buff) ? sizeof (buff) : len);
+               read(fileno(infile), buff, tlen);
+#endif
+               len -= tlen;
+               extent++;
+               write(STDOUT_FILENO, buff, tlen); /* FIXME: check return value */
+       }
+}
+
+void
+parse_dir(char *rootname, int extent, int len)
+{
+       char            testname[PATH_MAX+1];
+       struct todo     *td;
+       int             i;
+       struct iso_directory_record * idr;
+       unsigned char   uh, ul, uc, *up;
+
+
+       if (do_listing)
+               printf("\nDirectory listing of %s\n", rootname);
+
+       while (len > 0) {
+#ifdef USE_SCG
+               readsecs(extent - sector_offset, buffer, ISO_BLOCKS(sizeof (buffer)));
+#else
+               lseek(fileno(infile), ((off_t)(extent - sector_offset)) << 11, SEEK_SET);
+               read(fileno(infile), buffer, sizeof (buffer));
+#endif
+               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));
+                       found_rr = 0;
+                       name_buf[0] = xname[0] = 0;
+                       fstat_buf.st_size = (off_t)(unsigned)isonum_733((unsigned char *)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 {
+                               switch (ucs_level) {
+                               case 3:
+                               case 2:
+                               case 1:
+                                       /*
+                                        * Unicode name.  Convert as best we can.
+                                        */
+                                       {
+                                       int     j;
+
+                                       name_buf[0] = '\0';
+                                       for (j = 0; j < (int)idr->name_len[0] / 2; j++) {
+                                               uh = idr->name[j*2];
+                                               ul = idr->name[j*2+1];
+
+                                               up = unls->unls_uni2cs[uh];
+
+                                               if (up == NULL)
+                                                       uc = '\0';
+                                               else
+                                                       uc = up[ul];
+
+                                               name_buf[j] = uc ? uc : '_';
+                                       }
+                                       name_buf[idr->name_len[0]/2] = '\0';
+                                       }
+                                       break;
+                               case 0:
+                                       /*
+                                        * Normal non-Unicode name.
+                                        */
+                                       strncpy(name_buf, idr->name, idr->name_len[0]);
+                                       name_buf[idr->name_len[0]] = 0;
+                                       break;
+                               default:
+                                       /*
+                                        * Don't know how to do these yet.  Maybe they are the same
+                                        * as one of the above.
+                                        */
+                                       exit(1);
+                               }
+                       }
+                       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((unsigned char *)idr->extent);
+                               td->length = isonum_733((unsigned char *)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(idr, isonum_733((unsigned char *)idr->extent));
+                       i += buffer[i];
+                       if (i > 2048 - offsetof(struct iso_directory_record, name[0])) break;
+               }
+       }
+}
+
+void
+usage(int excode)
+{
+       errmsgno(EX_BAD, "Usage: %s [options] -i filename\n", get_progname());
+
+       fprintf(stderr, "Options:\n");
+       fprintf(stderr, "\t-help,-h     Print this help\n");
+       fprintf(stderr, "\t-version     Print version info and exit\n");
+       fprintf(stderr, "\t-debug               Print additional debug info\n");
+       fprintf(stderr, "\t-d           Print information from the primary volume descriptor\n");
+       fprintf(stderr, "\t-f           Generate output similar to 'find .  -print'\n");
+       fprintf(stderr, "\t-J           Print information from Joliet extensions\n");
+       fprintf(stderr, "\t-j charset   Use charset to display Joliet file names\n");
+       fprintf(stderr, "\t-l           Generate output similar to 'ls -lR'\n");
+       fprintf(stderr, "\t-p           Print Path Table\n");
+       fprintf(stderr, "\t-R           Print information from Rock Ridge extensions\n");
+       fprintf(stderr, "\t-s           Print file size infos in multiples of sector size (%ld bytes).\n", (long)PAGE);
+       fprintf(stderr, "\t-N sector    Sector number where ISO image should start on CD\n");
+       fprintf(stderr, "\t-T sector    Sector number where actual session starts on CD\n");
+       fprintf(stderr, "\t-i filename  Filename to read ISO-9660 image from\n");
+       fprintf(stderr, "\tdev=target   SCSI target to use as CD/DVD-Recorder\n");
+       fprintf(stderr, "\t-x pathname  Extract specified file to stdout\n");
+       exit(excode);
+}
+
+int
+main(int argc, char *argv[])
+{
+       int     cac;
+       char    * const *cav;
+       int     c;
+       char    * filename = NULL;
+       char    * devname = NULL;
+       /*
+        * Use toc_offset != 0 (-T #) if we have a complete multi-session
+        * disc that we want/need to play with.
+        * Here we specify the offset where we want to
+        * start searching for the TOC.
+        */
+       int     toc_offset = 0;
+       int     extent;
+       struct todo * td;
+       struct iso_primary_descriptor ipd;
+       struct iso_primary_descriptor jpd;
+       struct eltorito_boot_descriptor bpd;
+       struct iso_directory_record * idr;
+       char    *charset = NULL;
+       char    *opts = "help,h,version,debug,d,p,i*,dev*,J,R,l,x*,f,s,N#l,T#l,j*";
+       BOOL    help = FALSE;
+       BOOL    prvers = FALSE;
+       BOOL    found_eltorito = FALSE;
+       int     bootcat_offset = 0;
+
+
+       save_args(argc, argv);
+
+       cac = argc - 1;
+       cav = argv + 1;
+       if (getallargs(&cac, &cav, opts,
+                               &help, &help, &prvers, &debug,
+                               &do_pvd, &do_pathtab,
+                               &filename, &devname,
+                               &use_joliet, &use_rock,
+                               &do_listing,
+                               &xtract,
+                               &do_find, &do_sectors,
+                               &sector_offset, &toc_offset,
+                               &charset) < 0) {
+               errmsgno(EX_BAD, "Bad Option: '%s'\n", cav[0]);
+               usage(EX_BAD);
+       }
+       if (help)
+               usage(0);
+       if (prvers) {
+               printf("isoinfo %s (%s)\n", CDRKIT_VERSION, HOST_SYSTEM);
+               exit(0);
+       }
+       cac = argc - 1;
+       cav = argv + 1;
+       if (getfiles(&cac, &cav, opts) != 0) {
+               errmsgno(EX_BAD, "Bad Argument: '%s'\n", cav[0]);
+               usage(EX_BAD);
+       }
+
+       init_unls();            /* Initialize UNICODE tables */
+       init_unls_file(charset);
+       if (charset == NULL) {
+#if    (defined(__CYGWIN32__) || defined(__CYGWIN__) || defined(__DJGPP__)) && !defined(IS_CYGWIN_1)
+               unls = load_unls("cp437");
+#else
+               unls = load_unls("iso8859-1");
+#endif
+       } else {
+               if (strcmp(charset, "default") == 0)
+                       unls = load_unls_default();
+               else
+                       unls = load_unls(charset);
+       }
+       if (unls == NULL) {     /* Unknown charset specified */
+               fprintf(stderr, "Unknown charset: %s\nKnown charsets are:\n",
+                                                       charset);
+               list_unls();    /* List all known charset names */
+               exit(1);
+       }
+
+       if (filename != NULL && devname != NULL) {
+               errmsgno(EX_BAD, "Only one of -i or dev= allowed\n");
+               usage(EX_BAD);
+       }
+#ifdef USE_SCG
+       if (filename == NULL && devname == NULL)
+               cdr_defaults(&devname, NULL, NULL, NULL);
+#endif
+       if (filename == NULL && devname == NULL) {
+#ifdef USE_LIBSCHILY
+               errmsgno(EX_BAD, "ISO-9660 image not specified\n");
+#else
+               fprintf(stderr, "ISO-9660 image not specified\n");
+#endif
+               usage(EX_BAD);
+       }
+
+       if (filename != NULL)
+               infile = fopen(filename, "rb");
+       else
+               filename = devname;
+
+       if (infile != NULL) {
+               /* EMPTY */;
+#ifdef USE_SCG
+       } else if (scsidev_open(filename) < 0) {
+#else
+       } else {
+#endif
+#ifdef USE_LIBSCHILY
+               comerr("Unable to open %s\n", filename);
+#else
+               fprintf(stderr, "Unable to open %s\n", filename);
+               exit(1);
+#endif
+       }
+
+       /*
+        * Absolute sector offset, so don't subtract sector_offset here.
+        */
+#ifdef USE_SCG
+       readsecs(16 + toc_offset, &ipd, ISO_BLOCKS(sizeof (ipd)));
+#else
+       lseek(fileno(infile), ((off_t)(16 + toc_offset)) <<11, SEEK_SET);
+       read(fileno(infile), &ipd, sizeof (ipd));
+#endif
+       idr = (struct iso_directory_record *)ipd.root_directory_record;
+       if (do_pvd) {
+               /*
+                * High sierra:
+                *
+                *      DESC TYPE       == 1 (VD_SFS)   offset 8        len 1
+                *      STR ID          == "CDROM"      offset 9        len 5
+                *      STD_VER         == 1            offset 14       len 1
+                */
+               if ((((char *)&ipd)[8] == 1) &&
+                   (strncmp(&((char *)&ipd)[9], "CDROM", 5) == 0) &&
+                   (((char *)&ipd)[14] == 1)) {
+                       printf("CD-ROM is in High Sierra format\n");
+                       exit(0);
+               }
+               /*
+                * ISO 9660:
+                *
+                *      DESC TYPE       == 1 (VD_PVD)   offset 0        len 1
+                *      STR ID          == "CD001"      offset 1        len 5
+                *      STD_VER         == 1            offset 6        len 1
+                */
+               if ((ipd.type[0] != ISO_VD_PRIMARY) ||
+                   (strncmp(ipd.id, ISO_STANDARD_ID, sizeof (ipd.id)) != 0) ||
+                   (ipd.version[0] != 1)) {
+                       printf("CD-ROM is NOT in ISO 9660 format\n");
+                       exit(1);
+               }
+
+               printf("CD-ROM is in ISO 9660 format\n");
+               printf("System id: ");
+               printchars(ipd.system_id, 32);
+               putchar('\n');
+               printf("Volume id: ");
+               printchars(ipd.volume_id, 32);
+               putchar('\n');
+
+               printf("Volume set id: ");
+               printchars(ipd.volume_set_id, 128);
+               putchar('\n');
+               printf("Publisher id: ");
+               printchars(ipd.publisher_id, 128);
+               putchar('\n');
+               printf("Data preparer id: ");
+               printchars(ipd.preparer_id, 128);
+               putchar('\n');
+               printf("Application id: ");
+               printchars(ipd.application_id, 128);
+               putchar('\n');
+
+               printf("Copyright File id: ");
+               printchars(ipd.copyright_file_id, 37);
+               putchar('\n');
+               printf("Abstract File id: ");
+               printchars(ipd.abstract_file_id, 37);
+               putchar('\n');
+               printf("Bibliographic File id: ");
+               printchars(ipd.bibliographic_file_id, 37);
+               putchar('\n');
+
+               printf("Volume set size is: %d\n", isonum_723(ipd.volume_set_size));
+               printf("Volume set sequence number is: %d\n", isonum_723(ipd.volume_sequence_number));
+               printf("Logical block size is: %d\n", isonum_723(ipd.logical_block_size));
+               printf("Volume size is: %d\n", isonum_733((unsigned char *)ipd.volume_space_size));
+               if (debug) {
+                       int     dextent;
+                       int     dlen;
+
+                       dextent = isonum_733((unsigned char *)idr->extent);
+                       dlen = isonum_733((unsigned char *)idr->size);
+                       printf("Root directory extent:  %d size: %d\n",
+                               dextent, dlen);
+                       printf("Path table size is:     %d\n",
+                               isonum_733((unsigned char *)ipd.path_table_size));
+                       printf("L Path table start:     %d\n",
+                               isonum_731(ipd.type_l_path_table));
+                       printf("L Path opt table start: %d\n",
+                               isonum_731(ipd.opt_type_l_path_table));
+                       printf("M Path table start:     %d\n",
+                               isonum_732(ipd.type_m_path_table));
+                       printf("M Path opt table start: %d\n",
+                               isonum_732(ipd.opt_type_m_path_table));
+                       printf("Creation Date:     %s\n",
+                               sdate(ipd.creation_date));
+                       printf("Modification Date: %s\n",
+                               sdate(ipd.modification_date));
+                       printf("Expiration Date:   %s\n",
+                               sdate(ipd.expiration_date));
+                       printf("Effective Date:    %s\n",
+                               sdate(ipd.effective_date));
+                       printf("File structure version: %d\n",
+                               ipd.file_structure_version[0]);
+               }
+               {
+                       int     block = 16;
+                       movebytes(&ipd, &jpd, sizeof (ipd));
+                       while ((Uchar)jpd.type[0] != ISO_VD_END) {
+
+                               if (debug && (Uchar) jpd.type[0] == ISO_VD_SUPPLEMENTARY)
+                                       fprintf(stderr, "Joliet escape sequence 0: '%c' 1: '%c' 2: '%c' 3: '%c'\n",
+                                               jpd.escape_sequences[0],
+                                               jpd.escape_sequences[1],
+                                               jpd.escape_sequences[2],
+                                               jpd.escape_sequences[3]);
+                                       /*
+                                        * If Joliet UCS escape sequence found, we may be wrong
+                                        */
+                                       if (jpd.escape_sequences[0] == '%' &&
+                                           jpd.escape_sequences[1] == '/' &&
+                                           (jpd.escape_sequences[3] == '\0' ||
+                                           jpd.escape_sequences[3] == ' ') &&
+                                           (jpd.escape_sequences[2] == '@' ||
+                                           jpd.escape_sequences[2] == 'C' ||
+                                           jpd.escape_sequences[2] == 'E')) {
+
+                                               if (jpd.version[0] == 1)
+                                                       goto nextblock;
+                               }
+                               if (jpd.type[0] == 0) {
+                                       movebytes(&jpd, &bpd, sizeof (bpd));
+                                       if (strncmp(bpd.system_id, EL_TORITO_ID, sizeof (EL_TORITO_ID)) == 0) {
+                                               bootcat_offset = (Uchar)bpd.bootcat_ptr[0] +
+                                                               (Uchar)bpd.bootcat_ptr[1] * 256 +
+                                                               (Uchar)bpd.bootcat_ptr[2] * 65536 +
+                                                               (Uchar)bpd.bootcat_ptr[3] * 16777216;
+                                               found_eltorito = TRUE;
+                                               printf("El Torito VD version %d found, boot catalog is in sector %d\n",
+                                                       bpd.version[0],
+                                                       bootcat_offset);
+                                       }
+                               }
+                               if (jpd.version[0] == 2) {
+                                       printf("CD-ROM uses ISO 9660:1999 relaxed format\n");
+                                       break;
+                               }
+
+                       nextblock:
+                               block++;
+#ifdef USE_SCG
+                               readsecs(block + toc_offset, &jpd, ISO_BLOCKS(sizeof (jpd)));
+#else
+                               lseek(fileno(infile), ((off_t)(block + toc_offset)) <<11, SEEK_SET);
+                               read(fileno(infile), &jpd, sizeof (jpd));
+#endif
+                       }
+               }
+       }
+       /*
+        * ISO 9660:
+        *
+        *      DESC TYPE       == 1 (VD_PVD)   offset 0        len 1
+        *      STR ID          == "CD001"      offset 1        len 5
+        *      STD_VER         == 1            offset 6        len 1
+        */
+       if ((ipd.type[0] != ISO_VD_PRIMARY) ||
+           (strncmp(ipd.id, ISO_STANDARD_ID, sizeof (ipd.id)) != 0) ||
+           (ipd.version[0] != 1)) {
+               printf("CD-ROM is NOT in ISO 9660 format\n");
+               exit(1);
+       }
+
+       if (use_joliet || do_pvd) {
+               int block = 16;
+               movebytes(&ipd, &jpd, sizeof (ipd));
+               while ((unsigned char) jpd.type[0] != ISO_VD_END) {
+                       if (debug && (unsigned char) jpd.type[0] == ISO_VD_SUPPLEMENTARY)
+                               fprintf(stderr, "Joliet escape sequence 0: '%c' 1: '%c' 2: '%c' 3: '%c'\n",
+                                       jpd.escape_sequences[0],
+                                       jpd.escape_sequences[1],
+                                       jpd.escape_sequences[2],
+                                       jpd.escape_sequences[3]);
+                       /*
+                        * Find the UCS escape sequence.
+                        */
+                       if (jpd.escape_sequences[0] == '%' &&
+                           jpd.escape_sequences[1] == '/' &&
+                           (jpd.escape_sequences[3] == '\0' ||
+                           jpd.escape_sequences[3] == ' ') &&
+                           (jpd.escape_sequences[2] == '@' ||
+                           jpd.escape_sequences[2] == 'C' ||
+                           jpd.escape_sequences[2] == 'E')) {
+                               break;
+                       }
+
+                       block++;
+#ifdef USE_SCG
+                       readsecs(block + toc_offset, &jpd, ISO_BLOCKS(sizeof (jpd)));
+#else
+                       lseek(fileno(infile),
+                               ((off_t)(block + toc_offset)) <<11, SEEK_SET);
+                       read(fileno(infile), &jpd, sizeof (jpd));
+#endif
+               }
+
+               if (use_joliet && ((unsigned char) jpd.type[0] == ISO_VD_END)) {
+#ifdef USE_LIBSCHILY
+                       comerrno(EX_BAD, "Unable to find Joliet SVD\n");
+#else
+                       fprintf(stderr, "Unable to find Joliet SVD\n");
+                       exit(1);
+#endif
+               }
+
+               switch (jpd.escape_sequences[2]) {
+               case '@':
+                       ucs_level = 1;
+                       break;
+               case 'C':
+                       ucs_level = 2;
+                       break;
+               case 'E':
+                       ucs_level = 3;
+                       break;
+               }
+
+               if (ucs_level > 3) {
+#ifdef USE_LIBSCHILY
+                       comerrno(EX_BAD,
+                               "Don't know what ucs_level == %d means\n",
+                               ucs_level);
+#else
+                       fprintf(stderr,
+                               "Don't know what ucs_level == %d means\n",
+                               ucs_level);
+                       exit(1);
+#endif
+               }
+               if (jpd.escape_sequences[3] == ' ')
+                       errmsgno(EX_BAD,
+                       "Warning: Joliet escape sequence uses illegal space at offset 3\n");
+       }
+
+       if (do_pvd) {
+               if (ucs_level > 0)
+                       printf("Joliet with UCS level %d found\n", ucs_level);
+               else
+                       printf("NO Joliet present\n");
+
+               extent = isonum_733((unsigned char *)idr->extent);
+
+#ifdef USE_SCG
+               readsecs(extent - sector_offset, buffer, ISO_BLOCKS(sizeof (buffer)));
+#else
+               lseek(fileno(infile),
+                       ((off_t)(extent - sector_offset)) <<11, SEEK_SET);
+               read(fileno(infile), buffer, sizeof (buffer));
+#endif
+               idr = (struct iso_directory_record *) buffer;
+               if ((c = dump_rr(idr)) != 0) {
+/*                     printf("RR %X %d\n", c, c);*/
+                       if (c & 1024) {
+                               printf(
+                               "Rock Ridge signatures version %d found\n",
+                               su_version);
+                       } else {
+                               printf(
+                               "Bad Rock Ridge signatures found (SU record missing)\n");
+                       }
+                       /*
+                        * This is currently a no op!
+                        * We need to check the first plain file instead of
+                        * the '.' entry in the root directory.
+                        */
+                       if (c & 2048) {
+                               printf("Apple signatures version %d found\n",
+                                                               aa_version);
+                       }
+               } else {
+                       printf("NO Rock Ridge present\n");
+               }
+               if (found_eltorito)
+                       printf_bootinfo(infile, bootcat_offset);
+               exit(0);
+       }
+
+       if (use_joliet)
+               idr = (struct iso_directory_record *)jpd.root_directory_record;
+
+       if (do_pathtab) {
+               if (use_joliet) {
+                       dump_pathtab(isonum_731(jpd.type_l_path_table),
+                       isonum_733((unsigned char *)jpd.path_table_size));
+               } else {
+                       dump_pathtab(isonum_731(ipd.type_l_path_table),
+                       isonum_733((unsigned char *)ipd.path_table_size));
+               }
+       }
+
+       parse_dir("/", isonum_733((unsigned char *)idr->extent),
+                               isonum_733((unsigned char *)idr->size));
+       td = todo_idr;
+       while (td) {
+               parse_dir(td->name, td->extent, td->length);
+               td = td->next;
+       }
+
+       if (infile != NULL)
+               fclose(infile);
+       return (0);
+}
+
+#include <intcvt.h>
+
+static void
+printf_bootinfo(FILE *f, int bootcat_offset)
+{
+       struct eltorito_validation_entry        *evp;
+       struct eltorito_defaultboot_entry       *ebe;
+
+#ifdef USE_SCG
+       readsecs(bootcat_offset, buffer, ISO_BLOCKS(sizeof (buffer)));
+#else
+       lseek(fileno(f), ((off_t)bootcat_offset) <<11, SEEK_SET);
+       read(fileno(f), buffer, sizeof (buffer));
+#endif
+
+       evp = (struct eltorito_validation_entry *)buffer;
+       ebe = (struct eltorito_defaultboot_entry *)&buffer[32];
+
+       printf("Eltorito validation header:\n");
+       printf("    Hid %d\n", (Uchar)evp->headerid[0]);
+       printf("    Arch %d (%s)\n", (Uchar)evp->arch[0], arch_name((Uchar)evp->arch[0]));
+       printf("    ID '%.23s'\n", evp->id);
+       printf("    Key %X %X\n", (Uchar)evp->key1[0], (Uchar)evp->key2[0]);
+
+       printf("    Eltorito defaultboot header:\n");
+       printf("        Bootid %X (%s)\n", (Uchar)ebe->boot_id[0], boot_name((Uchar)ebe->boot_id[0]));
+       printf("        Boot media %X (%s)\n", (Uchar)ebe->boot_media[0], bootmedia_name((Uchar)ebe->boot_media[0]));
+       printf("        Load segment %X\n", la_to_2_byte(ebe->loadseg));
+       printf("        Sys type %X\n", (Uchar)ebe->sys_type[0]);
+       printf("        Nsect %X\n", la_to_2_byte(ebe->nsect));
+       printf("        Bootoff %lX %ld\n", la_to_4_byte(ebe->bootoff), la_to_4_byte(ebe->bootoff));
+
+}
+
+static char *
+arch_name(int val)
+{
+       switch (val) {
+
+       case EL_TORITO_ARCH_x86:
+               return ("x86");
+       case EL_TORITO_ARCH_PPC:
+               return ("PPC");
+       case EL_TORITO_ARCH_MAC:
+               return ("MAC");
+       default:
+               return ("Unknown Arch");
+       }
+}
+
+static char *
+boot_name(int val)
+{
+       switch (val) {
+
+       case EL_TORITO_BOOTABLE:
+               return ("bootable");
+       case EL_TORITO_NOT_BOOTABLE:
+               return ("not bootable");
+       default:
+               return ("Illegal");
+       }
+}
+
+static char *
+bootmedia_name(int val)
+{
+       switch (val) {
+
+       case EL_TORITO_MEDIA_NOEMUL:
+               return ("No Emulation Boot");
+       case EL_TORITO_MEDIA_12FLOP:
+               return ("1200 Floppy");
+       case EL_TORITO_MEDIA_144FLOP:
+               return ("1.44MB Floppy");
+       case EL_TORITO_MEDIA_288FLOP:
+               return ("2.88MB Floppy");
+       case EL_TORITO_MEDIA_HD:
+               return ("Hard Disk Emulation");
+       default:
+               return ("Illegal Bootmedia");
+       }
+}
diff --git a/genisoimage/diag/isovfy.1 b/genisoimage/diag/isovfy.1
new file mode 100644 (file)
index 0000000..b170c59
--- /dev/null
@@ -0,0 +1,2 @@
+.so man1/isoinfo.1
+.\" %Z%%M%     %I% %E% joerg
diff --git a/genisoimage/diag/isovfy.c b/genisoimage/diag/isovfy.c
new file mode 100644 (file)
index 0000000..18ed340
--- /dev/null
@@ -0,0 +1,794 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)isovfy.c        1.26 05/05/15 joerg */
+/*
+ * File isovfy.c - verify consistency of iso9660 filesystem.
+ *
+ *
+ * Written by Eric Youngdale (1993).
+ *
+ * Copyright 1993 Yggdrasil Computing, Incorporated
+ * Copyright (c) 1999-2004 J. Schilling
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <mconfig.h>
+#include <stdxlib.h>
+#include <unixstd.h>
+#include <strdefs.h>
+#include <utypes.h>
+
+#include <stdio.h>
+#include <standard.h>
+#include <signal.h>
+#include <schily.h>
+
+#include "../scsi.h"
+#include "../../wodim/defaults.h"
+
+/*
+ * XXX JS: Some structures have odd lengths!
+ * Some compilers (e.g. on Sun3/mc68020) padd the structures to even length.
+ * For this reason, we cannot use sizeof (struct iso_path_table) or
+ * sizeof (struct iso_directory_record) to compute on disk sizes.
+ * Instead, we use offsetof(..., name) and add the name size.
+ * See iso9660.h
+ */
+#ifndef        offsetof
+#define        offsetof(TYPE, MEMBER)  ((size_t) &((TYPE *)0)->MEMBER)
+#endif
+
+/*
+ * Note: always use these macros to avoid problems.
+ *
+ * ISO_ROUND_UP(X)     may cause an integer overflow and thus give
+ *                     incorrect results. So avoid it if possible.
+ *
+ * ISO_BLOCKS(X)       is overflow safe. Prefer this when ever it is possible.
+ */
+#define        SECTOR_SIZE     (2048)
+#define        ISO_ROUND_UP(X) (((X) + (SECTOR_SIZE - 1)) & ~(SECTOR_SIZE - 1))
+#define        ISO_BLOCKS(X)   (((X) / SECTOR_SIZE) + (((X)%SECTOR_SIZE)?1:0))
+
+#define        infile  in_image
+FILE *infile = NULL;
+int blocksize;
+
+#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];
+};
+
+static int     isonum_721(char * p);
+static int     isonum_723(char * p);
+static int     isonum_711(char * p);
+static int     isonum_731(char * p);
+static int     isonum_722(char * p);
+static int     isonum_732(char * p);
+static int     isonum_733(unsigned char * p);
+static int     parse_rr(unsigned char * pnt, int len, int cont_flag);
+static int     dump_rr(struct iso_directory_record * idr);
+static void    check_tree(off_t file_addr, int file_size, off_t parent_addr);
+static void    check_path_tables(int typel_extent, int typem_extent, 
+                                                                               int path_table_size);
+static void    usage(int excode);
+
+static int
+isonum_721(char *p)
+{
+       return ((p[0] & 0xff) | ((p[1] & 0xff) << 8));
+}
+
+static int
+isonum_723(char *p)
+{
+#if 0
+       if (p[0] != p[3] || p[1] != p[2]) {
+#ifdef USE_LIBSCHILY
+               comerrno(EX_BAD, "invalid format 7.2.3 number\n");
+#else
+               fprintf(stderr, "invalid format 7.2.3 number\n");
+               exit(1);
+#endif
+       }
+#endif
+       return (isonum_721(p));
+}
+
+static int
+isonum_711(char *p)
+{
+       return (*p & 0xff);
+}
+
+static int
+isonum_731(char *p)
+{
+       return ((p[0] & 0xff)
+               | ((p[1] & 0xff) << 8)
+               | ((p[2] & 0xff) << 16)
+               | ((p[3] & 0xff) << 24));
+}
+
+static int
+isonum_722(char *p)
+{
+       return ((p[1] & 0xff)
+               | ((p[0] & 0xff) << 8));
+}
+
+static int
+isonum_732(char *p)
+{
+       return ((p[3] & 0xff)
+               | ((p[2] & 0xff) << 8)
+               | ((p[1] & 0xff) << 16)
+               | ((p[0] & 0xff) << 24));
+}
+
+static int
+isonum_733(unsigned char *p)
+{
+       return (isonum_731((char *)p));
+}
+
+char   lbuffer[1024];
+int    iline;
+int    rr_goof;
+
+
+static int
+parse_rr(unsigned char *pnt, int len, int cont_flag)
+{
+       int             slen;
+       int             ncount;
+       int             flag1;
+       int             flag2;
+       int             extent;
+       unsigned char   *pnts;
+       off_t           cont_extent;
+       int             cont_offset;
+       int             cont_size;
+       char            symlinkname[1024];
+
+       sprintf(lbuffer+iline, " RRlen=%d ", len);
+       iline += strlen(lbuffer+iline);
+
+       cont_extent = (off_t)0;
+       cont_offset = cont_size = 0;
+
+       symlinkname[0] = 0;
+
+       ncount = 0;
+       flag1 = flag2 = 0;
+       while (len >= 4) {
+               if (ncount)
+                       sprintf(lbuffer+iline, ",");
+               else
+                       sprintf(lbuffer+iline, "[");
+               iline += strlen(lbuffer + iline);
+               sprintf(lbuffer+iline, "%c%c", pnt[0], pnt[1]);
+               iline += strlen(lbuffer + iline);
+               if (pnt[0] < 'A' || pnt[0] > 'Z' || pnt[1] < 'A' ||
+                   pnt[1] > 'Z') {
+                       sprintf(lbuffer+iline, "**BAD SUSP %d %d]",
+                                       pnt[0], pnt[1]);
+                       rr_goof++;
+                       iline += strlen(lbuffer + iline);
+                       return (flag2);
+               }
+
+               if (pnt[3] != 1 && pnt[3] != 2) {
+                       sprintf(lbuffer+iline, "**BAD RRVERSION (%d)\n", pnt[3]);
+                       rr_goof++;
+                       iline += strlen(lbuffer + iline);
+                       return (flag2);
+               }
+               ncount++;
+               if (pnt[0] == 'R' && pnt[1] == 'R') flag1 = pnt[4] & 0xff;
+               if (strncmp((char *)pnt, "PX", 2) == 0) flag2 |= 1;
+               if (strncmp((char *)pnt, "PN", 2) == 0) flag2 |= 2;
+               if (strncmp((char *)pnt, "SL", 2) == 0) flag2 |= 4;
+               if (strncmp((char *)pnt, "NM", 2) == 0) flag2 |= 8;
+               if (strncmp((char *)pnt, "CL", 2) == 0) flag2 |= 16;
+               if (strncmp((char *)pnt, "PL", 2) == 0) flag2 |= 32;
+               if (strncmp((char *)pnt, "RE", 2) == 0) flag2 |= 64;
+               if (strncmp((char *)pnt, "TF", 2) == 0) flag2 |= 128;
+
+               if (strncmp((char *)pnt, "CE", 2) == 0) {
+                       cont_extent = (off_t)isonum_733(pnt+4);
+                       cont_offset = isonum_733(pnt+12);
+                       cont_size = isonum_733(pnt+20);
+                       sprintf(lbuffer+iline, "=[%x,%x,%d]",
+                                       (int)cont_extent, cont_offset, cont_size);
+                       iline += strlen(lbuffer + iline);
+               }
+
+               if (strncmp((char *)pnt, "PL", 2) == 0 || strncmp((char *)pnt, "CL", 2) == 0) {
+                       extent = isonum_733(pnt+4);
+                       sprintf(lbuffer+iline, "=%x", extent);
+                       iline += strlen(lbuffer + iline);
+                       if (extent == 0)
+                               rr_goof++;
+               }
+               if (strncmp((char *)pnt, "SL", 2) == 0) {
+                       pnts = pnt+5;
+                       slen = pnt[2] - 5;
+                       while (slen >= 1) {
+                               switch (pnts[0] & 0xfe) {
+                               case 0:
+                                       strncat(symlinkname, (char *)(pnts+2), pnts[1]);
+                                       break;
+                               case 2:
+                                       strcat(symlinkname, ".");
+                                       break;
+                               case 4:
+                                       strcat(symlinkname, "..");
+                                       break;
+                               case 8:
+                                       strcat(symlinkname, "/");
+                                       break;
+                               case 16:
+                                       strcat(symlinkname, "/mnt");
+                                       sprintf(lbuffer+iline, "Warning - mount point requested");
+                                       iline += strlen(lbuffer + iline);
+                                       break;
+                               case 32:
+                                       strcat(symlinkname, "kafka");
+                                       sprintf(lbuffer+iline, "Warning - host_name requested");
+                                       iline += strlen(lbuffer + iline);
+                                       break;
+                               default:
+                                       sprintf(lbuffer+iline, "Reserved bit setting in symlink");
+                                       rr_goof++;
+                                       iline += strlen(lbuffer + iline);
+                                       break;
+                               }
+                               if ((pnts[0] & 0xfe) && pnts[1] != 0) {
+                                       sprintf(lbuffer+iline, "Incorrect length in symlink component");
+                                       iline += strlen(lbuffer + iline);
+                               }
+                               if ((pnts[0] & 1) == 0)
+                                       strcat(symlinkname, "/");
+                               slen -= (pnts[1] + 2);
+                               pnts += (pnts[1] + 2);
+                       }
+                       if (symlinkname[0] != 0) {
+                               sprintf(lbuffer+iline, "=%s", symlinkname);
+                               iline += strlen(lbuffer + iline);
+                               symlinkname[0] = 0;
+                       }
+               }
+
+               len -= pnt[2];
+               pnt += pnt[2];
+               if (len <= 3 && cont_extent) {
+                       unsigned char sector[2048];
+#ifdef USE_SCG
+                       readsecs(cont_extent * blocksize / 2048, sector, ISO_BLOCKS(sizeof (sector)));
+#else
+                       lseek(fileno(infile), cont_extent * blocksize, SEEK_SET);
+                       read(fileno(infile), sector, sizeof (sector));
+#endif
+                       flag2 |= parse_rr(&sector[cont_offset], cont_size, 1);
+               }
+       }
+       if (ncount) {
+               sprintf(lbuffer+iline, "]");
+               iline += strlen(lbuffer + iline);
+       }
+       if (!cont_flag && flag1 && flag1 != flag2) {
+               sprintf(lbuffer+iline, "Flag %x != %x", flag1, flag2);
+               rr_goof++;
+               iline += strlen(lbuffer + iline);
+       }
+       return (flag2);
+}
+
+static int
+dump_rr(struct iso_directory_record *idr)
+{
+       int len;
+       char * pnt;
+
+       len = idr->length[0] & 0xff;
+       len -= offsetof(struct iso_directory_record, name[0]);
+       len -= idr->name_len[0];
+       pnt = (char *) idr;
+       pnt += offsetof(struct iso_directory_record, name[0]);
+       pnt += idr->name_len[0];
+
+       if ((idr->name_len[0] & 1) == 0) {
+               pnt++;
+               len--;
+       }
+
+       rr_goof = 0;
+       parse_rr((unsigned char *)pnt, len, 0);
+       return (rr_goof);
+}
+
+
+static int     dir_count = 0;
+static int     dir_size_count = 0;
+static int     ngoof = 0;
+
+static void
+check_tree(off_t file_addr, int file_size, off_t parent_addr)
+{
+       unsigned char   buffer[2048];
+       unsigned int    k;
+       int             rflag = 0;
+       int             i;
+       int             i1;
+       int             j;
+       int             goof;
+       int             extent;
+       int             size;
+       off_t           orig_file_addr;
+       off_t           parent_file_addr;
+       struct iso_directory_record     *idr;
+
+       i1 = 0;
+
+       orig_file_addr = file_addr / blocksize;  /* Actual extent of this directory */
+       parent_file_addr = parent_addr / blocksize;
+
+       if ((dir_count % 100) == 0)
+               printf("[%d %d]\n", dir_count, dir_size_count);
+#if 0
+       if (sizeof (file_addr) > sizeof (long)) {
+               printf("Starting directory %ld %d %lld\n",
+                               file_addr, file_size,
+                               (Llong)parent_addr);
+       } else {
+               printf("Starting directory %ld %d %ld\n", file_addr, file_size, parent_addr);
+       }
+#endif
+
+       dir_count++;
+       dir_size_count += file_size / blocksize;
+
+       if (file_size & 0x3ff)
+               printf("********Directory has unusual size\n");
+
+       for (k = 0; k < (file_size / sizeof (buffer)); k++) {
+#ifdef USE_SCG
+               readsecs(file_addr / 2048, buffer, ISO_BLOCKS(sizeof (buffer)));
+#else
+               lseek(fileno(infile), file_addr, SEEK_SET);
+               read(fileno(infile), buffer, sizeof (buffer));
+#endif
+               i = 0;
+               while (1 == 1) {
+                       goof = iline = 0;
+                       idr = (struct iso_directory_record *) &buffer[i];
+                       if (idr->length[0] == 0) break;
+                       sprintf(&lbuffer[iline], "%3d ", idr->length[0]);
+                       iline += strlen(lbuffer + iline);
+                       extent = isonum_733(idr->extent);
+                       size = isonum_733(idr->size);
+                       sprintf(&lbuffer[iline], "%5x ", extent);
+                       iline += strlen(lbuffer + iline);
+                       sprintf(&lbuffer[iline], "%8d ", size);
+                       iline += strlen(lbuffer + iline);
+                       sprintf(&lbuffer[iline], "%c", (idr->flags[0] & 2) ? '*' : ' ');
+                       iline += strlen(lbuffer + iline);
+
+                       if (idr->name_len[0] > 33) {
+                               sprintf(&lbuffer[iline], "File name length=(%d)",
+                                                       idr->name_len[0]);
+                               goof++;
+                               iline += strlen(lbuffer + iline);
+                       } else if (idr->name_len[0] == 1 && idr->name[0] == 0) {
+                               sprintf(&lbuffer[iline], ".             ");
+                               iline += strlen(lbuffer + iline);
+                               rflag = 0;
+                               if (orig_file_addr != (off_t)(isonum_733(idr->extent) + isonum_711((char *) idr->ext_attr_length))) {
+                                       sprintf(&lbuffer[iline], "***** Directory has null extent.");
+                                       goof++;
+                                       iline += strlen(lbuffer + iline);
+                               }
+                               if (i1) {
+                                       sprintf(&lbuffer[iline], "***** . not  first entry.");
+                                       rr_goof++;
+                                       iline += strlen(lbuffer + iline);
+                               }
+                       } else if (idr->name_len[0] == 1 && idr->name[0] == 1) {
+                               sprintf(&lbuffer[iline], "..            ");
+                               iline += strlen(lbuffer + iline);
+                               rflag = 0;
+                               if (parent_file_addr != (off_t)(isonum_733(idr->extent) + isonum_711((char *) idr->ext_attr_length))) {
+                                       sprintf(&lbuffer[iline], "***** Directory has null extent.");
+                                       goof++;
+                                       iline += strlen(lbuffer + iline);
+                               }
+                               if (i1 != 1) {
+                                       sprintf(&lbuffer[iline], "***** .. not second entry.");
+                                       rr_goof++;
+                                       iline += strlen(lbuffer + iline);
+                               }
+                       } else {
+                               if (i1 < 2) {
+                                       sprintf(&lbuffer[iline], " Improper sorting.");
+                                       rr_goof++;
+                               }
+                               for (j = 0; j < (int)idr->name_len[0]; j++) {
+                                       sprintf(&lbuffer[iline], "%c", idr->name[j]);
+                               }
+                               for (j = 0; j < (14 - (int) idr->name_len[0]); j++) {
+                                       sprintf(&lbuffer[iline], " ");
+                                       iline += strlen(lbuffer + iline);
+                               }
+                               rflag = 1;
+                       }
+
+                       if (size && extent == 0) {
+                               sprintf(&lbuffer[iline], "****Extent==0, size != 0");
+                               goof++;
+                               iline += strlen(lbuffer + iline);
+                       }
+#if 0
+                       /* This is apparently legal. */
+                       if (size == 0 && extent) {
+                               sprintf(&lbuffer[iline], "****Extent!=0, size == 0");
+                               goof++;
+                               iline += strlen(lbuffer + iline);
+                       }
+#endif
+
+                       if (idr->flags[0] & 0xf5) {
+                               sprintf(&lbuffer[iline], "Flags=(%x) ", idr->flags[0]);
+                               goof++;
+                               iline += strlen(lbuffer + iline);
+                       }
+                       if (idr->interleave[0]) {
+                               sprintf(&lbuffer[iline], "Interleave=(%d) ", idr->interleave[0]);
+                               goof++;
+                               iline += strlen(lbuffer + iline);
+                       }
+
+                       if (idr->file_unit_size[0]) {
+                               sprintf(&lbuffer[iline], "File unit size=(%d) ", idr->file_unit_size[0]);
+                               goof++;
+                               iline += strlen(lbuffer + iline);
+                       }
+
+                       if (idr->volume_sequence_number[0] != 1) {
+                               sprintf(&lbuffer[iline], "Volume sequence number=(%d) ", idr->volume_sequence_number[0]);
+                               goof++;
+                               iline += strlen(lbuffer + iline);
+                       }
+
+                       goof += dump_rr(idr);
+                       sprintf(&lbuffer[iline], "\n");
+                       iline += strlen(lbuffer + iline);
+
+
+                       if (goof) {
+                               ngoof++;
+                               lbuffer[iline++] = 0;
+                               if (sizeof (orig_file_addr) > sizeof (long)) {
+                                       printf("%llx: %s", (Llong)orig_file_addr, lbuffer);
+                               } else {
+                                       printf("%lx: %s", (long)orig_file_addr, lbuffer);
+                               }
+                       }
+
+
+
+                       if (rflag && (idr->flags[0] & 2))
+                               check_tree((off_t)(isonum_733(idr->extent) + isonum_711((char *)idr->ext_attr_length)) * blocksize,
+                                               isonum_733(idr->size),
+                                               orig_file_addr * blocksize);
+                       i += buffer[i];
+                       i1++;
+                       if (i > 2048 - offsetof(struct iso_directory_record, name[0]))
+                               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;
+};
+
+static void
+check_path_tables(int typel_extent, int typem_extent, int path_table_size)
+{
+       int     count;
+       int     j;
+       char    *pnt;
+       char    *typel;
+       char    *typem;
+
+       /* Now read in the path tables */
+
+       typel = (char *) malloc(ISO_ROUND_UP(path_table_size));
+#ifdef USE_SCG
+       readsecs(typel_extent * blocksize / 2048, typel, ISO_BLOCKS(path_table_size));
+#else
+       lseek(fileno(infile), (off_t)((off_t)typel_extent) * blocksize, SEEK_SET);
+       read(fileno(infile), typel, path_table_size); /* FIXME: check return value */
+#endif
+       typem = (char *) malloc(path_table_size);
+       lseek(fileno(infile), (off_t)((off_t)typem_extent) * blocksize, SEEK_SET);
+       read(fileno(infile), typem, path_table_size); /* FIXME: check return value */
+
+       j = path_table_size;
+       pnt = typel;
+       count = 1;
+       while (j) {
+               int     namelen;
+               int     extent;
+               int     idx;
+               char    name[32];
+
+               namelen = *pnt++; pnt++;
+               extent = isonum_731(pnt);
+               pnt += 4;
+               idx = 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++, idx, extent, name);
+       }
+
+       j = path_table_size;
+       pnt = typem;
+       count = 1;
+
+       while (j) {
+               int     namelen;
+               int     extent;
+               int     idx;
+               char    name[32];
+
+               namelen = *pnt++; pnt++;
+               extent = isonum_732(pnt);
+               pnt += 4;
+               idx = 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++, idx, extent, name);
+       }
+}
+
+static void
+usage(int excode)
+{
+       errmsgno(EX_BAD, "Usage: %s [options] image\n",
+                                               get_progname());
+
+       fprintf(stderr, "Options:\n");
+       fprintf(stderr, "\t-help, -h    Print this help\n");
+       fprintf(stderr, "\t-version     Print version info and exit\n");
+       fprintf(stderr, "\t-i filename  Filename to read ISO-9660 image from\n");
+       fprintf(stderr, "\tdev=target   SCSI target to use as CD/DVD-Recorder\n");
+       fprintf(stderr, "\nIf neither -i nor dev= are speficied, <image> is needed.\n");
+       exit(excode);
+}
+
+int
+main(int argc, char *argv[])
+{
+       int     cac;
+       char    * const *cav;
+       char    *opts = "help,h,version,i*,dev*";
+       BOOL    help = FALSE;
+       BOOL    prvers = FALSE;
+       char    *filename = NULL;
+       char    *devname = NULL;
+       off_t   file_addr;
+       int     file_size;
+       struct iso_primary_descriptor   ipd;
+       struct iso_directory_record     *idr;
+       int     typel_extent;
+       int     typem_extent;
+       int     path_table_size;
+
+       save_args(argc, argv);
+
+       cac = argc - 1;
+       cav = argv + 1;
+       if (getallargs(&cac, &cav, opts, &help, &help, &prvers,
+                       &filename, &devname) < 0) {
+               errmsgno(EX_BAD, "Bad Option: '%s'\n", cav[0]);
+               usage(EX_BAD);
+       }
+       if (help)
+               usage(0);
+       if (prvers) {
+               printf("isovfy %s (%s)\n", CDRKIT_VERSION, HOST_SYSTEM);
+               exit(0);
+       }
+       cac = argc - 1;
+       cav = argv + 1;
+       if (filename == NULL && devname == NULL) {
+               if (getfiles(&cac, &cav, opts) != 0) {
+                       filename = cav[0];
+                       cac--, cav++;
+               }
+       }
+       if (getfiles(&cac, &cav, opts) != 0) {
+               errmsgno(EX_BAD, "Bad Argument: '%s'\n", cav[0]);
+               usage(EX_BAD);
+       }
+       if (filename != NULL && devname != NULL) {
+               errmsgno(EX_BAD, "Only one of -i or dev= allowed\n");
+               usage(EX_BAD);
+       }
+#ifdef USE_SCG
+       if (filename == NULL && devname == NULL)
+               cdr_defaults(&devname, NULL, NULL, NULL);
+#endif
+       if (filename == NULL && devname == NULL) {
+#ifdef USE_LIBSCHILY
+               errmsgno(EX_BAD, "ISO-9660 image not specified\n");
+#else
+               fprintf(stderr, "ISO-9660 image not specified\n");
+#endif
+               usage(EX_BAD);
+       }
+
+       if (filename != NULL)
+               infile = fopen(filename, "rb");
+       else
+               filename = devname;
+
+       if (infile != NULL) {
+               /* EMPTY */;
+#ifdef USE_SCG
+       } else if (scsidev_open(filename) < 0) {
+#else
+       } else {
+#endif
+#ifdef USE_LIBSCHILY
+               comerr("Cannot open '%s'\n", filename);
+#else
+               fprintf(stderr, "Cannot open '%s'\n", filename);
+               exit(1);
+#endif
+       }
+
+
+       file_addr = (off_t)32768;
+#ifdef USE_SCG
+       readsecs(file_addr / 2048, &ipd, ISO_BLOCKS(sizeof (ipd)));
+#else
+       lseek(fileno(infile), file_addr, SEEK_SET);
+       read(fileno(infile), &ipd, sizeof (ipd));
+#endif
+
+       idr = (struct iso_directory_record *)ipd.root_directory_record;
+
+       blocksize = isonum_723((char *)ipd.logical_block_size);
+       if (blocksize != 512 && blocksize != 1024 && blocksize != 2048) {
+               blocksize = 2048;
+       }
+
+       file_addr = (off_t)isonum_733(idr->extent) + isonum_711((char *)idr->ext_attr_length);
+       file_size = isonum_733(idr->size);
+
+       if (sizeof (file_addr) > sizeof (long)) {
+               printf("Root at extent %llx, %d bytes\n", (Llong)file_addr, file_size);
+       } else {
+               printf("Root at extent %lx, %d bytes\n", (long)file_addr, file_size);
+       }
+       file_addr = file_addr * blocksize;
+
+       check_tree(file_addr, file_size, file_addr);
+
+       typel_extent = isonum_731((char *)ipd.type_l_path_table);
+       typem_extent = isonum_732((char *)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
+
+       if (infile != NULL)
+               fclose(infile);
+
+       if (!ngoof)
+               printf("No errors found\n");
+       return (0);
+}
diff --git a/genisoimage/diskmbr.h b/genisoimage/diskmbr.h
new file mode 100644 (file)
index 0000000..84501bd
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)diskmbr.h       1.2 04/03/02 Copyright 1999-2004 J. Schilling */
+/*
+ *     Header file diskmbr.h - assorted structure definitions and macros
+ *     describing standard PC partition table
+ *
+ *     Copyright (c) 1999-2004 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _DISKMBR_H
+#define        _DISKMBR_H
+
+#define        MBR_MAGIC               0xAA55
+
+#define        PARTITION_UNUSED        0x00
+#define        PARTITION_ACTIVE        0x80
+
+#define        PARTITION_COUNT         4
+
+#define        MBR_SECTOR(x)           ((x)&0x3F)
+#define        MBR_CYLINDER(x)         ((x)>>8|((x)<<2&0x300))
+
+struct disk_partition {
+       unsigned char   status;
+       unsigned char   s_head;
+       unsigned char   s_cyl_sec[2];
+       unsigned char   type;
+       unsigned char   e_head;
+       unsigned char   e_cyl_sec[2];
+       unsigned char   boot_sec[4];
+       unsigned char   size[4];
+};
+
+struct disk_master_boot_record {
+       char                    pad[0x1BE];
+       struct disk_partition   partition[PARTITION_COUNT];
+       unsigned char           magic[2];
+};
+
+#endif /* _DISKMBR_H */
diff --git a/genisoimage/dvd_file.c b/genisoimage/dvd_file.c
new file mode 100644 (file)
index 0000000..ffd4ef1
--- /dev/null
@@ -0,0 +1,771 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)dvd_file.c      1.3 04/03/04 joerg */
+/*
+ * DVD_VIDEO code
+ *  Copyright (c) 2002 Olaf Beck - olaf_sc@yahoo.com
+ *                     Jörg Schilling <schilling@fokus.gmd.de>
+ *                     (making the code portable)
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef DVD_VIDEO
+
+#include <mconfig.h>
+#include "genisoimage.h"
+#include <schily.h>
+#include "dvd_reader.h"
+#include "dvd_file.h"
+#include "ifo_read.h"
+
+static void    bsort(int sector[], int title[], int size);
+static void    uniq(int sector[], int title[], int title_sets_array[],
+                                                 int sector_sets_array[], int titles);
+static void    DVDFreeFileSetArrays(int *sector, int *title, 
+                                                                                               int *title_sets_array, 
+                                                                                               int *sector_sets_array);
+void   DVDFreeFileSet(title_set_info_t *title_set_info);
+title_set_info_t *DVDGetFileSet(char *dvd);
+int    DVDGetFilePad(title_set_info_t *title_set_info, char *name);
+
+
+static void
+bsort(int sector[], int title[], int size)
+{
+       int     temp_title;
+       int     temp_sector;
+       int     i;
+       int     j;
+
+  /* this is not bubble sort, this is primitive selection sort. Replace with
+   * bubble sort later, maybe bidirectional, aka Coctail Sort */
+       for (i = 0; i < size; i++) {
+               for (j = 0; j < size; j++) {
+                       if (sector[i] < sector[j]) {
+                               temp_sector = sector[i];
+                               temp_title = title[i];
+                               sector[i] = sector[j];
+                               title[i] = title[j];
+                               sector[j] = temp_sector;
+                               title[j] = temp_title;
+                       }
+               }
+       }
+}
+
+
+static void
+uniq(int sector[], int title[], int title_sets_array[], 
+         int sector_sets_array[], int titles)
+{
+       int     i;
+       int     j;
+
+
+       for (i = 0, j = 0; j < titles; ) {
+               if (sector[j] != sector[j+1]) {
+                       title_sets_array[i]  = title[j];
+                       sector_sets_array[i] = sector[j];
+#ifdef DEBUG
+                       fprintf(stderr, "Sector offset is %d\n", sector_sets_array[i]);
+#endif
+                       i++;
+                       j++;
+               } else {
+                       do {
+                               if (j < titles)
+                                       j++;
+
+                       } while (sector[j] == sector[j+1]);
+
+               }
+       }
+
+}
+
+static void
+DVDFreeFileSetArrays(int *sector, int *title, int *title_sets_array, 
+                                                       int *sector_sets_array)
+{
+       free(sector);
+       free(title);
+       free(title_sets_array);
+       free(sector_sets_array);
+}
+
+void
+DVDFreeFileSet(title_set_info_t *title_set_info)
+{
+       free(title_set_info->title_set);
+       free(title_set_info);
+}
+
+title_set_info_t *
+DVDGetFileSet(char *dvd)
+{
+       /*
+        * TODO  Fix close of files if
+        *      we error out
+        *      We also assume that all
+        *      DVD files are of valid
+        *      size i.e. file%2048 == 0
+        */
+
+       /* title interation */
+       int             title_sets;
+       int             titles;
+       int             counter;
+       int             i;
+
+       /* DVD file structures */
+       dvd_reader_t *  _dvd = NULL;
+
+       ifo_handle_t *  vmg_ifo = NULL;
+       ifo_handle_t *  vts_ifo = NULL;
+
+       dvd_file_t   *  vmg_vob_file = NULL;
+       dvd_file_t   *  vmg_ifo_file = NULL;
+
+       dvd_file_t   *  vts_ifo_file = NULL;
+       dvd_file_t   *  vts_menu_file = NULL;
+       dvd_file_t   *  vts_title_file = NULL;
+
+       /* The sizes it self of each file */
+       int             ifo;
+       int             bup;
+       int             menu_vob;
+       int             title_vob;
+
+       /* Arrays keeping the title - filset relationship */
+       int             * sector;
+       int             * title;
+       int             * title_sets_array;
+       int             * sector_sets_array;
+
+       /* DVD Video files */
+       struct stat     fileinfo;
+       char            temppoint[PATH_MAX + 1];
+
+       /* The Title Set Info struct*/
+       title_set_info_t * title_set_info;
+
+       /* Temporary mount point - to be used later */
+       char            mountpoint[PATH_MAX + 1];
+
+       strncpy(mountpoint, dvd, sizeof (mountpoint));
+       mountpoint[sizeof (mountpoint)-1] = '\0';
+
+
+       _dvd = DVDOpen(dvd);
+       if (!_dvd) {
+#ifdef USE_LIBSCHILY
+               errmsgno(EX_BAD, "Can't open device '%s'\n", dvd);
+#else
+               fprintf(stderr, "Can't open device\n");
+#endif
+               return (0);
+       }
+       vmg_ifo = ifoOpen(_dvd, 0);
+       if (!vmg_ifo) {
+#ifdef USE_LIBSCHILY
+               errmsgno(EX_BAD, "Can't open VMG info for '%s'.\n", dvd);
+#else
+               fprintf(stderr, "Can't open VMG info.\n");
+#endif
+               return (0);
+       }
+
+       /* Check mount point */
+
+       snprintf(temppoint, sizeof (temppoint),
+                               "%s/VIDEO_TS/VIDEO_TS.IFO", mountpoint);
+
+
+       if (stat(temppoint, &fileinfo) < 0) {
+               /* If we can't stat the file, give up */
+#ifdef USE_LIBSCHILY
+               errmsg("Can't stat %s\n", temppoint);
+#else
+               fprintf(stderr, "Can't stat %s\n", temppoint);
+               perror("");
+#endif
+               return (0);
+       }
+
+
+
+       title_sets = vmg_ifo->vmgi_mat->vmg_nr_of_title_sets;
+       titles = vmg_ifo->tt_srpt->nr_of_srpts;
+
+       sector = e_malloc(titles * sizeof (int));
+       memset(sector, 0, titles * sizeof (int));
+       title = e_malloc(titles * sizeof (int));
+       title_sets_array = e_malloc(title_sets * sizeof (int));
+       sector_sets_array = e_malloc(title_sets * sizeof (int));
+       title_set_info = (title_set_info_t *)e_malloc(sizeof (title_set_info_t));
+       title_set_info->title_set = (title_set_t *)e_malloc((title_sets + 1) *
+                                                       sizeof (title_set_t));
+
+       title_set_info->num_titles = title_sets;
+
+
+       /* Fill and sort the arrays for titles*/
+
+       if (titles >= 1) {
+               for (counter = 0; counter < titles; counter++) {
+                       sector[counter] = vmg_ifo->tt_srpt->title[counter].title_set_sector;
+                       title[counter]  = counter + 1;
+               }
+       }
+
+       /* Yes, we should probably do a better sort than B - but what the heck*/
+       bsort(sector, title, titles);
+
+
+       /*
+        * Since title sets and titles are not the same we will need to sort
+        * out "bogus" titles
+        */
+
+       uniq(sector, title, title_sets_array, sector_sets_array, titles);
+
+
+       /* Open VIDEO_TS.VOB is present */
+
+       vmg_vob_file = DVDOpenFile(_dvd, 0, DVD_READ_MENU_VOBS);
+
+       /* Check VIDEO_TS title set */
+
+       vmg_ifo_file = DVDOpenFile(_dvd, 0, DVD_READ_INFO_FILE);
+
+       if ((vmg_vob_file == 0) && vmg_ifo->vmgi_mat->vmg_last_sector + 1
+                       < 2 * DVDFileSize(vmg_ifo_file)) {
+#ifdef USE_LIBSCHILY
+               errmsgno(EX_BAD, "IFO is not of correct size aborting\n");
+#else
+               fprintf(stderr, "IFO is not of correct size aborting\n");
+#endif
+               DVDFreeFileSetArrays(sector, title, title_sets_array,
+                                       sector_sets_array);
+               DVDFreeFileSet(title_set_info);
+               return (0);
+       } else if ((vmg_vob_file != 0) && (vmg_ifo->vmgi_mat->vmg_last_sector
+                   + 1  < 2 * DVDFileSize(vmg_ifo_file) +
+                   DVDFileSize(vmg_vob_file))) {
+#ifdef USE_LIBSCHILY
+               errmsgno(EX_BAD, "Either VIDEO_TS.IFO or VIDEO_TS.VOB is not of correct size");
+#else
+               fprintf(stderr, "Either VIDEO_TS.IFO or VIDEO_TS.VOB is not of correct size");
+#endif
+               DVDFreeFileSetArrays(sector, title, title_sets_array,
+                                       sector_sets_array);
+               DVDFreeFileSet(title_set_info);
+               return (0);
+       }
+
+       /* Find the actuall right size of VIDEO_TS.IFO */
+       if (vmg_vob_file == 0) {
+               if (vmg_ifo->vmgi_mat->vmg_last_sector + 1 > 2
+                               *  DVDFileSize(vmg_ifo_file)) {
+                       ifo = vmg_ifo->vmgi_mat->vmg_last_sector
+                               - DVDFileSize(vmg_ifo_file) + 1;
+               } else {
+                       ifo = vmg_ifo->vmgi_mat->vmgi_last_sector + 1;
+               }
+       } else {
+               if (vmg_ifo->vmgi_mat->vmgi_last_sector + 1
+                               < vmg_ifo->vmgi_mat->vmgm_vobs) {
+                       ifo = vmg_ifo->vmgi_mat->vmgm_vobs;
+               } else {
+                       ifo = vmg_ifo->vmgi_mat->vmgi_last_sector + 1;
+               }
+       }
+
+       title_set_info->title_set[0].size_ifo = ifo * 2048;
+       title_set_info->title_set[0].realsize_ifo = fileinfo.st_size;
+       title_set_info->title_set[0].pad_ifo = ifo - DVDFileSize(vmg_ifo_file);
+
+       /* Find the actuall right size of VIDEO_TS.VOB */
+       if (vmg_vob_file != 0) {
+               if (ifo + DVDFileSize(vmg_ifo_file) +
+                   DVDFileSize(vmg_vob_file) - 1 <
+                   vmg_ifo->vmgi_mat->vmg_last_sector) {
+                               menu_vob = vmg_ifo->vmgi_mat->vmg_last_sector -
+                                               ifo - DVDFileSize(vmg_ifo_file) + 1;
+               } else {
+                       menu_vob = vmg_ifo->vmgi_mat->vmg_last_sector
+                       - ifo - DVDFileSize(vmg_ifo_file) + 1;
+               }
+
+               snprintf(temppoint, sizeof (temppoint),
+                               "%s/VIDEO_TS/VIDEO_TS.VOB", mountpoint);
+               if (stat(temppoint, &fileinfo) < 0) {
+#ifdef USE_LIBSCHILY
+                       errmsg("calc: Can't stat %s\n", temppoint);
+#else
+                       fprintf(stderr, "calc: Can't stat %s\n", temppoint);
+                       perror("");
+#endif
+                       DVDFreeFileSetArrays(sector, title, title_sets_array,
+                                               sector_sets_array);
+                       DVDFreeFileSet(title_set_info);
+                       return (0);
+               }
+
+               title_set_info->title_set[0].realsize_menu = fileinfo.st_size;
+               title_set_info->title_set[0].pad_menu = menu_vob -
+                                               DVDFileSize(vmg_vob_file);
+               title_set_info->title_set[0].size_menu = menu_vob * 2048;
+               DVDCloseFile(vmg_vob_file);
+       } else {
+               title_set_info->title_set[0].size_menu = 0;
+               title_set_info->title_set[0].realsize_menu = 0;
+               title_set_info->title_set[0].pad_menu = 0;
+               menu_vob = 0;
+       }
+
+
+       /* Finding the actuall right size of VIDEO_TS.BUP */
+       if (title_sets >= 1) {
+               bup = sector_sets_array[0] - menu_vob - ifo;
+       } else {
+               /* Just in case we burn a DVD-Video without any title_sets */
+               bup = vmg_ifo->vmgi_mat->vmg_last_sector + 1 - menu_vob - ifo;
+       }
+
+       /* Never trust the BUP file - use a copy of the IFO */
+       snprintf(temppoint, sizeof (temppoint),
+                               "%s/VIDEO_TS/VIDEO_TS.IFO", mountpoint);
+
+       if (stat(temppoint, &fileinfo) < 0) {
+#ifdef USE_LIBSCHILY
+               errmsg("calc: Can't stat %s\n", temppoint);
+#else
+               fprintf(stderr, "calc: Can't stat %s\n", temppoint);
+               perror("");
+#endif
+               DVDFreeFileSetArrays(sector, title, title_sets_array,
+                                       sector_sets_array);
+               DVDFreeFileSet(title_set_info);
+               return (0);
+       }
+
+       title_set_info->title_set[0].realsize_bup = fileinfo.st_size;
+       title_set_info->title_set[0].size_bup = bup * 2048;
+       title_set_info->title_set[0].pad_bup = bup - DVDFileSize(vmg_ifo_file);
+
+       /* Take care of the titles which we don't have in VMG */
+
+       title_set_info->title_set[0].number_of_vob_files = 0;
+       title_set_info->title_set[0].realsize_vob[0] = 0;
+       title_set_info->title_set[0].pad_title = 0;
+
+       DVDCloseFile(vmg_ifo_file);
+
+       if (title_sets >= 1) {
+               for (counter = 0; counter < title_sets; counter++) {
+
+                       vts_ifo = ifoOpen(_dvd, counter + 1);
+
+                       if (!vts_ifo) {
+#ifdef USE_LIBSCHILY
+                               errmsgno(EX_BAD, "Can't open VTS info.\n");
+#else
+                               fprintf(stderr, "Can't open VTS info.\n");
+#endif
+                               DVDFreeFileSetArrays(sector, title,
+                                       title_sets_array, sector_sets_array);
+                               DVDFreeFileSet(title_set_info);
+                               return (0);
+                       }
+
+                       snprintf(temppoint, sizeof (temppoint),
+                               "%s/VIDEO_TS/VTS_%02i_0.IFO",
+                               mountpoint, counter + 1);
+
+                       if (stat(temppoint, &fileinfo) < 0) {
+#ifdef USE_LIBSCHILY
+                               errmsg("calc: Can't stat %s\n", temppoint);
+#else
+                               fprintf(stderr, "calc: Can't stat %s\n",
+                                       temppoint);
+                               perror("");
+#endif
+                               DVDFreeFileSetArrays(sector, title,
+                                       title_sets_array, sector_sets_array);
+                               DVDFreeFileSet(title_set_info);
+                               return (0);
+                       }
+
+
+                       /* Test if VTS_XX_0.VOB is present */
+
+                       vts_menu_file = DVDOpenFile(_dvd, counter + 1,
+                                       DVD_READ_MENU_VOBS);
+
+                       /* Test if VTS_XX_X.VOB are present */
+
+                       vts_title_file = DVDOpenFile(_dvd, counter + 1,
+                                               DVD_READ_TITLE_VOBS);
+
+                       /* Check VIDEO_TS.IFO */
+
+                       vts_ifo_file = DVDOpenFile(_dvd, counter + 1,
+                                                       DVD_READ_INFO_FILE);
+
+                       /*
+                        * Checking that title will fit in the
+                        * space given by the ifo file
+                        */
+
+
+                       if (vts_ifo->vtsi_mat->vts_last_sector + 1
+                               < 2 * DVDFileSize(vts_ifo_file)) {
+#ifdef USE_LIBSCHILY
+                               errmsgno(EX_BAD, "IFO is not of correct size aborting.\n");
+#else
+                               fprintf(stderr, "IFO is not of correct size aborting\n");
+#endif
+                               DVDFreeFileSetArrays(sector, title,
+                                       title_sets_array, sector_sets_array);
+                               DVDFreeFileSet(title_set_info);
+                               return (0);
+                       } else if ((vts_title_file != 0) &&
+                                   (vts_menu_file != 0) &&
+                                   (vts_ifo->vtsi_mat->vts_last_sector + 1
+                                   < 2 * DVDFileSize(vts_ifo_file) +
+                                   DVDFileSize(vts_title_file) +
+                                   DVDFileSize(vts_menu_file))) {
+#ifdef USE_LIBSCHILY
+                               errmsgno(EX_BAD, "Either VIDEO_TS.IFO or VIDEO_TS.VOB is not of correct size.\n");
+#else
+                               fprintf(stderr, "Either VIDEO_TS.IFO or VIDEO_TS.VOB is not of correct size");
+#endif
+                               DVDFreeFileSetArrays(sector, title,
+                                       title_sets_array, sector_sets_array);
+                               DVDFreeFileSet(title_set_info);
+                               return (0);
+                       } else if ((vts_title_file != 0) &&
+                                   (vts_menu_file == 0) &&
+                                   (vts_ifo->vtsi_mat->vts_last_sector + 1
+                                   < 2 * DVDFileSize(vts_ifo_file) +
+                                   DVDFileSize(vts_title_file))) {
+#ifdef USE_LIBSCHILY
+                               errmsgno(EX_BAD, "Either VIDEO_TS.IFO or VIDEO_TS.VOB is not of correct size.\n");
+#else
+                               fprintf(stderr, "Either VIDEO_TS.IFO or VIDEO_TS.VOB is not of correct size");
+#endif
+                               DVDFreeFileSetArrays(sector, title,
+                                       title_sets_array, sector_sets_array);
+                               DVDFreeFileSet(title_set_info);
+                               return (0);
+                       } else if ((vts_menu_file != 0) &&
+                                   (vts_title_file == 0) &&
+                                   (vts_ifo->vtsi_mat->vts_last_sector + 1
+                                   < 2 * DVDFileSize(vts_ifo_file) +
+                                   DVDFileSize(vts_menu_file))) {
+#ifdef USE_LIBSCHILY
+                               errmsgno(EX_BAD, "Either VIDEO_TS.IFO or VIDEO_TS.VOB is not of correct size.\n");
+#else
+                               fprintf(stderr, "Either VIDEO_TS.IFO or VIDEO_TS.VOB is not of correct size");
+#endif
+                               DVDFreeFileSetArrays(sector, title,
+                                       title_sets_array, sector_sets_array);
+                               DVDFreeFileSet(title_set_info);
+                               return (0);
+                       }
+
+
+                       /* Find the actuall right size of VTS_XX_0.IFO */
+                       if ((vts_title_file == 0) && (vts_menu_file == 0)) {
+                               if (vts_ifo->vtsi_mat->vts_last_sector + 1 >
+                                   2 * DVDFileSize(vts_ifo_file)) {
+                                       ifo = vts_ifo->vtsi_mat->vts_last_sector
+                                               - DVDFileSize(vts_ifo_file) + 1;
+                               } else {
+                                       ifo = vts_ifo->vtsi_mat->vts_last_sector
+                                               - DVDFileSize(vts_ifo_file) + 1;
+                               }
+                       } else if (vts_title_file == 0) {
+                               if (vts_ifo->vtsi_mat->vtsi_last_sector + 1 <
+                                   vts_ifo->vtsi_mat->vtstt_vobs) {
+                                       ifo = vmg_ifo->vtsi_mat->vtstt_vobs;
+                               } else {
+                                       ifo = vmg_ifo->vtsi_mat->vtstt_vobs;
+                               }
+                       } else {
+                               if (vts_ifo->vtsi_mat->vtsi_last_sector + 1 <
+                                   vts_ifo->vtsi_mat->vtsm_vobs) {
+                                       ifo = vts_ifo->vtsi_mat->vtsm_vobs;
+                               } else {
+                                       ifo = vts_ifo->vtsi_mat->vtsi_last_sector + 1;
+                               }
+                       }
+                       title_set_info->title_set[counter + 1].size_ifo =
+                                               ifo * 2048;
+                       title_set_info->title_set[counter + 1].realsize_ifo =
+                                               fileinfo.st_size;
+                       title_set_info->title_set[counter + 1].pad_ifo =
+                                               ifo - DVDFileSize(vts_ifo_file);
+
+
+                       /* Find the actuall right size of VTS_XX_0.VOB */
+                       if (vts_menu_file != 0) {
+                               if (vts_ifo->vtsi_mat->vtsm_vobs == 0)  {
+                                       /*
+                                        * Apparently start sector 0 means that
+                                        * VTS_XX_0.VOB is empty after all...
+                                        */
+                                       menu_vob = 0;
+                                       if (DVDFileSize(vts_menu_file) != 0) {
+                                               /*
+                                                * Paranoia: we most likely never
+                                                * come here...
+                                                */
+#ifdef USE_LIBSCHILY
+                                               errmsgno(EX_BAD,
+                                                       "%s/VIDEO_TS/VTS_%02i_0.IFO appears to be corrupted.\n",
+                                                       mountpoint, counter+1);
+#else
+                                               fprintf(stderr,
+                                                       "%s/VIDEO_TS/VTS_%02i_0.IFO appears to be corrupted.\n",
+                                                       mountpoint, counter+1);
+#endif
+                                               return (0);
+                                       }
+                               } else if ((vts_title_file != 0) &&
+                                       (vts_ifo->vtsi_mat->vtstt_vobs -
+                                       vts_ifo->vtsi_mat->vtsm_vobs >
+                                               DVDFileSize(vts_menu_file))) {
+                                       menu_vob = vts_ifo->vtsi_mat->vtstt_vobs -
+                                                       vts_ifo->vtsi_mat->vtsm_vobs;
+                               } else if ((vts_title_file == 0) &&
+                                           (vts_ifo->vtsi_mat->vtsm_vobs +
+                                           DVDFileSize(vts_menu_file) +
+                                           DVDFileSize(vts_ifo_file) - 1 <
+                                           vts_ifo->vtsi_mat->vts_last_sector)) {
+                                       menu_vob = vts_ifo->vtsi_mat->vts_last_sector
+                                               - DVDFileSize(vts_ifo_file)
+                                               - vts_ifo->vtsi_mat->vtsm_vobs + 1;
+                               } else {
+                                       menu_vob = vts_ifo->vtsi_mat->vtstt_vobs -
+                                                       vts_ifo->vtsi_mat->vtsm_vobs;
+                               }
+
+                               snprintf(temppoint, sizeof (temppoint),
+                                       "%s/VIDEO_TS/VTS_%02i_0.VOB", mountpoint, counter + 1);
+
+                               if (stat(temppoint, &fileinfo)  < 0) {
+#ifdef USE_LIBSCHILY
+                                       errmsg("calc: Can't stat %s\n", temppoint);
+#else
+                                       fprintf(stderr, "calc: Can't stat %s\n",
+                                               temppoint);
+                                       perror("");
+#endif
+                                       DVDFreeFileSetArrays(sector, title,
+                                               title_sets_array, sector_sets_array);
+                                       DVDFreeFileSet(title_set_info);
+                                       return (0);
+                               }
+
+                               title_set_info->title_set[counter + 1].realsize_menu = fileinfo.st_size;
+                               title_set_info->title_set[counter + 1].size_menu = menu_vob * 2048;
+                               title_set_info->title_set[counter + 1].pad_menu = menu_vob - DVDFileSize(vts_menu_file);
+
+                       } else {
+                               title_set_info->title_set[counter + 1].size_menu = 0;
+                               title_set_info->title_set[counter + 1].realsize_menu = 0;
+                               title_set_info->title_set[counter + 1].pad_menu = 0;
+                               menu_vob = 0;
+                       }
+
+
+                       /* Find the actuall total size of VTS_XX_[1 to 9].VOB */
+
+                       if (vts_title_file != 0) {
+                               if (ifo + menu_vob + DVDFileSize(vts_ifo_file) -
+                                   1 < vts_ifo->vtsi_mat->vts_last_sector) {
+                                   title_vob = vts_ifo->vtsi_mat->vts_last_sector
+                                               + 1 - ifo - menu_vob -
+                                               DVDFileSize(vts_ifo_file);
+                               } else {
+                                       title_vob = vts_ifo->vtsi_mat->vts_last_sector +
+                                               1 - ifo - menu_vob -
+                                               DVDFileSize(vts_ifo_file);
+                               }
+                               /*
+                                * Find out how many vob files
+                                * and the size of them
+                                */
+                               for (i = 0; i < 9; ++i) {
+                                       snprintf(temppoint, sizeof (temppoint),
+                                               "%s/VIDEO_TS/VTS_%02i_%i.VOB",
+                                               mountpoint, counter + 1, i + 1);
+                                       if (stat(temppoint, &fileinfo) < 0) {
+                                               break;
+                                       }
+                                       title_set_info->title_set[counter + 1].realsize_vob[i] = fileinfo.st_size;
+                               }
+                               title_set_info->title_set[counter + 1].number_of_vob_files = i;
+                               title_set_info->title_set[counter + 1].size_title = title_vob * 2048;
+                               title_set_info->title_set[counter + 1].pad_title = title_vob - DVDFileSize(vts_title_file);
+                       } else {
+                               title_set_info->title_set[counter + 1].number_of_vob_files = 0;
+                               title_set_info->title_set[counter + 1].realsize_vob[0] = 0;
+                               title_set_info->title_set[counter + 1].size_title = 0;
+                               title_set_info->title_set[counter + 1].pad_title = 0;
+                               title_vob = 0;
+
+                       }
+
+
+                       /* Find the actuall total size of VTS_XX_0.BUP */
+                       if (title_sets - 1 > counter) {
+                               bup = sector_sets_array[counter+1]
+                                       - sector_sets_array[counter]
+                                       - title_vob - menu_vob - ifo;
+                       } else {
+                               bup = vts_ifo->vtsi_mat->vts_last_sector + 1
+                                       - title_vob - menu_vob - ifo;
+                       }
+
+                       /* Never trust the BUP use a copy of the IFO */
+                       snprintf(temppoint, sizeof (temppoint),
+                               "%s/VIDEO_TS/VTS_%02i_0.IFO",
+                               mountpoint, counter + 1);
+
+                       if (stat(temppoint, &fileinfo) < 0) {
+#ifdef USE_LIBSCHILY
+                               errmsg("calc: Can't stat %s\n", temppoint);
+#else
+                               fprintf(stderr, "calc: Can't stat %s\n",
+                                       temppoint);
+                               perror("");
+#endif
+                               DVDFreeFileSetArrays(sector, title,
+                                       title_sets_array, sector_sets_array);
+                               DVDFreeFileSet(title_set_info);
+                               return (0);
+                       }
+
+                       title_set_info->title_set[counter + 1].size_bup =
+                                               bup * 2048;
+                       title_set_info->title_set[counter + 1].realsize_bup =
+                                               fileinfo.st_size;
+                       title_set_info->title_set[counter + 1].pad_bup =
+                                               bup - DVDFileSize(vts_ifo_file);
+
+
+                       /* Closing files */
+
+                       if (vts_menu_file != 0) {
+                               DVDCloseFile(vts_menu_file);
+                       }
+
+                       if (vts_title_file != 0) {
+                               DVDCloseFile(vts_title_file);
+                       }
+
+
+                       if (vts_ifo_file != 0) {
+                               DVDCloseFile(vts_ifo_file);
+                       }
+
+                       ifoClose(vts_ifo);
+
+               }
+
+       }
+
+       DVDFreeFileSetArrays(sector, title, title_sets_array, sector_sets_array);
+
+       /* Close the VMG ifo file we got all the info we need */
+       ifoClose(vmg_ifo);
+
+
+       /* Close the DVD */
+       DVDClose(_dvd);
+
+       /* Return the actuall info*/
+       return (title_set_info);
+
+
+}
+
+int
+DVDGetFilePad(title_set_info_t *title_set_info, char *name)
+{
+       char    title_a[3];
+       char    vob_a[2];
+       int     title;
+       int     vob;
+
+       title_a[0] = title_a[1] = title_a[2] = '\0';
+       vob_a[0] = vob_a[1] = '\0';
+
+       if (name[0] != 'V') {
+               return (0);
+       }
+       if (memcmp(name, "VIDEO_TS", 8) == 0) {
+               if (strstr(name, ".IFO") != 0) {
+                       return (title_set_info->title_set[0].pad_ifo);
+               } else if (strstr(name, ".VOB") != 0) {
+                       return (title_set_info->title_set[0].pad_menu);
+               } else if (strstr(name, ".BUP") != 0) {
+                       return (title_set_info->title_set[0].pad_bup);
+               } else {
+                       return (0);
+               }
+       } else if (memcmp(name, "VTS_", 4) == 0) {
+               title_a[0] = name[4];
+               title_a[1] = name[5];
+               title_a[2] = '\0';
+               vob_a[0] = name[7];
+               vob_a[1] = '\0';
+               title = atoi(title_a);
+               vob = atoi(vob_a);
+               if (title > title_set_info->num_titles) {
+                       return (0);
+               } else {
+                       if (strstr(name, ".IFO") != 0) {
+                               return (title_set_info->title_set[title].pad_ifo);
+                       } else if (strstr(name, ".BUP") != 0) {
+                               return (title_set_info->title_set[title].pad_bup);
+                       } else if (vob == 0) {
+                               return (title_set_info->title_set[title].pad_menu);
+                       } else if (vob == title_set_info->title_set[title].number_of_vob_files) {
+                               return (title_set_info->title_set[title].pad_title);
+                       } else {
+                               return (0);
+                       }
+               }
+       } else {
+               return (0);
+       }
+}
+
+#endif /*DVD_VIDEO*/
diff --git a/genisoimage/dvd_file.h b/genisoimage/dvd_file.h
new file mode 100644 (file)
index 0000000..234a1de
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)dvd_file.h      1.1 02/07/21 Copyright 2002 J. Schilling */
+/*
+ *     Defnitions for users of dvd_file.c
+ *
+ *     Copyright (c) 2002 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef        _DVD_FILE_H
+#define        _DVD_FILE_H
+
+extern void            DVDFreeFileSet(title_set_info_t *title_set_info);
+extern title_set_info_t *DVDGetFileSet(char *dvd);
+extern int             DVDGetFilePad(title_set_info_t *title_set_info, char *name);
+
+#endif /* _DVD_FILE_H */
diff --git a/genisoimage/dvd_reader.c b/genisoimage/dvd_reader.c
new file mode 100644 (file)
index 0000000..1a85abe
--- /dev/null
@@ -0,0 +1,295 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)dvd_reader.c    1.3 04/03/04 joerg */
+/*
+ * Copyright (C) 2001, 2002 Billy Biggs <vektor@dumbterm.net>,
+ *                          HÃ¥kan Hjort <d95hjort@dtek.chalmers.se>,
+ *                          Olaf Beck <olaf_sc@yahoo.com>
+ *                         (I only did the cut down no other contribs)
+ *                         Jörg Schilling <schilling@fokus.gmd.de>
+ *                         (making the code portable)
+ * 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 of the License, 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ * NOTE: This is a cut down version of libdvdread for genisoimage, due
+ * to portability issues with the current libdvdread according to
+ * the maintainer of genisoimage.
+ * This cut down version only reads from a harddisk file structure
+ * and it only implements the functions necessary inorder to make
+ * genisoimage produce valid DVD-Video images.
+ * DON'T USE THIS LIBRARY IN ANY OTHER PROGRAM GET THE REAL
+ * LIBDVDREAD INSTEAD
+ */
+#ifdef DVD_VIDEO
+
+#include "genisoimage.h"
+#include <fctldefs.h>
+#include <schily.h>
+
+#include "dvd_reader.h"
+
+struct dvd_file_s {
+       /* Basic information. */
+       dvd_reader_t    *dvd;
+
+       /* Calculated at open-time, size in blocks. */
+       ssize_t         filesize;
+};
+
+
+void           DVDCloseFile(dvd_file_t *dvd_file);
+static dvd_file_t *DVDOpenFilePath(dvd_reader_t *dvd, char *filename);
+static dvd_file_t *DVDOpenVOBPath(dvd_reader_t *dvd, int title, int menu);
+dvd_file_t *DVDOpenFile(dvd_reader_t *dvd, int titlenum, 
+                                                               dvd_read_domain_t domain);
+static dvd_reader_t *DVDOpenPath(const char *path_root);
+dvd_reader_t *DVDOpen(const char *path);
+void           DVDClose(dvd_reader_t *dvd);
+ssize_t                DVDFileSize(dvd_file_t *dvd_file);
+
+
+/*
+ * Free a DVD file
+ */
+void
+DVDCloseFile(dvd_file_t *dvd_file)
+{
+       free(dvd_file);
+       dvd_file = 0;
+}
+
+
+/*
+ * Stat a IFO or BUP file from a DVD directory tree.
+ */
+static dvd_file_t *
+DVDOpenFilePath(dvd_reader_t *dvd, char *filename)
+{
+
+       char            full_path[PATH_MAX + 1];
+       dvd_file_t      *dvd_file;
+       struct stat     fileinfo;
+
+       /* Get the full path of the file. */
+
+       snprintf(full_path, sizeof (full_path),
+                               "%s/%s", dvd->path_root, filename);
+
+
+       dvd_file = (dvd_file_t *) e_malloc(sizeof (dvd_file_t));
+       if (!dvd_file)
+               return (0);
+       dvd_file->dvd = dvd;
+       dvd_file->filesize = 0;
+
+       if (stat(full_path, &fileinfo) < 0) {
+               free(dvd_file);
+               return (0);
+       }
+       dvd_file->filesize = fileinfo.st_size / DVD_VIDEO_LB_LEN;
+
+       return (dvd_file);
+}
+
+
+/*
+ * Stat a VOB file from a DVD directory tree.
+ */
+static dvd_file_t *
+DVDOpenVOBPath(dvd_reader_t *dvd, int title, int menu)
+{
+
+       char            filename[PATH_MAX + 1];
+       struct stat     fileinfo;
+       dvd_file_t      *dvd_file;
+       int             i;
+
+       dvd_file = (dvd_file_t *) e_malloc(sizeof (dvd_file_t));
+       if (!dvd_file)
+               return (0);
+       dvd_file->dvd = dvd;
+       dvd_file->filesize = 0;
+
+       if (menu) {
+               if (title == 0) {
+                       snprintf(filename, sizeof (filename),
+                               "%s/VIDEO_TS/VIDEO_TS.VOB", dvd->path_root);
+               } else {
+                       snprintf(filename, sizeof (filename),
+                               "%s/VIDEO_TS/VTS_%02i_0.VOB", dvd->path_root, title);
+               }
+               if (stat(filename, &fileinfo) < 0) {
+                       free(dvd_file);
+                       return (0);
+               }
+               dvd_file->filesize = fileinfo.st_size / DVD_VIDEO_LB_LEN;
+       } else {
+               for (i = 0; i < 9; ++i) {
+
+                       snprintf(filename, sizeof (filename),
+                               "%s/VIDEO_TS/VTS_%02i_%i.VOB", dvd->path_root, title, i + 1);
+                       if (stat(filename, &fileinfo) < 0) {
+                                       break;
+                       }
+
+                       dvd_file->filesize += fileinfo.st_size / DVD_VIDEO_LB_LEN;
+               }
+       }
+
+       return (dvd_file);
+}
+
+/*
+ * Stat a DVD file from a DVD directory tree
+ */
+EXPORT dvd_file_t *
+DVDOpenFile(dvd_reader_t *dvd, int titlenum, dvd_read_domain_t domain)
+{
+       char            filename[MAX_UDF_FILE_NAME_LEN];
+
+       switch (domain) {
+
+       case DVD_READ_INFO_FILE:
+               if (titlenum == 0) {
+                       snprintf(filename, sizeof (filename),
+                                       "/VIDEO_TS/VIDEO_TS.IFO");
+               } else {
+                       snprintf(filename, sizeof (filename),
+                                       "/VIDEO_TS/VTS_%02i_0.IFO", titlenum);
+               }
+               break;
+
+       case DVD_READ_INFO_BACKUP_FILE:
+               if (titlenum == 0) {
+                       snprintf(filename, sizeof (filename),
+                                       "/VIDEO_TS/VIDEO_TS.BUP");
+               } else {
+                       snprintf(filename, sizeof (filename),
+                                       "/VIDEO_TS/VTS_%02i_0.BUP", titlenum);
+               }
+               break;
+
+       case DVD_READ_MENU_VOBS:
+               return (DVDOpenVOBPath(dvd, titlenum, 1));
+
+       case DVD_READ_TITLE_VOBS:
+               if (titlenum == 0)
+                       return (0);
+               return (DVDOpenVOBPath(dvd, titlenum, 0));
+
+       default:
+#ifdef USE_LIBSCHILY
+               errmsgno(EX_BAD, "Invalid domain for file open.\n");
+#else
+               fprintf(stderr, "Invalid domain for file open.\n");
+#endif
+               return (0);
+       }
+       return (DVDOpenFilePath(dvd, filename));
+}
+
+
+
+/*
+ * Stat a DVD directory structure
+ */
+static dvd_reader_t *
+DVDOpenPath(const char *path_root)
+{
+       dvd_reader_t    *dvd;
+
+       dvd = (dvd_reader_t *) e_malloc(sizeof (dvd_reader_t));
+       if (!dvd)
+               return (0);
+       dvd->path_root = strdup(path_root);
+
+       return (dvd);
+}
+
+
+/*
+ * Stat a DVD structure - this one only works with directory structures
+ */
+dvd_reader_t *
+DVDOpen(const char *path)
+{
+       struct stat     fileinfo;
+       int             ret;
+
+       if (!path)
+               return (0);
+
+       ret = stat(path, &fileinfo);
+       if (ret < 0) {
+       /* If we can't stat the file, give up */
+#ifdef USE_LIBSCHILY
+               errmsg("Can't stat %s\n", path);
+#else
+               fprintf(stderr, "Can't stat %s\n", path);
+               perror("");
+#endif
+               return (0);
+       }
+
+
+       if (S_ISDIR(fileinfo.st_mode)) {
+               return (DVDOpenPath(path));
+       }
+
+       /* If it's none of the above, screw it. */
+#ifdef USE_LIBSCHILY
+       errmsgno(EX_BAD, "Could not open %s\n", path);
+#else
+       fprintf(stderr, "Could not open %s\n", path);
+#endif
+       return (0);
+}
+
+/*
+ * Free a DVD structure - this one will only close a directory tree
+ */
+void
+DVDClose(dvd_reader_t *dvd)
+{
+       if (dvd) {
+               if (dvd->path_root) free(dvd->path_root);
+               free(dvd);
+               dvd = 0;
+       }
+}
+
+
+
+/*
+ * Return the size of a DVD file
+ */
+ssize_t
+DVDFileSize(dvd_file_t *dvd_file)
+{
+       return (dvd_file->filesize);
+}
+
+#endif /* DVD_VIDEO */
diff --git a/genisoimage/dvd_reader.h b/genisoimage/dvd_reader.h
new file mode 100644 (file)
index 0000000..1ec2648
--- /dev/null
@@ -0,0 +1,151 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)dvd_reader.h    1.2 04/03/02 joerg */
+
+#ifndef        _DVD_READER_H
+#define        _DVD_READER_H
+
+/*
+ * Copyright (C) 2001, 2002 Billy Biggs <vektor@dumbterm.net>,
+ *                         HÃ¥kan Hjort <d95hjort@dtek.chalmers.se
+ *                         Olaf Beck <olaf_sc@yahoo.com>
+ *                         (I only did the cut down no other contribs)
+ *                         Jörg Schilling <schilling@fokus.gmd.de>
+ *                         (making the code portable)
+ * 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 of the License, 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ * NOTE: This is a cut down version of libdvdread for genisoimage, due
+ * to portability issues with the current libdvdread according to
+ * the maintainer of genisoimage.
+ * This cut down version only reads from a harddisk file structure
+ * and it only implements the functions necessary inorder to make
+ * genisoimage produce valid DVD-Video images.
+ * DON'T USE THIS LIBRARY IN ANY OTHER PROGRAM GET THE REAL
+ * LIBDVDREAD INSTEAD
+ */
+
+
+#include <unixstd.h>   /* Make sure <sys/types.h> is included */
+
+/*
+ * Maximum length of filenames for UDF.
+ */
+#define        MAX_UDF_FILE_NAME_LEN 2048
+
+/*
+ * The length of one Logical Block of a DVD Video.
+ */
+#define        DVD_VIDEO_LB_LEN 2048
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+struct dvd_reader_s {
+       /* Information required for a directory path drive. */
+       char    *path_root;
+};
+
+
+typedef struct dvd_reader_s    dvd_reader_t;
+typedef struct dvd_file_s      dvd_file_t;
+
+
+/*
+ * dvd = DVDOpen(path);
+ * Opens a directory name of a DVD-Video structure on HD.
+ * Returns zero if it fails.
+ * The path should be like this
+ * "path/VIDEO_TS/VTS_01_1.VOB"
+ */
+
+
+extern dvd_reader_t *DVDOpen(const char *);
+
+
+/*
+ * DVDClose(dvd);
+ *
+ * Closes and cleans up the DVD reader object.  You must close all open files
+ * before calling this function.
+ */
+
+
+extern void DVDClose(dvd_reader_t *);
+
+/*
+ * INFO_FILE       : VIDEO_TS.IFO     (manager)
+ *                   VTS_XX_0.IFO     (title)
+ *
+ * INFO_BACKUP_FILE: VIDEO_TS.BUP     (manager)
+ *                   VTS_XX_0.BUP     (title)
+ *
+ * MENU_VOBS       : VIDEO_TS.VOB     (manager)
+ *                   VTS_XX_0.VOB     (title)
+ *
+ * TITLE_VOBS      : VTS_XX_[1-9].VOB (title)
+ *                   All files in the title set are opened and
+ *                   read as a single file.
+ */
+typedef enum {
+       DVD_READ_INFO_FILE,
+       DVD_READ_INFO_BACKUP_FILE,
+       DVD_READ_MENU_VOBS,
+       DVD_READ_TITLE_VOBS
+} dvd_read_domain_t;
+
+/*
+ * dvd_file = DVDOpenFile(dvd, titlenum, domain);
+ *
+ * Opens a file on the DVD given the title number and domain.  If the title
+ * number is 0, the video manager information is opened
+ * (VIDEO_TS.[IFO,BUP,VOB]).  Returns a file structure which may be used for
+ * reads, or 0 if the file was not found.
+ */
+extern dvd_file_t * DVDOpenFile(dvd_reader_t *, int, dvd_read_domain_t);
+
+/*
+ * DVDCloseFile(dvd_file);
+ *
+ * Closes a file and frees the associated structure.
+ */
+extern void DVDCloseFile(dvd_file_t *);
+
+
+/*
+ * blocks = DVDFileSize(dvd_file);
+ *
+ * Returns the file size in blocks.
+ */
+extern ssize_t DVDFileSize(dvd_file_t *);
+
+
+#ifdef __cplusplus
+};
+#endif
+#endif /* _DVD_READER_H */
diff --git a/genisoimage/eltorito.c b/genisoimage/eltorito.c
new file mode 100644 (file)
index 0000000..d52e17e
--- /dev/null
@@ -0,0 +1,716 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)eltorito.c      1.33 05/02/27 joerg */
+/*
+ * Program eltorito.c - Handle El Torito specific extensions to iso9660.
+ *
+ *
+ *  Written by Michael Fulbright <msf@redhat.com> (1996).
+ *
+ * Copyright 1996 RedHat Software, Incorporated
+ * Copyright (c) 1999-2004 J. Schilling
+ *
+ * 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 <mconfig.h>
+#include "genisoimage.h"
+#include <fctldefs.h>
+#include <utypes.h>
+#include <intcvt.h>
+#include "match.h"
+#include "diskmbr.h"
+#include "bootinfo.h"
+#include <schily.h>
+
+#undef MIN
+#define        MIN(a, b) (((a) < (b))? (a): (b))
+
+static struct eltorito_validation_entry valid_desc;
+static struct eltorito_boot_descriptor gboot_desc;
+static struct disk_master_boot_record disk_mbr;
+static unsigned int bcat_de_flags;
+
+void   init_boot_catalog(const char *path);
+void   insert_boot_cat(void);
+static void    get_torito_desc(struct eltorito_boot_descriptor *boot_desc);
+static void    fill_boot_desc(struct eltorito_defaultboot_entry *boot_desc_entry,
+                                                                               struct eltorito_boot_entry_info *boot_entry);
+void   get_boot_entry(void);
+void   new_boot_entry(void);
+static int     tvd_write(FILE *outfile);
+
+
+static char    *bootcat_path;          /* filename of boot catalog */
+/*
+ * Make sure any existing boot catalog is excluded
+ */
+void
+init_boot_catalog(const char *path)
+{
+#ifdef SORTING
+       struct eltorito_boot_entry_info * cbe;
+
+       for (cbe = first_boot_entry;
+           cbe != NULL;
+           cbe = cbe->next) {
+               char    *p;
+
+               if (cbe->boot_image == NULL)
+                       comerrno(EX_BAD, "Missing boot image name, use -eltorito-boot option.\n");
+               p = (char *) e_malloc(strlen(cbe->boot_image) + strlen(path) + 2);
+               strcpy(p, path);
+               if (p[strlen(p) - 1] != '/') {
+                       strcat(p, "/");
+               }
+               strcat(p, cbe->boot_image);
+               add_sort_match(p, sort_matches(p, 1));
+               free(p);
+       }
+#endif
+       bootcat_path = (char *) e_malloc(strlen(boot_catalog) + strlen(path) + 2);
+       strcpy(bootcat_path, path);
+       if (bootcat_path[strlen(bootcat_path) - 1] != '/') {
+               strcat(bootcat_path, "/");
+       }
+       strcat(bootcat_path, boot_catalog);
+
+       /*
+        * we are going to create a virtual catalog file
+        * - so make sure any existing is excluded
+        */
+       add_match(bootcat_path);
+
+       /* flag the file as a memory file */
+       bcat_de_flags = MEMORY_FILE;
+
+       /* find out if we want to "hide" this file */
+       if (i_matches(boot_catalog) || i_matches(bootcat_path))
+               bcat_de_flags |= INHIBIT_ISO9660_ENTRY;
+
+       if (j_matches(boot_catalog) || j_matches(bootcat_path))
+               bcat_de_flags |= INHIBIT_JOLIET_ENTRY;
+
+}/* init_boot_catalog(... */
+
+/*
+ * Create a boot catalog file in memory - genisoimage already uses this type of
+ * file for the TRANS.TBL files. Therefore the boot catalog is set up in
+ * similar way
+ */
+void
+insert_boot_cat()
+{
+       struct directory_entry  *de;
+       struct directory_entry  *s_entry;
+       char                    *p1;
+       char                    *p2;
+       char                    *p3;
+       struct directory        *this_dir;
+       struct directory        *dir;
+       char                    *buffer;
+
+       init_fstatbuf();
+
+       buffer = (char *) e_malloc(SECTOR_SIZE);
+       memset(buffer, 0, SECTOR_SIZE);
+
+       /*
+        * try to find the directory that will contain the boot.cat file
+        * - not very neat, but I can't think of a better way
+        */
+       p1 = strdup(boot_catalog);
+
+       /* get dirname (p1) and basename (p2) of boot.cat */
+       if ((p2 = strrchr(p1, '/')) != NULL) {
+               *p2 = '\0';
+               p2++;
+
+               /* find the dirname directory entry */
+               de = search_tree_file(root, p1);
+               if (!de) {
+#ifdef USE_LIBSCHILY
+                       comerrno(EX_BAD,
+                       "Uh oh, I cant find the boot catalog directory '%s'!\n",
+                                                               p1);
+#else
+                       fprintf(stderr,
+                       "Uh oh, I cant find the boot catalog directory '%s'!\n",
+                                                               p1);
+                       exit(1);
+#endif
+               }
+               this_dir = 0;
+
+               /* get the basename (p3) of the directory */
+               if ((p3 = strrchr(p1, '/')) != NULL)
+                       p3++;
+               else
+                       p3 = p1;
+
+               /* find the correct sub-directory entry */
+               for (dir = de->filedir->subdir; dir; dir = dir->next)
+                       if (!(strcmp(dir->de_name, p3)))
+                               this_dir = dir;
+
+               if (this_dir == 0) {
+#ifdef USE_LIBSCHILY
+                       comerrno(EX_BAD,
+                       "Uh oh, I cant find the boot catalog directory '%s'!\n",
+                                                               p3);
+#else
+                       fprintf(stderr,
+                       "Uh oh, I cant find the boot catalog directory '%s'!\n",
+                                                               p3);
+                       exit(1);
+#endif
+               }
+       } else {
+               /* boot.cat is in the root directory */
+               this_dir = root;
+               p2 = p1;
+       }
+
+       /*
+        * make a directory entry in memory (using the same set up as for table
+        * entries
+        */
+       s_entry = (struct directory_entry *)
+               e_malloc(sizeof (struct directory_entry));
+       memset(s_entry, 0, sizeof (struct directory_entry));
+       s_entry->next = this_dir->contents;
+       this_dir->contents = s_entry;
+
+#ifdef SORTING
+       /* inherit any sort weight from parent directory */
+       s_entry->sort = this_dir->sort;
+       s_entry->sort += 2;
+
+       /* see if this entry should have a new weighting */
+       if (do_sort) {
+               s_entry->sort = sort_matches(bootcat_path, s_entry->sort);
+       }
+#endif /* SORTING */
+
+       s_entry->isorec.flags[0] = ISO_FILE;
+       s_entry->priority = 32768;
+       iso9660_date(s_entry->isorec.date, fstatbuf.st_mtime);
+       s_entry->inode = TABLE_INODE;
+       s_entry->dev = (dev_t) UNCACHED_DEVICE;
+       set_723(s_entry->isorec.volume_sequence_number,
+                                               volume_sequence_number);
+       set_733((char *) s_entry->isorec.size, SECTOR_SIZE);
+       s_entry->size = SECTOR_SIZE;
+       s_entry->filedir = this_dir;
+       s_entry->name = strdup(p2);
+       iso9660_file_length(p2, s_entry, 0);
+
+       /* flag file as necessary */
+
+       /*
+        * If the current directory is hidden, then hide this entry
+        */
+       if (this_dir->dir_flags & INHIBIT_ISO9660_ENTRY)
+               bcat_de_flags |= INHIBIT_ISO9660_ENTRY;
+       if (this_dir->dir_flags & INHIBIT_JOLIET_ENTRY)
+               bcat_de_flags |= INHIBIT_JOLIET_ENTRY;
+
+       s_entry->de_flags = bcat_de_flags;
+
+       if ((use_XA || use_RockRidge) &&
+           !(bcat_de_flags & INHIBIT_ISO9660_ENTRY)) {
+               fstatbuf.st_mode = 0444 | S_IFREG;
+               fstatbuf.st_nlink = 1;
+               generate_xa_rr_attributes("",
+                       p2, s_entry,
+                       &fstatbuf, &fstatbuf, 0);
+       }
+       /*
+        *  memory files are stored at s_entry->table
+        * - but this is also used for each s_entry to generate
+        * TRANS.TBL entries. So if we are generating tables,
+        * store the TRANS.TBL data here for the moment
+        */
+       if (generate_tables && !(bcat_de_flags & INHIBIT_ISO9660_ENTRY)) {
+               sprintf(buffer, "F\t%s\n", s_entry->name);
+
+               /* copy the TRANS.TBL entry info and clear the buffer */
+               s_entry->table = strdup(buffer);
+               memset(buffer, 0, SECTOR_SIZE);
+
+               /*
+                * store the (empty) file data in the
+                * unused s_entry->whole_name element for the time being
+                * - this will be transferred to s_entry->table after any
+                * TRANS.TBL processing later
+                */
+               s_entry->whole_name = buffer;
+       } else {
+               /* store the (empty) file data in the s_entry->table element */
+               s_entry->table = buffer;
+               s_entry->whole_name = NULL;
+       }
+}
+
+static void
+get_torito_desc(struct eltorito_boot_descriptor *boot_desc)
+{
+       int                     checksum;
+       unsigned char           *checksum_ptr;
+       struct directory_entry  *de2;   /* Boot catalog */
+       int                     i;
+       int                     offset;
+       struct eltorito_defaultboot_entry boot_desc_record;
+
+       memset(boot_desc, 0, sizeof (*boot_desc));
+       boot_desc->type[0] = 0;
+       memcpy(boot_desc->id, ISO_STANDARD_ID, sizeof (ISO_STANDARD_ID));
+       boot_desc->version[0] = 1;
+
+       memcpy(boot_desc->system_id, EL_TORITO_ID, sizeof (EL_TORITO_ID));
+
+       /*
+        * search from root of iso fs to find boot catalog
+        * - we already know where the boot catalog is
+        * - we created it above - but lets search for it anyway
+        * - good sanity check!
+        */
+       de2 = search_tree_file(root, boot_catalog);
+       if (!de2 || !(de2->de_flags & MEMORY_FILE)) {
+#ifdef USE_LIBSCHILY
+               comerrno(EX_BAD, "Uh oh, I cant find the boot catalog '%s'!\n",
+                                                       boot_catalog);
+#else
+               fprintf(stderr, "Uh oh, I cant find the boot catalog '%s'!\n",
+                                                       boot_catalog);
+               exit(1);
+#endif
+       }
+       set_731(boot_desc->bootcat_ptr,
+               (unsigned int) get_733(de2->isorec.extent));
+
+       /*
+        * we have the boot image, so write boot catalog information
+        * Next we write out the primary descriptor for the disc
+        */
+       memset(&valid_desc, 0, sizeof (valid_desc));
+       valid_desc.headerid[0] = 1;
+       valid_desc.arch[0] = EL_TORITO_ARCH_x86;
+
+       /*
+        * we'll shove start of publisher id into id field,
+        * may get truncated but who really reads this stuff!
+        */
+       if (publisher)
+               memcpy_max(valid_desc.id, publisher,
+                                               MIN(23, strlen(publisher)));
+
+       valid_desc.key1[0] = (char) 0x55;
+       valid_desc.key2[0] = (char) 0xAA;
+
+       /* compute the checksum */
+       checksum = 0;
+       checksum_ptr = (unsigned char *) &valid_desc;
+       /* Set checksum to 0 before computing checksum */
+       set_721(valid_desc.cksum, 0);
+       for (i = 0; i < (int)sizeof (valid_desc); i += 2) {
+               checksum += (unsigned int) checksum_ptr[i];
+               checksum += ((unsigned int) checksum_ptr[i + 1]) * 256;
+       }
+
+       /* now find out the real checksum */
+       checksum = -checksum;
+       set_721(valid_desc.cksum, (unsigned int) checksum);
+
+       /* now write it to the virtual boot catalog */
+       memcpy(de2->table, &valid_desc, 32);
+
+       for (current_boot_entry = first_boot_entry, offset = sizeof (valid_desc);
+               current_boot_entry != NULL;
+               current_boot_entry = current_boot_entry->next,
+               offset += sizeof (boot_desc_record)) {
+
+               if (offset >= SECTOR_SIZE) {
+#ifdef USE_LIBSCHILY
+                       comerrno(EX_BAD,
+                       "Too many El Torito boot entries\n");
+#else
+                       fprintf(stderr,
+                       "Too many El Torito boot entries\n");
+                       exit(1);
+#endif
+               }
+               fill_boot_desc(&boot_desc_record, current_boot_entry);
+               memcpy(de2->table + offset, &boot_desc_record,
+                                       sizeof (boot_desc_record));
+       }
+}/* get_torito_desc(... */
+
+static void
+fill_boot_desc(struct eltorito_defaultboot_entry *boot_desc_entry, 
+                                       struct eltorito_boot_entry_info *boot_entry)
+{
+       struct directory_entry  *de;    /* Boot file */
+       int                     bootmbr;
+       int                     i;
+       int                     nsectors;
+       int                     geosec;
+
+       if (!boot_desc_entry || !boot_entry)
+               return;
+
+       /* now adjust boot catalog lets find boot image first */
+       de = search_tree_file(root, boot_entry->boot_image);
+       if (!de) {
+#ifdef USE_LIBSCHILY
+               comerrno(EX_BAD, "Uh oh, I cant find the boot image '%s' !\n",
+                                                       boot_entry->boot_image);
+#else
+               fprintf(stderr, "Uh oh, I cant find the boot image '%s' !\n",
+                                                       boot_entry->boot_image);
+               exit(1);
+#endif
+       }
+       /* now make the initial/default entry for boot catalog */
+       memset(boot_desc_entry, 0, sizeof (*boot_desc_entry));
+       boot_desc_entry->boot_id[0] = (char) boot_entry->not_bootable ?
+                               EL_TORITO_NOT_BOOTABLE : EL_TORITO_BOOTABLE;
+
+       /* use default BIOS loadpnt */
+       set_721(boot_desc_entry->loadseg, boot_entry->load_addr);
+
+       /*
+        * figure out size of boot image in 512-byte sectors.
+        * However, round up to the nearest integral CD (2048-byte) sector.
+        * This is only used for no-emulation booting.
+        */
+       nsectors = boot_entry->load_size ? boot_entry->load_size :
+                               ISO_BLOCKS(de->size) * (SECTOR_SIZE/512);
+
+       if (verbose > 0) {
+               fprintf(stderr,
+                       "Size of boot image is %d sectors -> ", nsectors);
+       }
+
+       if (boot_entry->hard_disk_boot) {
+               /* sanity test hard disk boot image */
+               boot_desc_entry->boot_media[0] = EL_TORITO_MEDIA_HD;
+               if (verbose > 0)
+                       fprintf(stderr, "Emulating a hard disk\n");
+
+               /* read MBR */
+               bootmbr = open(de->whole_name, O_RDONLY | O_BINARY);
+               if (bootmbr == -1) {
+#ifdef USE_LIBSCHILY
+                       comerr("Error opening boot image '%s' for read.\n",
+                                                       de->whole_name);
+#else
+                       fprintf(stderr,
+                               "Error opening boot image '%s' for read.\n",
+                                                       de->whole_name);
+                       perror("");
+                       exit(1);
+#endif
+               }
+               if (read(bootmbr, &disk_mbr, sizeof (disk_mbr)) !=
+                                                       sizeof (disk_mbr)) {
+#ifdef USE_LIBSCHILY
+                       comerr("Error reading MBR from boot image '%s'.\n",
+                                                       de->whole_name);
+#else
+                       fprintf(stderr,
+                               "Error reading MBR from boot image '%s'.\n",
+                                                       de->whole_name);
+                       exit(1);
+#endif
+               }
+               close(bootmbr);
+               if (la_to_u_2_byte(disk_mbr.magic) != MBR_MAGIC) {
+#ifdef USE_LIBSCHILY
+                       errmsgno(EX_BAD,
+                       "Warning: boot image '%s' MBR is not a boot sector.\n",
+                                                       de->whole_name);
+#else
+                       fprintf(stderr,
+                               "Warning: boot image '%s' MBR is not a boot sector.\n",
+                                                       de->whole_name);
+#endif
+               }
+               /* find partition type */
+               boot_desc_entry->sys_type[0] = PARTITION_UNUSED;
+               for (i = 0; i < PARTITION_COUNT; ++i) {
+                       int             s_cyl_sec;
+                       int             e_cyl_sec;
+
+                       s_cyl_sec =
+                       la_to_u_2_byte(disk_mbr.partition[i].s_cyl_sec);
+                       e_cyl_sec =
+                       la_to_u_2_byte(disk_mbr.partition[i].e_cyl_sec);
+
+                       if (disk_mbr.partition[i].type != PARTITION_UNUSED) {
+                               if (boot_desc_entry->sys_type[0] !=
+                                                       PARTITION_UNUSED) {
+#ifdef USE_LIBSCHILY
+                                       comerrno(EX_BAD,
+                                       "Boot image '%s' has multiple partitions.\n",
+                                                       de->whole_name);
+#else
+                                       fprintf(stderr,
+                                       "Boot image '%s' has multiple partitions.\n",
+                                                       de->whole_name);
+                                       exit(1);
+#endif
+                               }
+                               boot_desc_entry->sys_type[0] =
+                                               disk_mbr.partition[i].type;
+
+                               /* a few simple sanity warnings */
+                               if (!boot_entry->not_bootable &&
+                                   disk_mbr.partition[i].status !=
+                                                       PARTITION_ACTIVE) {
+                                       fprintf(stderr,
+                                       "Warning: partition not marked active.\n");
+                               }
+                               if (MBR_CYLINDER(s_cyl_sec) != 0 ||
+                                       disk_mbr.partition[i].s_head != 1 ||
+                                       MBR_SECTOR(s_cyl_sec != 1)) {
+                                       fprintf(stderr,
+                                       "Warning: partition does not start at 0/1/1.\n");
+                               }
+                               geosec = (MBR_CYLINDER(e_cyl_sec) + 1) *
+                                       (disk_mbr.partition[i].e_head + 1) *
+                                       MBR_SECTOR(e_cyl_sec);
+                               if (geosec != nsectors) {
+                                       fprintf(stderr,
+                                       "Warning: image size does not match geometry (%d)\n",
+                                               geosec);
+                               }
+#ifdef DEBUG_TORITO
+                               fprintf(stderr, "Partition start %u/%u/%u\n",
+                                       MBR_CYLINDER(s_cyl_sec),
+                                       disk_mbr.partition[i].s_head,
+                                       MBR_SECTOR(s_cyl_sec));
+                               fprintf(stderr, "Partition end %u/%u/%u\n",
+                                       MBR_CYLINDER(e_cyl_sec),
+                                       disk_mbr.partition[i].e_head,
+                                       MBR_SECTOR(e_cyl_sec));
+#endif
+                       }
+               }
+               if (boot_desc_entry->sys_type[0] == PARTITION_UNUSED) {
+#ifdef USE_LIBSCHILY
+                       comerrno(EX_BAD,
+                                       "Boot image '%s' has no partitions.\n",
+                                                       de->whole_name);
+#else
+                       fprintf(stderr,
+                                       "Boot image '%s' has no partitions.\n",
+                                                       de->whole_name);
+                       exit(1);
+#endif
+               }
+#ifdef DEBUG_TORITO
+               fprintf(stderr, "Partition type %u\n",
+                                               boot_desc_entry->sys_type[0]);
+#endif
+       /* load single boot sector, in this case the MBR */
+               nsectors = 1;
+
+       } else if (boot_entry->no_emul_boot) {
+               /*
+                * no emulation is a simple image boot of all the sectors
+                * in the boot image
+                */
+               boot_desc_entry->boot_media[0] = EL_TORITO_MEDIA_NOEMUL;
+               if (verbose > 0)
+                       fprintf(stderr, "No emulation\n");
+
+       } else {
+               /* choose size of emulated floppy based on boot image size */
+               if (nsectors == 2880) {
+                       boot_desc_entry->boot_media[0] = EL_TORITO_MEDIA_144FLOP;
+                       if (verbose > 0)
+                               fprintf(stderr, "Emulating a 1440 kB floppy\n");
+
+               } else if (nsectors == 5760) {
+                       boot_desc_entry->boot_media[0] = EL_TORITO_MEDIA_288FLOP;
+                       if (verbose > 0)
+                               fprintf(stderr, "Emulating a 2880 kB floppy\n");
+
+               } else if (nsectors == 2400) {
+                       boot_desc_entry->boot_media[0] = EL_TORITO_MEDIA_12FLOP;
+                       if (verbose > 0)
+                               fprintf(stderr, "Emulating a 1200 kB floppy\n");
+
+               } else {
+#ifdef USE_LIBSCHILY
+                       comerrno(EX_BAD,
+                       "Error - boot image '%s' has not an allowable size.\n",
+                                                       de->whole_name);
+#else
+                       fprintf(stderr,
+                       "Error - boot image '%s' has not an allowable size.\n",
+                                                       de->whole_name);
+                       exit(1);
+#endif
+               }
+
+               /* load single boot sector for floppies */
+               nsectors = 1;
+       }
+
+       /* fill in boot image details */
+#ifdef DEBUG_TORITO
+       fprintf(stderr, "Boot %u sectors\n", nsectors);
+       fprintf(stderr, "Extent of boot images is %d\n",
+                               get_733(de->isorec.extent));
+#endif
+       set_721(boot_desc_entry->nsect, (unsigned int) nsectors);
+       set_731(boot_desc_entry->bootoff,
+               (unsigned int) get_733(de->isorec.extent));
+
+
+       /* If the user has asked for it, patch the boot image */
+       if (boot_entry->boot_info_table) {
+               int             bootimage;
+               unsigned int    bi_checksum;
+               unsigned int    total_len;
+               static char     csum_buffer[SECTOR_SIZE];
+               int             len;
+               struct genisoimage_boot_info bi_table;
+               bootimage = open(de->whole_name, O_RDWR | O_BINARY);
+               if (bootimage == -1) {
+#ifdef USE_LIBSCHILY
+                       comerr(
+                       "Error opening boot image file '%s' for update.\n",
+                                                       de->whole_name);
+#else
+                       fprintf(stderr,
+                       "Error opening boot image file '%s' for update.\n",
+                                                       de->whole_name);
+                       perror("");
+                       exit(1);
+#endif
+               }
+       /* Compute checksum of boot image, sans 64 bytes */
+               total_len = 0;
+               bi_checksum = 0;
+               while ((len = read(bootimage, csum_buffer, SECTOR_SIZE)) > 0) {
+                       if (total_len & 3) {
+#ifdef USE_LIBSCHILY
+                               comerrno(EX_BAD,
+                               "Odd alignment at non-end-of-file in boot image '%s'.\n",
+                                                       de->whole_name);
+#else
+                               fprintf(stderr,
+                               "Odd alignment at non-end-of-file in boot image '%s'.\n",
+                                                       de->whole_name);
+                               exit(1);
+#endif
+                       }
+                       if (total_len < 64)
+                               memset(csum_buffer, 0, 64 - total_len);
+                       if (len < SECTOR_SIZE)
+                               memset(csum_buffer + len, 0, SECTOR_SIZE-len);
+                       for (i = 0; i < SECTOR_SIZE; i += 4)
+                               bi_checksum += get_731(&csum_buffer[i]);
+                       total_len += len;
+               }
+
+               if (total_len != de->size) {
+#ifdef USE_LIBSCHILY
+                       comerrno(EX_BAD,
+                       "Boot image file '%s' changed underneath us!\n",
+                                               de->whole_name);
+#else
+                       fprintf(stderr,
+                       "Boot image file '%s' changed underneath us!\n",
+                                               de->whole_name);
+                       exit(1);
+#endif
+               }
+               /* End of file, set position to byte 8 */
+               lseek(bootimage, (off_t)8, SEEK_SET);
+               memset(&bi_table, 0, sizeof (bi_table));
+               /* Is it always safe to assume PVD is at session_start+16? */
+               set_731(bi_table.bi_pvd, session_start + 16);
+               set_731(bi_table.bi_file, de->starting_block);
+               set_731(bi_table.bi_length, de->size);
+               set_731(bi_table.bi_csum, bi_checksum);
+
+               write(bootimage, &bi_table, sizeof (bi_table)); /* FIXME: check return value */
+               close(bootimage);
+       }
+}/* fill_boot_desc(... */
+
+void
+get_boot_entry()
+{
+       if (current_boot_entry)
+               return;
+
+       current_boot_entry = (struct eltorito_boot_entry_info *)
+                       e_malloc(sizeof (struct eltorito_boot_entry_info));
+       memset(current_boot_entry, 0, sizeof (*current_boot_entry));
+
+       if (!first_boot_entry) {
+               first_boot_entry = current_boot_entry;
+               last_boot_entry = current_boot_entry;
+       } else {
+               last_boot_entry->next = current_boot_entry;
+               last_boot_entry = current_boot_entry;
+       }
+}
+
+void
+new_boot_entry()
+{
+       current_boot_entry = NULL;
+}
+
+/*
+ * Function to write the EVD for the disc.
+ */
+static int
+tvd_write(FILE *outfile)
+{
+       /* check the boot image is not NULL */
+       if (!boot_image) {
+#ifdef USE_LIBSCHILY
+               comerrno(EX_BAD, "No boot image specified.\n");
+#else
+               fprintf(stderr, "No boot image specified.\n");
+               exit(1);
+#endif
+       }
+       /* Next we write out the boot volume descriptor for the disc */
+       get_torito_desc(&gboot_desc);
+       jtwrite(&gboot_desc, SECTOR_SIZE, 1, 0, FALSE);
+       xfwrite(&gboot_desc, SECTOR_SIZE, 1, outfile, 0, FALSE);
+       last_extent_written++;
+       return (0);
+}
+
+struct output_fragment torito_desc = {NULL, oneblock_size, NULL, tvd_write, "Eltorito Volume Descriptor"};
diff --git a/genisoimage/endian.c b/genisoimage/endian.c
new file mode 100644 (file)
index 0000000..461e65c
--- /dev/null
@@ -0,0 +1,177 @@
+/*
+ * endian.c
+ *
+ * Copyright (c) 2004-2006 Steve McIntyre <steve@einval.com>
+ *
+ * Simple helper routines for marshalling data
+ *
+ * GNU GPL v2
+ */
+
+#include <mconfig.h>
+#include "endianconv.h"
+
+/* Write a 64-bit quantity out into memory in BIG ENDIAN order */
+void write_be64(unsigned long long in, unsigned char *out)
+{
+    out[0] = (in >> 56) & 0xFF;
+    out[1] = (in >> 48) & 0xFF;
+    out[2] = (in >> 40) & 0xFF;
+    out[3] = (in >> 32) & 0xFF;
+    out[4] = (in >> 24) & 0xFF;
+    out[5] = (in >> 16) & 0xFF;
+    out[6] = (in >> 8) & 0xFF;
+    out[7] = in & 0xFF;
+}
+
+/* Read in a 64-bit BIG ENDIAN quantity */
+unsigned long long read_be64(unsigned char *in)
+{
+    unsigned long long result = 0;
+
+    result |= (unsigned long long)in[0] << 56;
+    result |= (unsigned long long)in[1] << 48;
+    result |= (unsigned long long)in[2] << 40;
+    result |= (unsigned long long)in[3] << 32;
+    result |= (unsigned long long)in[4] << 24;
+    result |= (unsigned long long)in[5] << 16;
+    result |= (unsigned long long)in[6] << 8;
+    result |= (unsigned long long)in[7];
+    
+    return result;
+}
+
+/* Write a 64-bit quantity out into memory in LITTLE ENDIAN order */
+void write_le64(unsigned long long in, unsigned char *out)
+{
+    out[0] = in & 0xFF;
+    out[1] = (in >> 8) & 0xFF;
+    out[2] = (in >> 16) & 0xFF;
+    out[3] = (in >> 24) & 0xFF;
+    out[4] = (in >> 32) & 0xFF;
+    out[5] = (in >> 40) & 0xFF;
+    out[6] = (in >> 48) & 0xFF;
+    out[7] = (in >> 56) & 0xFF;
+}
+
+/* Read in a 64-bit LITTLE ENDIAN quantity */
+unsigned long long read_le64(unsigned char *in)
+{
+    unsigned long long result = 0;
+
+    result |= (unsigned long long)in[0];
+    result |= (unsigned long long)in[1] << 8;
+    result |= (unsigned long long)in[2] << 16;
+    result |= (unsigned long long)in[3] << 24;
+    result |= (unsigned long long)in[4] << 32;
+    result |= (unsigned long long)in[5] << 40;
+    result |= (unsigned long long)in[6] << 48;
+    result |= (unsigned long long)in[7] << 56;
+    
+    return result;
+}
+
+/* Write a 48-bit quantity out into memory in LITTLE ENDIAN order */
+void write_le48(unsigned long long in, unsigned char *out)
+{
+    out[0] = in & 0xFF;
+    out[1] = (in >> 8) & 0xFF;
+    out[2] = (in >> 16) & 0xFF;
+    out[3] = (in >> 24) & 0xFF;
+    out[4] = (in >> 32) & 0xFF;
+    out[5] = (in >> 40) & 0xFF;
+}
+
+/* Read in a 48-bit LITTLE ENDIAN quantity */
+unsigned long long read_le48(unsigned char *in)
+{
+    unsigned long long result = 0;
+
+    result |= (unsigned long long)in[0];
+    result |= (unsigned long long)in[1] << 8;
+    result |= (unsigned long long)in[2] << 16;
+    result |= (unsigned long long)in[3] << 24;
+    result |= (unsigned long long)in[4] << 32;
+    result |= (unsigned long long)in[5] << 40;
+    
+    return result;
+}
+
+/* Write a 32-bit quantity out into memory in BIG ENDIAN order */
+void write_be32(unsigned long in, unsigned char *out)
+{
+    out[0] = (in >> 24) & 0xFF;
+    out[1] = (in >> 16) & 0xFF;
+    out[2] = (in >> 8) & 0xFF;
+    out[3] = in & 0xFF;
+}
+
+/* Read in a 32-bit BIG ENDIAN quantity */
+unsigned long read_be32(unsigned char *in)
+{
+    unsigned long result = 0;
+
+    result |= (unsigned long)in[0] << 24;
+    result |= (unsigned long)in[1] << 16;
+    result |= (unsigned long)in[2] << 8;
+    result |= (unsigned long)in[3];
+    
+    return result;
+}
+
+/* Write a 32-bit quantity out into memory in LITTLE ENDIAN order */
+void write_le32(unsigned long in, unsigned char *out)
+{
+    out[0] = in & 0xFF;
+    out[1] = (in >> 8) & 0xFF;
+    out[2] = (in >> 16) & 0xFF;
+    out[3] = (in >> 24) & 0xFF;
+}
+
+/* Read in a 32-bit LITTLE ENDIAN quantity */
+unsigned long read_le32(unsigned char *in)
+{
+    unsigned long result = 0;
+
+    result |= (unsigned long)in[0];
+    result |= (unsigned long)in[1] << 8;
+    result |= (unsigned long)in[2] << 16;
+    result |= (unsigned long)in[3] << 24;
+    
+    return result;
+}
+
+/* Write a 16-bit quantity out into memory in BIG ENDIAN order */
+void write_be16(unsigned short in, unsigned char *out)
+{
+    out[0] = (in >> 8) & 0xFF;
+    out[1] = in & 0xFF;
+}
+    
+/* Read in a 16-bit BIG ENDIAN quantity */
+unsigned short read_be16(unsigned char *in)
+{
+    unsigned short result = 0;
+    
+    result |= (unsigned short)in[0] << 8;
+    result |= (unsigned short)in[1];
+    return result;
+}
+
+/* Write a 16-bit quantity out into memory in LITTLE ENDIAN order */
+void write_le16(unsigned short in, unsigned char *out)
+{
+    out[0] = in & 0xFF;
+    out[1] = in & 0xFF >> 8;
+}
+    
+/* Read in a 16-bit LITTLE ENDIAN quantity */
+unsigned short read_le16(unsigned char *in)
+{
+    unsigned short result = 0;
+    
+    result |= (unsigned short)in[0];
+    result |= (unsigned short)in[1] << 8;
+    return result;
+}
+
diff --git a/genisoimage/endianconv.h b/genisoimage/endianconv.h
new file mode 100644 (file)
index 0000000..2337cf9
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * endian_conv.h
+ *
+ * Copyright (c) 2004-2006 Steve McIntyre <steve@einval.com>
+ *
+ * Simple helper routines for marshalling data - prototypes
+ *
+ * GNU GPL v2
+ */
+
+void                  write_be64(unsigned long long in, unsigned char *out);
+unsigned long long    read_be64(unsigned char *in);
+void                  write_le64(unsigned long long in, unsigned char *out);
+unsigned long long    read_le64(unsigned char *in);
+
+void                  write_le48(unsigned long long in, unsigned char *out);
+unsigned long long    read_le48(unsigned char *in);
+
+void                  write_be32(unsigned long in, unsigned char *out);
+unsigned long         read_be32(unsigned char *in);
+void                  write_le32(unsigned long in, unsigned char *out);
+unsigned long         read_le32(unsigned char *in);
+
+void                  write_be16(unsigned short in, unsigned char *out);
+unsigned short        read_be16(unsigned char *in);
+void                  write_le16(unsigned short in, unsigned char *out);
+unsigned short        read_le16(unsigned char *in);
diff --git a/genisoimage/exclude.c b/genisoimage/exclude.c
new file mode 100644 (file)
index 0000000..759bf35
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)exclude.c       1.9 04/03/04 joerg */
+/*
+ * 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 <mconfig.h>
+#include <stdio.h>
+#include <stdxlib.h>
+#include <strdefs.h>
+#include <standard.h>
+#include <schily.h>
+
+
+/* this allows for 1000 entries to be excluded ... */
+#define        MAXEXCL         1000
+
+static char            *excl[MAXEXCL];
+
+void   exclude(char *fn);
+int    is_excluded(char *fn);
+
+
+void
+exclude(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] == NULL) {
+#ifdef USE_LIBSCHILY
+               errmsg("Can't allocate memory for excluded filename\n");
+#else
+               fprintf(stderr,
+                       "Can't allocate memory for excluded filename\n");
+#endif
+               return;
+       }
+       strcpy(excl[i], fn);
+}
+
+int
+is_excluded(char *fn)
+{
+       register int    i;
+
+       /*
+        * very dumb search method ...
+        */
+       for (i = 0; excl[i] && i < MAXEXCL; i++) {
+               if (strcmp(excl[i], fn) == 0) {
+                       return (1);     /* found -> excluded filenmae */
+               }
+       }
+       return (0);     /* not found -> not excluded */
+}
diff --git a/genisoimage/exclude.h b/genisoimage/exclude.h
new file mode 100644 (file)
index 0000000..ca20879
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)exclude.h       1.3 04/03/02 eric */
+/*
+ * 9-Dec-93 R.-D. Marzusch, marzusch@odiehh.hanse.de:
+ * added 'exclude' option (-x) to specify pathnames NOT to be included in
+ * CD image.
+ */
+
+void exclude(char * fn);
+int is_excluded(char * fn);
diff --git a/genisoimage/files.c b/genisoimage/files.c
new file mode 100644 (file)
index 0000000..d17a2c7
--- /dev/null
@@ -0,0 +1,398 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)files.c 1.12 04/03/04 joerg */
+/*
+ * File files.c - Handle ADD_FILES related stuff.
+ *
+ * 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 <mconfig.h>
+#include "genisoimage.h"
+#include <errno.h>
+#include <schily.h>
+#include <ctype.h>
+
+#ifdef ADD_FILES
+
+void   add_one_file(char *addpath, char *path);
+void   add_file_list(int argc, char **argv, int ind);
+void   add_file(char *filename);
+char *look_up_addition(char **newpath, char *path, struct dirent **de);
+void   nuke_duplicates(char *path, struct dirent **de);
+struct dirent  *readdir_add_files(char **pathp, char *path, DIR *dir);
+
+struct file_adds {
+       char                    *name;
+       struct file_adds        *child;
+       struct file_adds        *next;
+       int                     add_count;
+       int                     used;
+       union diru {
+       /*
+        * XXX Struct dirent is not guaranteed to be any size on a POSIX
+        * XXX compliant system.
+        * XXX We need to allocate enough space here, to allow the hacky
+        * XXX code in tree.c made by Ross Biro biro@yggdrasil.com
+        * XXX to work on operating systems other than Linux :-(
+        * XXX Changes made by Joerg Schilling
+        * XXX joerg@schily.isdn.cs.tu-berlin.de
+        * XXX to prevent core dumps on Solaris.
+        * XXX Space allocated:
+        * XXX          1024 bytes == NAME_MAX
+        * XXX  +       2   bytes for directory record length
+        * XXX  +       2*8 bytes for inode number & offset (64 for future exp)
+        */
+               struct dirent   de;
+               char            dspace[NAME_MAX + 2 + 2 * 8];
+       } du;
+       struct {
+               char            *path;
+               char            *name;
+       } *adds;
+};
+extern struct file_adds *root_file_adds;
+
+/*
+ * FIXME(eric) - the file adding code really doesn't work very well
+ * at all.  We should differentiate between adding directories, and adding
+ * single files, as adding a full directory affects how we should be
+ * searching for things.  Ideally what we should do is make two passes
+ * through the local filesystem - one to figure out what trees we need
+ * to scan (and merge in any additions at that point), and the second to
+ * actually fill out each structure with the appropriate contents.
+ */
+
+struct file_adds *root_file_adds = NULL;
+
+void
+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 = strrchr(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);
+}
+
+/*
+ * Function:   add_file_list
+ *
+ * Purpose:    Register an add-in file.
+ *
+ * Arguments:
+ */
+void
+add_file_list(int argc, char **argv, int ind)
+{
+       char    *ptr;
+       char    *dup_arg;
+
+       while (ind < argc) {
+               dup_arg = strdup(argv[ind]);
+               ptr = strchr(dup_arg, '=');
+               if (ptr == NULL) {
+                       free(dup_arg);
+                       return;
+               }
+               *ptr = 0;
+               ptr++;
+               add_one_file(dup_arg, ptr);
+               free(dup_arg);
+               ind++;
+       }
+}
+
+void
+add_file(char *filename)
+{
+       char    buff[PATH_MAX];
+       FILE    *f;
+       char    *ptr;
+       char    *p2;
+       int     count = 0;
+
+       if (strcmp(filename, "-") == 0) {
+               f = stdin;
+       } else {
+               f = fopen(filename, "r");
+               if (f == NULL) {
+#ifdef USE_LIBSCHILY
+                       comerr("Cannot open '%s'.\n", filename);
+#else
+                       perror("fopen");
+                       exit(1);
+#endif
+               }
+       }
+       while (fgets(buff, sizeof (buff), 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 = strchr(ptr, '=');
+               if (p2 == NULL) {
+#ifdef USE_LIBSCHILY
+                       comerrno(EX_BAD, "Error in file '%s' line %d: %s\n",
+                                               filename, count, buff);
+#else
+                       fprintf(stderr, "Error in file '%s' line %d: %s\n",
+                                               filename, count, buff);
+                       exit(1);
+#endif
+               }
+               *p2 = 0;
+               p2++;
+               add_one_file(ptr, p2);
+       }
+       if (f != stdin)
+               fclose(f);
+}
+
+/* This function looks up additions. */
+char *
+look_up_addition(char **newpath, char *path, struct dirent **de)
+{
+       char                    *dup_path;
+       char                    *cp;
+       struct file_adds        *f;
+       struct file_adds        *tmp = NULL;
+
+       f = root_file_adds;
+       if (!f)
+               return (NULL);
+
+       /* I don't trust strtok */
+       dup_path = strdup(path);
+
+       cp = strtok(dup_path, SPATH_SEPARATOR);
+       while (cp != NULL) {
+               for (tmp = f->child; tmp != NULL; tmp = tmp->next) {
+                       if (strcmp(tmp->name, cp) == 0)
+                               break;
+               }
+               if (tmp == NULL) {
+                       /* no match */
+                       free(dup_path);
+                       return (NULL);
+               }
+               f = tmp;
+               cp = strtok(NULL, SPATH_SEPARATOR);
+       }
+       free(dup_path);
+
+       /* If nothing, then return. */
+       if (tmp == NULL) {
+       /* no match */
+               return (NULL);
+       }
+       /* looks like we found something. */
+       if (tmp->used >= tmp->add_count)
+               return (NULL);
+
+       *newpath = tmp->adds[tmp->used].path;
+       tmp->used++;
+       *de = &(tmp->du.de);
+       return (tmp->adds[tmp->used - 1].name);
+
+}
+
+/* This function looks up additions. */
+void
+nuke_duplicates(char *path, struct dirent **de)
+{
+       char                    *dup_path;
+       char                    *cp;
+       struct file_adds        *f;
+       struct file_adds        *tmp;
+
+       f = root_file_adds;
+       if (!f)
+               return;
+
+       /* I don't trust strtok */
+       dup_path = strdup(path);
+
+       cp = strtok(dup_path, SPATH_SEPARATOR);
+       while (cp != NULL) {
+               for (tmp = f->child; tmp != NULL; tmp = tmp->next) {
+                       if (strcmp(tmp->name, cp) == 0)
+                               break;
+               }
+               if (tmp == NULL) {
+                       /* no match */
+                       free(dup_path);
+                       return;
+               }
+               f = tmp;
+               cp = strtok(NULL, SPATH_SEPARATOR);
+       }
+       free(dup_path);
+
+#if 0
+       /* looks like we found something. */
+       if (tmp->used >= tmp->add_count)
+               return;
+
+       *newpath = tmp->adds[tmp->used].path;
+       tmp->used++;
+       *de = &(tmp->du.de);
+       return (tmp->adds[tmp->used - 1].name);
+#endif
+}
+
+/*
+ * This function lets us add files from outside the standard file tree.
+ * It is useful if we want to duplicate a cd, but add/replace things.
+ * We should note that the real path will be used for exclusions.
+ */
+
+struct dirent  *
+readdir_add_files(char **pathp, char **path, DIR *dir)
+{
+       struct dirent  *de;
+
+       char    *addpath;
+       char    *name;
+
+       de = readdir(dir);
+       if (de) {
+               nuke_duplicates(path, &de);
+               return (de);
+       }
+       name = look_up_addition(&addpath, path, &de);
+
+       if (!name) {
+               return (NULL);
+       }
+       *pathp = addpath;
+
+       /*
+        * Now we must create the directory entry.
+        * fortuneately only the name seems to matter.
+        */
+/*     de->d_ino = -1; de->d_off = 0; de->d_reclen = strlen (name); */
+       strncpy(de->d_name, name, NAME_MAX);
+       de->d_name[NAME_MAX] = 0;
+       nuke_duplicates(path, &de);
+       return (de);
+
+}
+
+#else
+struct dirent  *
+readdir_add_files(char **pathp, char *path, DIR *dir)
+{
+       return (readdir(dir));
+}
+
+#endif
diff --git a/genisoimage/fnmatch.c b/genisoimage/fnmatch.c
new file mode 100644 (file)
index 0000000..d30de89
--- /dev/null
@@ -0,0 +1,239 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)fnmatch.c       1.4 02/02/10 eric */
+/* Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc.
+
+NOTE: The canonical source of this file is maintained with the GNU C Library.
+Bugs can be reported to bug-glibc@prep.ai.mit.edu.
+
+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, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <errno.h>
+#include <utypes.h>
+#include "fnmatch.h"
+
+#ifndef        __STDC__
+#define        const
+#endif
+
+#ifndef FNM_FILE_NAME
+#define        FNM_FILE_NAME   FNM_PATHNAME /* Preferred GNU name.  */
+#endif
+
+#ifndef FNM_LEADING_DIR
+#define        FNM_LEADING_DIR (1 << 3) /* Ignore `/...' after a match.  */
+#endif
+
+#ifndef FNM_CASEFOLD
+#define        FNM_CASEFOLD    (1 << 4) /* Compare without regard to case.  */
+#endif
+
+
+#include <ctype.h>
+
+#if defined (STDC_HEADERS) || !defined (isascii)
+#define ISASCII(c) 1
+#else
+#define ISASCII(c) isascii(c)
+#endif
+
+#define ISUPPER(c) (ISASCII (c) && isupper (c))
+
+
+/* Comment out all this code if we are using the GNU C Library, and are not
+   actually compiling the library itself.  This code is part of the GNU C
+   Library, but also included in many other GNU distributions.  Compiling
+   and linking in this code is a waste when using the GNU C library
+   (especially if it is a shared library).  Rather than having every GNU
+   program understand `configure --with-gnu-libc' and omit the object files,
+   it is simpler to just do this in the source for each such file.  */
+
+#if defined (_LIBC) || !defined (__GNU_LIBRARY__)
+
+
+#if !defined(__GNU_LIBRARY__) && !defined(STDC_HEADERS)
+extern int errno;
+#endif
+
+/* Match STRING against the filename pattern PATTERN, returning zero if
+   it matches, nonzero if not.  */
+int
+fnmatch (const char *pattern, const char *string, int flags)
+{
+  register const char *p = pattern, *n = string;
+  register char c;
+
+/* Note that this evalutes C many times.  */
+#define FOLD(c)        ((flags & FNM_CASEFOLD) && ISUPPER (c) ? tolower (c) : (c))
+
+  while ((c = *p++) != '\0')
+    {
+      c = FOLD ((Uchar)c);
+
+      switch (c)
+       {
+       case '?':
+         if (*n == '\0')
+           return FNM_NOMATCH;
+         else if ((flags & FNM_FILE_NAME) && *n == '/')
+           return FNM_NOMATCH;
+         else if ((flags & FNM_PERIOD) && *n == '.' &&
+                  (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
+           return FNM_NOMATCH;
+         break;
+
+       case '\\':
+         if (!(flags & FNM_NOESCAPE))
+           {
+             c = *p++;
+             c = FOLD ((Uchar )c);
+           }
+         if (FOLD ((Uchar )*n) != c)
+           return FNM_NOMATCH;
+         break;
+
+       case '*':
+         if ((flags & FNM_PERIOD) && *n == '.' &&
+             (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
+           return FNM_NOMATCH;
+
+         for (c = *p++; c == '?' || c == '*'; c = *p++, ++n)
+           if (((flags & FNM_FILE_NAME) && *n == '/') ||
+               (c == '?' && *n == '\0'))
+             return FNM_NOMATCH;
+
+         if (c == '\0')
+           return 0;
+
+         {
+           char c1 = (!(flags & FNM_NOESCAPE) && c == '\\') ? *p : c;
+           c1 = FOLD ((Uchar )c1);
+           for (--p; *n != '\0'; ++n)
+             if ((c == '[' || FOLD ((Uchar )*n) == c1) &&
+                 fnmatch (p, n, flags & ~FNM_PERIOD) == 0)
+               return 0;
+           return FNM_NOMATCH;
+         }
+
+       case '[':
+         {
+           /* Nonzero if the sense of the character class is inverted.  */
+           register int not;
+
+           if (*n == '\0')
+             return FNM_NOMATCH;
+
+           if ((flags & FNM_PERIOD) && *n == '.' &&
+               (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
+             return FNM_NOMATCH;
+
+           not = (*p == '!' || *p == '^');
+           if (not)
+             ++p;
+
+           c = *p++;
+           for (;;)
+             {
+               register char cstart = c, cend = c;
+
+               if (!(flags & FNM_NOESCAPE) && c == '\\')
+                 cstart = cend = *p++;
+
+               cstart = cend = FOLD ((Uchar)cstart);
+
+               if (c == '\0')
+                 /* [ (unterminated) loses.  */
+                 return FNM_NOMATCH;
+
+               c = *p++;
+               c = FOLD ((Uchar)c);
+
+               if ((flags & FNM_FILE_NAME) && c == '/')
+                 /* [/] can never match.  */
+                 return FNM_NOMATCH;
+
+               if (c == '-' && *p != ']')
+                 {
+                   cend = *p++;
+                   if (!(flags & FNM_NOESCAPE) && cend == '\\')
+                     cend = *p++;
+                   if (cend == '\0')
+                     return FNM_NOMATCH;
+                   cend = FOLD ((Uchar)cend);
+
+                   c = *p++;
+                 }
+
+               if ((Uchar)FOLD((Uchar)*n) >= (Uchar)cstart && (Uchar)FOLD((Uchar)*n) <= (Uchar)cend)
+                 goto matched;
+
+               if (c == ']')
+                 break;
+             }
+           if (!not)
+             return FNM_NOMATCH;
+           break;
+
+         matched:;
+           /* Skip the rest of the [...] that already matched.  */
+           while (c != ']')
+             {
+               if (c == '\0')
+                 /* [... (unterminated) loses.  */
+                 return FNM_NOMATCH;
+
+               c = *p++;
+               if (!(flags & FNM_NOESCAPE) && c == '\\')
+                 /* XXX 1003.2d11 is unclear if this is right.  */
+                 ++p;
+             }
+           if (not)
+             return FNM_NOMATCH;
+         }
+         break;
+
+       default:
+         if (c != FOLD ((Uchar)*n))
+           return FNM_NOMATCH;
+       }
+
+      ++n;
+    }
+
+  if (*n == '\0')
+    return 0;
+
+  if ((flags & FNM_LEADING_DIR) && *n == '/')
+    /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz".  */
+    return 0;
+
+  return FNM_NOMATCH;
+}
+
+#endif /* _LIBC or not __GNU_LIBRARY__.  */
diff --git a/genisoimage/fnmatch.h b/genisoimage/fnmatch.h
new file mode 100644 (file)
index 0000000..ef2bbd9
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)fnmatch.h       1.4 04/03/02 eric */
+/*
+ * Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc.
+ *
+ * NOTE: The canonical source of this file is maintained with the GNU C Library.
+ * Bugs can be reported to bug-glibc@prep.ai.mit.edu.
+ *
+ * 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, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef        _FNMATCH_H
+
+#define        _FNMATCH_H      1
+
+#ifndef        _PROTOTYP_H
+#include <prototyp.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*#if defined (__cplusplus) || (defined (__STDC__) && __STDC__)*/
+#ifdef PROTOTYPES
+#undef __P
+#define        __P(protos)     protos
+#else /* Not C++ or ANSI C.  */
+#undef __P
+#define        __P(protos)     ()
+/*
+ * We can get away without defining `const' here only because in this file
+ * it is used only inside the prototype for `fnmatch', which is elided in
+ * non-ANSI C where `const' is problematical.
+ */
+#endif /* C++ or ANSI C.  */
+
+
+/*
+ * We #undef these before defining them because some losing systems
+ * (HP-UX A.08.07 for example) define these in <unistd.h>.
+ */
+#undef FNM_PATHNAME
+#undef FNM_NOESCAPE
+#undef FNM_PERIOD
+
+/* Bits set in the FLAGS argument to `fnmatch'.  */
+#define        FNM_PATHNAME    (1 << 0) /* No wildcard can ever match `/'.  */
+#define        FNM_NOESCAPE    (1 << 1) /* Backslashes don't quote special chars.  */
+#define        FNM_PERIOD      (1 << 2) /* Leading `.' is matched only explicitly.  */
+
+#if !defined(_POSIX_C_SOURCE) || _POSIX_C_SOURCE < 2 || defined(_GNU_SOURCE)
+#define        FNM_FILE_NAME   FNM_PATHNAME /* Preferred GNU name.  */
+#define        FNM_LEADING_DIR (1 << 3) /* Ignore `/...' after a match.  */
+#define        FNM_CASEFOLD    (1 << 4) /* Compare without regard to case.  */
+#endif
+
+#ifndef FNM_FILE_NAME
+/*
+ * Apparently GNU libc doesn't define this thing.
+ */
+#define        FNM_FILE_NAME   FNM_PATHNAME /* Preferred GNU name.  */
+#endif
+
+/* Value returned by `fnmatch' if STRING does not match PATTERN.  */
+#define        FNM_NOMATCH     1
+
+/*
+ * Match STRING against the filename pattern PATTERN,
+ * returning zero if it matches, FNM_NOMATCH if not.
+ */
+extern int fnmatch(const char *__pattern, const char *__string, int __flags);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* fnmatch.h */
diff --git a/genisoimage/genisoimage.1 b/genisoimage/genisoimage.1
new file mode 100644 (file)
index 0000000..d05b24a
--- /dev/null
@@ -0,0 +1,2823 @@
+'\" t
+.\" genisoimage.1 -*- nroff -*-  To render, first run through tbl
+.\" Copyright 1993-1998 by Yggdrasil Computing
+.\" Copyright 1996-1997 by Robert Leslie
+.\" Copyright 1997-2001 by James Pearson
+.\" Copyright 1999-2006 by Joerg Schilling
+.\" Copyright 2002-2003 by Jungshik Shin
+.\" Copyright 2003 by Jaakko Heinonen
+.\" Copyright 2006 by the Cdrkit maintainers
+.\"
+.TH GENISOIMAGE 1 "13 Dec 2006"
+.\" ----------------------------------------
+.SH NAME
+genisoimage \- create ISO9660/Joliet/HFS filesystem with optional Rock Ridge attributes
+.\" ----------------------------------------
+.SH SYNOPSIS
+.B genisoimage
+.RI [ options ]
+.RB [ \-o
+.IR filename ]
+.IR pathspec " [" "pathspec ..." ]
+.\" ----------------------------------------
+.SH DESCRIPTION
+.B genisoimage
+is a pre-mastering program to generate ISO9660/Joliet/HFS hybrid
+filesystems.
+.PP
+.B genisoimage
+is capable of generating the 
+.B System Use Sharing Protocol records (SUSP)
+specified by the
+.BR "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 long filenames, UID/GID, POSIX permissions, symbolic links, and
+block and character device files.
+.PP
+If Joliet or HFS hybrid command line options are specified, 
+.B genisoimage
+will create the additional filesystem metadata needed for Joliet or HFS.
+Otherwise
+.B genisoimage
+will generate a pure ISO9660 filesystem.
+.PP
+.B genisoimage
+can generate a 
+.I true
+(or
+.IR shared )
+HFS hybrid filesystem. The same files are seen as HFS files when
+accessed from a Macintosh and as ISO9660 files when accessed from other 
+machines. HFS stands for
+.I Hierarchical File System
+and is the native filesystem used on Macintosh computers.
+.PP
+As an alternative,
+.B genisoimage
+can generate the
+.I Apple Extensions to ISO9660
+for each file. These extensions provide each file with CREATOR, TYPE and
+certain Finder flags when accessed from a Macintosh. See the
+.B HFS MACINTOSH FILE FORMATS
+section below.
+.PP
+.B genisoimage
+takes a snapshot of a given directory tree, and generates a
+binary image which will correspond to an ISO9660 and/or HFS filesystem when
+written to a block device.
+.PP
+Each file written to the ISO9660 filesystem must have a filename in the 8.3
+format (up to 8 characters, period, up to 3 characters, all uppercase), 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 genisoimage
+generally tries to form correct names by forcing the Unix filename to
+uppercase and truncating as required, but often this yields unsatisfactory
+results when the truncated names are not all unique.
+.B genisoimage
+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 include a
+3-digit number (guaranteed to be unique).  For example, the two files
+.I foo.bar
+and
+.I foo.bar.~1~
+could be rendered as
+.I FOO.BAR;1
+and
+.IR FOO000.BAR;1 .
+.PP
+When used with various HFS options,
+.B genisoimage
+will attempt to recognise files stored in a number of Apple/Unix file formats
+and will copy the data and resource forks as well as any
+relevant Finder information. See the
+.B HFS MACINTOSH FILE FORMATS
+section below for more about formats
+.B genisoimage
+supports.
+.PP
+Note that
+.B genisoimage
+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 disc.
+.B wodim
+is one such tool.  The latest version of
+.B wodim
+is available from
+.IR http://www.cdrkit.org/ .
+.PP
+.B pathspec
+is the path of the directory tree to be copied into the ISO9660 filesystem.
+Multiple paths can be specified, and
+.B genisoimage
+will merge the files found in all of the specified path components to
+form the filesystem image.
+.PP
+If the option
+.B \-graft\-points
+has been specified, it is possible to graft the paths at points other
+than the root directory, and it is possible to graft files or
+directories onto the cdrom image with names different than what they
+have in the source filesystem.  This is easiest to illustrate with a
+couple of examples.  Let's start by assuming that a local file
+.I ../old.lis
+exists, and you wish to include it in the cdrom image.
+.IP
+foo/bar/=../old.lis
+.PP
+will include
+.I old.lis
+in the cdrom image at
+.IR /foo/bar/old.lis ,
+while
+.IP
+foo/bar/xxx=../old.lis
+.PP
+will include 
+.I old.lis
+in the cdrom image at
+.IR /foo/bar/xxx .
+The same sort of syntax can be used with directories as well.
+.B genisoimage
+will create any directories required such that the graft
+points exist on the cdrom image \(em the directories do not need to
+appear in one of the paths.  By default, any directories that are created on 
+the fly like this will have permissions 0555 and appear to be owned by the
+person running
+.BR genisoimage .
+If you wish other permissions or owners of
+the intermediate directories, see
+.BR \-uid ", " \-gid ", " \-dir\-mode ", " \-file\-mode " and " \-new\-dir\-mode .
+.PP
+.B genisoimage
+will also run on Windows machines when compiled with Cygnus' cygwin
+(available from
+.IR http://www.cygwin.com/ ).
+Therefore most references in this man page to
+.I Unix
+can be replaced with
+.IR Win32 .
+.\" ----------------------------------------
+.SH OPTIONS
+.PP
+Several options can be specified as defaults in a
+.I .genisoimagerc
+configuration file, as well as on the command line.  If a parameter is
+specified in both places, the setting from the command line is used.
+For details on the format and possible locations of this file, see
+.BR genisoimagerc (5).
+.TP
+.BI \-abstract " file"
+Specifies the abstract filename.  There is space for 37 characters.
+Equivalent to
+.B ABST
+in the
+.I .genisoimagerc
+file.
+.TP
+.BI \-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 for 128 characters.  Equivalent to
+.B APPI
+in the
+.I .genisoimagerc
+file.
+.TP
+.B \-allow\-limited\-size
+When processing files larger than 2GiB which cannot be easily represented in
+ISO9660, add them with a shrunk visible file size to ISO9660 and with the
+correct visible file size to the UDF system. The result is an inconsistent
+filesystem and users need to make sure that they really use UDF rather than
+ISO9660 driver to read a such disk. Implies enabling
+.BR \-udf.
+.TP
+.B \-allow\-leading\-dots
+.TP
+.B \-ldots
+Allow ISO9660 filenames to begin with a period.  Usually, a leading dot is
+replaced with an underscore in order to maintain MS-DOS compatibility.
+.br
+This violates the ISO9660 standard, but it happens to work on many systems.
+Use with caution.
+.TP
+.B \-allow\-lowercase
+This options allows lowercase characters to appear in ISO9660 filenames.
+.br
+This violates the ISO9660 standard, but it happens to work on some systems.
+Use with caution.
+.TP
+.B \-allow\-multidot
+This options allows more than one dot to appear in ISO9660 filenames.
+A leading dot is not affected by this option, it
+may be allowed separately using
+.BR \-allow\-leading\-dots .
+.br
+This violates the ISO9660 standard, but it happens to work on many systems.
+Use with caution.
+.TP
+.BI \-biblio " file"
+Specifies the bibliographic filename.  There is space for 37 characters.
+Equivalent to
+.B BIBL
+in the
+.I .genisoimagerc
+file.
+.TP
+.B \-cache\-inodes
+.TP
+.B \-no\-cache\-inodes
+Enable or disable caching inode and device numbers to find hard links
+to files.  If
+.B genisoimage
+finds a hard link (a file with multiple names), the file will also be
+hard-linked on the CD, so the file contents only appear once.  This
+helps to save space.
+.B \-cache\-inodes
+is default on Unix-like operating systems, but
+.B \-no\-cache\-inodes
+is default on some other systems such as Cygwin, because it is not safe
+to assume that inode numbers are unique on those systems.  (Some
+versions of Cygwin create fake inode numbers using a weak hashing
+algorithm, which may produce duplicates.)  If two files have the same
+inode number but are not hard links to the same file,
+.B genisoimage \-cache\-inodes
+will not behave correctly.
+.B \-no\-cache\-inodes
+is safe in all situations, but in that case
+.B genisoimage
+cannot detect hard links, so the resulting CD image may be larger
+than necessary.
+.TP
+.BI \-alpha\-boot " alpha_boot_image"
+Specifies the path and filename of the boot image to be used when
+making an Alpha/SRM bootable CD. The pathname must be relative to the
+source path specified to
+.BR genisoimage .
+.TP
+.BI \-hppa\-bootloader " hppa_bootloader_image"
+Specifies the path and filename of the boot image to be used when
+making an HPPA bootable CD. The pathname must be relative to the
+source path specified to
+.BR genisoimage .
+Other options are required, at the very least a kernel filename and
+a boot command line.  See the
+.B HPPA NOTES
+section below for more information.
+.TP
+.BI \-hppa\-cmdline " hppa_boot_command_line"
+Specifies the command line to be passed to the HPPA boot loader when
+making a bootable CD. Separate the parameters with spaces or
+commas. More options must be passed to
+.B genisoimage,
+at the very least a kernel filename and the boot loader filename.
+See the
+.B HPPA NOTES
+section below for more information.
+.TP
+.BI \-hppa\-kernel\-32 " hppa_kernel_32"
+.TP
+.BI \-hppa\-kernel\-64 " hppa_kernel_64"
+Specifies the path and filename of the 32-bit and/or 64-bit kernel images
+to be used when making an HPPA bootable CD. The pathnames must be
+relative to the source path specified to
+.BR genisoimage .
+Other options are required, at the very least the boot loader filename
+and the boot command line.  See the
+.B HPPA NOTES
+section below for more information.
+.TP
+.BI \-hppa\-ramdisk " hppa_ramdisk_image"
+Specifies the path and filename of the ramdisk image to be used when
+making an HPPA bootable CD. The pathname must be relative to the
+source path specified to
+.BR genisoimage .
+This parameter is optional.  Other options are required, at the very
+least a kernel filename and the boot command line. See the
+.B HPPA NOTES
+section below for more information.
+.TP
+.BI \-mips\-boot " mips_boot_image"
+Specifies the path and filename of the boot image to be used when
+making an SGI/big-endian MIPS bootable CD. The pathname must be
+relative to the source path specified to
+.BR genisoimage .
+This option may be specified several times, to store up to 15 boot
+images.
+.TP
+.BI \-mipsel\-boot " mipsel_boot_image"
+Specifies the path and filename of the boot image to be used when
+making an DEC/little-endian MIPS bootable CD. The pathname must be
+relative to the source path specified to
+.BR genisoimage .
+.TP
+.BI \-B " img_sun4,img_sun4c,img_sun4m,img_sun4d,img_sun4e"
+.TP
+.BI \-sparc\-boot " img_sun4,img_sun4c,img_sun4m,img_sun4d,img_sun4e"
+Specifies a comma-separated list of boot images that are needed to make
+a bootable CD for SPARC systems.
+Partition 0 is used for the ISO9660 image, the first image file is mapped
+to partition 1.
+The comma-separated list may have up to 7 fields, including empty fields.
+This option is required to make a bootable CD for Sun SPARC systems.
+If
+.B \-B
+or
+.B \-sparc\-boot
+has been specified, the first sector of the resulting image will
+contain a Sun disk label. This disk label specifies slice 0 for the
+ISO9660 image and slices 1 to 7 for the boot images that
+have been specified with this option. Byte offsets 512 to 8191
+within each of the additional boot images must contain a primary boot
+that works for the appropriate SPARC architecture. The rest of each
+of the images usually contains a UFS filesystem used for the primary
+kernel boot stage.
+.IP
+The implemented boot method is the one found with SunOS 4.x and SunOS 5.x.
+However, it does not depend on SunOS internals but only on properties of
+the Open Boot prom, so it should be usable for any OS for SPARC systems.
+For more information also see the 
+.B NOTES
+section below.
+.IP
+If the special filename
+.B ...
+is used, the actual and all following boot partitions are mapped to the
+previous partition. If
+.B genisoimage
+is called with
+.BI \-G " image " \-B " ..."
+all boot partitions are mapped to the partition that contains the ISO9660
+filesystem image and the generic boot image that is located in the first
+16 sectors of the disc is used for all architectures.
+.TP
+.BI \-G " generic_boot_image"
+Specifies the path and filename of the generic boot image to be used when making
+a generic bootable CD.  The boot image will be placed on the first 16
+sectors of the CD, before the ISO9660 primary volume descriptor.
+If this option is used together with
+.BR \-sparc\-boot ,
+the Sun disk label will overlay the first 512 bytes of the generic
+boot image.
+.TP
+.BI \-b " eltorito_boot_image"
+Specifies the path and filename of the boot image to be used when making
+an El Torito bootable CD for x86 PCs. The pathname must be relative to
+the source path specified to
+.BR genisoimage .
+This option is required to make an El Torito bootable CD.
+The boot image must be exactly 1200 kB, 1440 kB or 2880 kB, and
+.B genisoimage
+will use this size when creating the output ISO9660 filesystem.  The PC
+BIOS will use the image to emulate a floppy disk, so the first 512-byte
+sector should contain PC boot code.  This will work, for example, if
+the boot image is a LILO-based boot floppy.
+.IP
+If the boot image is not an image of a floppy, you need to add either
+.BR \-hard\-disk\-boot " or " \-no\-emul\-boot .
+If the system should not boot off the emulated disk, use
+.BR \-no\-boot .
+.IP
+If
+.B \-sort
+has not been specified, the boot images are sorted
+with low priority (+2) to the beginning of the medium.
+If you don't like this, you need to specify a sort weight of 0 for the boot images.
+.TP
+.B \-eltorito\-alt\-boot
+Start with a new set of El Torito boot parameters.  Up to 63 El Torito
+boot entries may be stored on a single CD.
+.TP
+.BI \-hard\-disk\-boot
+Specifies that the boot image used to create El Torito bootable CDs is
+a hard disk image. The image must begin with a master boot
+record that contains a single partition.
+.TP
+.BI \-no\-emul\-boot
+Specifies that the boot image used to create El Torito bootable CDs is
+a "no emulation" image. The system will load and execute this image without
+performing any disk emulation.
+.TP
+.BI \-no\-boot
+Specifies that the created El Torito CD should be marked as not bootable. The
+system will provide an emulated drive for the image, but will boot off
+a standard boot device.
+.TP
+.BI \-boot\-load\-seg " segment_address"
+Specifies the load segment address of the boot image for no-emulation
+El Torito CDs.
+.TP
+.BI \-boot\-load\-size " load_sectors"
+Specifies the number of "virtual" (512-byte) sectors to load in
+no-emulation mode.  The default is to load the entire boot file.  Some
+BIOSes may have problems if this is not a multiple of 4.
+.TP
+.B \-boot\-info\-table
+Specifies that a 56-byte table with information of the CD-ROM layout
+will be patched in at offset 8 in the boot file.  If this option is
+given, the boot file is
+.IR "modified in the source filesystem" ,
+so make a copy of this file if it cannot be easily regenerated!
+See the
+.B EL TORITO BOOT INFO TABLE
+section for a description of this table.
+.TP
+.BI \-C " last_sess_start,next_sess_start"
+This option is needed to create a CD Extra or the image of a second
+session or a higher-level session for a multisession disc.
+.B \-C
+takes two numbers separated by a comma. The first is the first sector
+in the last session of the disc that should be appended to.
+The second number is the starting sector number of the new session.
+The correct numbers may be retrieved by calling
+.B wodim \-msinfo ...
+If
+.B \-C
+is used in conjunction with
+.BR \-M ,
+.B genisoimage
+will create a filesystem image that is intended to be a continuation
+of the previous session.
+If
+.B \-C
+is used without
+.BR \-M ,
+.B genisoimage
+will create a filesystem image that is intended to be used for a second
+session on a CD Extra. This is a multisession CD that holds audio data
+in the first session and an ISO9660 filesystem in the second session.
+.TP
+.BI \-c " boot_catalog"
+Specifies the path and filename of the boot catalog, which is required
+for an El Torito bootable CD. The pathname must be relative to the source
+path specified to
+.BR genisoimage .
+This file will be inserted into the output tree and not created
+in the source filesystem, so be
+sure the specified filename does not conflict with an existing file, or
+it will be excluded. Usually a name like
+.I boot.catalog
+is chosen.
+.IP
+If
+.B \-sort
+has not been specified, the boot catalog sorted
+with low priority (+1) to the beginning of the medium.
+If you don't like this, you need to specify a sort weight of 0 for the boot catalog.
+.TP
+.B \-check\-oldnames
+Check all filenames imported from the old session for compliance with
+the ISO9660 file naming rules.
+Without this option, only names longer than 31 characters are checked,
+as these files are a serious violation of the ISO9660 standard.
+.TP
+.BI \-check\-session " file"
+Check all old sessions for compliance with actual
+.B genisoimage 
+ISO9660 file naming rules.
+This is a high-level option that combines
+.B \-M
+.I file
+.BR "\-C 0,0 \-check\-oldnames" .
+For the parameter 
+.IR file ,
+see the description of
+.BR \-M .
+.TP
+.BI \-copyright " file"
+Specifies copyright information, typically a filename on the disc.
+There is space for 37 characters.  Equivalent to
+.B COPY
+in the
+.I .genisoimagerc
+file.
+.TP
+.B \-d
+Do not append a period to files that do not have one.
+.br
+This violates the ISO9660 standard, but it happens to work on many systems.
+Use with caution.
+.TP
+.B \-D
+Do not use deep directory relocation, and instead just pack them in the
+way we see them.
+.br
+If ISO9660:1999 has not been selected,
+this violates the ISO9660 standard, but it happens to work on many systems.
+Use with caution.
+.TP
+.BI \-dir\-mode " mode"
+Overrides the mode of directories used to create the image to
+.IR mode ,
+specified as 4 digits of permission bits as in
+.BR chmod (1).
+This option automatically enables Rock Ridge extensions.
+.TP
+.B \-dvd\-video
+Generate a DVD-Video compliant UDF filesystem. This is done by sorting the
+order of the content of the appropriate files and by adding padding 
+between the files if needed.
+Note that the sorting only works if the DVD-Video filenames include uppercase
+characters only.
+.IP
+Note that in order to get a DVD-Video compliant filesystem image, you
+need to prepare a DVD-Video compliant directory tree.  This requires a
+directory
+.B VIDEO_TS
+(all caps) in the root directory of the resulting DVD, and usually
+another directory
+.BR AUDIO_TS .
+.B VIDEO_TS
+needs to include all needed files (filenames must be all caps) for a
+compliant DVD-Video filesystem.
+.TP
+.B \-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
+they will be ignored.
+.TP
+.BI \-file\-mode " mode"
+Overrides the mode of regular files used to create the image to
+.IR mode ,
+specified as 4 digits of permission bits as in
+.BR chmod (1).
+This option automatically enables Rock Ridge extensions.
+.TP
+.BI \-gid " gid"
+Overrides the group ID read from the source files to the value of
+.IR gid . 
+Specifying this option automatically enables Rock Ridge extensions.
+.TP
+.B \-gui
+Switch the behaviour for a GUI. This currently makes the output more verbose
+but may have other effects in the future.
+.TP
+.B \-graft\-points
+Allow use of graft points for filenames. If this option is used, all
+filenames are checked for graft points. The filename is divided at the
+first unescaped equal sign. All occurrences of `\(rs' and `=' characters
+must be escaped with `\(rs' if
+.B \-graft\-points
+has been specified.
+.TP
+.BI \-hide " glob"
+Hide any files matching
+.IR glob ,
+a shell wildcard pattern, from being seen in the ISO9660 or Rock Ridge
+directory.
+.I glob
+may match any part of the filename or path.  If
+.I glob
+matches a directory, the contents of that directory will be hidden.
+In order to match a directory name, make sure the pathname does not include
+a trailing `/' character.
+All the hidden files will still be written to the output CD image file.
+See also
+.BR \-hide\-joliet ,
+and
+.IR README.hide .
+This option may be used multiple times.
+.TP
+.BI \-hide\-list " file"
+A file containing a list of shell wildcards to be hidden.  See
+.BR \-hide .
+.TP
+.BI \-hidden " glob"
+Add the hidden (existence) ISO9660 directory attribute for files and
+directories matching
+.IR glob ,
+a shell wildcard pattern.  This attribute will prevent the files from
+being shown by some MS-DOS and Windows commands.
+.I glob
+may match any part of the filename or path.
+In order to match a directory name, make sure the pathname does not include
+a trailing `/' character.
+This option may be used multiple times.
+.TP
+.BI \-hidden\-list " file"
+A file containing a list of shell wildcards to get the hidden
+attribute.  See
+.BR \-hidden .
+.TP
+.BI \-hide\-joliet " glob"
+Hide files and directories matching
+.IR glob ,
+a shell wildcard pattern, from being seen in the Joliet directory.
+.I glob
+may match any part of the filename or path.  If
+.I glob
+matches a directory, the contents of that directory will be hidden.
+In order to match a directory name, make sure the pathname does not include
+a trailing `/' character.
+All the hidden files will still be written to the output CD image file.
+This option is usually used with
+.BR \-hide .
+See also
+.IR README.hide .
+This option may be used multiple times.
+.TP
+.BI \-hide\-joliet\-list " file"
+A file containing a list of shell wildcards to be hidden from the
+Joliet tree.  See
+.BR \-hide\-joliet .
+.TP
+.B \-hide\-joliet\-trans\-tbl
+Hide the
+.I TRANS.TBL
+files from the Joliet tree.
+These files usually don't make sense in the Joliet world as they list
+the real name and the ISO9660 name which may both be different from the
+Joliet name.
+.TP
+.B \-hide\-rr\-moved
+Rename the directory
+.I RR_MOVED
+to
+.I .rr_moved
+in the Rock Ridge tree.
+It seems to be impossible to completely hide the
+.I RR_MOVED
+directory from the Rock Ridge tree.
+This option only makes the visible tree less confusing for
+people who don't know what this directory is for.
+If you need to have no
+.I RR_MOVED
+directory at all, you should use
+.BR \-D .
+Note that if
+.B \-D
+has been specified, the resulting filesystem is not ISO9660
+level-1 compliant and will not be readable on MS-DOS.
+See also the
+.B NOTES
+section.
+.TP
+.BI \-input\-charset " charset"
+Input charset that defines the characters used in local filenames.
+To get a list of valid charset names, call
+.BR "genisoimage \-input\-charset help" .
+To get a 1:1 mapping, you may use
+.B default
+as charset name. The default initial values are
+.I cp437
+on DOS-based systems and
+.I iso8859-1
+on all other systems.  See the
+.B CHARACTER SETS
+section below for more details.
+.TP
+.BI \-output\-charset " charset"
+Output charset that defines the characters that will be used in Rock Ridge
+filenames.  Defaults to the input charset.  See
+.B CHARACTER SETS
+section below for more details.
+.TP
+.BI \-iso\-level " level"
+Set the ISO9660 conformance level. Valid numbers are 1 to 4.
+.IP
+With level 1, files may only consist of one section and filenames are
+restricted to 8.3 characters.
+.IP
+With level 2, files may only consist of one section.
+.IP
+With level 3, no restrictions (other than ISO-9660:1988) do apply.
+.IP
+With all ISO9660 levels from 1 to 3, all filenames are restricted to
+uppercase letters, numbers and underscores (_). Filenames are
+limited to 31 characters, directory nesting is limited to 8
+levels, and pathnames are limited to 255 characters.
+.IP
+Level 4 officially does not exist but
+.B genisoimage
+maps it to ISO-9660:1999, which is ISO9660 version 2.
+.IP
+With level 4, an enhanced volume descriptor with version number
+and file structure version number set to 2 is emitted.
+Directory nesting is not limited to 8 levels,
+there is no need for a file to contain a dot and the dot has no
+special meaning, filenames do not have version numbers,
+.\" (f XXX ??? The character used for filling byte positions which are
+.\"     specified to be characters is subject to agreement between the
+.\"     originator and the recipient of the volume),
+and filenames can be up to 207 characters long, or 197 characters if
+Rock Ridge is used.
+.IP
+When creating Version 2 images,
+.B genisoimage
+emits an enhanced volume descriptor, similar but not identical to a
+primary volume descriptor. Be careful not to use broken software
+to make ISO9660 images bootable by assuming a second PVD copy and patching 
+this putative PVD copy into an El Torito VD.
+.TP
+.B \-J
+Generate Joliet directory records in addition to regular ISO9660
+filenames.  This is primarily useful when the discs are to be used on
+Windows machines.  Joliet filenames are specified in Unicode and each
+path component can be up to 64 Unicode characters long.
+Note that Joliet is not a standard \(em only Microsoft Windows and Linux
+systems can read Joliet extensions.  For greater portability, consider
+using both Joliet and Rock Ridge extensions.
+.TP
+.B \-joliet\-long
+Allow Joliet filenames to be up to 103 Unicode characters, instead of
+64.  This breaks the Joliet specification, but appears to work. Use
+with caution.
+.\" The number 103 is derived from: the maximum Directory Record Length
+.\" (254), minus the length of Directory Record (33), minus CD-ROM XA
+.\" System Use Extension Information (14), divided by the UTF-16
+.\" character size (2).
+.TP
+.BI \-jcharset " charset"
+A combination of
+.B \-J \-input\-charset
+.IR charset .
+See the
+.B CHARACTER SETS
+section below for more details.
+.TP
+.B \-l
+Allow full 31-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 31 characters.  If you use this option, the disc may
+be difficult to use on a MS-DOS system, but will work on most other systems.
+Use with caution.
+.TP
+.B \-L
+Outdated option; use
+.B \-allow\-leading\-dots
+instead.
+.TP
+.BI \-jigdo\-jigdo " jigdo_file"
+Produce a
+.B jigdo
+.I .jigdo
+metadata file as well as the filesystem image.  See the
+.B JIGDO NOTES
+section below for more information.
+.TP
+.BI \-jigdo\-template " template_file"
+Produce a
+.B jigdo
+.I .template
+file as well as the filesystem image.  See the
+.B JIGDO NOTES
+section below for more information.
+.TP
+.BI \-jigdo\-min\-file\-size " size"
+Specify the minimum size for a file to be listed in the
+.I .jigdo
+file. Default (and minimum allowed) is 1KB. See the
+.B JIGDO NOTES
+section below for more information.
+.TP
+.BI \-jigdo\-force\-md5 " path"
+Specify a file pattern where files
+.I must
+be contained in the externally-supplied MD5 list as supplied by
+.BR \-md5\-list .
+See the
+.B JIGDO NOTES
+section below for more information.
+.TP
+.BI \-jigdo\-exclude " path"
+Specify a file pattern where files will not be listed in the
+.I .jigdo
+file. See the
+.B JIGDO NOTES
+section below for more information.
+.TP
+.BI \-jigdo\-map " path"
+Specify a pattern mapping for the jigdo file
+(e.g.
+.IR Debian=/mirror/debian ).
+See the
+.B JIGDO NOTES
+section below for more information.
+.TP
+.BI \-md5\-list " md5_file"
+Specify a file containing the MD5sums, sizes and pathnames of the
+files to be included in the
+.I .jigdo
+file. See the
+.B JIGDO NOTES
+section below for more information.
+.TP
+.BI \-jigdo\-template\-compress " algorithm
+Specify a compression algorithm to use for template date. gzip and
+bzip2 are currently supported, and gzip is the default. See the
+.B JIGDO NOTES
+section below for more information.
+.TP
+.BI \-log\-file " log_file"
+Redirect all error, warning and informational messages to
+.I log_file
+instead of the standard error.
+.TP
+.BI \-m " glob"
+Exclude files matching
+.IR glob ,
+a shell wildcard pattern, from being written to CD-ROM.
+.I glob
+may match either the filename component or the full pathname.
+This option may be used multiple times.  For example:
+.sp
+     genisoimage \-o rom \-m \(aq*.o\(aq \-m core \-m foobar
+.sp
+would exclude all files ending in `.o', or called
+.IR core " or " foobar
+from the image.  Note that if you had a directory called
+.IR foobar ,
+it too (and of course all its descendants) would be excluded.
+.TP
+.BI \-exclude\-list " file"
+A file containing a list of shell wildcards to be excluded.  See
+.BR \-m .
+.TP
+.B \-max\-iso9660\-filenames
+Allow ISO9660 filenames to be up to 37 characters long.
+This option enables
+.B \-N
+as the extra name space is taken from the space reserved for
+file version numbers.
+.br
+This violates the ISO9660 standard, but it happens to work on many systems.
+Although a conforming application needs to provide a buffer space of at
+least 37 characters, discs created with this option may cause a buffer
+overflow in the reading operating system. Use with extreme care.
+.TP
+.BI \-M " path"
+.TP
+.BI \-M " device"
+.TP
+.BI \-dev " device"
+Specifies path to existing ISO9660 image to be merged. The alternate form
+takes a SCSI device specifier that uses the same syntax as the
+.B dev=
+parameter of
+.BR wodim .
+The output of 
+.B genisoimage
+will be a new session which should get written to the end of the
+image specified in
+.BR \-M .
+Typically this requires multisession capability for the CD recorder
+used to write the image.  This option may only be used in conjunction
+with
+.BR \-C .
+.TP
+.B \-N
+Omit version numbers from ISO9660 filenames.
+.br
+This violates the ISO9660 standard, but no one really uses the
+version numbers anyway.  Use with caution.
+.TP
+.BI \-new\-dir\-mode " mode"
+Specify the mode, a 4-digit number as used in
+.BR chmod (1),
+to use when creating new directories in the filesystem image.  The
+default is 0555.
+.TP
+.B \-nobak
+.TP
+.B \-no\-bak
+Exclude backup files files on the ISO9660 filesystem; that is,
+filenames that contain the characters `~' or `#' or end in
+.IR .bak .
+These are typically backup files for Unix text editors.
+.TP
+.B \-force\-rr
+Do not use the automatic Rock Ridge attributes recognition for previous sessions.
+This can work around problems with images created by, e.g., NERO Burning ROM.
+.TP
+.B \-no\-rr
+Do not use the Rock Ridge attributes from previous sessions.
+This may help to avoid problems when
+.B genisoimage
+finds illegal Rock Ridge signatures on an old session.
+.TP
+.B \-no\-split\-symlink\-components
+Don't split the symlink components, but begin a new Continuation Area (CE)
+instead. This may waste some space, but the SunOS 4.1.4 cdrom driver
+has a bug in reading split symlink components.
+.IP
+It is questionable whether this option is useful nowadays.
+.TP
+.B \-no\-split\-symlink\-fields
+Don't split the symlink fields, but begin a new Continuation Area (CE)
+instead. This may waste some space, but the SunOS 4.1.4 and
+Solaris 2.5.1 cdrom driver have a bug in reading split symlink fields
+(a `/' can be dropped).
+.IP
+It is questionable whether this option is useful nowadays.
+.TP
+.BI \-o " filename"
+Specify the output file for the the ISO9660 filesystem image.
+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 device for a regular
+disk partition, in which case the ISO9660 filesystem can be mounted
+normally to verify that it was generated correctly.
+.TP
+.B \-pad
+Pad the end of the whole image by 150 sectors (300 kB).  This option is
+enabled by default.  If used in combination with
+.BR \-B ,
+padding is inserted between the ISO9660 partition and the boot
+partitions, such that the first boot partition starts
+on a sector number that is a multiple of 16.
+.IP
+The padding is needed as many operating systems (e.g. Linux)
+implement read-ahead bugs in their filesystem I/O. These bugs result in read
+errors on files that are located near the end of a track, particularly
+if the disc is written in Track At Once mode, or where a CD audio track
+follows the data track.
+.\" XXX: Someone should check to see if the Linux readahead bug is
+.\" XXX: still present, and update this comment accordingly.
+.TP
+.B \-no\-pad
+Do not pad the end by 150 sectors (300 kB) and do not make the the boot partitions
+start on a multiple of 16 sectors.
+.TP
+.BI \-path\-list " file"
+A file containing a list of
+.I pathspec
+directories and filenames to be added to the ISO9660 filesystem. This list
+of pathspecs are processed after any that appear on the command line. If the
+argument is
+.IR \- ,
+the list is read from the standard input.
+.TP
+.B \-P
+Outdated option; use
+.B \-publisher
+instead.
+.TP
+.BI \-publisher " publisher_id"
+Specifies a text string that will be written into the volume header.
+This should describe the publisher of the CD-ROM, usually with a
+mailing address and phone number.  There is space for 128 characters.
+Equivalent to
+.B PUBL
+in the
+.I .genisoimagerc
+file.
+.TP
+.BI \-p " preparer_id"
+Specifies a text string that will be written into the volume header.
+This should describe the preparer of the CD-ROM, usually with a mailing
+address and phone number.  There is space for 128 characters.
+Equivalent to
+.B PREP
+in the
+.I .genisoimagerc
+file.
+.TP
+.B \-print\-size
+Print estimated filesystem size in multiples of the sector size (2048 bytes)
+and exit. This option is needed for
+Disk At Once mode and with some CD-R drives when piping directly into
+.BR wodim ,
+cases where
+.B wodim
+needs to know the size of the filesystem image in advance.
+Old versions of
+.B mkisofs
+wrote this information (among other information) to 
+.IR stderr .
+As this turns out to be hard to parse, the number without any other information
+is now printed on 
+.I stdout
+too.
+If you like to write a simple shell script, redirect
+.I stderr
+and catch the number from
+.IR stdout .
+This may be done with:
+.sp
+     cdblocks=\` genisoimage \-print\-size \-quiet .\|.\|. \`
+.br
+     genisoimage .\|.\|. | wodim .\|.\|. tsize=${cdblocks}s \-
+.TP
+.B \-quiet
+This makes
+.B genisoimage
+even less verbose.  No progress output will be provided.
+.TP
+.B \-R
+Generate SUSP and RR records using the Rock Ridge protocol to further describe
+the files on the ISO9660 filesystem.
+.TP
+.B \-r
+This is like the \-R option, but file ownership and modes are set to
+more useful values.  The uid and gid are set to zero, because they are
+usually only useful on the author's system, and not useful to the
+client.  All the file read bits are set true, so that files and
+directories are globally readable on the client.  If any execute bit is
+set for a file, set all of the execute bits, so that executables are
+globally executable on the client.  If any search bit is set for a
+directory, set all of the search bits, so that directories are globally
+searchable on the client.  All write bits are cleared, because the
+filesystem will be mounted read-only in any case.  If any of the special
+mode bits are set, clear them, because file locks are not useful on a
+read-only filesystem, and set-id bits are not desirable for uid 0 or
+gid 0.
+When used on Win32, the execute bit is set on
+.I all
+files. This is a result of the lack of file permissions on Win32 and the
+Cygwin POSIX emulation layer.  See also
+.BR \-uid ", " \-gid ,
+.BR \-dir\-mode ", " \-file\-mode
+and
+.BR \-new\-dir\-mode .
+.TP
+.B \-relaxed\-filenames
+Allows ISO9660 filenames to include all 7-bit ASCII characters except
+lowercase letters.
+.br
+This violates the ISO9660 standard, but it happens to work on many systems.
+Use with caution.
+.TP
+.BI \-root " dir"
+Moves all files and directories into
+.I dir
+in the image. This is essentially the
+same as using 
+.B \-graft\-points
+and adding
+.I dir
+in front of every pathspec, but is easier to use.
+.I dir
+may actually be several levels deep. It is
+created with the same permissions as other graft points.
+.TP
+.BI \-old-root " dir"
+This option is necessary when writing a multisession
+image and the previous (or even older) session was written with
+.B -root
+.IR dir .
+Using a directory name not found in the previous session
+causes
+.B genisoimage
+to abort with an error.
+Without this option,
+.B genisoimage
+would not be able to find unmodified files and would
+be forced to write their data into the image once more.
+.B \-root
+and
+.B \-old-root
+are meant to be used together to do incremental backups.
+The initial session would e.g. use:
+.B genisoimage \-root backup_1
+.IR dirs .
+The next incremental backup with
+.B genisoimage \-root backup_2 \-old-root backup_1
+.I dirs
+would take another snapshot of these directories. The first
+snapshot would be found in
+.BR backup_1 ,
+the second one in
+.BR backup_2 ,
+but only modified or new files need to be written
+into the second session.
+Without these options, new files would be added and old ones would be
+preserved. But old ones would be overwritten if the file was
+modified. Recovering the files by copying the whole directory back
+from CD would also restore files that were deleted
+intentionally. Accessing several older versions of a file requires
+support by the operating system to choose which sessions are to be
+mounted.
+.TP
+.BI \-sort " sort_file"
+Sort file locations on the media. Sorting is controlled by a file that
+contains pairs of filenames and sorting offset weighting.
+If the weighting is higher, the file will be located closer to the
+beginning of the media, if the weighting is lower, the file will be located
+closer to the end of the media. There must be only one space or tabs
+character between the filename and the
+weight and the weight must be the last characters on a line. The filename
+is taken to include all the characters up to, but not including the last
+space or tab character on a line. This is to allow for space characters to
+be in, or at the end of a filename.
+This option does
+.B not
+sort the order of the filenames that appear
+in the ISO9660 directory. It sorts the order in which the file data is
+written to the CD image, which is useful in order to optimize the
+data layout on a CD. See
+.B README.sort
+for more details.
+.TP
+.BI \-sparc\-boot " img_sun4,img_sun4c,img_sun4m,img_sun4d,img_sun4e"
+See
+.B \-B
+above.
+.TP
+.BI \-sparc\-label " label"
+Set the Sun disk label name for the Sun disk label that is created with
+.BR \-sparc-boot .
+.TP
+.B \-split\-output
+Split the output image into several files of approximately 1 GB each.
+This helps to create DVD-sized ISO9660 images on operating systems without
+large file support.
+.B wodim
+will concatenate more than one file into a single track if writing to a DVD.
+To make
+.B \-split\-output
+work,
+.BI \-o " filename"
+must be specified. The resulting output images will be named:
+.IR filename_00 ", " filename_01 ", " filename_02 ....
+.TP
+.BI \-stream\-media\-size " #"
+Select streaming operation and set the media size to # sectors.
+This allows you to pipe the output of the
+.BR tar (1)
+program into
+.B genisoimage
+and to create an ISO9660 filesystem without the need of an intermediate
+tar archive file. 
+If this option has been specified,
+.B genisoimage
+reads from 
+.I stdin 
+and creates a file with the name
+.IR STREAM.IMG .
+The maximum size of the file (with padding) is 200 sectors less than the 
+specified media size. If 
+.B \-no\-pad
+has been specified, the file size is 50 sectors less than the specified media size.
+If the file is smaller,
+.B genisoimage
+will write padding. This may take awhile.
+.IP
+The option 
+.B \-stream\-media\-size
+creates simple ISO9660 filesystems only and may not used together with multisession
+or hybrid filesystem options.
+.TP
+.BI \-stream\-file\-name " name"
+Reserved for future use.
+.TP
+.BI \-sunx86\-boot " UFS_img,,,AUX1_img"
+Specifies a comma-separated list of filesystem images that are needed to make
+a bootable CD for Solaris x86 systems.
+.IP
+Note that partition 1 is used for the ISO9660 image and that partition 2 is
+the whole disk, so partition 1 and 2 may not be used by external partition data.
+The first image file is mapped to partition 0.
+There may be empty fields in the comma-separated list,
+and list entries for partition 1 and 2 must be empty.
+The maximum number of supported partitions is 8 (although the Solaris x86
+partition table could support up to 16 partitions), so it is impossible
+to specify more than 6 partition images.
+This option is required to make a bootable CD for Solaris x86 systems.
+.IP
+If
+.B \-sunx86\-boot
+has been specified, the first sector of the resulting image will
+contain a PC fdisk label with a Solaris type 0x82 fdisk partition that
+starts at offset 512 and spans the whole CD.
+In addition, for the Solaris type 0x82 fdisk partition, there is a
+SVr4 disk label at offset 1024 in the first sector of the CD.
+This disk label specifies slice 0 for the first (usually UFS type)
+filesystem image that is used to boot the PC and slice 1 for
+the ISO9660 image.
+Slice 2 spans the whole CD slice 3 .\|.\|. slice 7 may be used for additional
+filesystem images that have been specified with this option.
+.IP
+A Solaris x86 boot CD uses a 1024 byte sized primary boot that uses the
+.B El-Torito no-emulation
+boot mode and a secondary generic boot that is in CD sectors 1\|.\|.15.
+For this reason, both
+.BI "-b " bootimage " \-no\-emul\-boot"
+and
+.BI \-G " genboot"
+must be specified.
+.TP
+.BI \-sunx86\-label " label"
+Set the SVr4 disk label name for the SVr4 disk label that is created with
+.BR \-sunx86-boot .
+.TP
+.BI \-sysid " ID"
+Specifies the system ID.  There is space for 32 characters.
+Equivalent to
+.B SYSI
+in the
+.I .genisoimagerc
+file.
+.TP
+.B \-T
+Generate a file
+.I TRANS.TBL
+in each directory on the CD-ROM, which can be used
+on non-Rock\ Ridge-capable systems to help establish the correct filenames.
+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
+.BI \-table\-name " table_name"
+Alternative translation table filename (see above). Implies
+.BR \-T .
+If you are creating a multisession image you must use the same name
+as in the previous session.
+.TP
+.BI \-ucs\-level " level"
+Set Unicode conformance level in the Joliet SVD. The default level is 3.
+It may be set to 1..3 using this option.
+.TP
+.B \-udf
+Include UDF filesystem support in the generated filesystem image.  UDF
+support is currently in alpha status and for this reason, it is not
+possible to create UDF-only images.  UDF data structures are currently
+coupled to the Joliet structures, so there are many pitfalls with the
+current implementation. There is no UID/GID support, there is no POSIX
+permission support, there is no support for symlinks.  Note that UDF
+wastes the space from sector ~20 to sector 256 at the beginning of the
+disc in addition to the space needed for real UDF data structures.
+.TP
+.BI \-uid " uid"
+Overrides the uid read from the source files to the value of
+.IR uid . 
+Specifying this option automatically enables Rock Ridge extensions.
+.TP
+.B \-use\-fileversion
+The option 
+.B \-use\-fileversion
+allows
+.B genisoimage
+to use file version numbers from the filesystem.
+If the option is not specified, 
+.B genisoimage
+creates a version number of 1 for all files.
+File versions are strings in the range 
+.I ;1
+to
+.I ;32767
+This option is the default on VMS. 
+.TP
+.B \-U
+Allows "untranslated" filenames, completely violating the ISO9660 standards
+described above.  Enables the following flags:
+.B \-d \-l \-N \-allow\-leading\-dots \-relaxed\-filenames
+.BR "\-allow\-lowercase \-allow\-multidot \-no\-iso\-translate" .
+Allows more than one `.' character in the filename, as well as
+mixed-case filenames.  This is useful on HP-UX, where the built-in
+.I cdfs
+filesystem does not recognize any extensions. Use with extreme caution.
+.TP
+.B \-no\-iso\-translate
+Do not translate the characters `#' and `~' which are invalid for ISO9660 filenames.
+Although invalid, these characters are often used by Microsoft systems.
+.br
+This violates the ISO9660 standard, but it happens to work on many systems.
+Use with caution.
+.TP
+.BI \-V " volid"
+Specifies the volume ID (volume name or label) to be written into the
+master block.  There is space for 32 characters.  Equivalent to
+.B VOLI
+in the
+.I .genisoimagerc
+file.  The volume ID is used as the mount point by the Solaris volume
+manager and as a label assigned to a disc on various other platforms
+such as Windows and Apple Mac OS.
+.TP
+.BI \-volset " ID"
+Specifies the volume set ID.  There is space for 128 characters.
+Equivalent to
+.B VOLS
+in the
+.I .genisoimagerc
+file.
+.TP
+.BI \-volset\-size " #"
+Sets the volume set size to #.
+The volume set size is the number of CDs that are in a CD volume set.
+A volume set is a collection of one or more volumes, on which a set of
+files is recorded.
+.IP
+Volume Sets are not intended to be used to create a set numbered CDs
+that are part of e.g. a Operation System installation set of CDs.
+Volume Sets are rather used to record a big directory tree that would not
+fit on a single volume.
+Each volume of a Volume Set contains a description of all the directories
+and files that are recorded on the volumes where the sequence numbers
+are less than, or equal to, the assigned Volume Set Size of the current
+volume.
+.IP
+.B genisoimage
+currently does not support a
+.B \-volset\-size
+that is larger than 1.
+.IP
+The option
+.B \-volset\-size
+must be specified before
+.B \-volset\-seqno
+on each command line.
+.TP
+.BI \-volset\-seqno " #"
+Sets the volume set sequence number to #.
+The volume set sequence number is the index number of the current
+CD in a CD set.
+The option
+.B \-volset\-size
+must be specified before
+.B \-volset\-seqno
+on each command line.
+.TP
+.B \-v
+Verbose execution. If given twice on the command line, extra debug information
+will be printed.
+.TP
+.BI \-x " glob"
+Identical to
+.B \-m
+.IR glob .
+.TP
+.B \-z
+Generate special
+.I RRIP
+records for transparently compressed files.
+This is only of use and interest for hosts that support transparent
+decompression, such as Linux 2.4.14 or later.  You must specify
+.BR \-R " or " \-r
+to enable Rock Ridge, and generate compressed files using the
+.B mkzftree
+utility before running
+.BR genisoimage .
+Note that transparent compression is a nonstandard Rock Ridge extension.
+The resulting disks are only transparently readable if used on Linux.
+On other operating systems you will need to call
+.B mkzftree
+by hand to decompress the files.
+.\" ----------------------------------------
+.SH "HFS OPTIONS"
+.TP
+.B \-hfs
+Create an ISO9660/HFS hybrid CD. This option should be used in conjunction
+with the
+.BR \-map ,
+.B \-magic
+and/or the various
+.I double dash
+options given below.
+.TP
+.B \-apple
+Create an ISO9660 CD with Apple's extensions. Similar to
+.BR \-hfs ,
+except that the Apple Extensions to ISO9660 are added instead of
+creating an HFS hybrid volume.
+Former 
+.B genisoimage
+versions did include Rock Ridge attributes by default if 
+.B \-apple
+was specified. This versions of
+.B genisoimage
+does not do this anymore. If you like to have Rock Ridge attributes,
+you need to specify this separately.
+.TP
+.BI \-map " mapping_file"
+Use the
+.I mapping_file
+to set the CREATOR and TYPE information for a file based on the
+filename's extension. A filename is 
+mapped only if it is not one of the know Apple/Unix file formats. See the
+.B HFS CREATOR/TYPE
+section below.
+.TP
+.BI \-magic " magic_file"
+The CREATOR and TYPE information is set by using a file's
+.I magic number
+(usually the first few bytes of a file). The
+.I magic_file
+is only used if a file is not one of the known Apple/Unix file formats, or
+the filename extension has not been mapped using
+.BR \-map .
+See the 
+.B HFS CREATOR/TYPE
+section below for more details.
+.TP
+.BI \-hfs\-creator " creator"
+Set the default CREATOR for all files. Must be exactly 4 characters. See the
+.B HFS CREATOR/TYPE
+section below for more details.
+.TP
+.BI \-hfs\-type " type"
+Set the default TYPE for all files. Must be exactly 4 characters. See the
+.B HFS CREATOR/TYPE
+section below for more details.
+.TP
+.B \-probe
+Search the contents of files for all the known Apple/Unix file formats.
+See the
+.B HFS MACINTOSH FILE FORMATS
+section below for more about these formats.
+However, the only way to check for
+.I MacBinary
+and
+.I AppleSingle
+files is to open and read them, so this option may
+increase processing time. It is better to use one or more
+.I double dash
+options given below if the Apple/Unix formats in use are known.
+.TP
+.B \-no\-desktop
+Do not create (empty) Desktop files. New HFS Desktop files will be created
+when the CD is used on a Macintosh (and stored in the System Folder).
+By default, empty Desktop files are added to the HFS volume.
+.TP
+.B \-mac\-name
+Use the HFS filename as the starting point for the ISO9660, Joliet and
+Rock Ridge filenames. See the
+.B HFS MACINTOSH FILENAMES
+section below for more information.
+.TP
+.BI \-boot\-hfs\-file " driver_file"
+Installs the
+.I driver_file
+that
+.I may
+make the CD bootable on a Macintosh. See the
+.B HFS BOOT DRIVER
+section below. (Alpha).
+.TP
+.B \-part
+Generate an HFS partition table. By default, no partition table is generated,
+but some older Macintosh CD-ROM drivers need an HFS partition table on the
+CD-ROM to be able to recognize a hybrid CD-ROM.
+.TP
+.BI \-auto " AutoStart_file"
+Make the HFS CD use the QuickTime 2.0 Autostart feature to launch an
+application or document. The given filename must be the name of a document or
+application located at the top level of the CD. The filename must be less
+than 12 characters. (Alpha).
+.TP
+.BI \-cluster\-size " size"
+Set the size in bytes of the cluster or allocation units of PC Exchange
+files. Implies
+.BR \-\-exchange .
+See the
+.B HFS MACINTOSH FILE FORMATS
+section below.
+.TP
+.BI \-hide\-hfs " glob"
+Hide
+.IR glob ,
+a shell wildcard pattern, from the HFS volume.  The file or directory
+will still exist in the ISO9660 and/or Joliet directory.
+.I glob
+may match any part of the filename.  Multiple globs may be excluded.
+Example:
+.sp
+     genisoimage \-o rom \-hfs \-hide\-hfs \(aq*.o\(aq \-hide\-hfs foobar
+.sp
+would exclude all files ending in `.o' or called
+.I foobar
+from the HFS volume. Note that if you had a directory called
+.IR foobar ,
+it too (and of course all its descendants) would be excluded.  The
+.I glob
+can also be a path name relative to the source directories given on the
+command line. Example:
+.sp
+     genisoimage \-o rom \-hfs \-hide\-hfs src/html src
+.sp
+would exclude just the file or directory called
+.I html
+from the
+.I src
+directory.  Any other file or directory called
+.I html
+in the tree will not be excluded.  Should be used with
+.B \-hide
+and/or
+.BR \-hide\-joliet .
+In order to match a directory name, make sure the pattern does not
+include a trailing `/' character. See
+.I README.hide
+for more details.
+.TP
+.BI \-hide\-hfs\-list " file"
+Specify a file containing a list of wildcard patterns to be hidden as in
+.BR \-hide\-hfs .
+.TP
+.BI \-hfs\-volid " hfs_volid"
+Volume name for the HFS partition. This is the name that is
+assigned to the disc on a Macintosh and replaces the
+.I volid
+used with
+.BR \-V .
+.TP
+.B \-icon\-position
+Use the icon position information, if it exists, from the Apple/Unix file.
+The icons will appear in the same position as they would on a Macintosh
+desktop. Folder location and size on screen, its scroll positions, folder
+View (view as Icons, Small Icons, etc.) are also preserved.
+.\" This option may become set by default in the future.
+(Alpha).
+.TP
+.BI \-root\-info " file"
+Set the location, size on screen, scroll positions, folder View etc. for the
+root folder of an HFS volume. See
+.I README.rootinfo
+for more information.  (Alpha)
+.TP
+.BI \-prep\-boot " file"
+PReP boot image file. Up to 4 are allowed. See
+.I README.prep_boot
+for more information.  (Alpha)
+.TP
+.BI \-chrp\-boot
+Add CHRP boot header.
+.TP
+.BI \-input\-hfs\-charset " charset"
+Input charset that defines the characters used in HFS filenames when
+used with
+.BR \-mac\-name .
+The default charset is
+.I cp10000
+(Mac Roman).  See the
+.B CHARACTER SETS
+and
+.B HFS MACINTOSH FILENAMES
+sections below for more details.
+.TP
+.BI \-output\-hfs\-charset " charset"
+Output charset that defines the characters that will be used in the HFS
+filenames. Defaults to the input charset. See the
+.B CHARACTER SETS
+section below for more details.
+.TP
+.B \-hfs\-unlock
+By default,
+.B genisoimage
+will create an HFS volume that is locked.
+This option leaves the volume unlocked so that other applications (e.g.
+.BR hfsutils )
+can modify the volume. See the
+.B HFS PROBLEMS/LIMITATIONS
+section below for warnings about using this option.
+.TP
+.BI \-hfs\-bless " folder_name"
+"Bless" the given directory (folder). This is usually the 
+.I System Folder
+and is used in creating HFS bootable CDs. The name of the directory must
+be the whole path name as
+.B genisoimage
+sees it.  E.g., if the given pathspec is
+.I ./cddata
+and the required folder is called
+.IR "System Folder" ,
+the whole path name is
+.I \(dq/cddata/System Folder\(dq
+(remember to use quotes if the name contains spaces).
+.TP
+.BI \-hfs\-parms " parameters"
+Override certain parameters used to create the HFS filesystem. Unlikely to
+be used in normal circumstances.  See the
+.I libhfs_iso/hybrid.h
+source file for details.
+.TP
+.B \-\-cap
+Look for AUFS CAP Macintosh files. Search for CAP Apple/Unix file formats
+only. Searching for the other possible Apple/Unix file formats is disabled,
+unless other
+.I double dash
+options are given.
+.TP
+.B \-\-netatalk
+Look for NETATALK Macintosh files
+.TP
+.B \-\-double
+Look for AppleDouble Macintosh files
+.TP
+.B \-\-ethershare
+Look for Helios EtherShare Macintosh files
+.TP
+.B \-\-ushare
+Look for IPT UShare Macintosh files
+.TP
+.B \-\-exchange
+Look for PC Exchange Macintosh files
+.TP
+.B \-\-sgi
+Look for SGI Macintosh files
+.TP
+.B \-\-xinet
+Look for XINET Macintosh files
+.TP
+.B \-\-macbin
+Look for MacBinary Macintosh files
+.TP
+.B \-\-single
+Look for AppleSingle Macintosh files
+.TP
+.B \-\-dave
+Look for Thursby Software Systems DAVE Macintosh files
+.TP
+.B \-\-sfm
+Look for Microsoft's Services for Macintosh files (NT only) (Alpha)
+.TP
+.B \-\-osx\-double
+Look for Mac OS X AppleDouble Macintosh files
+.TP
+.B \-\-osx\-hfs
+Look for Mac OS X HFS Macintosh files
+.\" ----------------------------------------
+.SH "CHARACTER SETS"
+.B genisoimage
+processes filenames in a POSIX-compliant way as strings of 8-bit characters.
+To represent all codings for all languages, 8-bit characters are not
+sufficient.  Unicode or ISO-10646
+define character codings that need at least 21 bits to represent all
+known languages. They may be represented with
+.IR UTF-32 ", " UTF-16 " or " UTF-8
+coding.  UTF-32 uses a plain 32-bit coding but seems to be uncommon.
+UTF-16 is used by Microsoft with Win32 with the disadvantage that
+16-bit characters are not compliant with the POSIX filesystem
+interface.
+.PP
+Modern Unix operating systems may use UTF-8 coding for filenames.
+Each 32-bit character is represented by one or more 8-bit characters.
+If a character is coded in
+.I ISO-8859-1
+(used in Central Europe and North America) is maps 1:1 to a 
+UTF-32 or UTF-16 coded Unicode character.
+If a character is coded in
+.I 7-Bit ASCII
+(used in USA and other countries with limited character set)
+is maps 1:1 to a UTF-32, UTF-16 or UTF-8 coded Unicode character.
+Character codes that cannot be represented as a single byte in UTF-8
+(if the value is > 0x7F) use escape sequences that map to more than
+one 8-bit character.
+.PP
+If all operating systems used UTF-8,
+.B genisoimage
+would not need to recode characters in filenames.
+Unfortunately, Apple uses completely nonstandard codings and Microsoft
+uses a Unicode coding that is not compatible with the POSIX filename
+interface.
+.PP
+For all non-UTF-8-coded operating systems, the actual character
+that each byte represents depends on the
+.I character set
+or
+.I codepage
+(the name used by Microsoft)
+used by the local operating system \(em the characters in a character
+set will reflect the region or natural language set by the user.
+.PP
+Usually character codes 0x00-0x1f are control characters, codes 0x20-0x7f
+are the 7-bit ASCII characters and (on PCs and Macs) 0x80-0xff are used
+for other characters.
+.PP
+As there are a lot more than 256 characters/symbols in use, only a small
+subset are represented in a character set. Therefore the same character code
+may represent a different character in different character sets. So a filename
+generated, say in central Europe, may not display the same character
+when viewed on a machine in, say eastern Europe.
+.PP
+To make matters more complicated, different operating systems use
+different character sets for the region or language. For example, the
+character code for `\('e' (small e with acute accent)
+may be character code 0x82 on a PC, 
+code 0x8e on a Macintosh, code 0xe9 on a Unix system in western Europe,
+and code 0x000e9 in Unicode.
+.PP
+As long as not all operating systems and applications use the same
+character set as the basis for filenames, it may be
+necessary to specify which character set your filenames use in and which
+character set the filenames should appear on the CD.
+.PP
+There are four options to specify the character sets you want to use:
+.TP
+.B \-input\-charset
+Defines the local character set you are using on your host machine.
+Any character set conversions that take place will use this character
+set as the starting point. The default input character sets are
+.I cp437
+on MS-DOS-based systems and
+.I iso8859-1
+on all other systems.  If
+.B \-J
+is given, the Unicode equivalents of the input character set
+will be used in the Joliet directory.
+.B \-jcharset
+is the same as
+.BR "\-input\-charset \-J" .
+.TP
+.B \-output\-charset
+Defines the character set that will be used with for the Rock Ridge names
+on the CD.  Defaults to the input character set.
+.TP
+.B \-input\-hfs\-charset
+Defines the HFS character set used for HFS filenames decoded from
+any of the various Apple/Unix file formats. Only useful when used with
+.BR \-mac\-name .
+See the
+.B HFS MACINTOSH FILENAMES
+for more information. Defaults to
+.I cp10000
+(Mac Roman).
+.TP
+.B \-output\-hfs\-charset
+Defines the HFS character set used to create HFS filenames from the input
+character set in use. In most cases this will be from the character set
+given with
+.BR \-input\-charset .
+Defaults to the input HFS character set.
+.PP
+There are a number of character sets built in to
+.BR genisoimage .
+To get a listing, use
+.BR "\-input\-charset help" .
+This list doesn't include the charset derived from the current locale,
+if
+.B genisoimage
+is built with
+.I iconv
+support.
+.PP
+Additional character sets can be read from file for any of the character
+set options by giving a filename as the argument to the options. The given
+file will only be read if its name does not match one of the built-in
+character sets.
+.PP
+The format of the character set files is the same as the mapping files
+available from
+.IR http://www.unicode.org/Public/MAPPINGS .
+This format is:
+.IP
+Column #1 is the input byte code (in hex as 0xXX)
+.br
+Column #2 is the Unicode (in hex as 0xXXXX)
+.br
+The rest of the line is ignored.
+.PP
+Any blank line, line without two (or more) columns in the above format
+or comments lines (starting with the # character) are ignored without any
+warnings. Any missing input code is mapped to Unicode character 0x0000.
+.PP
+Note that, while UTF-8 is supported, other Unicode encodings such as
+UCS-2/UTF-16 and UCS-4/UTF-32 are not, as POSIX operating systems
+cannot handle them natively.
+.PP
+A 1:1 character set mapping can be defined by using the keyword
+.I default
+as the argument to any of the character set options. This is the behaviour
+of old versions of
+.BR mkisofs .
+.PP
+The ISO9660 filenames generated from the input filenames are not converted
+from the input character set. The ISO9660 character set is a very limited
+subset of the ASCII characters, so any conversion would be pointless.
+.PP
+Any character that
+.B genisoimage
+cannot convert will be replaced with a `_' character.
+.\" ----------------------------------------
+.SH "HFS CREATOR/TYPE"
+A Macintosh file has two properties associated with it which define
+which application created the file, the
+.I CREATOR
+and what data the file contains, the
+.IR TYPE .
+Both are (exactly) 4 letter strings. Usually this
+allows a Macintosh user to double-click on a file and launch the correct
+application etc. The CREATOR and TYPE of a particular file can be found by
+using something like ResEdit (or similar) on a Macintosh.
+.PP
+The CREATOR and TYPE information is stored in all the various Apple/Unix
+encoded files.
+For other files it is possible to base the CREATOR and TYPE on the
+filename's extension using a
+.I mapping
+file (with
+.BR \-map )
+and/or using the
+.I magic number
+(usually a
+.I signature
+in the first few bytes) of a file (with
+.BR \-magic ).
+If both these options are given, their order on the command
+line is significant.  If
+.B \-map
+is given first, a filename extension match is attempted
+before a magic number match. However, if
+.B \-magic
+is given first, a magic number match is attempted before a
+filename extension match.
+.PP
+If a mapping or magic file is not used, or no match is found, the default
+CREATOR and TYPE for all regular files can be set by using entries in the 
+.I .genisoimagerc
+file or using
+.B \-hfs\-creator
+and/or
+.BR \-hfs\-type ,
+otherwise the default CREATOR and TYPE are
+.IR Unix " and " TEXT .
+.PP
+The format of the
+.I mapping
+file is the same
+.I afpfile
+format as used by
+.BR aufs .
+This file has five columns for the
+.IR extension ,
+.IR "file translation" ,
+.IR CREATOR ,
+.IR TYPE " and"
+.IR Comment .
+Lines starting with the `#' character are
+comment lines and are ignored. An example file would be like:
+.PP
+.TS
+tab (/);
+l s s s s
+l s s s s
+l l l l l .
+# Example filename mapping file
+#
+# EXTN/XLate/CREATOR/TYPE/Comment
+\&.tif/Raw/\(aq8BIM\(aq/\(aqTIFF\(aq/\(dqPhotoshop TIFF image\(dq
+\&.hqx/Ascii/\(aqBnHq\(aq/\(aqTEXT\(aq/\(dqBinHex file\(dq
+\&.doc/Raw/\(aqMSWD\(aq/\(aqWDBN\(aq/\(dqWord file\(dq
+\&.mov/Raw/\(aqTVOD\(aq/\(aqMooV\(aq/\(dqQuickTime Movie\(dq
+*/Ascii/\(aqttxt\(aq/\(aqTEXT\(aq/\(dqText file\(dq
+.TE
+.PP
+Where:
+.IP
+The first column
+.I EXTN
+defines the Unix filename extension to be
+mapped. The default mapping for any filename extension that doesn't
+match is defined with the `*' character.
+.IP
+The
+.I Xlate
+column defines the type of text translation between the Unix and
+Macintosh file it is ignored by
+.BR genisoimage ,
+but is kept to be compatible with
+.BR aufs (1).
+Although 
+.B genisoimage
+does not alter the contents of a file, if a binary file has its TYPE
+set as
+.IR TEXT ", it " may
+be read incorrectly on a Macintosh. Therefore a better choice for the
+default TYPE may be
+.IR ???? .
+.IP
+The
+.I CREATOR
+and
+.I TYPE
+keywords must be 4 characters long and enclosed in single quotes.
+.IP
+The comment field is enclosed in double quotes \(em it is ignored by
+.BR genisoimage ,
+but is kept to be compatible with 
+.BR aufs .
+.PP
+The format of the
+.I magic
+file is almost identical to the
+.BR magic (5)
+file used by the
+.BR file (1)
+command.
+.PP
+This file has four tab-separated columns for the
+.IR "byte offset" ,
+.IR type ,
+.I test
+and
+.IR message .
+Lines starting with the `#' character are
+comment lines and are ignored. An example file would be like:
+.PP
+.TS
+tab (/);
+l s s s
+l s s s
+l l l l .
+# Example magic file
+#
+# off/type/test/message
+0/string/GIF8/8BIM GIFf  GIF image
+0/beshort/0xffd8/8BIM JPEG  image data
+0/string/SIT!/SIT! SIT!  StuffIt Archive
+0/string/\(rs037\(rs235/LZIV ZIVU  standard Unix compress
+0/string/\(rs037\(rs213/GNUz ZIVU  gzip compressed data
+0/string/%!/ASPS TEXT  Postscript
+0/string/\(rs004%!/ASPS TEXT  PC Postscript with a ^D to start
+4/string/moov/txtt MooV  QuickTime movie file (moov)
+4/string/mdat/txtt MooV  QuickTime movie file (mdat)
+.TE
+.PP
+The format of the file is described in
+.BR magic (5).
+The only difference here is that for each entry in the magic file, the
+.I message
+for the initial offset must be be 4 characters for the CREATOR followed
+by 4 characters for the TYPE \(em white space is
+optional between them. Any other characters on this line are ignored.
+Continuation lines (starting with a `>') are also ignored, i.e., only
+the initial offset lines are used.
+.PP
+Using
+.B \-magic
+may significantly increase processing time as each file has to opened
+and read to find its magic number.
+.PP
+In summary, for all files, the default CREATOR is
+.I Unix
+and the default TYPE is
+.IR TEXT .
+These can be changed by using entries in the
+.I .genisoimagerc
+file or by using
+.B \-hfs\-creator
+and/or
+.BR \-hfs\-type .
+.PP
+If the a file is in one of the known Apple/Unix formats (and the format
+has been selected), the CREATOR and TYPE are taken from the values
+stored in the Apple/Unix file.
+.PP
+Other files can have their CREATOR and TYPE set from their filename
+extension (with
+.BR \-map ),
+or their magic number (with
+.BR \-magic ).
+If the default match is used in the
+.I mapping
+file, these values override the default CREATOR and TYPE.
+.PP
+A full CREATOR/TYPE database can be found at 
+.IR http://www.angelfire.com/il/szekely/ .
+.\" ----------------------------------------
+.SH "HFS MACINTOSH FILE FORMATS"
+Macintosh files have two parts called the
+.I Data
+and
+.IR "Resource fork" .
+Either may be empty. Unix (and many other OSs) can only
+cope with files having one part (or fork). To add to this, Macintosh files
+have a number of attributes associated with them \(em probably the most
+important are the TYPE and CREATOR.  Again, Unix has no concept of these
+types of attributes.
+.PP
+E.g., a Macintosh file may be a JPEG image where the image is stored in the
+Data fork and a desktop thumbnail stored in the Resource fork. It is usually
+the information in the data fork that is useful across platforms.
+.PP
+Therefore to store a Macintosh file on a Unix filesystem, a way has to be
+found to cope with the two forks and the extra attributes (which are
+referred to as the
+.IR "Finder info" ).
+Unfortunately, it seems that every software package that stores Macintosh
+files on Unix has chosen a completely different storage method.
+.PP
+The Apple/Unix formats that
+.B genisoimage
+(partially) supports are:
+.IP "CAP AUFS format"
+Data fork stored in a file. Resource fork in subdirectory
+.I .resource
+with same filename as data fork. Finder info in subdirectory
+.I .finderinfo
+with same filename.
+.IP "AppleDouble/Netatalk"
+Data fork stored in a file. Resource fork stored in a file with
+same name prefixed with `%'. Finder info also stored in same
+`%' file. Netatalk uses the same format, but the resource
+fork/Finder info stored in subdirectory
+.I .AppleDouble
+with same filename as data fork.
+.IP AppleSingle
+Data structures similar to above, except both forks and Finder
+info are stored in one file.
+.IP "Helios EtherShare"
+Data fork stored in a file.  Resource fork and Finder info together in
+subdirectory
+.I .rsrc
+with same filename as data fork.
+.IP "IPT UShare"
+Like the EtherShare format, but the Finder info
+is stored slightly differently.
+.IP MacBinary
+Both forks and Finder info stored in one file.
+.IP "Apple PC Exchange"
+Used by Macintoshes to store Apple files on DOS (FAT) disks.
+Data fork stored in a file. Resource fork in subdirectory
+.IR resource.frk " (or " RESOURCE.FRK ).
+Finder info as one record in file
+.IR finder.dat " (or " FINDER.DAT ).
+Separate
+.I finder.dat
+for each data fork directory.
+.IP
+Note: 
+.B genisoimage
+needs to know the native FAT cluster size of the disk that the PC Exchange
+files are on (or have been copied from). This size is given by
+.BR \-cluster\-size .
+The cluster or allocation size can be found by using the DOS utility
+.BR chkdsk .
+.IP
+May not work with PC Exchange v2.2 or higher files (available with MacOS 8.1).
+DOS media containing PC Exchange files should be mounted as type
+.I msdos
+(not
+.IR vfat )
+when using Linux.
+.IP SGI/XINET
+Used by SGI machines when they mount HFS disks. Data fork stored
+in a file.  Resource fork in subdirectory
+.I .HSResource
+with same filename.  Finder info as one record in file
+.IR .HSancillary ".  Separate " .HSancillary
+for each data fork directory.
+.IP "Thursby Software Systems DAVE"
+Allows Macintoshes to store Apple files on SMB servers.
+Data fork stored in a file. Resource fork in subdirectory
+.IR resource.frk .
+Uses the AppleDouble format to store resource fork.
+.IP "Services for Macintosh"
+Format of files stored by NT Servers on NTFS filesystems. Data fork is
+stored as
+.IR filename .
+Resource fork stored as a NTFS stream called
+.IR filename:AFP_Resource .
+The Finder info is stored as a NTFS stream called
+.IR filename:Afp_AfpInfo .
+NTFS streams are normally invisible to the user.
+.IP
+Warning:
+.B genisoimage
+only partially supports the SFM format. If an HFS file
+or folder stored on the NT server contains an illegal
+NT character in its name, NT converts these characters to
+.I Private Use Unicode
+characters.  The characters are: \(dq * / < > ? \(rs | and a space or
+period if it is the last character of the filename, character codes 0x01
+to 0x1f (control characters) and Apple's apple logo.
+.IP
+Unfortunately, these private Unicode characters are not readable by the
+.B genisoimage
+NT executable. Therefore any file or directory
+name containing these characters will be ignored \(em including the contents of
+any such directory.
+.IP "Mac OS X AppleDouble"
+When HFS/HFS+ files are copied or saved by Mac OS X on to a non-HFS
+filesystem (e.g. UFS, NFS etc.), the files are stored in AppleDouble format.
+Data fork stored in a file. Resource fork stored in a file with
+same name prefixed with `._'. Finder info also stored in same `._' file.
+.IP "Mac OS X HFS (Alpha)"
+Not really an Apple/Unix encoding, but actual HFS/HFS+ files on a Mac\ OS\ X
+system. Data fork stored in a file. Resource fork stored in a pseudo file
+with the same name with the suffix
+.IR /rsrc .
+The Finder info is only available via a Mac OS X library call.
+.IP
+See also
+.IR README.macosx .
+.IP
+Only works when used on Mac OS X.
+.IP
+If a file is found with a zero
+length resource fork and empty finderinfo, it is assumed not to have
+any Apple/Unix encoding \(em therefore a TYPE and CREATOR can be set using
+other methods.
+.PP
+.B genisoimage
+will attempt to set the CREATOR, TYPE, date and possibly other flags from
+the finder info. Additionally, if it exists, the Macintosh filename is set
+from the finder info, otherwise the Macintosh name is based on the Unix
+filename \(em see the
+.B HFS MACINTOSH FILENAMES
+section below.
+.PP
+When using
+.BR \-apple ,
+the TYPE and CREATOR are stored in the optional System Use or
+.I SUSP
+field
+in the ISO9660 Directory Record \(em in much the same way as the Rock Ridge
+attributes are. In fact to make life easy, the Apple extensions are added
+at the beginning of the existing Rock Ridge attributes (i.e., to get the Apple
+extensions you get the Rock Ridge extensions as well).
+.PP
+The Apple extensions require the resource fork to be stored as an ISO9660
+.I associated
+file. This is just like any normal file stored in the ISO9660 filesystem
+except that the associated file flag is set in the Directory Record (bit
+2). This file has the same name as the data fork (the file seen by
+non-Apple machines). Associated files are normally ignored by other OSs
+.PP
+When using
+.BR \-hfs ,
+the TYPE and CREATOR plus other finder info, are stored in a separate
+HFS directory, not visible on the ISO9660 volume. The HFS directory references
+the same data and resource fork files described above.
+.PP
+In most cases, it is better to use
+.B \-hfs
+instead of
+.BR \-apple ,
+as the latter imposes the limited ISO9660 characters allowed in
+filenames. However, the Apple extensions do give the advantage that the
+files are packed on the disk more efficiently and it may be possible to fit 
+more files on a CD.
+.\" ----------------------------------------
+.SH "HFS MACINTOSH FILENAMES"
+Where possible, the HFS filename that is stored with an Apple/Unix file
+is used for the HFS part of the CD. However, not all the Apple/Unix
+encodings store the HFS filename with the finderinfo. In these cases,
+the Unix filename is used \(em with escaped special characters. Special
+characters include `/' and characters with codes over 127.
+.PP
+AUFS escapes these characters by using `:' followed by the character code
+as two hex digits. Netatalk and EtherShare have a similar scheme, but uses
+`%' instead of a `:'.
+.PP
+If
+.B genisoimage
+cannot find an HFS filename, it uses the Unix name, with any
+.IR %xx " or " :xx
+characters
+.RI ( xx
+are two hex digits) converted to a single character code.  If
+.I xx
+are not hex digits ([0-9a-fA-F]), they are
+left alone \(em although any remaining `:' is converted to `%', as `:'
+is the HFS directory separator. Care must be taken, as an ordinary Unix
+file with
+.I %xx
+or
+.I :xx
+will also be converted. e.g.
+.PP
+.TS
+l l 
+l s
+l l
+l s
+l l .
+This:2fFile    converted to This/File
+       
+This:File      converted to This%File
+       
+This:t7File    converted to This%t7File
+.TE
+.PP
+Although HFS filenames appear to support uppercase and lowercase letters,
+the filesystem is case-insensitive, i.e., the filenames
+.IR aBc " and " AbC
+are the same. If a file is found in a directory with the same HFS name,
+.B genisoimage
+will attempt to make a unique name by adding `_' characters
+to one of the filenames. 
+.PP
+If an HFS filename exists for a file,
+.B genisoimage
+can use this name as the starting point for the ISO9660, Joliet and
+Rock Ridge filenames using
+.BR \-mac\-name .
+Normal Unix files without an HFS name will still use their Unix name.
+e.g.
+.PP
+If a MacBinary (or PC Exchange) file is stored as
+.I someimage.gif.bin
+on the Unix filesystem, but contains a HFS file called
+.IR someimage.gif ,
+this is the name that would appear on the HFS part of the CD. However, as
+.B genisoimage
+uses the Unix name as the starting point for the other names,
+the ISO9660 name generated will probably be 
+.I SOMEIMAG.BIN
+and the Joliet/Rock Ridge would be
+.IR someimage.gif.bin .
+This option will use
+the HFS filename as the starting point and the ISO9660 name will probably be
+.I SOMEIMAG.GIF
+and the Joliet/Rock Ridge would be
+.IR someimage.gif .
+.PP
+.B \-mac\-name
+will not currently work with
+.B \-T
+\(em the Unix name will be used in the
+.I TRANS.TBL
+file, not the Macintosh name.
+.PP
+The character set used to convert any HFS filename to a Joliet/Rock Ridge
+filename defaults to
+.I cp10000
+(Mac Roman).
+The character set used can be specified using
+.BR \-input\-hfs\-charset .
+Other built-in HFS character sets are:
+.I cp10006
+(MacGreek),
+.I cp10007
+(MacCyrillic),
+.I cp10029
+(MacLatin2),
+.I cp10079
+(MacIcelandandic) and
+.I cp10081
+(MacTurkish).
+.PP
+Note: the character codes used by HFS filenames taken from the various
+Apple/Unix formats will not be converted as they are assumed to be in the
+correct Apple character set. Only the Joliet/Rock Ridge names derived from
+the HFS filenames will be converted.
+.PP
+The existing
+.B genisoimage
+code will filter out any illegal characters for the ISO9660 and Joliet
+filenames, but as
+.B genisoimage
+expects to be dealing directly with Unix names, it leaves the Rock
+Ridge names as is.  But as `/' is a legal HFS filename character,
+.B \-mac\-name
+converts `/' to a `_' in Rock Ridge filenames.
+.PP
+If the Apple extensions are used, only the ISO9660 filenames will
+appear on the Macintosh. However, as the Macintosh ISO9660 drivers can use
+.I Level 2
+filenames, you can use options like
+.B \-allow\-multidot
+without problems on
+a Macintosh \(em still take care over the names, for example
+.I this.file.name
+will be converted to
+.I THIS.FILE
+i.e. only have one `.', also filename
+.I abcdefgh
+will be seen as
+.I ABCDEFGH
+but
+.I abcdefghi
+will be seen as
+.I ABCDEFGHI.
+i.e. with a `.' at the end \(em don't know if this is a Macintosh
+problem or a
+.BR genisoimage / mkhybrid
+problem. All filenames will be in uppercase
+when viewed on a Macintosh. Of course, DOS/Win3.X machines will not be able
+to see Level 2 filenames...
+.\" ----------------------------------------
+.SH "HFS CUSTOM VOLUME/FOLDER ICONS"
+To give a HFS CD a custom icon, make sure the root (top level) folder includes
+a standard Macintosh volume icon file. To give a volume a custom icon on
+a Macintosh, an icon has to be pasted over the volume's icon in the "Get Info"
+box of the volume. This creates an invisible file called
+.I Icon\(rsr
+(`\(rsr' is the carriage return character) in the root folder.
+.P
+A custom folder icon is very similar \(em an invisible file called
+.I Icon\(rsr
+exists in the folder itself.
+.P
+Probably the easiest way to create a custom icon that
+.B genisoimage
+can use is to format a blank HFS floppy disk on a Mac and paste an icon
+to its "Get Info" box. If using Linux with the HFS module installed,
+mount the floppy:
+.IP
+mount \-t hfs /dev/fd0 /mnt/floppy
+.PP
+The floppy will be mounted as a CAP filesystem by default.  Then run
+.B genisoimage
+using something like:
+.IP
+genisoimage \-\-cap \-o output source_dir /mnt/floppy
+.PP
+If you are not using Linux, you can use
+.B hfsutils
+to copy the icon file from the floppy.  However, care has to be taken,
+as the icon file contains a control character.  For example:
+.IP
+hmount /dev/fd0
+.br
+hdir \-a
+.br
+hcopy \-m Icon^V^M icon_dir/icon
+.PP
+Where `^V^M' is control-V followed by control-M. Then run 
+.B genisoimage
+by using something like:
+.IP
+genisoimage \-\-macbin \-o output source_dir icon_dir
+.PP
+The procedure for creating/using custom folder icons is very similar \(em paste
+an icon to folder's "Get Info" box and transfer the resulting
+.I Icon\(rsr
+file to the relevant directory in the
+.B genisoimage
+source tree.
+.PP
+You may want to hide the icon files from the ISO9660 and Joliet trees.
+.PP
+To give a custom icon to a Joliet CD, follow the instructions found at
+.IR http://www.cdrfaq.org/faq03.html#S3-21-1 .
+.\" ----------------------------------------
+.SH "HFS BOOT DRIVER"
+It 
+.I may
+be possible to make the hybrid CD bootable on a Macintosh.
+.PP
+A bootable HFS CD requires an Apple CD-ROM (or compatible) driver, a bootable
+HFS partition and the necessary System, Finder, etc. files.
+.PP
+A driver can be obtained from any other Macintosh bootable CD-ROM using the
+.B apple_driver
+utility. This file can then be used with
+.BR \-boot\-hfs\-file .
+.PP
+The HFS partition (i.e. the hybrid disk in our case) must contain a
+suitable System Folder, again from another CD-ROM or disk.
+.PP
+For a partition to be bootable, it must have its 
+.I boot block
+set. The boot
+block is in the first two blocks of a partition. For a non-bootable partition
+the boot block is full of zeros. Normally, when a System file is copied to
+partition on a Macintosh disk, the boot block is filled with a number of
+required settings \(em unfortunately I don't know the full spec for the boot
+block, so I'm guessing that the following will work.
+.PP
+Therefore, the utility
+.B apple_driver
+also extracts the boot block from the
+first HFS partition it finds on the given CD-ROM and this is used for the
+HFS partition created by
+.BR genisoimage .
+.PP
+.I Please note:
+By using a driver from an Apple CD and copying Apple software to your CD,
+you become liable to obey Apple Computer, Inc. Software License Agreements.
+.\" ----------------------------------------
+.SH "EL TORITO BOOT INFORMATION TABLE"
+When
+.B \-boot\-info\-table
+is given,
+.B genisoimage
+will modify the boot file specified by
+.B \-b
+by inserting a 56-byte
+.I boot information table
+at offset 8 in
+the file.  This modification is done in the source filesystem, so make
+sure you use a copy if this file is not easily recreated!  This file
+contains pointers which may not be easily or reliably obtained at boot
+time.
+.PP
+The format of this table is as follows; all integers are in
+section 7.3.1 ("little endian") format.
+.sp
+.RS +.2i
+.ta 1.0i 2.5i 3.5i
+.nf
+Offset Name    Size    Meaning
+ 8     bi_pvd  4 bytes LBA of primary volume descriptor
+12     bi_file 4 bytes LBA of boot file
+16     bi_length       4 bytes Boot file length in bytes
+20     bi_csum 4 bytes 32-bit checksum
+24     bi_reserved     40 bytes        Reserved
+.fi
+.RE
+.IP
+The 32-bit checksum is the sum of all the 32-bit words in the boot
+file starting at byte offset 64.  All linear block addresses (LBAs)
+are given in CD sectors (normally 2048 bytes).
+.\" ----------------------------------------
+.SH "HPPA NOTES"
+To make a bootable CD for HPPA, at the very least a boot loader file
+.RB ( \-hppa\-bootloader ),
+a kernel image file (32-bit, 64-bit, or both, depending on hardware)
+and a boot command line
+.RB ( \-hppa\-cmdline )
+must be specified. Some systems can boot either a 32- or a 64-bit
+kernel, and the firmware will choose one if both are present.
+Optionally, a ramdisk can be used for the root filesystem using
+.BR \-hppa\-cmdline .
+.\" ----------------------------------------
+.SH "JIGDO NOTES"
+Jigdo is a tool to help in the distribution of large files like CD and
+DVD images; see
+.I http://atterer.org/jigdo/
+for more details.  Debian CDs and DVD ISO
+images are published on the web in jigdo format to allow end users to download
+them more efficiently.
+.PP
+To create jigdo and template files alongside the ISO image from
+.BR genisoimage ,
+you must first generate a list of the files that will be
+used, in the following format:
+.sp
+.RS +.2i
+.ta 2.0i 2.0i 5.0i
+.nf
+MD5sum   File size  Path
+32 chars 12 chars   to end of line
+.fi
+.RE
+.IP
+.PP
+The MD5sum must be written in standard hexadecimal notation, the
+file size must list the size of the file in bytes, and the path
+must list the absolute path to the file. For example:
+.sp
+.nf
+00006dcd58ff0756c36d2efae21be376         14736  /mirror/debian/file1
+000635c69b254a1be8badcec3a8d05c1        211822  /mirror/debian/file2
+00083436a3899a09633fc1026ef1e66e         22762  /mirror/debian/file3
+.fi
+.PP
+Once you have this file, call
+.B genisoimage
+with all of your normal command-line parameters. Specify the output
+filenames for the jigdo and template files using
+.BR \-jigdo\-jigdo " and " \-jigdo\-template ,
+and pass in the location of your MD5 list with
+.BR \-md5\-list .
+.PP
+If there are files that you do NOT want to be added into the jigdo
+file (e.g. if they are likely to change often), specify them using
+\-jigdo\-exclude. If you want to verify some of the files as they are
+written into the image, specify them using \-jigdo\-force\-md5. If any
+files don't match,
+.B genisoimage
+will then abort.  Both of these options take
+regular expressions as input. It is possible to restrict the set of
+files that will be used further based on size \(em use the
+\-jigdo\-min\-file\-size option.
+.PP
+Finally, the jigdo code needs to know how to map the files it is given
+onto a mirror-style configuration. Specify how to map paths using
+.BR \-jigdo\-map .
+Using
+.I Debian=/mirror/debian
+will cause all
+paths starting with
+.I /mirror/debian
+to be mapped to
+.I Debian:<file>
+in the output jigdo file.
+.\" ----------------------------------------
+.SH EXAMPLES
+.PP
+To create a vanilla ISO9660 filesystem image in the file 
+.IR cd.iso ,
+where the directory
+.I cd_dir
+will become the root directory of the CD, call:
+.IP
+% genisoimage \-o cd.iso cd_dir
+.PP
+To create a CD with Rock Ridge extensions of
+the source directory
+.IR cd_dir :
+.IP
+% genisoimage \-o cd.iso \-R cd_dir
+.PP
+To create a CD with Rock Ridge extensions of
+the source directory
+.I cd_dir
+where all files have at least read permission and all files
+are owned by
+.IR root ,
+call:
+.IP
+% genisoimage \-o cd.iso \-r cd_dir
+.PP
+To write a tar archive directly to a CD that will later contain a simple
+ISO9660 filesystem with the tar archive call:
+.IP
+% tar cf \- . | genisoimage \-stream\-media\-size 333000 | \(rs
+.br
+     wodim dev=b,t,l \-dao tsize=333000s \-
+.PP
+To create a HFS hybrid CD with the Joliet and Rock Ridge extensions of
+the source directory
+.IR cd_dir :
+.IP
+% genisoimage \-o cd.iso \-R \-J \-hfs cd_dir
+.PP
+To create a HFS hybrid CD from the source directory 
+.I cd_dir
+that contains
+Netatalk Apple/Unix files:
+.IP
+% genisoimage \-o cd.iso \-\-netatalk cd_dir
+.PP
+To create a HFS hybrid CD from the source directory
+.IR cd_dir ,
+giving all files
+CREATOR and TYPES based on just their filename extensions listed in the file 
+"mapping".:
+.IP
+% genisoimage \-o cd.iso \-map mapping cd_dir
+.PP
+To create a CD with the Apple Extensions to ISO9660, from the source
+directories
+.I cd_dir
+and
+.IR another_dir .
+Files in all the known Apple/Unix format
+are decoded and any other files are given CREATOR and TYPE based on their
+magic number given in the file
+.IR magic :
+.IP
+% genisoimage \-o cd.iso \-apple \-magic magic \-probe \(rs
+.br
+        cd_dir another_dir
+.PP
+The following example puts different files on the CD that all have
+the name README, but have different contents when seen as a
+ISO9660/Rock Ridge, Joliet or HFS CD.
+.PP
+Current directory contains:
+.IP
+% ls \-F
+.br
+README.hfs     README.joliet  README.Unix    cd_dir/
+.PP
+The following command puts the contents of the directory
+.I cd_dir
+on the
+CD along with the three README files \(em but only one will be seen from
+each of the three filesystems:
+.IP
+% genisoimage \-o cd.iso \-hfs \-J \-r \-graft\-points \(rs
+.br
+        \-hide README.hfs \-hide README.joliet \(rs
+.br
+        \-hide\-joliet README.hfs \-hide\-joliet README.Unix \(rs
+.br
+        \-hide\-hfs README.joliet \-hide\-hfs README.Unix \(rs
+.br
+        README=README.hfs README=README.joliet \(rs
+.br
+        README=README.Unix cd_dir
+.PP
+i.e. the file README.hfs will be seen as README on the HFS CD and the
+other two README files will be hidden. Similarly for the Joliet and
+ISO9660/Rock Ridge CD.
+.PP
+There are probably all sorts of strange results possible with
+combinations of the hide options ...
+.\" ----------------------------------------
+.SH NOTES
+.PP
+.B genisoimage
+may safely be installed suid root. This may be needed to allow
+.B genisoimage
+to read the previous session when creating a multisession image.
+.PP
+If 
+.B genisoimage 
+is creating a filesystem image with Rock Ridge attributes and the
+directory nesting level of the source directory tree is too much
+for ISO9660, 
+.B genisoimage 
+will do deep directory relocation.
+This results in a directory called
+.B RR_MOVED
+in the root directory of the CD. You cannot avoid this directory.
+.PP
+Many boot code options for different platforms are mutualy exclusive because
+the boot blocks cannot coexist, ie. different platforms share the same data
+locations in the image. See
+http://lists.debian.org/debian-cd/2006/12/msg00109.html for details.
+.\" ----------------------------------------
+.SH BUGS
+.PP
+Any files that have hard links to files not in the tree being copied to the
+ISO9660 filesystem will have an incorrect file reference count.
+.PP
+Does not check for SUSP record(s) in `.' entry of the
+root directory to verify the existence of Rock Ridge
+enhancements.
+This problem is present when reading old sessions while
+adding data in multisession mode.
+.PP
+Does not properly read relocated directories in multisession
+mode when adding data.
+Any relocated deep directory is lost if the new session does not
+include the deep directory.
+.\" Repeat by: create first session with deep directory relocation
+.\" then add new session with a single dir that differs from the
+.\" old deep path.
+.PP
+Does not re-use
+.I RR_MOVED
+when doing multisession from
+.IR TRANS.TBL .
+.PP
+Does not create whole_name entry for
+.I RR_MOVED
+in multisession mode.
+.PP
+There may be other bugs.  Please, report them to the maintainers.
+.\" ----------------------------------------
+.SH "HFS PROBLEMS/LIMITATIONS"
+I have had to make several assumptions on how I expect the modified
+libhfs routines to work, however there may be situations that either
+I haven't thought of, or come across when these assumptions fail.
+Therefore I can't guarantee that
+.B genisoimage
+will work as expected
+(although I haven't had a major problem yet). Most of the HFS features work
+fine, but some are not fully tested. These are marked as
+.I Alpha
+above.
+.PP
+Although HFS filenames appear to support uppercase and lowercase letters,
+the filesystem is case-insensitive, i.e., the filenames
+.IR aBc " and "AbC
+are the same. If a file is found in a directory with the same HFS name,
+.B genisoimage
+will attempt to make a unique name by adding `_' characters
+to one of the filenames.
+.PP
+HFS file/directory names that share the first 31 characters have
+`_N' (a decimal number) substituted for the last few characters
+to generate unique names.
+.PP
+Care must be taken when "grafting" Apple/Unix files or directories (see
+above for the method and syntax involved). It is not possible to use a
+new name for an Apple/Unix encoded file/directory. e.g. If a Apple/Unix
+encoded file called
+.I oldname
+is to added to the CD, you cannot use the command line:
+.IP
+genisoimage \-o output.raw \-hfs \-graft\-points newname=oldname cd_dir
+.PP
+.B genisoimage
+will be unable to decode
+.IR oldname .
+However, you can graft
+Apple/Unix encoded files or directories as long as you do not attempt to
+give them new names as above.
+.PP
+When creating an HFS volume with the multisession options,
+.B \-M
+and
+.BR \-C ,
+only files in the last session will be in the HFS volume. i.e.
+.B genisoimage
+cannot
+.I add
+existing files from previous sessions to the HFS volume.
+.PP
+However, if each session is created with
+.BR \-part ,
+each session will appear as 
+separate volumes when mounted on a Mac. In this case, it is worth using
+.BR \-V " or " \-hfs\-volid
+to give each session a unique volume name,
+otherwise each "volume" will appear on the Desktop with the same name.
+.PP
+Symbolic links (as with all other non-regular files) are not added to
+the HFS directory.
+.PP
+Hybrid volumes may be larger than pure ISO9660 volumes
+containing the same data. In some cases (e.g. DVD sized volumes) the
+difference can be significant. As an HFS volume gets bigger, so does the
+allocation block size (the smallest amount of space a file can occupy).
+For a 650MB CD, the allocation block is 10kB, for a 4.7GB DVD it will be
+about 70kB.
+.PP
+The maximum number of files in an HFS volume is about 65500 \(em although
+the real limit will be somewhat less than this.
+.PP
+The resulting hybrid volume can be accessed on a Unix machine by using
+the hfsutils routines. However, no changes can be made to the volume as it
+is set as
+.B locked.
+The option
+.B \-hfs\-unlock
+will create an output image that is unlocked \(em however no changes should be
+made to the contents of the volume (unless you really know what you are
+doing) as it's not a "real" HFS volume.
+.PP
+.B \-mac\-name
+will not currently work with
+.B \-T
+\(em the Unix name will be used in the
+.I TRANS.TBL
+file, not the Macintosh name.
+.PP
+Although 
+.B genisoimage
+does not alter the contents of a file, if a binary file has its TYPE
+set as
+.IR TEXT ", it " may
+be read incorrectly on a Macintosh. Therefore a better choice for the
+default TYPE may be
+.IR ???? .
+.PP
+.B \-mac\-boot\-file
+may not work at all...
+.PP
+May not work with PC Exchange v2.2 or higher files (available with MacOS 8.1).
+DOS media containing PC Exchange files should be mounted as type
+.B msdos
+(not
+.BR vfat )
+when using Linux.
+.PP
+The SFM format is only partially supported \(em see
+.B HFS MACINTOSH FILE FORMATS
+section above.
+.PP
+It is not possible to use
+.BR \-sparc\-boot " or " \-generic\-boot " with"
+.BR \-boot\-hfs\-file " or " \-prep\-boot .
+.PP
+.B genisoimage
+should be able to create HFS hybrid images over 4Gb, although this has not
+been fully tested.
+.\" ----------------------------------------
+.SH "SEE ALSO"
+.BR genisoimagerc (5),
+.BR wodim (1),
+.BR mkzftree (8),
+.BR magic (5).
+.\" ----------------------------------------
+.SH AUTHORS
+.B genisoimage
+is derived from
+.B mkisofs
+from the
+.B cdrtools 2.01.01a08
+package from May 2006 (with few updates extracted from cdrtools 2.01.01a24 from
+March 2007) from .IR http://cdrecord.berlios.de/ ,
+but is now part of the
+.B cdrkit
+suite, maintained by Joerg Jaspert, Eduard Bloch, Steve McIntyre, Peter
+Samuelson, Christian Fromme, Ben Hutchings, and other contributors.
+The maintainers can be contacted at
+.IR debburn-devel@lists.alioth.debian.org ,
+or see the
+.B cdrkit
+project web site at
+.IR http://www.cdrkit.org/ .
+.PP
+Eric Youngdale wrote the first versions (1993\(en1998) of
+.BR mkisofs .
+J\(:org Schilling wrote the SCSI transport library and its
+interface, and has maintained
+.B mkisofs
+since 1999.  James Pearson wrote the HFS hybrid code, using
+.I libhfs
+by Robert Leslie.  Pearson, Schilling, Jungshik Shin and Jaakko
+Heinonen contributed to the character set conversion code.  The
+.B cdrkit
+maintainers have maintained
+.B genisoimage
+since 2006.
+.PP
+.nf
+Copyright 1993-1998 by Yggdrasil Computing, Inc.
+Copyright 1996-1997 by Robert Leslie
+Copyright 1997-2001 by James Pearson
+Copyright 1999-2006 by J\(:org Schilling
+Copyright 2007 by J\(:org Schilling (originating few updates)
+Copyright 2002-2003 by Jungshik Shin
+Copyright 2003 by Jaakko Heinonen
+Copyright 2006 by the Cdrkit maintainers
+.fi
+.PP
+If you want to take part in the development of
+.BR genisoimage ,
+you may join the
+.B cdrkit
+developer mailing list by following the instructions on
+.IR http://alioth.debian.org/mail/?group_id=31006 .
+The email address of the list is
+.IR debburn-devel@lists.alioth.debian.org .
+This is also the address for user support questions.  Note that
+.BR cdrkit " and " cdrtools
+are not affiliated.
+.PP
+.\" ----------------------------------------
+.SH ACKNOWLEDGEMENTS
+UNIX is a registered trademark of The Open Group in the US and other countries.
diff --git a/genisoimage/genisoimage.c b/genisoimage/genisoimage.c
new file mode 100644 (file)
index 0000000..46f0cb7
--- /dev/null
@@ -0,0 +1,3831 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/*
+ *
+ * Patched version with stuff from the Debian's cdrtools.
+ * Replaced various warnings/disclaimers with more simple ones.
+ *
+ * Eduard Bloch <blade@debian.org>
+*/
+/* @(#)mkisofs.c       1.167 06/01/30 joerg */
+/* Parts from @(#)mkisofs.c    1.206 07/02/26 joerg */
+/*
+ * Program genisoimage.c - generate iso9660 filesystem  based upon directory
+ * tree on hard disk.
+ *
+ * Written by Eric Youngdale (1993).
+ *
+ * Copyright 1993 Yggdrasil Computing, Incorporated
+ * Copyright (c) 1999,2000-2004 J. Schilling
+ *
+ * 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.
+ */
+
+/* APPLE_HYB James Pearson j.pearson@ge.ucl.ac.uk 22/2/2000 */
+
+#include <mconfig.h>
+#include "genisoimage.h"
+#include <errno.h>
+#include <timedefs.h>
+#include <fctldefs.h>
+#include <ctype.h>
+#include "match.h"
+#include "exclude.h"
+#include <unls.h>      /* For UNICODE translation */
+#include <schily.h>
+#ifdef UDF
+#include "udf.h"
+#endif
+
+#ifdef NEED_O_BINARY
+#include <io.h>                                        /* for setmode() prototype */
+#endif
+
+#ifdef HAVE_GETOPT_H
+#include <getopt.h>
+#else
+#include "getopt.h"
+extern int      optind;
+extern char     *optarg;
+#endif
+
+#ifdef VMS
+#include "vms.h"
+#endif
+
+#ifdef no_more_needed
+#ifdef __NetBSD__
+#include <sys/resource.h>
+#endif
+#endif /* no_more_needed */
+
+#ifdef USE_ICONV
+#include <locale.h>
+#include <langinfo.h>
+#endif
+
+struct directory *root = NULL;
+int            path_ind;
+
+char   version_string[] = "genisoimage " CDRKIT_VERSION;
+
+char           *outfile;
+FILE           *discimage;
+unsigned int   next_extent     = 0;
+unsigned int   last_extent     = 0;
+unsigned int   session_start   = 0;
+unsigned int   path_table_size = 0;
+unsigned int   path_table[4]   = {0, };
+unsigned int   path_blocks     = 0;
+
+
+unsigned int   jpath_table_size = 0;
+unsigned int   jpath_table[4]  = {0, };
+unsigned int   jpath_blocks    = 0;
+
+struct iso_directory_record root_record;
+struct iso_directory_record jroot_record;
+
+char   *extension_record = NULL;
+int    extension_record_extent = 0;
+int    extension_record_size = 0;
+
+/* These variables are associated with command line options */
+int    check_oldnames = 0;
+int    check_session = 0;
+int    use_eltorito = 0;
+int    hard_disk_boot = 0;
+int    not_bootable = 0;
+int    no_emul_boot = 0;
+int    load_addr = 0;
+int    load_size = 0;
+int    boot_info_table = 0;
+int    use_alphaboot = 0;
+int    use_sparcboot = 0;
+int    use_hppaboot = 0;
+int    use_mipsboot = 0;
+int    use_mipselboot = 0;
+int    use_sunx86boot = 0;
+int    use_genboot = 0;
+int    use_RockRidge = 0;
+int    use_XA = 0;
+int    osecsize = 0;   /* Output-sector size, 0 means default secsize 2048 */
+int    use_Joliet = 0;
+int    jlen = JMAX;    /* maximum Joliet file name length */
+int    verbose = 1;
+int    debug = 0;
+int    gui = 0;
+int    all_files = 1;  /* New default is to include all files */
+int    follow_links = 0;
+#ifdef IS_CYGWIN
+int    cache_inodes = 0; /* Do not cache inodes on Cygwin by default */
+#else
+int    cache_inodes = 1; /* Cache inodes if OS has unique inodes */
+#endif
+int    rationalize = 0;
+int    rationalize_uid = 0;
+int    rationalize_gid = 0;
+int    rationalize_filemode = 0;
+int    rationalize_dirmode = 0;
+uid_t  uid_to_use = 0;         /* when rationalizing uid */
+gid_t  gid_to_use = 0;         /* when rationalizing gid */
+int    filemode_to_use = 0;    /* if non-zero, when rationalizing file mode */
+int    dirmode_to_use = 0;     /* if non-zero, when rationalizing dir mode */
+int    new_dir_mode = 0555;
+int    generate_tables = 0;
+int    dopad = 1;      /* Now default to do padding */
+int    print_size = 0;
+int    split_output = 0;
+char   *icharset = NULL;       /* input charset to convert to UNICODE */
+char   *ocharset = NULL;       /* output charset to convert from UNICODE */
+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;
+char   *boot_catalog = BOOT_CATALOG_DEFAULT;
+char   *boot_image = BOOT_IMAGE_DEFAULT;
+char   *genboot_image = BOOT_IMAGE_DEFAULT;
+int    ucs_level = 3;          /* We now have Unicode tables so use level 3 */
+int    volume_set_size = 1;
+int    volume_sequence_number = 1;
+
+struct eltorito_boot_entry_info *first_boot_entry = NULL;
+struct eltorito_boot_entry_info *last_boot_entry = NULL;
+struct eltorito_boot_entry_info *current_boot_entry = NULL;
+
+int    use_graft_ptrs;         /* Use graft points */
+int    jhide_trans_tbl;        /* Hide TRANS.TBL from Joliet tree */
+int    hide_rr_moved;          /* Name RR_MOVED .rr_moved in Rock Ridge tree */
+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    no_rr = 0;              /* Do not use RR attributes from old session */
+int    force_rr = 0;           /* Force to use RR attributes from old session */
+Uint   RR_relocation_depth = 6; /* Violates iso9660, but most systems work */
+int    iso9660_level = 1;
+int    iso9660_namelen = LEN_ISONAME; /* 31 characters, may be set to 37 */
+int    full_iso9660_filenames = 0; /* Full 31 character iso9660 filenames */
+int    relaxed_filenames = 0;  /* For Amiga.  Disc will not work with DOS */
+int    allow_lowercase = 0;    /* Allow lower case letters */
+int    allow_multidot = 0;     /* Allow more than on dot in filename */
+int    iso_translate = 1;      /* 1 == enables '#', '-' and '~' removal */
+int    allow_leading_dots = 0; /* DOS cannot read names with leading dots */
+int    allow_limited_size = 0; /* Let the user to allow the trick explicitely */
+#ifdef VMS
+int    use_fileversion = 1;    /* Use file version # from filesystem */
+#else
+int    use_fileversion = 0;    /* Use file version # from filesystem */
+#endif
+int    split_SL_component = 1; /* circumvent a bug in the SunOS driver */
+int    split_SL_field = 1;     /* circumvent a bug in the SunOS */
+char   *trans_tbl = "TRANS.TBL"; /* default name for translation table */
+int    stream_media_size = 0;  /* # of blocks on the media */
+char   *stream_filename = NULL; /* Stream file, 0 to use default STREAM.IMG */
+
+#ifdef APPLE_HYB
+int    apple_hyb = 0;          /* create HFS hybrid flag */
+int    apple_ext = 0;          /* create HFS extensions flag */
+int    apple_both = 0;         /* common flag (for above) */
+int    hfs_extra = 0;          /* extra HFS blocks added to end of ISO vol */
+int    use_mac_name = 0;       /* use Mac name for ISO/Joliet/RR flag */
+hce_mem        *hce;                   /* libhfs/genisoimage extras */
+char   *hfs_boot_file = 0;     /* name of HFS boot file */
+int    gen_pt = 0;             /* generate HFS partition table */
+char   *autoname = 0;          /* AutoStart filename */
+char   *magic_filename = 0;    /* name of magic file */
+int    probe = 0;              /* search files for HFS/Unix type */
+int    nomacfiles = 0;         /* don't look for Mac/Unix files */
+int    hfs_select = 0;         /* Mac/Unix types to select */
+int    create_dt = 1;          /* create the Desktp files */
+int    afe_size = 0;           /* Apple File Exchange block size */
+int    hfs_last = MAG_LAST;    /* process magic file after map file */
+char   *deftype = APPLE_TYPE_DEFAULT;  /* default Apple TYPE */
+char   *defcreator = APPLE_CREATOR_DEFAULT;    /* default Apple CREATOR */
+char   *hfs_volume_id = NULL;  /* HFS volume ID */
+int    icon_pos = 0;           /* Keep icon position */
+char   *hfs_icharset = NULL;   /* input HFS charset name */
+char    *hfs_ocharset = NULL;  /* output HFS charset name */
+int    hfs_lock = 1;           /* lock HFS volume (read-only) */
+char   *hfs_bless = NULL;      /* name of folder to 'bless' (System Folder) */
+char   *hfs_parms = NULL;      /* low level HFS parameters */
+
+#ifdef PREP_BOOT
+char   *prep_boot_image[4];
+int    use_prep_boot = 0;
+int    use_chrp_boot = 0;
+#endif /* PREP_BOOT */
+#endif /* APPLE_HYB */
+
+#ifdef UDF
+int    use_udf = 0;
+#endif
+
+#ifdef DVD_VIDEO
+int    dvd_video = 0;
+#endif
+
+#ifdef SORTING
+int    do_sort = 0;            /* sort file data */
+#endif /* SORTING */
+
+#ifdef USE_ICONV
+int   iconv_possible;
+#endif
+
+struct unls_table *in_nls = NULL;  /* input UNICODE conversion table */
+struct unls_table *out_nls = NULL; /* output UNICODE conversion table */
+#ifdef APPLE_HYB
+struct unls_table *hfs_inls = NULL; /* input HFS UNICODE conversion table */
+struct unls_table *hfs_onls = NULL; /* output HFS UNICODE conversion table */
+#endif /* APPLE_HYB */
+
+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},
+#ifdef APPLE_HYB
+       {"HFS_TYPE", &deftype},
+       {"HFS_CREATOR", &defcreator},
+#endif /* APPLE_HYB */
+       {NULL, NULL}
+};
+
+char           *merge_warn_msg=0; /* use as pointer and boolean */
+
+/*
+ * In case it isn't obvious, the option handling code was ripped off
+ * from GNU-ld.
+ */
+struct ld_option {
+       /* The long option information.  */
+       struct option   opt;
+       /* The short option with the same meaning ('\0' if none).  */
+       char            shortopt;
+       /* The name of the argument (NULL if none).  */
+       const char      *arg;
+       /*
+        * The documentation string.  If this is NULL, this is a synonym for
+        * the previous option.
+        */
+       const char      *doc;
+       enum {
+               /* Use one dash before long option name.  */
+               ONE_DASH,
+               /* Use two dashes before long option name.  */
+               TWO_DASHES,
+               /* Don't mention this option in --help output.  */
+               NO_HELP
+       } control;
+};
+
+/*
+ * Codes used for the long options with no short synonyms. Note that all these
+ * values must not be ASCII or EBCDIC.
+ */
+#define        OPTION_HELP                     1000
+#define        OPTION_QUIET                    1001
+#define        OPTION_NOSPLIT_SL_COMPONENT     1002
+#define        OPTION_NOSPLIT_SL_FIELD         1003
+#define        OPTION_PRINT_SIZE               1004
+#define        OPTION_SPLIT_OUTPUT             1005
+#define        OPTION_ABSTRACT                 1006
+#define        OPTION_BIBLIO                   1007
+#define        OPTION_COPYRIGHT                1008
+#define        OPTION_SYSID                    1009
+#define        OPTION_VOLSET                   1010
+#define        OPTION_VOLSET_SIZE              1011
+#define        OPTION_VOLSET_SEQ_NUM           1012
+#define        OPTION_I_HIDE                   1013
+#define        OPTION_J_HIDE                   1014
+#define        OPTION_LOG_FILE                 1015
+#define        OPTION_PVERSION                 1016
+#define        OPTION_NOBAK                    1017
+#define        OPTION_SPARCLABEL               1018
+#define        OPTION_HARD_DISK_BOOT           1019
+#define        OPTION_NO_EMUL_BOOT             1020
+#define        OPTION_NO_BOOT                  1021
+#define        OPTION_BOOT_LOAD_ADDR           1022
+#define        OPTION_BOOT_LOAD_SIZE           1023
+#define        OPTION_BOOT_INFO_TABLE          1024
+#define        OPTION_HIDE_TRANS_TBL           1025
+#define        OPTION_HIDE_RR_MOVED            1026
+#define        OPTION_GUI                      1027
+#define        OPTION_TRANS_TBL                1028
+#define        OPTION_P_LIST                   1029
+#define        OPTION_I_LIST                   1030
+#define        OPTION_J_LIST                   1031
+#define        OPTION_X_LIST                   1032
+#define        OPTION_NO_RR                    1033
+#define        OPTION_JCHARSET                 1034
+#define        OPTION_PAD                      1035
+#define        OPTION_H_HIDE                   1036
+#define        OPTION_H_LIST                   1037
+#define        OPTION_CHECK_OLDNAMES           1038
+
+#ifdef SORTING
+#define        OPTION_SORT                     1039
+#endif /* SORTING */
+#define        OPTION_UCS_LEVEL                1040
+#define        OPTION_ISO_TRANSLATE            1041
+#define        OPTION_ISO_LEVEL                1042
+#define        OPTION_RELAXED_FILENAMES        1043
+#define        OPTION_ALLOW_LOWERCASE          1044
+#define        OPTION_ALLOW_MULTIDOT           1045
+#define        OPTION_USE_FILEVERSION          1046
+#define        OPTION_MAX_FILENAMES            1047
+#define        OPTION_ALT_BOOT                 1048
+#define        OPTION_USE_GRAFT                1049
+
+#define        OPTION_INPUT_CHARSET            1050
+#define        OPTION_OUTPUT_CHARSET           1051
+
+#define        OPTION_NOPAD                    1052
+#define        OPTION_UID                      1053
+#define        OPTION_GID                      1054
+#define        OPTION_FILEMODE                 1055
+#define        OPTION_DIRMODE                  1056
+#define        OPTION_NEW_DIR_MODE             1057
+#define        OPTION_CACHE_INODES             1058
+#define        OPTION_NOCACHE_INODES           1059
+
+#define        OPTION_CHECK_SESSION            1060
+#define        OPTION_FORCE_RR                 1061
+
+#define        OPTION_DEBUG                    1062
+
+#define        OPTION_JLONG                    1063
+
+#define        OPTION_STREAM_FILE_NAME         1064
+#define        OPTION_STREAM_CD_SIZE           1065
+
+#define        OPTION_XA                       1066
+#define        OPTION_XA_RATIONALIZED          1067
+
+#define        OPTION_SUNX86BOOT               1068
+#define        OPTION_SUNX86LABEL              1069
+
+#define        OPTION_ALLOW_LEADING_DOTS       1070
+#define        OPTION_PUBLISHER                1071
+
+#ifdef         JIGDO_TEMPLATE
+#define        OPTION_JTT_OUTPUT               1101
+#define        OPTION_JTJ_OUTPUT               1102
+#define        OPTION_JT_MIN_SIZE              1103
+#define        OPTION_JT_PATH_MAP              1104
+#define        OPTION_JT_MD5_LIST              1105
+#define        OPTION_JT_INCLUDE               1106
+#define        OPTION_JT_EXCLUDE               1107
+#define        OPTION_JT_COMPRESS_ALGO 1108
+
+#define OPTION_JT_CHECKSUM_ALGO_ISO   1120
+#define OPTION_JT_CHECKSUM_ALGO_TMPL  1121
+#endif
+
+#define        OPTION_BOOTALPHA                1200
+
+#define        OPTION_HPPA_CMDLINE             1210
+#define        OPTION_HPPA_KERNEL_32           1211
+#define        OPTION_HPPA_KERNEL_64           1212
+#define        OPTION_HPPA_BOOTLOADER          1213
+#define        OPTION_HPPA_RAMDISK             1214
+
+#define        OPTION_BOOTMIPS                 1220
+
+#define        OPTION_BOOTMIPSEL               1230
+
+#ifdef UDF
+#define        OPTION_UDF                      1500
+#endif
+#ifdef DVD_VIDEO
+#define        OPTION_DVD                      1501
+#endif
+
+#ifdef APPLE_HYB
+#define        OPTION_CAP                      2000
+#define        OPTION_NETA                     2001
+#define        OPTION_DBL                      2002
+#define        OPTION_ESH                      2003
+#define        OPTION_FE                       2004
+#define        OPTION_SGI                      2005
+#define        OPTION_MBIN                     2006
+#define        OPTION_SGL                      2007
+/* aliases */
+#define        OPTION_USH                      2008
+#define        OPTION_XIN                      2009
+
+#define        OPTION_DAVE                     2010
+#define        OPTION_SFM                      2011
+#define        OPTION_XDBL                     2012
+#define        OPTION_XHFS                     2013
+
+#define        OPTION_PROBE                    2020
+#define        OPTION_MACNAME                  2021
+#define        OPTION_NOMACFILES               2022
+#define        OPTION_BOOT_HFS_FILE            2023
+#define        OPTION_MAGIC_FILE               2024
+
+#define        OPTION_HFS_LIST                 2025
+
+#define        OPTION_GEN_PT                   2026
+
+#define        OPTION_CREATE_DT                2027
+#define        OPTION_HFS_HIDE                 2028
+
+#define        OPTION_AUTOSTART                2029
+#define        OPTION_BSIZE                    2030
+#define        OPTION_HFS_VOLID                2031
+#define        OPTION_PREP_BOOT                2032
+#define        OPTION_ICON_POS                 2033
+
+#define        OPTION_HFS_TYPE                 2034
+#define        OPTION_HFS_CREATOR              2035
+
+#define        OPTION_ROOT_INFO                2036
+
+#define        OPTION_HFS_INPUT_CHARSET        2037
+#define        OPTION_HFS_OUTPUT_CHARSET       2038
+
+#define        OPTION_HFS_UNLOCK               2039
+#define        OPTION_HFS_BLESS                2040
+#define        OPTION_HFS_PARMS                2041
+
+#define        OPTION_CHRP_BOOT                2042
+
+#define        OPTION_RELOC_ROOT               2043
+#define        OPTION_RELOC_OLD_ROOT           2044
+
+#define        OPTION_MAP_FILE                 2045
+
+#define        OPTION_ALLOW_LIMITED_SIZE 2046
+
+#endif /* APPLE_HYB */
+
+static int     save_pname = 0;
+
+static const struct ld_option ld_options[] =
+{
+       {{"nobak", no_argument, NULL, OPTION_NOBAK},
+       '\0', NULL, "Do not include backup files", ONE_DASH},
+       {{"no-bak", no_argument, NULL, OPTION_NOBAK},
+       '\0', NULL, "Do not include backup files", ONE_DASH},
+       {{"abstract", required_argument, NULL, OPTION_ABSTRACT},
+       '\0', "FILE", "Set Abstract filename", ONE_DASH},
+       {{"appid", required_argument, NULL, 'A'},
+       'A', "ID", "Set Application ID", ONE_DASH},
+       {{"biblio", required_argument, NULL, OPTION_BIBLIO},
+       '\0', "FILE", "Set Bibliographic filename", ONE_DASH},
+       {{"cache-inodes", no_argument, NULL, OPTION_CACHE_INODES},
+       '\0', NULL, "Cache inodes (needed to detect hard links)", ONE_DASH},
+       {{"no-cache-inodes", no_argument, NULL, OPTION_NOCACHE_INODES},
+       '\0', NULL, "Do not cache inodes (if filesystem has no unique unides)", ONE_DASH},
+       {{"check-oldnames", no_argument, NULL, OPTION_CHECK_OLDNAMES},
+       '\0', NULL, "Check all imported ISO9660 names from old session", ONE_DASH},
+       {{"check-session", required_argument, NULL, OPTION_CHECK_SESSION},
+       '\0', "FILE", "Check all ISO9660 names from previous session", ONE_DASH},
+       {{"copyright", required_argument, NULL, OPTION_COPYRIGHT},
+       '\0', "FILE", "Set Copyright filename", ONE_DASH},
+       {{"debug", no_argument, NULL, OPTION_DEBUG},
+       '\0', NULL, "Set debug flag", ONE_DASH},
+       {{"eltorito-boot", required_argument, NULL, 'b'},
+       'b', "FILE", "Set El Torito boot image name", ONE_DASH},
+       {{"eltorito-alt-boot", no_argument, NULL, OPTION_ALT_BOOT},
+       '\0', NULL, "Start specifying alternative El Torito boot parameters", ONE_DASH},
+       {{"sparc-boot", required_argument, NULL, 'B'},
+       'B', "FILES", "Set sparc boot image names", ONE_DASH},
+       {{"sunx86-boot", required_argument, NULL, OPTION_SUNX86BOOT},
+       '\0', "FILES", "Set sunx86 boot image names", ONE_DASH},
+       {{"generic-boot", required_argument, NULL, 'G'},
+       'G', "FILE", "Set generic boot image name", ONE_DASH},
+       {{"sparc-label", required_argument, NULL, OPTION_SPARCLABEL},
+       '\0', "label text", "Set sparc boot disk label", ONE_DASH},
+       {{"sunx86-label", required_argument, NULL, OPTION_SUNX86LABEL},
+       '\0', "label text", "Set sunx86 boot disk label", ONE_DASH},
+       {{"eltorito-catalog", required_argument, NULL, 'c'},
+       'c', "FILE", "Set El Torito boot catalog name", ONE_DASH},
+       {{"cdrecord-params", required_argument, NULL, 'C'},
+       'C', "PARAMS", "Magic paramters from cdrecord", ONE_DASH},
+       {{"omit-period", no_argument, NULL, 'd'},
+       'd', NULL, "Omit trailing periods from filenames (violates ISO9660)", ONE_DASH},
+       {{"dir-mode", required_argument, NULL, OPTION_DIRMODE},
+       '\0', "mode", "Make the mode of all directories this mode.", ONE_DASH},
+       {{"disable-deep-relocation", no_argument, NULL, 'D'},
+       'D', NULL, "Disable deep directory relocation (violates ISO9660)", ONE_DASH},
+       {{"file-mode", required_argument, NULL, OPTION_FILEMODE},
+       '\0', "mode", "Make the mode of all plain files this mode.", ONE_DASH},
+       {{"follow-links", no_argument, NULL, 'f'},
+       'f', NULL, "Follow symbolic links", ONE_DASH},
+       {{"gid", required_argument, NULL, OPTION_GID},
+       '\0', "gid", "Make the group owner of all files this gid.",
+       ONE_DASH},
+       {{"graft-points", no_argument, NULL, OPTION_USE_GRAFT},
+       '\0', NULL, "Allow to use graft points for filenames", ONE_DASH},
+       {{"root", required_argument, NULL, OPTION_RELOC_ROOT},
+       '\0', "DIR", "Set root directory for all new files and directories", ONE_DASH},
+       {{"old-root", required_argument, NULL, OPTION_RELOC_OLD_ROOT},
+       '\0', "DIR", "Set root directory in previous session that is searched for files", ONE_DASH},
+       {{"help", no_argument, NULL, OPTION_HELP},
+       '\0', NULL, "Print option help", ONE_DASH},
+       {{"hide", required_argument, NULL, OPTION_I_HIDE},
+       '\0', "GLOBFILE", "Hide ISO9660/RR file", ONE_DASH},
+       {{"hide-list", required_argument, NULL, OPTION_I_LIST},
+       '\0', "FILE", "File with list of ISO9660/RR files to hide", ONE_DASH},
+       {{"hidden", required_argument, NULL, OPTION_H_HIDE},
+       '\0', "GLOBFILE", "Set hidden attribute on ISO9660 file", ONE_DASH},
+       {{"hidden-list", required_argument, NULL, OPTION_H_LIST},
+       '\0', "FILE", "File with list of ISO9660 files with hidden attribute", ONE_DASH},
+       {{"hide-joliet", required_argument, NULL, OPTION_J_HIDE},
+       '\0', "GLOBFILE", "Hide Joliet file", ONE_DASH},
+       {{"hide-joliet-list", required_argument, NULL, OPTION_J_LIST},
+       '\0', "FILE", "File with list of Joliet files to hide", ONE_DASH},
+       {{"hide-joliet-trans-tbl", no_argument, NULL, OPTION_HIDE_TRANS_TBL},
+       '\0', NULL, "Hide TRANS.TBL from Joliet tree", ONE_DASH},
+       {{"hide-rr-moved", no_argument, NULL, OPTION_HIDE_RR_MOVED},
+       '\0', NULL, "Rename RR_MOVED to .rr_moved in Rock Ridge tree", ONE_DASH},
+       {{"gui", no_argument, NULL, OPTION_GUI},
+       '\0', NULL, "Switch behaviour for GUI", ONE_DASH},
+       {{NULL, required_argument, NULL, 'i'},
+       'i', "ADD_FILES", "No longer supported", TWO_DASHES},
+       {{"input-charset", required_argument, NULL, OPTION_INPUT_CHARSET},
+       '\0', "CHARSET", "Local input charset for file name conversion", ONE_DASH},
+       {{"output-charset", required_argument, NULL, OPTION_OUTPUT_CHARSET},
+       '\0', "CHARSET", "Output charset for file name conversion", ONE_DASH},
+       {{"iso-level", required_argument, NULL, OPTION_ISO_LEVEL},
+       '\0', "LEVEL", "Set ISO9660 conformance level (1..3) or 4 for ISO9660 version 2", ONE_DASH},
+       {{"joliet", no_argument, NULL, 'J'},
+       'J', NULL, "Generate Joliet directory information", ONE_DASH},
+       {{"joliet-long", no_argument, NULL, OPTION_JLONG},
+       '\0', NULL, "Allow Joliet file names to be 103 Unicode characters", ONE_DASH},
+       {{"jcharset", required_argument, NULL, OPTION_JCHARSET},
+       '\0', "CHARSET", "Local charset for Joliet directory information", ONE_DASH},
+       {{"full-iso9660-filenames", no_argument, NULL, 'l'},
+       'l', NULL, "Allow full 31 character filenames for ISO9660 names", ONE_DASH},
+       {{"max-iso9660-filenames", no_argument, NULL, OPTION_MAX_FILENAMES},
+       '\0', NULL, "Allow 37 character filenames for ISO9660 names (violates ISO9660)", ONE_DASH},
+
+       {{"allow-limited-size", no_argument, NULL, OPTION_ALLOW_LIMITED_SIZE},
+       '\0', NULL, "Allow different file sizes in ISO9660/UDF on large files", ONE_DASH},
+
+       {{"allow-leading-dots", no_argument, NULL, OPTION_ALLOW_LEADING_DOTS},
+       '\0', NULL, "Allow ISO9660 filenames to start with '.' (violates ISO9660)", ONE_DASH},
+       {{"ldots", no_argument, NULL, OPTION_ALLOW_LEADING_DOTS},
+       '\0', NULL, "Allow ISO9660 filenames to start with '.' (violates ISO9660)", ONE_DASH},
+       {{"allow-leading-dots", no_argument, NULL, 'L'},
+       'L', NULL, "Allow ISO9660 filenames to start with '.' (violates ISO9660)", ONE_DASH},
+
+       {{"log-file", required_argument, NULL, OPTION_LOG_FILE},
+       '\0', "LOG_FILE", "Re-direct messages to LOG_FILE", ONE_DASH},
+       {{"exclude", required_argument, NULL, 'm'},
+       'm', "GLOBFILE", "Exclude file name", ONE_DASH},
+       {{"exclude-list", required_argument, NULL, OPTION_X_LIST},
+       '\0', "FILE", "File with list of file names to exclude", ONE_DASH},
+       {{"pad", no_argument, NULL, OPTION_PAD},
+       0, NULL, "Pad output to a multiple of 32k (default)", ONE_DASH},
+       {{"no-pad", no_argument, NULL, OPTION_NOPAD},
+       0, NULL, "Do not pad output to a multiple of 32k", ONE_DASH},
+       {{"prev-session", required_argument, NULL, 'M'},
+       'M', "FILE", "Set path to previous session to merge", ONE_DASH},
+       {{"dev", required_argument, NULL, 'M'},
+       '\0', "SCSIdev", "Set path to previous session to merge", ONE_DASH},
+       {{"omit-version-number", no_argument, NULL, 'N'},
+       'N', NULL, "Omit version number from ISO9660 filename (violates ISO9660)", ONE_DASH},
+       {{"new-dir-mode", required_argument, NULL, OPTION_NEW_DIR_MODE},
+       '\0', "mode", "Mode used when creating new directories.", ONE_DASH},
+       {{"force-rr", no_argument, NULL, OPTION_FORCE_RR},
+       0, NULL, "Inhibit automatic Rock Ridge detection for previous session", ONE_DASH},
+       {{"no-rr", no_argument, NULL, OPTION_NO_RR},
+       0, NULL, "Inhibit reading of Rock Ridge attributes from previous session", ONE_DASH},
+       {{"no-split-symlink-components", no_argument, NULL, OPTION_NOSPLIT_SL_COMPONENT},
+       0, NULL, "Inhibit splitting symlink components", ONE_DASH},
+       {{"no-split-symlink-fields", no_argument, NULL, OPTION_NOSPLIT_SL_FIELD},
+       0, NULL, "Inhibit splitting symlink fields", ONE_DASH},
+       {{"output", required_argument, NULL, 'o'},
+       'o', "FILE", "Set output file name", ONE_DASH},
+       {{"path-list", required_argument, NULL, OPTION_P_LIST},
+       '\0', "FILE", "File with list of pathnames to process", ONE_DASH},
+       {{"preparer", required_argument, NULL, 'p'},
+       'p', "PREP", "Set Volume preparer", ONE_DASH},
+       {{"print-size", no_argument, NULL, OPTION_PRINT_SIZE},
+       '\0', NULL, "Print estimated filesystem size and exit", ONE_DASH},
+       {{"publisher", required_argument, NULL, OPTION_PUBLISHER},
+       '\0', "PUB", "Set Volume publisher", ONE_DASH},
+       {{"publisher", required_argument, NULL, 'P'},
+       'P', "PUB", "Set Volume publisher", ONE_DASH},
+       {{"quiet", no_argument, NULL, OPTION_QUIET},
+       '\0', NULL, "Run quietly", ONE_DASH},
+       {{"rational-rock", no_argument, NULL, 'r'},
+       'r', NULL, "Generate rationalized Rock Ridge directory information", ONE_DASH},
+       {{"rock", no_argument, NULL, 'R'},
+       'R', NULL, "Generate Rock Ridge directory information", ONE_DASH},
+       {{"sectype", required_argument, NULL, 's'},
+       's', "TYPE", "Set output sector type to e.g. data/xa1/raw", ONE_DASH},
+
+       {{"alpha-boot", required_argument, NULL, OPTION_BOOTALPHA},
+       '\0', "FILE", "Set alpha boot image name (relative to image root)", ONE_DASH},
+
+       {{"hppa-cmdline", required_argument, NULL, OPTION_HPPA_CMDLINE},
+       '\0', "CMDLINE", "Set hppa boot command line (relative to image root)", ONE_DASH},
+       {{"hppa-kernel-32", required_argument, NULL, OPTION_HPPA_KERNEL_32},
+       '\0', "FILE", "Set hppa 32-bit image name (relative to image root)", ONE_DASH},
+       {{"hppa-kernel-64", required_argument, NULL, OPTION_HPPA_KERNEL_64},
+       '\0', "FILE", "Set hppa 64-bit image name (relative to image root)", ONE_DASH},
+       {{"hppa-bootloader", required_argument, NULL, OPTION_HPPA_BOOTLOADER},
+       '\0', "FILE", "Set hppa boot loader file name (relative to image root)", ONE_DASH},
+       {{"hppa-ramdisk", required_argument, NULL, OPTION_HPPA_RAMDISK},
+       '\0', "FILE", "Set hppa ramdisk file name (relative to image root)", ONE_DASH},
+
+       {{"mips-boot", required_argument, NULL, OPTION_BOOTMIPS},
+       '\0', "FILE", "Set mips boot image name (relative to image root)", ONE_DASH},
+
+       {{"mipsel-boot", required_argument, NULL, OPTION_BOOTMIPSEL},
+       '\0', "FILE", "Set mipsel boot image name (relative to image root)", ONE_DASH},
+
+#ifdef JIGDO_TEMPLATE
+       {{"jigdo-jigdo", required_argument, NULL, OPTION_JTJ_OUTPUT},
+       '\0', "FILE", "Produce a jigdo .jigdo file as well as the .iso", ONE_DASH },
+       {{"jigdo-template", required_argument, NULL, OPTION_JTT_OUTPUT},
+       '\0', "FILE", "Produce a jigdo .template file as well as the .iso", ONE_DASH },
+       {{"jigdo-min-file-size", required_argument, NULL, OPTION_JT_MIN_SIZE},
+       '\0', "SIZE", "Minimum size for a file to be listed in the jigdo file", ONE_DASH },
+       {{"jigdo-force-md5", required_argument, NULL, OPTION_JT_INCLUDE},
+       '\0', "PATTERN", "Pattern(s) where files MUST match an externally-supplied MD5sum", ONE_DASH },
+       {{"jigdo-exclude", required_argument, NULL, OPTION_JT_EXCLUDE},
+       '\0', "PATTERN", "Pattern(s) to exclude from the jigdo file", ONE_DASH },
+       {{"jigdo-map", required_argument, NULL, OPTION_JT_PATH_MAP},
+       '\0', "PATTERN1=PATTERN2", "Pattern(s) to map paths (e.g. Debian=/mirror/debian)", ONE_DASH },
+       {{"md5-list", required_argument, NULL, OPTION_JT_MD5_LIST},
+       '\0', "FILE", "File containing MD5 sums of the files that should be checked", ONE_DASH },
+    {{"jigdo-template-compress", required_argument, NULL, OPTION_JT_COMPRESS_ALGO},
+     '\0', "ALGORITHM", "Choose to use gzip or bzip2 compression for template data; default is gzip", ONE_DASH },
+       {{"checksum_algorithm_iso", required_argument, NULL, OPTION_JT_CHECKSUM_ALGO_ISO},
+       '\0', "alg1,alg2,...", "Specify the checksum types desired for the output image", ONE_DASH},
+       {{"checksum_algorithm_template", required_argument, NULL, OPTION_JT_CHECKSUM_ALGO_TMPL},
+       '\0', "alg1,alg2,...", "Specify the checksum types desired for the output jigdo template", ONE_DASH},
+#endif
+
+#ifdef SORTING
+       { {"sort", required_argument, NULL, OPTION_SORT},
+       '\0', "FILE", "Sort file content locations according to rules in FILE", ONE_DASH },
+#endif /* SORTING */
+
+       {{"split-output", no_argument, NULL, OPTION_SPLIT_OUTPUT},
+       '\0', NULL, "Split output into files of approx. 1GB size", ONE_DASH},
+       {{"stream-file-name", required_argument, NULL, OPTION_STREAM_FILE_NAME},
+       '\0', "FILE_NAME", "Set the stream file ISO9660 name (incl. version)", ONE_DASH},
+       {{"stream-media-size", required_argument, NULL, OPTION_STREAM_CD_SIZE},
+       '\0', "#", "Set the size of your CD media in sectors", ONE_DASH},
+       {{"sysid", required_argument, NULL, OPTION_SYSID},
+       '\0', "ID", "Set System ID", ONE_DASH},
+       {{"translation-table", no_argument, NULL, 'T'},
+       'T', NULL, "Generate translation tables for systems that don't understand long filenames", ONE_DASH},
+       {{"table-name", required_argument, NULL, OPTION_TRANS_TBL},
+       '\0', "TABLE_NAME", "Translation table file name", ONE_DASH},
+       {{"ucs-level", required_argument, NULL, OPTION_UCS_LEVEL},
+       '\0', "LEVEL", "Set Joliet UCS level (1..3)", ONE_DASH},
+
+#ifdef UDF
+       {{"udf", no_argument, NULL, OPTION_UDF},
+       '\0', NULL, "Generate UDF file system", ONE_DASH},
+#endif
+
+#ifdef DVD_VIDEO
+       {{"dvd-video", no_argument, NULL, OPTION_DVD},
+       '\0', NULL, "Generate DVD-Video compliant UDF file system", ONE_DASH},
+#endif
+
+       {{"uid", required_argument, NULL, OPTION_UID},
+       '\0', "uid", "Make the owner of all files this uid.",
+       ONE_DASH},
+       {{"untranslated-filenames", no_argument, NULL, 'U'},
+       /* CSTYLED */
+       'U', NULL, "Allow Untranslated filenames (for HPUX & AIX - violates ISO9660). Forces -l, -d, -N, -allow-leading-dots, -relaxed-filenames, -allow-lowercase, -allow-multidot", ONE_DASH},
+       {{"relaxed-filenames", no_argument, NULL, OPTION_RELAXED_FILENAMES},
+       '\0', NULL, "Allow 7 bit ASCII except lower case characters (violates ISO9660)", ONE_DASH},
+       {{"no-iso-translate", no_argument, NULL, OPTION_ISO_TRANSLATE},
+       '\0', NULL, "Do not translate illegal ISO characters '~', '-' and '#' (violates ISO9660)", ONE_DASH},
+       {{"allow-lowercase", no_argument, NULL, OPTION_ALLOW_LOWERCASE},
+       '\0', NULL, "Allow lower case characters in addition to the current character set (violates ISO9660)", ONE_DASH},
+       {{"allow-multidot", no_argument, NULL, OPTION_ALLOW_MULTIDOT},
+       '\0', NULL, "Allow more than one dot in filenames (e.g. .tar.gz) (violates ISO9660)", ONE_DASH},
+       {{"use-fileversion", no_argument, NULL, OPTION_USE_FILEVERSION},
+       '\0', "LEVEL", "Use file version # from filesystem", ONE_DASH},
+       {{"verbose", no_argument, NULL, 'v'},
+       'v', NULL, "Verbose", ONE_DASH},
+       {{"version", no_argument, NULL, OPTION_PVERSION},
+       '\0', NULL, "Print the current version", ONE_DASH},
+       {{"volid", required_argument, NULL, 'V'},
+       'V', "ID", "Set Volume ID", ONE_DASH},
+       {{"volset", required_argument, NULL, OPTION_VOLSET},
+       '\0', "ID", "Set Volume set ID", ONE_DASH},
+       {{"volset-size", required_argument, NULL, OPTION_VOLSET_SIZE},
+       '\0', "#", "Set Volume set size", ONE_DASH},
+       {{"volset-seqno", required_argument, NULL, OPTION_VOLSET_SEQ_NUM},
+       '\0', "#", "Set Volume set sequence number", ONE_DASH},
+       {{"old-exclude", required_argument, NULL, 'x'},
+       'x', "FILE", "Exclude file name(depreciated)", ONE_DASH},
+       {{"hard-disk-boot", no_argument, NULL, OPTION_HARD_DISK_BOOT},
+       '\0', NULL, "Boot image is a hard disk image", ONE_DASH},
+       {{"no-emul-boot", no_argument, NULL, OPTION_NO_EMUL_BOOT},
+       '\0', NULL, "Boot image is 'no emulation' image", ONE_DASH},
+       {{"no-boot", no_argument, NULL, OPTION_NO_BOOT},
+       '\0', NULL, "Boot image is not bootable", ONE_DASH},
+       {{"boot-load-seg", required_argument, NULL, OPTION_BOOT_LOAD_ADDR},
+       '\0', "#", "Set load segment for boot image", ONE_DASH},
+       {{"boot-load-size", required_argument, NULL, OPTION_BOOT_LOAD_SIZE},
+       '\0', "#", "Set numbers of load sectors", ONE_DASH},
+       {{"boot-info-table", no_argument, NULL, OPTION_BOOT_INFO_TABLE},
+       '\0', NULL, "Patch boot image with info table", ONE_DASH},
+       {{"XA", no_argument, NULL, OPTION_XA},
+       '\0', NULL, "Generate XA directory attruibutes", ONE_DASH},
+       {{"xa", no_argument, NULL, OPTION_XA_RATIONALIZED},
+       '\0', NULL, "Generate rationalized XA directory attruibutes", ONE_DASH},
+       {{"transparent-compression", no_argument, NULL, 'z'},
+       'z', NULL, "Enable transparent compression of files", ONE_DASH},
+
+#ifdef APPLE_HYB
+       {{"hfs-type", required_argument, NULL, OPTION_HFS_TYPE},
+       '\0', "TYPE", "Set HFS default TYPE", ONE_DASH},
+       {{"hfs-creator", required_argument, NULL, OPTION_HFS_CREATOR},
+       '\0', "CREATOR", "Set HFS default CREATOR", ONE_DASH},
+       {{"apple", no_argument, NULL, 'g'},
+       'g', NULL, "Add Apple ISO9660 extensions", ONE_DASH},
+       {{"hfs", no_argument, NULL, 'h'},
+       'h', NULL, "Create ISO9660/HFS hybrid", ONE_DASH},
+       {{"map", required_argument, NULL, OPTION_MAP_FILE},
+       '\0', "MAPPING_FILE", "Map file extensions to HFS TYPE/CREATOR", ONE_DASH},
+       {{"map", required_argument, NULL, 'H'},
+       'H', "MAPPING_FILE", "Map file extensions to HFS TYPE/CREATOR", ONE_DASH},
+       {{"magic", required_argument, NULL, OPTION_MAGIC_FILE},
+       '\0', "FILE", "Magic file for HFS TYPE/CREATOR", ONE_DASH},
+       {{"probe", no_argument, NULL, OPTION_PROBE},
+       '\0', NULL, "Probe all files for Apple/Unix file types", ONE_DASH},
+       {{"mac-name", no_argument, NULL, OPTION_MACNAME},
+       '\0', NULL, "Use Macintosh name for ISO9660/Joliet/RockRidge file name",
+       ONE_DASH},
+       {{"no-mac-files", no_argument, NULL, OPTION_NOMACFILES},
+       '\0', NULL, "Do not look for Unix/Mac files (depreciated)", ONE_DASH},
+       {{"boot-hfs-file", required_argument, NULL, OPTION_BOOT_HFS_FILE},
+       '\0', "FILE", "Set HFS boot image name", ONE_DASH},
+       {{"part", no_argument, NULL, OPTION_GEN_PT},
+       '\0', NULL, "Generate HFS partition table", ONE_DASH},
+       {{"cluster-size", required_argument, NULL, OPTION_BSIZE},
+       '\0', "SIZE", "Cluster size for PC Exchange Macintosh files", ONE_DASH},
+       {{"auto", required_argument, NULL, OPTION_AUTOSTART},
+       '\0', "FILE", "Set HFS AutoStart file name", ONE_DASH},
+       {{"no-desktop", no_argument, NULL, OPTION_CREATE_DT},
+       '\0', NULL, "Do not create the HFS (empty) Desktop files", ONE_DASH},
+       {{"hide-hfs", required_argument, NULL, OPTION_HFS_HIDE},
+       '\0', "GLOBFILE", "Hide HFS file", ONE_DASH},
+       {{"hide-hfs-list", required_argument, NULL, OPTION_HFS_LIST},
+       '\0', "FILE", "List of HFS files to hide", ONE_DASH},
+       {{"hfs-volid", required_argument, NULL, OPTION_HFS_VOLID},
+       '\0', "HFS_VOLID", "Volume name for the HFS partition", ONE_DASH},
+       {{"icon-position", no_argument, NULL, OPTION_ICON_POS},
+       '\0', NULL, "Keep HFS icon position", ONE_DASH},
+       {{"root-info", required_argument, NULL, OPTION_ROOT_INFO},
+       '\0', "FILE", "finderinfo for root folder", ONE_DASH},
+       {{"input-hfs-charset", required_argument, NULL, OPTION_HFS_INPUT_CHARSET},
+       '\0', "CHARSET", "Local input charset for HFS file name conversion", ONE_DASH},
+       {{"output-hfs-charset", required_argument, NULL, OPTION_HFS_OUTPUT_CHARSET},
+       '\0', "CHARSET", "Output charset for HFS file name conversion", ONE_DASH},
+       {{"hfs-unlock", no_argument, NULL, OPTION_HFS_UNLOCK},
+       '\0', NULL, "Leave HFS Volume unlocked", ONE_DASH},
+       {{"hfs-bless", required_argument, NULL, OPTION_HFS_BLESS},
+       '\0', "FOLDER_NAME", "Name of Folder to be blessed", ONE_DASH},
+       {{"hfs-parms", required_argument, NULL, OPTION_HFS_PARMS},
+       '\0', "PARAMETERS", "Comma separated list of HFS parameters", ONE_DASH},
+#ifdef PREP_BOOT
+       {{"prep-boot", required_argument, NULL, OPTION_PREP_BOOT},
+       '\0', "FILE", "PReP boot image file -- up to 4 are allowed", ONE_DASH},
+       {{"chrp-boot", no_argument, NULL, OPTION_CHRP_BOOT},
+       '\0', NULL, "Add CHRP boot header", ONE_DASH},
+#endif /* PREP_BOOT */
+       {{"cap", no_argument, NULL, OPTION_CAP},
+       '\0', NULL, "Look for AUFS CAP Macintosh files", TWO_DASHES},
+       {{"netatalk", no_argument, NULL, OPTION_NETA},
+       '\0', NULL, "Look for NETATALK Macintosh files", TWO_DASHES},
+       {{"double", no_argument, NULL, OPTION_DBL},
+       '\0', NULL, "Look for AppleDouble Macintosh files", TWO_DASHES},
+       {{"ethershare", no_argument, NULL, OPTION_ESH},
+       '\0', NULL, "Look for Helios EtherShare Macintosh files", TWO_DASHES},
+       {{"exchange", no_argument, NULL, OPTION_FE},
+       '\0', NULL, "Look for PC Exchange Macintosh files", TWO_DASHES},
+       {{"sgi", no_argument, NULL, OPTION_SGI},
+       '\0', NULL, "Look for SGI Macintosh files", TWO_DASHES},
+       {{"macbin", no_argument, NULL, OPTION_MBIN},
+       '\0', NULL, "Look for MacBinary Macintosh files", TWO_DASHES},
+       {{"single", no_argument, NULL, OPTION_SGL},
+       '\0', NULL, "Look for AppleSingle Macintosh files", TWO_DASHES},
+       {{"ushare", no_argument, NULL, OPTION_USH},
+       '\0', NULL, "Look for IPT UShare Macintosh files", TWO_DASHES},
+       {{"xinet", no_argument, NULL, OPTION_XIN},
+       '\0', NULL, "Look for XINET Macintosh files", TWO_DASHES},
+       {{"dave", no_argument, NULL, OPTION_DAVE},
+       '\0', NULL, "Look for DAVE Macintosh files", TWO_DASHES},
+       {{"sfm", no_argument, NULL, OPTION_SFM},
+       '\0', NULL, "Look for SFM Macintosh files", TWO_DASHES},
+       {{"osx-double", no_argument, NULL, OPTION_XDBL},
+       '\0', NULL, "Look for MacOS X AppleDouble Macintosh files", TWO_DASHES},
+       {{"osx-hfs", no_argument, NULL, OPTION_XHFS},
+       '\0', NULL, "Look for MacOS X HFS Macintosh files", TWO_DASHES},
+#endif /* APPLE_HYB */
+};
+
+#define        OPTION_COUNT (sizeof ld_options / sizeof (ld_options[0]))
+
+static void    read_rcfile(char *appname);
+static void    susage(int excode);
+static void    usage(int excode);
+int    iso9660_date(char *result, time_t crtime);
+static void    hide_reloc_dir(void);
+static char *get_pnames(int argc, char **argv, int opt, char *pname, 
+                                                                 int pnsize, FILE *fp);
+char *findgequal(char *s);
+static char *escstrcpy(char *to, char *from);
+void *e_malloc(size_t size);
+
+static int
+read_one_rcfile(char *filename)
+{
+       int linum = 0;
+       char linebuffer[256];
+       FILE *fp;
+
+       if (!filename)
+               return 0;
+
+       fp = fopen(filename, "r");
+       if (!fp) {
+               if (errno == ENOENT)
+                       return 0;
+#ifdef USE_LIBSCHILY
+               errmsg("Cannot open '%s'.\n", filename);
+#else
+               perror(filename);
+#endif
+               return 0;
+       }
+       if (verbose > 0)
+               fprintf(stderr, "Using \"%s\"\n", filename);
+
+       while (fgets(linebuffer, sizeof(linebuffer), fp)) {
+               char *name, *p, *p1;
+               struct rcopts *rco;
+
+               ++linum;
+               /* skip any leading white space */
+               for (p = linebuffer; *p == ' ' || *p == '\t'; p++)
+                       ;
+               /* Skip comments and blank lines */
+               if (!*p || *p == '\n' || *p == '\r' || *p == '#')
+                       continue;
+               /*
+                * The name should begin in the left margin.  Make sure it is
+                * in upper case.  Stop when we see white space or a comment.
+                */
+               name = p;
+               while (*p && (isalpha((unsigned char) *p) || *p == '_'))
+                       *p++ = toupper((unsigned char) *p);
+
+               if (name == p) {
+                       fprintf(stderr, "%s:%d: name required\n", filename,
+                                       linum);
+                       continue;
+               }
+
+               p1 = p;
+               /* Skip past white space after the name */
+               while (*p == ' ' || *p == '\t')
+                       p++;
+               /* silently ignore errors in the rc file. */
+               if (*p != '=') {
+                       fprintf(stderr, "%s:%d: equals sign required after '%.*s'\n",
+                                               filename, linum,
+                                               (int)(p1-name), name);
+                       continue;
+               }
+               *p1 = 0;
+
+               /* Skip pas the = sign, and any white space following it */
+               p++;
+               while (*p == ' ' || *p == '\t')
+                       p++;
+
+               /* Get rid of trailing newline */
+               for (p1 = p; *p1 && *p1 != '\n' && *p1 != '\r'; p1++)
+                       ;
+               *p1 = 0;
+
+               /* Figure out which option we have */
+               for (rco = rcopt; rco->tag; rco++)
+                       if (strcmp(rco->tag, name) == 0) {
+                               /* memleak if we ever do this more than once */
+                               *rco->variable = strdup(p);
+                               break;
+                       }
+
+               if (!rco->tag) {
+                       fprintf(stderr, "%s:%d: field name '%s' unknown\n",
+                               filename, linum,
+                               name);
+               }
+       }
+       if (ferror(fp)) {
+#ifdef USE_LIBSCHILY
+               errmsg("Read error on '%s'.\n", filename);
+#else
+               perror(filename);
+#endif
+               fclose(fp);
+               return 0;
+       }
+       fclose(fp);
+       return 1;
+}
+
+#define ETCDIR "/etc"
+#define RCFILENAME "genisoimagerc"
+#define OLD_RCFILENAME "mkisofsrc"
+
+static void
+read_rcfile(char *appname)
+{
+       char *p;
+       char filename[1000];
+
+       if (read_one_rcfile(getenv("GENISOIMAGERC")))
+               return;
+       if (read_one_rcfile(getenv("MKISOFSRC")))
+               return;
+       if (read_one_rcfile("." RCFILENAME))
+               return;
+       if (read_one_rcfile("." OLD_RCFILENAME))
+               return;
+
+       p = getenv("HOME");
+       if (p && strlen(p) + 1 + sizeof(RCFILENAME) < sizeof(filename)) {
+               strcpy(filename, p);
+               p = filename + strlen(filename);
+               *p++ = PATH_SEPARATOR;
+               strcpy(p, "." RCFILENAME);
+               if (read_one_rcfile(filename))
+                       return;
+               strcpy(p, "." OLD_RCFILENAME);
+               if (read_one_rcfile(filename))
+                       return;
+       }
+
+       if (read_one_rcfile(ETCDIR SPATH_SEPARATOR RCFILENAME))
+               return;
+
+       if (appname &&
+           strlen(appname) + 1 + sizeof(RCFILENAME) < sizeof(filename)) {
+               strcpy(filename, appname);
+               p = strrchr(filename, PATH_SEPARATOR);
+               if (p) {
+                       strcpy(p + 1, RCFILENAME);
+                       if (read_one_rcfile(filename))
+                               return;
+               }
+       }
+}
+
+char   *path_table_l = NULL;
+char   *path_table_m = NULL;
+
+char   *jpath_table_l = NULL;
+char   *jpath_table_m = NULL;
+
+int    goof = 0;
+
+#ifndef TRUE
+#define        TRUE 1
+#endif
+
+#ifndef FALSE
+#define        FALSE 0
+#endif
+
+static void
+susage(int excode)
+{
+       const char      *program_name = "genisoimage";
+
+       fprintf(stderr, "Usage: %s [options] -o file directory ...\n", program_name);
+       fprintf(stderr, "\nUse %s -help\n", program_name);
+       fprintf(stderr, "to get a list of valid options.\n");
+       fprintf(stderr, "\nReport problems to debburn-devel@lists.alioth.debian.org.\n");
+
+       exit(excode);
+}
+
+static void
+usage(int excode)
+{
+       const char      *program_name = "genisoimage";
+
+       int     i;
+
+/*     const char **targets, **pp;*/
+
+       fprintf(stderr, "Usage: %s [options] file...\n", program_name);
+
+       fprintf(stderr, "Options:\n");
+       for (i = 0; i < (int)OPTION_COUNT; i++) {
+               if (ld_options[i].doc != NULL) {
+                       int     comma;
+                       int     len;
+                       int     j;
+
+                       fprintf(stderr, "  ");
+
+                       comma = FALSE;
+                       len = 2;
+
+                       j = i;
+                       do {
+                               if (ld_options[j].shortopt != '\0' &&
+                                       ld_options[j].control != NO_HELP) {
+                                       fprintf(stderr, "%s-%c",
+                                               comma ? ", " : "",
+                                               ld_options[j].shortopt);
+                                       len += (comma ? 2 : 0) + 2;
+                                       if (ld_options[j].arg != NULL) {
+                                               if (ld_options[j].opt.has_arg != optional_argument) {
+                                                       fprintf(stderr, " ");
+                                                       ++len;
+                                               }
+                                               fprintf(stderr, "%s",
+                                                       ld_options[j].arg);
+                                               len += strlen(ld_options[j].arg);
+                                       }
+                                       comma = TRUE;
+                               }
+                               ++j;
+                       }
+                       while (j < (int)OPTION_COUNT && ld_options[j].doc == NULL);
+
+                       j = i;
+                       do {
+                               if (ld_options[j].opt.name != NULL &&
+                                       ld_options[j].control != NO_HELP) {
+                                       fprintf(stderr, "%s-%s%s",
+                                               comma ? ", " : "",
+                                               ld_options[j].control == TWO_DASHES ? "-" : "",
+                                               ld_options[j].opt.name);
+                                       len += ((comma ? 2 : 0)
+                                               + 1
+                                               + (ld_options[j].control == TWO_DASHES ? 1 : 0)
+                                               + strlen(ld_options[j].opt.name));
+                                       if (ld_options[j].arg != NULL) {
+                                               fprintf(stderr, " %s",
+                                                       ld_options[j].arg);
+                                               len += 1 +
+                                                   strlen(ld_options[j].arg);
+                                       }
+                                       comma = TRUE;
+                               }
+                               ++j;
+                       }
+                       while (j < (int)OPTION_COUNT && ld_options[j].doc == NULL);
+
+                       if (len >= 30) {
+                               fprintf(stderr, "\n");
+                               len = 0;
+                       }
+                       for (; len < 30; len++)
+                               fputc(' ', stderr);
+
+                       fprintf(stderr, "%s\n", ld_options[i].doc);
+               }
+       }
+       fprintf(stderr, 
+        "\nReport problems to debburn-devel@lists.alioth.debian.org.\n");
+       exit(excode);
+}
+
+
+/*
+ * Fill in date in the iso9660 format
+ *
+ * The standards  state that the timezone offset is in multiples of 15
+ * minutes, and is what you add to GMT to get the localtime.  The U.S.
+ * is always at a negative offset, from -5h to -8h (can vary a little
+ * with DST,  I guess).  The Linux iso9660 filesystem has had the sign
+ * of this wrong for ages (genisoimage had it wrong too for the longest time).
+ */
+int
+iso9660_date(char *result, time_t crtime)
+{
+       struct tm       *local;
+
+       local = localtime(&crtime);
+       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;
+
+       /*
+        * Must recalculate proper timezone offset each time, as some files use
+        * daylight savings time and some don't...
+        */
+       result[6] = local->tm_yday;     /* save yday 'cause gmtime zaps it */
+       local = gmtime(&crtime);
+       local->tm_year -= result[0];
+       local->tm_yday -= result[6];
+       local->tm_hour -= result[3];
+       local->tm_min -= result[4];
+       if (local->tm_year < 0) {
+               local->tm_yday = -1;
+       } else {
+               if (local->tm_year > 0)
+                       local->tm_yday = 1;
+       }
+
+       result[6] = -(local->tm_min + 60 *
+                       (local->tm_hour + 24 * local->tm_yday)) / 15;
+
+       return (0);
+}
+
+/* hide "./rr_moved" if all its contents are hidden */
+static void
+hide_reloc_dir()
+{
+       struct directory_entry *s_entry;
+
+       for (s_entry = reloc_dir->contents; s_entry; s_entry = s_entry->next) {
+               if (strcmp(s_entry->name, ".") == 0 ||
+                               strcmp(s_entry->name, "..") == 0)
+                       continue;
+
+               if ((s_entry->de_flags & INHIBIT_ISO9660_ENTRY) == 0)
+                       return;
+       }
+
+       /* all entries are hidden, so hide this directory */
+       reloc_dir->dir_flags |= INHIBIT_ISO9660_ENTRY;
+       reloc_dir->self->de_flags |= INHIBIT_ISO9660_ENTRY;
+}
+
+/*
+ * get pathnames from the command line, and then from given file
+ */
+static char *
+get_pnames(int argc, char **argv, int opt, char *pname, int pnsize, FILE *fp)
+{
+       int     len;
+
+       /* we may of already read the first line from the pathnames file */
+       if (save_pname) {
+               save_pname = 0;
+               return (pname);
+       }
+
+       if (opt < argc)
+               return (argv[opt]);
+
+       if (fp == NULL)
+               return ((char *) 0);
+
+       if (fgets(pname, pnsize, fp)) {
+               /* Discard newline */
+               len = strlen(pname);
+               if (pname[len - 1] == '\n') {
+                       pname[len - 1] = '\0';
+               }
+               return (pname);
+       }
+       return ((char *) 0);
+}
+
+extern char    *cdrecord_data;
+
+int main(int argc, char *argv[])
+{
+       struct directory_entry de;
+
+#ifdef HAVE_SBRK
+       unsigned long   mem_start;
+
+#endif
+       struct stat     statbuf;
+       char            *merge_image = NULL;
+       char            *reloc_root = NULL;
+       char            *reloc_old_root = NULL;
+       struct iso_directory_record *mrootp = NULL;
+       struct output_fragment *opnt;
+       int             longind;
+       char            shortopts[OPTION_COUNT * 3 + 2];
+       struct option   longopts[OPTION_COUNT + 1];
+       int             c;
+       int             n;
+       char            *log_file = 0;
+       char            *node = NULL;
+       char            *pathnames = 0;
+       FILE            *pfp = NULL;
+       char            pname[2*PATH_MAX + 1 + 1];      /* may be too short */
+       char            *arg;                           /* if '\\' present  */
+       char            nodename[PATH_MAX + 1];
+       int             no_path_names = 1;
+       int             warn_violate = 0;
+       int             have_cmd_line_pathspec = 0;
+       int             rationalize_all = 0;
+       char            *mkisofs_call = 0; /* use as pointer and boolean */
+
+#ifdef APPLE_HYB
+       char            *afpfile = "";  /* mapping file for TYPE/CREATOR */
+       int             hfs_ct = 0;
+       char            *root_info = 0;
+#endif /* APPLE_HYB */
+
+  /* abusing arg */
+  mkisofs_call=strstr(argv[0], "mkisofs");
+  if(mkisofs_call && '\0' == mkisofs_call[7]) /* lame cheater detected */
+     argv[0]="genisoimage";
+
+#ifdef __EMX__
+       /* This gives wildcard expansion with Non-Posix shells with EMX */
+       _wildcard(&argc, &argv);
+#endif
+       save_args(argc, argv);
+
+       if (argc < 2) {
+#ifdef USE_LIBSCHILY
+               errmsgno(EX_BAD, "Missing pathspec.\n");
+#endif
+               susage(1);
+       }
+       /* Get the defaults from the .genisoimagerc file */
+       read_rcfile(argv[0]);
+
+       outfile = NULL;
+
+       /*
+        * Copy long option initialization from GNU-ld.
+        */
+       /*
+        * Starting the short option string with '-' is for programs that
+        * expect options and other ARGV-elements in any order and that care
+        * about the ordering of the two.  We describe each non-option
+        * ARGV-element as if it were the argument of an option with
+        * character code 1.
+        */
+       {
+               int             i,
+                               is,
+                               il;
+
+               shortopts[0] = '-';
+               is = 1;
+               il = 0;
+               for (i = 0; i < (int)OPTION_COUNT; i++) {
+                       if (ld_options[i].shortopt != '\0') {
+                               shortopts[is] = ld_options[i].shortopt;
+                               ++is;
+                               if (ld_options[i].opt.has_arg ==
+                                       required_argument ||
+                                       ld_options[i].opt.has_arg ==
+                                                       optional_argument) {
+                                       shortopts[is] = ':';
+                                       ++is;
+                                       if (ld_options[i].opt.has_arg ==
+                                                       optional_argument) {
+                                               shortopts[is] = ':';
+                                               ++is;
+                                       }
+                               }
+                       }
+                       if (ld_options[i].opt.name != NULL) {
+                               longopts[il] = ld_options[i].opt;
+                               ++il;
+                       }
+               }
+               shortopts[is] = '\0';
+               longopts[il].name = NULL;
+       }
+
+       while ((c = getopt_long_only(argc, argv, shortopts,
+                                               longopts, &longind)) != EOF)
+               switch (c) {
+               case 1:
+                       /* A filename that we take as input. */
+                       optind--;
+                       have_cmd_line_pathspec = 1;
+                       goto parse_input_files;
+
+               case OPTION_USE_GRAFT:
+                       use_graft_ptrs = 1;
+                       break;
+               case 'C':
+                       /*
+                        * This is a temporary hack until cdrecord gets the
+                        * proper hooks in it.
+                        */
+                       cdrecord_data = optarg;
+                       break;
+               case OPTION_GUI:
+                       gui++;
+                       break;
+               case 'i':
+#ifdef USE_LIBSCHILY
+                       comerrno(EX_BAD, "-i option no longer supported.\n");
+#else
+                       fprintf(stderr, "-i option no longer supported.\n");
+                       exit(1);
+#endif
+                       break;
+               case OPTION_ISO_LEVEL:
+                       iso9660_level = atoi(optarg);
+
+                       switch (iso9660_level) {
+
+                       case 1:
+                               /*
+                                * Only on file section
+                                * 8.3 d or d1 characters for files
+                                * 8   d or d1 characters for directories
+                                */
+                               break;
+                       case 2:
+                               /*
+                                * Only on file section
+                                */
+                               break;
+                       case 3:
+                               /*
+                                * No restrictions
+                                */
+                               break;
+                       case 4:
+                               /*
+                                * This is ISO-9660:1988 (ISO-9660 version 2)
+                                */
+                               iso9660_namelen = MAX_ISONAME_V2; /* allow 207 chars */
+                               full_iso9660_filenames++;       /* 31+ chars    */
+                               omit_version_number++;
+                               RR_relocation_depth = 32767;
+
+                               /*
+                                * From -U ...
+                                */
+                               omit_period++;                  /* trailing dot */
+                               allow_leading_dots++;
+                               relaxed_filenames++;            /* all chars    */
+                               allow_lowercase++;              /* even lowcase */
+                               allow_multidot++;               /* > 1 dots     */
+                               break;
+
+                       default:
+                               comerrno(EX_BAD, "Illegal iso9660 Level %d, use 1..3 or 4.\n",
+                                                       iso9660_level);
+                       }
+                       break;
+               case 'J':
+                       use_Joliet++;
+                       break;
+               case OPTION_JLONG:
+                       use_Joliet++;
+                       jlen = JLONGMAX;
+                       break;
+               case OPTION_JCHARSET:
+                       use_Joliet++;
+                       /* FALLTHROUGH */
+               case OPTION_INPUT_CHARSET:
+                       icharset = optarg;
+                       break;
+               case OPTION_OUTPUT_CHARSET:
+                       ocharset = optarg;
+                       break;
+#ifdef JIGDO_TEMPLATE
+               case OPTION_JTT_OUTPUT:
+                       jtemplate_out = optarg;
+                       break;
+               case OPTION_JTJ_OUTPUT:
+                       jjigdo_out = optarg;
+                       break;
+               case OPTION_JT_MD5_LIST:
+                       jmd5_list = optarg;
+                       break;
+               case OPTION_JT_MIN_SIZE:
+                       jte_min_size = atoi(optarg);
+                       if (jte_min_size < MIN_JIGDO_FILE_SIZE) {
+                               fprintf(stderr, "Jigdo min size %d too small; using default %d instead\n", jte_min_size, MIN_JIGDO_FILE_SIZE);
+                               jte_min_size = MIN_JIGDO_FILE_SIZE;
+                       }
+                       break;
+               case OPTION_JT_INCLUDE:
+                       if (jte_add_include(optarg)) {
+#ifdef USE_LIBSCHILY
+                               comerrno(EX_BAD,
+                                        "Failed to build jigdo-include list\n");
+#else
+                               fprintf(stderr,
+                                       "Failed to build jigdo-include list\n");
+                               exit(1);
+#endif
+                       }
+                       break;
+               case OPTION_JT_EXCLUDE:
+                       if (jte_add_exclude(optarg)) {
+#ifdef USE_LIBSCHILY
+                               comerrno(EX_BAD,
+                                        "Failed to build jigdo-exclude list\n");
+#else
+                               fprintf(stderr,
+                                       "Failed to build jigdo-exclude list\n");
+                               exit(1);
+#endif
+                       }
+                       break;
+               case OPTION_JT_PATH_MAP:
+                       if (jte_add_mapping(optarg)) {
+#ifdef USE_LIBSCHILY
+                               comerrno(EX_BAD,
+                                        "Failed to build jigdo mapping list\n");
+#else
+                               fprintf(stderr,
+                                       "Failed to build jigdo mapping list\n");
+                               exit(1);
+#endif
+                       }
+                       break;
+        case OPTION_JT_COMPRESS_ALGO:
+            if (!strcasecmp(optarg, "gzip"))
+                jte_template_compression = JTE_TEMP_GZIP;
+            else if (!strcasecmp(optarg, "bzip2"))
+                jte_template_compression = JTE_TEMP_BZIP2;
+            else
+            {
+#ifdef USE_LIBSCHILY
+                comerrno(EX_BAD, "Compression algorithm %s unknown\n", optarg);
+#else
+                fprintf(stderr, "Compression algorithm %s unknown\n", optarg);
+                exit(1);
+#endif
+            }
+            break;
+
+        case OPTION_JT_CHECKSUM_ALGO_ISO:
+            if (parse_checksum_algo(optarg, &checksum_algo_iso))
+            {
+#ifdef USE_LIBSCHILY
+                comerrno(EX_BAD, "Problem with ISO checksum choices: %s \n", optarg);
+#else
+                fprintf(stderr, "Problem with ISO checksum choices: %s\n", optarg);
+                exit(1);
+#endif
+            }
+
+            break;
+
+        case OPTION_JT_CHECKSUM_ALGO_TMPL:
+            if (parse_checksum_algo(optarg, &checksum_algo_tmpl))
+            {
+#ifdef USE_LIBSCHILY
+                comerrno(EX_BAD, "Problem with template checksum choices: %s \n", optarg);
+#else
+                fprintf(stderr, "Problem with template checksum choices: %s\n", optarg);
+                exit(1);
+#endif
+            }
+            break;
+
+#endif /* JIGDO_TEMPLATE */
+               case OPTION_NOBAK:
+                       all_files = 0;
+                       break;
+               case 'b':
+                       do_sort++;              /* We sort bootcat/botimage */
+                       use_eltorito++;
+                       boot_image = optarg;    /* pathname of the boot image */
+                                               /* on disk */
+                       if (boot_image == NULL) {
+#ifdef USE_LIBSCHILY
+                               comerrno(EX_BAD,
+                               "Required Eltorito boot image pathname missing\n");
+#else
+                               fprintf(stderr,
+                               "Required Eltorito boot image pathname missing\n");
+                               exit(1);
+#endif
+                       }
+                       get_boot_entry();
+                       current_boot_entry->boot_image = boot_image;
+                       break;
+               case OPTION_ALT_BOOT:
+                       /*
+                        * Start new boot entry parameter list.
+                        */
+                       new_boot_entry();
+                       break;
+               case OPTION_BOOTALPHA:
+                       use_alphaboot++;
+                       /* list of pathnames of boot images */
+                       add_boot_alpha_filename(optarg);
+                       break;
+               case OPTION_HPPA_CMDLINE:
+                       use_hppaboot++;
+                       add_boot_hppa_cmdline(optarg);
+                       break;
+               case OPTION_HPPA_KERNEL_32:
+                       use_hppaboot++;
+                       add_boot_hppa_kernel_32(optarg);
+                       break;
+               case OPTION_HPPA_KERNEL_64:
+                       use_hppaboot++;
+                       add_boot_hppa_kernel_64(optarg);
+                       break;
+               case OPTION_HPPA_BOOTLOADER:
+                       use_hppaboot++;
+                       add_boot_hppa_bootloader(optarg);
+                       break;
+               case OPTION_HPPA_RAMDISK:
+                       use_hppaboot++;
+                       /* list of pathnames of boot images */
+                       add_boot_hppa_ramdisk(optarg);
+                       break;
+               case OPTION_BOOTMIPS:
+                       use_mipsboot++;
+                       /* list of pathnames of boot images */
+                       add_boot_mips_filename(optarg);
+                       break;
+               case OPTION_BOOTMIPSEL:
+                       use_mipselboot++;
+                       add_boot_mipsel_filename(optarg);
+                       break;
+               case 'B':
+                       if (use_sunx86boot)
+                               comerrno(EX_BAD,
+                               "-sparc-boot and -sunx86-boot are mutual exclusive.\n");
+                       use_sparcboot++;
+                       /* list of pathnames of boot images */
+                       scan_sparc_boot(optarg);
+                       break;
+               case OPTION_SUNX86BOOT:
+                       if (use_sparcboot)
+                               comerrno(EX_BAD,
+                               "-sparc-boot and -sunx86-boot are mutual exclusive.\n");
+                       use_sunx86boot++;
+                       /* list of pathnames of boot images */
+                       scan_sunx86_boot(optarg);
+                       break;
+               case 'G':
+                       use_genboot++;
+                       /* pathname of the boot image on disk */
+                       genboot_image = optarg;
+                       if (genboot_image == NULL) {
+#ifdef USE_LIBSCHILY
+                               comerrno(EX_BAD,
+                               "Required generic boot image pathname missing\n");
+#else
+                               fprintf(stderr,
+                               "Required generic boot image pathname missing\n");
+                               exit(1);
+#endif
+                       }
+                       break;
+               case OPTION_SPARCLABEL:
+                       /* Sun disk label string */
+                       sparc_boot_label(optarg);
+                       break;
+               case OPTION_SUNX86LABEL:
+                       /* Sun disk label string */
+                       sunx86_boot_label(optarg);
+                       break;
+               case 'c':
+                       use_eltorito++;
+                       /* pathname of the boot image on cd */
+                       boot_catalog = optarg;
+                       if (boot_catalog == NULL) {
+#ifdef USE_LIBSCHILY
+                               comerrno(EX_BAD,
+                               "Required boot catalog pathname missing\n");
+#else
+                               fprintf(stderr,
+                               "Required boot catalog pathname missing\n");
+                               exit(1);
+#endif
+                       }
+                       break;
+               case OPTION_ABSTRACT:
+                       abstract = optarg;
+                       if (strlen(abstract) > 37) {
+#ifdef USE_LIBSCHILY
+                               comerrno(EX_BAD,
+                               "Abstract filename string too long\n");
+#else
+                               fprintf(stderr,
+                               "Abstract filename string too long\n");
+                               exit(1);
+#endif
+                       }
+                       break;
+               case 'A':
+                       appid = optarg;
+                       if (strlen(appid) > 128) {
+#ifdef USE_LIBSCHILY
+                               comerrno(EX_BAD,
+                               "Application-id string too long\n");
+#else
+                               fprintf(stderr,
+                               "Application-id string too long\n");
+                               exit(1);
+#endif
+                       }
+                       break;
+               case OPTION_BIBLIO:
+                       biblio = optarg;
+                       if (strlen(biblio) > 37) {
+#ifdef USE_LIBSCHILY
+                               comerrno(EX_BAD,
+                               "Bibliographic filename string too long\n");
+#else
+                               fprintf(stderr,
+                               "Bibliographic filename string too long\n");
+                               exit(1);
+#endif
+                       }
+                       break;
+               case OPTION_CACHE_INODES:
+                       cache_inodes = 1;
+                       break;
+               case OPTION_NOCACHE_INODES:
+                       cache_inodes = 0;
+                       break;
+               case OPTION_CHECK_OLDNAMES:
+                       check_oldnames++;
+                       break;
+               case OPTION_CHECK_SESSION:
+                       check_session++;
+                       check_oldnames++;
+                       merge_image = optarg;
+                       outfile = "/dev/null";
+                       /*
+                        * cdrecord_data is handled specially in multi.c
+                        * as we cannot write to all strings.
+                        * If genisoimage is called with -C xx,yy
+                        * our default is overwritten.
+                        */
+/*                     cdrecord_data = "0,0";*/
+                       break;
+               case OPTION_COPYRIGHT:
+                       copyright = optarg;
+                       if (strlen(copyright) > 37) {
+#ifdef USE_LIBSCHILY
+                               comerrno(EX_BAD,
+                               "Copyright filename string too long\n");
+#else
+                               fprintf(stderr,
+                               "Copyright filename string too long\n");
+                               exit(1);
+#endif
+                       }
+                       break;
+               case OPTION_DEBUG:
+                       debug++;
+                       break;
+               case 'd':
+                       omit_period++;
+                       warn_violate++;
+                       break;
+               case 'D':
+                       RR_relocation_depth = 32767;
+                       break;
+               case 'f':
+                       follow_links++;
+                       break;
+               case 'l':
+                       full_iso9660_filenames++;
+                       break;
+               case OPTION_MAX_FILENAMES:
+                       iso9660_namelen = MAX_ISONAME_V1; /* allow 37 chars */
+                       full_iso9660_filenames++;
+                       omit_version_number++;
+                       warn_violate++;
+                       break;
+               case 'L':
+                       /* FALLTHRU */
+               case OPTION_ALLOW_LEADING_DOTS:
+                       allow_leading_dots++;
+                       warn_violate++;
+                       break;
+               case OPTION_LOG_FILE:
+                       log_file = optarg;
+                       break;
+               case 'M':
+                       merge_image = optarg;
+                       break;
+               case OPTION_RELOC_ROOT:
+                       reloc_root = optarg;
+                       break;
+               case OPTION_RELOC_OLD_ROOT:
+                       reloc_old_root = optarg;
+                       break;
+               case 'N':
+                       omit_version_number++;
+                       warn_violate++;
+                       break;
+               case OPTION_FORCE_RR:
+                       force_rr++;
+                       break;
+               case OPTION_NO_RR:
+                       no_rr++;
+                       break;
+               case 'o':
+                       outfile = optarg;
+                       break;
+               case OPTION_PAD:
+                       dopad++;
+                       break;
+               case OPTION_NOPAD:
+                       dopad = 0;
+                       break;
+               case OPTION_P_LIST:
+                       pathnames = optarg;
+                       break;
+               case 'p':
+                       preparer = optarg;
+                       if (strlen(preparer) > 128) {
+#ifdef USE_LIBSCHILY
+                               comerrno(EX_BAD, "Preparer string too long\n");
+#else
+                               fprintf(stderr, "Preparer string too long\n");
+                               exit(1);
+#endif
+                       }
+                       break;
+               case OPTION_PRINT_SIZE:
+                       print_size++;
+                       break;
+               case 'P':
+                       /* FALLTHRU */
+               case OPTION_PUBLISHER:
+                       publisher = optarg;
+                       if (strlen(publisher) > 128) {
+#ifdef USE_LIBSCHILY
+                               comerrno(EX_BAD,
+                                               "Publisher string too long\n");
+#else
+                               fprintf(stderr, "Publisher string too long\n");
+                               exit(1);
+#endif
+                       }
+                       break;
+               case OPTION_QUIET:
+                       verbose = 0;
+                       break;
+               case 'R':
+                       use_RockRidge++;
+                       break;
+               case 'r':
+                       rationalize_all++;
+                       use_RockRidge++;
+                       break;
+               case OPTION_XA:
+                       use_XA++;
+                       break;
+               case OPTION_XA_RATIONALIZED:
+                       rationalize_all++;
+                       use_XA++;
+                       break;
+
+               case 's':
+                       if (strcmp(optarg, "data") == 0)
+                               osecsize = 2048;
+                       else if (strcmp(optarg, "xa1") == 0)
+                               osecsize = 2056;
+                       else if (strcmp(optarg, "raw") == 0) {
+                               osecsize = 2352;
+                               comerrno(EX_BAD,
+                                       "Unsupported sector type '%s'.\n",
+                                       optarg);
+                       }
+                       break;
+               case 'S':
+#ifdef USE_LIBSCHILY
+                       errmsgno(EX_BAD, "Option -%c is reserved for future use.\n", c);
+#else
+                       fprintf(stderr, "Option -%c is reserved for future use.\n", c);
+#endif
+                       susage(1);
+                       /* NOTREACHED */
+
+               case OPTION_NEW_DIR_MODE:
+                       rationalize++;
+               {
+                       char    *end = 0;
+
+                       new_dir_mode = strtol(optarg, &end, 8);
+                       if (!end || *end != 0 ||
+                           new_dir_mode < 0 || new_dir_mode > 07777) {
+#ifdef USE_LIBSCHILY
+                               comerrno(EX_BAD, "Bad mode for -new-dir-mode\n");
+#else
+                               fprintf(stderr, "Bad mode for -new-dir-mode\n");
+                               exit(1);
+#endif
+                       }
+                       break;
+               }
+
+               case OPTION_UID:
+                       rationalize++;
+                       use_RockRidge++;
+                       rationalize_uid++;
+               {
+                       char    *end = 0;
+
+                       uid_to_use = strtol(optarg, &end, 0);
+                       if (!end || *end != 0) {
+#ifdef USE_LIBSCHILY
+                               comerrno(EX_BAD, "Bad value for -uid\n");
+#else
+                               fprintf(stderr, "Bad value for -uid\n");
+                               exit(1);
+#endif
+                       }
+                       break;
+               }
+
+               case OPTION_GID:
+                       rationalize++;
+                       use_RockRidge++;
+                       rationalize_gid++;
+               {
+                       char    *end = 0;
+
+                       gid_to_use = strtol(optarg, &end, 0);
+                       if (!end || *end != 0) {
+#ifdef USE_LIBSCHILY
+                               comerrno(EX_BAD, "Bad value for -gid\n");
+#else
+                               fprintf(stderr, "Bad value for -gid\n");
+                               exit(1);
+#endif
+                       }
+                       break;
+               }
+
+               case OPTION_FILEMODE:
+                       rationalize++;
+                       use_RockRidge++;
+                       rationalize_filemode++;
+               {
+                       char    *end = 0;
+
+                       filemode_to_use = strtol(optarg, &end, 8);
+                       if (!end || *end != 0 ||
+                           filemode_to_use < 0 || filemode_to_use > 07777) {
+#ifdef USE_LIBSCHILY
+                               comerrno(EX_BAD, "Bad mode for -file-mode\n");
+#else
+                               fprintf(stderr, "Bad mode for -file-mode\n");
+                               exit(1);
+#endif
+                       }
+                       break;
+               }
+
+               case OPTION_DIRMODE:
+                       rationalize++;
+                       use_RockRidge++;
+                       rationalize_dirmode++;
+               {
+                       char    *end = 0;
+
+                       dirmode_to_use = strtol(optarg, &end, 8);
+                       if (!end || *end != 0 ||
+                           dirmode_to_use < 0 || dirmode_to_use > 07777) {
+#ifdef USE_LIBSCHILY
+                               comerrno(EX_BAD, "Bad mode for -dir-mode\n");
+#else
+                               fprintf(stderr, "Bad mode for -dir-mode\n");
+                               exit(1);
+#endif
+                       }
+                       break;
+               }
+
+#ifdef SORTING
+               case OPTION_SORT:
+                       do_sort++;
+                       add_sort_list(optarg);
+                       break;
+#endif /* SORTING */
+
+               case OPTION_SPLIT_OUTPUT:
+                       split_output++;
+                       break;
+
+               case OPTION_STREAM_FILE_NAME:
+                       stream_filename = optarg;
+                       break;
+
+               case OPTION_STREAM_CD_SIZE:
+                       stream_media_size = atoi(optarg);
+                       break;
+
+               case OPTION_SYSID:
+                       system_id = optarg;
+                       if (strlen(system_id) > 32) {
+#ifdef USE_LIBSCHILY
+                               comerrno(EX_BAD,
+                                               "System ID string too long\n");
+#else
+                               fprintf(stderr, "System ID string too long\n");
+                               exit(1);
+#endif
+                       }
+                       break;
+               case OPTION_TRANS_TBL:
+                       trans_tbl = optarg;
+                       /* FALLTHRU */
+               case 'T':
+                       generate_tables++;
+                       break;
+               case OPTION_UCS_LEVEL:
+                       ucs_level = atoi(optarg);
+                       if (ucs_level < 1 || ucs_level > 3)
+                               comerrno(EX_BAD, "Illegal UCS Level %d, use 1..3.\n",
+                                                       ucs_level);
+                       break;
+#ifdef UDF
+               case OPTION_UDF:
+                       use_udf++;
+                       break;
+#endif
+
+#ifdef DVD_VIDEO
+               case OPTION_DVD:
+                       use_udf++;
+                       dvd_video++;
+                       break;
+#endif
+               case OPTION_USE_FILEVERSION:
+                       use_fileversion++;
+                       break;
+               case 'U':
+                       /*
+                        * Minimal (only truncation of 31+ characters)
+                        * translation of filenames.
+                        *
+                        * Forces -l, -d, -N, -allow-leading-dots,
+                        * -relaxed-filenames,
+                        * -allow-lowercase, -allow-multidot
+                        *
+                        * This is for HP-UX, which does not recognize ANY
+                        * extentions (Rock Ridge, Joliet), causing pain when
+                        * loading software. pfs_mount can be used to read the
+                        * extensions, but the untranslated filenames can be
+                        * read by the "native" cdfs mounter. Completely
+                        * violates iso9660.
+                        */
+                       full_iso9660_filenames++;       /* 31 chars     */
+                       omit_period++;                  /* trailing dot */
+                       allow_leading_dots++;
+                       omit_version_number++;
+                       relaxed_filenames++;            /* all chars    */
+                       allow_lowercase++;              /* even lowcase */
+                       allow_multidot++;               /* > 1 dots     */
+                       warn_violate++;
+                       break;
+
+               case OPTION_RELAXED_FILENAMES:
+                       relaxed_filenames++;
+                       warn_violate++;
+                       break;
+               case OPTION_ALLOW_LOWERCASE:
+                       allow_lowercase++;
+                       warn_violate++;
+                       break;
+               case OPTION_ALLOW_MULTIDOT:
+                       allow_multidot++;
+                       warn_violate++;
+                       break;
+               case OPTION_ISO_TRANSLATE:
+                       iso_translate = 0;
+                       warn_violate++;
+                       break;
+               case 'V':
+                       volume_id = optarg;
+                       if (strlen(volume_id) > 32) {
+#ifdef USE_LIBSCHILY
+                               comerrno(EX_BAD,
+                                       "Volume ID string too long\n");
+#else
+                               fprintf(stderr,
+                                       "Volume ID string too long\n");
+                               exit(1);
+#endif
+                       }
+                       break;
+               case OPTION_VOLSET:
+                       volset_id = optarg;
+                       if (strlen(volset_id) > 128) {
+#ifdef USE_LIBSCHILY
+                               comerrno(EX_BAD,
+                               "Volume set ID string too long\n");
+#else
+                               fprintf(stderr,
+                               "Volume set ID string too long\n");
+                               exit(1);
+#endif
+                       }
+                       break;
+               case OPTION_VOLSET_SIZE:
+                       volume_set_size = atoi(optarg);
+                       if (volume_set_size <= 0) {
+#ifdef USE_LIBSCHILY
+                               comerrno(EX_BAD,
+                               "Illegal Volume Set Size %s\n", optarg);
+#else
+                               fprintf(stderr,
+                               "Illegal Volume Set Size %s\n", optarg);
+                               exit(1);
+#endif
+                       }
+                       if (volume_set_size > 1) {
+#ifdef USE_LIBSCHILY
+                               comerrno(EX_BAD,
+                               "Volume Set Size > 1 not yet supported\n");
+#else
+                               fprintf(stderr,
+                               "Volume Set Size > 1 not yet supported\n");
+                               exit(1);
+#endif
+                       }
+                       break;
+               case OPTION_VOLSET_SEQ_NUM:
+                       volume_sequence_number = atoi(optarg);
+                       if (volume_sequence_number > volume_set_size) {
+#ifdef USE_LIBSCHILY
+                               comerrno(EX_BAD,
+                               "Volume set sequence number too big\n");
+#else
+                               fprintf(stderr,
+                               "Volume set sequence number too big\n");
+                               exit(1);
+#endif
+                       }
+                       break;
+               case 'v':
+                       verbose++;
+                       break;
+               case 'z':
+#ifdef VMS
+#ifdef USE_LIBSCHILY
+                       comerrno(EX_BAD,
+                       "Transparent compression not supported with VMS\n");
+#else
+                       fprintf(stderr,
+                       "Transparent compression not supported with VMS\n");
+                       exit(1);
+#endif
+#else
+                       transparent_compression++;
+#endif
+                       break;
+               case 'x':
+               case 'm':
+                       /*
+                        * Somehow two options to do basically the same thing
+                        * got added somewhere along the way.  The 'match'
+                        * code supports limited globbing, so this is the one
+                        * that got selected. Unfortunately the 'x' switch is
+                        * probably more intuitive.
+                        */
+                       add_match(optarg);
+                       break;
+               case OPTION_X_LIST:
+                       add_list(optarg);
+                       break;
+               case OPTION_I_HIDE:
+                       i_add_match(optarg);
+                       break;
+               case OPTION_I_LIST:
+                       i_add_list(optarg);
+                       break;
+               case OPTION_H_HIDE:
+                       h_add_match(optarg);
+                       break;
+               case OPTION_H_LIST:
+                       h_add_list(optarg);
+                       break;
+               case OPTION_J_HIDE:
+                       j_add_match(optarg);
+                       break;
+               case OPTION_J_LIST:
+                       j_add_list(optarg);
+                       break;
+               case OPTION_HIDE_TRANS_TBL:
+                       jhide_trans_tbl++;
+                       break;
+               case OPTION_HIDE_RR_MOVED:
+                       hide_rr_moved++;
+                       break;
+               case OPTION_HELP:
+                       usage(0);
+                       break;
+               case OPTION_PVERSION:
+      if(mkisofs_call)
+         printf("mkisofs 2.01 is not what you see here. This line is only a fake for too clever\n"
+               "GUIs and other frontend applications. In fact, this program is:\n");
+                       printf("%s (%s)\n", version_string, HOST_SYSTEM);
+                       exit(0);
+                       break;
+               case OPTION_NOSPLIT_SL_COMPONENT:
+                       split_SL_component = 0;
+                       break;
+               case OPTION_NOSPLIT_SL_FIELD:
+                       split_SL_field = 0;
+                       break;
+               case OPTION_HARD_DISK_BOOT:
+                       use_eltorito++;
+                       hard_disk_boot++;
+                       get_boot_entry();
+                       current_boot_entry->hard_disk_boot = 1;
+                       break;
+               case OPTION_NO_EMUL_BOOT:
+                       use_eltorito++;
+                       no_emul_boot++;
+                       get_boot_entry();
+                       current_boot_entry->no_emul_boot = 1;
+                       break;
+               case OPTION_NO_BOOT:
+                       use_eltorito++;
+                       not_bootable++;
+                       get_boot_entry();
+                       current_boot_entry->not_bootable = 1;
+                       break;
+               case OPTION_BOOT_LOAD_ADDR:
+                       use_eltorito++;
+                       {
+                               long    val;
+                               char    *ptr;
+
+                               val = strtol(optarg, &ptr, 0);
+                               if (*ptr || val < 0 || val >= 0x10000) {
+#ifdef USE_LIBSCHILY
+                                       comerrno(EX_BAD, "Boot image load address invalid.\n");
+#else
+                                       fprintf(stderr, "Boot image load address invalid.\n");
+                                       exit(1);
+#endif
+                               }
+                               load_addr = val;
+                       }
+                       get_boot_entry();
+                       current_boot_entry->load_addr = load_addr;
+                       break;
+               case OPTION_BOOT_LOAD_SIZE:
+                       use_eltorito++;
+                       {
+                               long    val;
+                               char    *ptr;
+
+                               val = strtol(optarg, &ptr, 0);
+                               if (*ptr || val < 0 || val >= 0x10000) {
+#ifdef USE_LIBSCHILY
+                                       comerrno(EX_BAD,
+                                       "Boot image load size invalid.\n");
+#else
+                                       fprintf(stderr,
+                                       "Boot image load size invalid.\n");
+                                       exit(1);
+#endif
+                               }
+                               load_size = val;
+                       }
+                       get_boot_entry();
+                       current_boot_entry->load_size = load_size;
+                       break;
+               case OPTION_BOOT_INFO_TABLE:
+                       use_eltorito++;
+                       boot_info_table++;
+                       get_boot_entry();
+                       current_boot_entry->boot_info_table = 1;
+                       break;
+#ifdef APPLE_HYB
+               case OPTION_HFS_TYPE:
+                       deftype = optarg;
+                       hfs_ct++;
+                       if (strlen(deftype) != 4) {
+#ifdef USE_LIBSCHILY
+                               comerrno(EX_BAD,
+                               "HFS default TYPE string has illegal length.\n");
+#else
+                               fprintf(stderr,
+                               "HFS default TYPE string has illegal length.\n");
+                               exit(1);
+#endif
+                       }
+                       break;
+               case OPTION_HFS_CREATOR:
+                       defcreator = optarg;
+                       hfs_ct++;
+                       if (strlen(defcreator) != 4) {
+#ifdef USE_LIBSCHILY
+                               comerrno(EX_BAD,
+                               "HFS default CREATOR string has illegal length.\n");
+#else
+                               fprintf(stderr,
+                               "HFS default CREATOR string has illegal length.\n");
+                               exit(1);
+#endif
+                       }
+                       break;
+               case 'H':
+                       /* FALLTHRU */
+               case OPTION_MAP_FILE:
+                       afpfile = optarg;
+                       hfs_last = MAP_LAST;
+                       break;
+               case 'h':
+                       apple_hyb = 1;
+                       break;
+               case 'g':
+                       apple_ext = 1;
+                       break;
+               case OPTION_PROBE:
+                       probe = 1;
+                       break;
+               case OPTION_MACNAME:
+                       use_mac_name = 1;
+                       break;
+               case OPTION_NOMACFILES:
+#ifdef USE_LIBSCHILY
+                       errmsgno(EX_BAD,
+                       "Warning: -no-mac-files no longer used ... ignoring\n");
+#else
+                       fprintf(stderr,
+                       "Warning: -no-mac-files no longer used ... ignoring\n");
+#endif
+                       break;
+               case OPTION_BOOT_HFS_FILE:
+                       hfs_boot_file = optarg;
+                       /* FALLTHRU */
+               case OPTION_GEN_PT:
+                       gen_pt = 1;
+                       break;
+               case OPTION_MAGIC_FILE:
+#ifndef USE_MAGIC
+                       fprintf(stderr, "This program has been compiled without magic library support.\n"
+                               "Ignoring the -magic option.\n");
+#endif
+                       magic_filename = optarg;
+                       hfs_last = MAG_LAST;
+                       break;
+               case OPTION_AUTOSTART:
+                       autoname = optarg;
+                       /* gen_pt = 1; */
+                       break;
+               case OPTION_BSIZE:
+                       afe_size = atoi(optarg);
+                       hfs_select |= DO_FEU;
+                       hfs_select |= DO_FEL;
+                       break;
+               case OPTION_HFS_VOLID:
+                       hfs_volume_id = optarg;
+                       break;
+               case OPTION_ROOT_INFO:
+                       root_info = optarg;
+                       /* FALLTHRU */
+               case OPTION_ICON_POS:
+                       icon_pos = 1;
+                       break;
+               /* Mac/Unix types to include */
+               case OPTION_CAP:
+                       hfs_select |= DO_CAP;
+                       break;
+               case OPTION_NETA:
+                       hfs_select |= DO_NETA;
+                       break;
+               case OPTION_DBL:
+                       hfs_select |= DO_DBL;
+                       break;
+               case OPTION_ESH:
+               case OPTION_USH:
+                       hfs_select |= DO_ESH;
+                       break;
+               case OPTION_FE:
+                       hfs_select |= DO_FEU;
+                       hfs_select |= DO_FEL;
+                       break;
+               case OPTION_SGI:
+               case OPTION_XIN:
+                       hfs_select |= DO_SGI;
+                       break;
+               case OPTION_MBIN:
+                       hfs_select |= DO_MBIN;
+                       break;
+               case OPTION_SGL:
+                       hfs_select |= DO_SGL;
+                       break;
+               case OPTION_DAVE:
+                       hfs_select |= DO_DAVE;
+                       break;
+               case OPTION_SFM:
+                       hfs_select |= DO_SFM;
+                       break;
+               case OPTION_XDBL:
+                       hfs_select |= DO_XDBL;
+                       break;
+               case OPTION_XHFS:
+#ifdef IS_MACOS_X
+                       hfs_select |= DO_XHFS;
+#else /* IS_MACOS_X */
+#ifdef USE_LIBSCHILY
+                       errmsgno(EX_BAD,
+                       "Warning: --osx-hfs only works on MacOS X ... ignoring\n");
+#else /* USE_LIBSCHILY */
+                       fprintf(stderr,
+                       "Warning: --osx-hfs only works on MacOS X ... ignoring\n");
+#endif /* USE_LIBSCHILY */
+#endif /* IS_MACOS_X */
+                       break;
+               case OPTION_CREATE_DT:
+                       create_dt = 0;
+                       break;
+               case OPTION_HFS_HIDE:
+                       hfs_add_match(optarg);
+                       break;
+               case OPTION_HFS_LIST:
+                       hfs_add_list(optarg);
+                       break;
+               case OPTION_HFS_INPUT_CHARSET:
+                       use_mac_name = 1;
+                       hfs_icharset = optarg;
+                       break;
+               case OPTION_HFS_OUTPUT_CHARSET:
+                       hfs_ocharset = optarg;
+                       break;
+               case OPTION_HFS_UNLOCK:
+                       hfs_lock = 0;
+                       break;
+               case OPTION_HFS_BLESS:
+                       hfs_bless = optarg;
+                       break;
+               case OPTION_HFS_PARMS:
+                       hfs_parms = strdup(optarg);
+                       break;
+#ifdef PREP_BOOT
+               case OPTION_PREP_BOOT:
+                       use_prep_boot++;
+                       if (use_prep_boot > 4 - use_chrp_boot) {
+#ifdef USE_LIBSCHILY
+                               comerrno(EX_BAD,
+                               "Maximum of 4 PRep+CHRP partition entries are allowed\n");
+#else
+                               fprintf(stderr,
+                               "Maximum of 4 PRep+CHRP partition entries are allowed\n");
+#endif
+                               exit(1);
+                       }
+                       /* pathname of the boot image on cd */
+                       prep_boot_image[use_prep_boot - 1] = optarg;
+                       if (prep_boot_image[use_prep_boot - 1] == NULL) {
+#ifdef USE_LIBSCHILY
+                               comerrno(EX_BAD,
+                               "Required PReP boot image pathname missing\n");
+#else
+                               fprintf(stderr,
+                               "Required PReP boot image pathname missing\n");
+#endif
+                               exit(1);
+                       }
+                       break;
+               case OPTION_CHRP_BOOT:
+                       if (use_chrp_boot)
+                               break;          /* silently allow duplicates */
+                       use_chrp_boot = 1;
+                       if (use_prep_boot > 3) {
+#ifdef USE_LIBSCHILY
+                               comerrno(EX_BAD,
+                               "Maximum of 4 PRep+CHRP partition entries are allowed\n");
+#else
+                               fprintf(stderr,
+                               "Maximum of 4 PRep+CHRP partition entries are allowed\n");
+#endif
+                               exit(1);
+                       }
+                       break;
+#endif /* PREP_BOOT */
+#endif /* APPLE_HYB */
+               case OPTION_ALLOW_LIMITED_SIZE:
+                       allow_limited_size++;
+      use_udf++;
+                       break;
+               default:
+                       susage(1);
+               }
+       /*
+        * "--" was found, the next argument is a pathspec
+        */
+       if (argc != optind)
+               have_cmd_line_pathspec = 1;
+
+parse_input_files:
+       path_ind = optind;
+
+       /*
+        * XXX This is a hack until we have a decent separate name handling
+        * XXX for UDF filenames.
+        */
+       if (dvd_video && use_Joliet) {
+               use_Joliet = 0;
+               fprintf(stderr, "Warning: Disabling Joliet support for DVD-Video.\n");
+       }
+       if (use_udf && !use_Joliet)
+               jlen = 255;
+
+       if (preparer) {
+               if (strlen(preparer) > 128) {
+                       comerrno(EX_BAD, "Preparer string too long\n");
+               }
+       }
+       if (publisher) {
+               if (strlen(publisher) > 128) {
+                       comerrno(EX_BAD,
+                               "Publisher string too long\n");
+               }
+       }
+       if (stream_filename) {
+               if (strlen(stream_filename) > MAX_ISONAME)
+                       comerrno(EX_BAD,
+                                "stream-file-name too long (%d), max is %d.\n",
+                                (int)strlen(stream_filename), (int)MAX_ISONAME);
+               if (strchr(stream_filename, '/'))
+                       comerrno(EX_BAD, "Illegal character '/' in stream-file-name.\n");
+               iso9660_level = 4;
+       } else {
+               stream_filename = "STREAM.IMG;1";
+       }
+       if (system_id) {
+               if (strlen(system_id) > 32) {
+                       comerrno(EX_BAD,
+                                       "System ID string too long\n");
+               }
+       }
+
+
+       if (use_RockRidge && (iso9660_namelen > MAX_ISONAME_V2_RR))
+               iso9660_namelen = MAX_ISONAME_V2_RR;
+
+       if (warn_violate) /* this one is enough for quiet mode, print others warnings only in more verbose modes */
+               fprintf(stderr, "Warning: creating filesystem that does not conform to ISO-9660.\n");
+       if (iso9660_level > 3 && verbose>0)
+               fprintf(stderr, "Warning: Creating ISO-9660:1999 (version 2) filesystem.\n");
+       if (iso9660_namelen > LEN_ISONAME && verbose>0)
+               fprintf(stderr, "Warning: ISO-9660 filenames longer than %d may cause buffer overflows in the OS.\n",
+                       LEN_ISONAME);
+       if (use_Joliet && !use_RockRidge && verbose>0) {
+               fprintf(stderr,
+                      "Warning: creating filesystem with Joliet extensions but without Rock Ridge\n"
+                      "         extensions. It is highly recommended to add Rock Ridge.\n");
+       }
+       if (transparent_compression && verbose>0) {
+               fprintf(stderr, "Warning: using transparent compression. This is a nonstandard Rock Ridge\n");
+               fprintf(stderr, "         extension. The resulting filesystem can only be transparently\n");
+               fprintf(stderr, "         read on Linux. On other operating systems you need to call\n");
+               fprintf(stderr, "         mkzftree by hand to decompress the files.\n");
+       }
+       if (transparent_compression && !use_RockRidge && verbose>0) {
+               fprintf(stderr, "Warning: transparent decompression is a Linux Rock Ridge extension, but\n");
+               fprintf(stderr, "         creating filesystem without Rock Ridge attributes; files\n");
+               fprintf(stderr, "         will not be transparently decompressed.\n");
+       }
+    if(follow_links && verbose>0)
+        fprintf(stderr,
+                "Warning: -follow-links does not always work correctly; be careful.\n");
+
+       init_unls();            /* Initialize UNICODE tables */
+
+       /* initialize code tables from a file - if they exists */
+       init_unls_file(icharset);
+       init_unls_file(ocharset);
+#ifdef APPLE_HYB
+       init_unls_file(hfs_icharset);
+       init_unls_file(hfs_ocharset);
+#endif /* APPLE_HYB */
+
+#ifdef USE_ICONV
+       iconv_possible = !(iso9660_level >= 4 || ((ocharset &&
+               strcmp(ocharset, icharset ? icharset : "")) &&
+               use_RockRidge) || apple_ext || apple_hyb);
+
+       setlocale(LC_CTYPE, "");
+       
+       if (icharset == NULL && iconv_possible) {
+               char *charset = nl_langinfo(CODESET);
+               /* set to detected value but only if it is not pure US-ASCII */
+       if(charset) { /* workaround for SunOS, iconv is case-sensitive */
+                       char *t;
+                       charset = strdup(charset);
+                       for(t=charset;*t!='\0';t++)
+                               *t=tolower(*t);
+               }
+
+               if(strcmp(charset, "ansi_x3.4-1968") != 0)
+                       icharset = charset;
+
+               if(icharset && verbose > 0)
+                       fprintf(stderr, "I: -input-charset not specified, using %s (detected in locale settings)\n",
+                       icharset);
+       }
+
+       if(iconv_possible) {
+               /*
+                * don't care if initialization fails
+                */
+               init_nls_iconv(icharset);
+               init_nls_iconv(ocharset);
+       }
+#endif
+
+       if (icharset == NULL) {
+#if    (defined(__CYGWIN32__) || defined(__CYGWIN__) || defined(__DJGPP__)) && !defined(IS_CYGWIN_1)
+               in_nls = load_unls("cp437");
+#else
+               in_nls = load_unls("iso8859-1");
+#endif
+       } else {
+               if (strcmp(icharset, "default") == 0)
+                       in_nls = load_unls_default();
+               else
+                       in_nls = load_unls(icharset);
+       }
+       /*
+        * set the output charset to the same as the input or the given output
+        * charset
+        */
+       if (ocharset == NULL) {
+               out_nls = in_nls;
+       } else {
+               if (strcmp(ocharset, "default") == 0)
+                       out_nls = load_unls_default();
+               else
+                       out_nls = load_unls(ocharset);
+       }
+       if (in_nls == NULL || out_nls == NULL) { /* Unknown charset specified */
+               fprintf(stderr, "Unknown charset\nKnown charsets are:\n");
+               list_unls();    /* List all known charset names */
+#ifdef USE_ICONV
+        fprintf(stderr, "\nAdditional input charsets are available for Joliet through the iconv support."
+                "\nRun \"iconv -l\" to display them. Iconv charsets cannot be used with HFS, Apple"
+                "\nextension, ISO9660 version 2 or Rock Ridge.\n");
+#endif
+               exit(1);
+       }
+
+
+#ifdef APPLE_HYB
+       if (hfs_icharset == NULL || strcmp(hfs_icharset, "mac-roman")) {
+               hfs_inls = load_unls("cp10000");
+       } else {
+               if (strcmp(hfs_icharset, "default") == 0)
+                       hfs_inls = load_unls_default();
+               else
+                       hfs_inls = load_unls(hfs_icharset);
+       }
+       if (hfs_ocharset == NULL) {
+               hfs_onls = hfs_inls;
+       } else {
+               if (strcmp(hfs_ocharset, "default") == 0)
+                       hfs_onls = load_unls_default();
+               else if (strcmp(hfs_ocharset, "mac-roman") == 0)
+                       hfs_onls = load_unls("cp10000");
+               else
+                       hfs_onls = load_unls(hfs_ocharset);
+       }
+
+       if (hfs_inls == NULL || hfs_onls == NULL) {
+               fprintf(stderr, "Unknown HFS charset\nKnown charsets are:\n");
+               list_unls();
+               exit(1);
+       }
+#endif /* APPLE_HYB */
+
+       if (merge_image != NULL) {
+               if (open_merge_image(merge_image) < 0) {
+                       /* Complain and die. */
+#ifdef USE_LIBSCHILY
+                       comerr("Unable to open previous session image '%s'.\n",
+                               merge_image);
+#else
+                       fprintf(stderr,
+                               "Unable to open previous session image '%s'.\n",
+                               merge_image);
+                       exit(1);
+#endif
+               }
+       }
+       /* We don't need root privilleges anymore. */
+#ifdef HAVE_SETREUID
+       if (setreuid(-1, getuid()) < 0)
+#else
+#ifdef HAVE_SETEUID
+       if (seteuid(getuid()) < 0)
+#else
+       if (setuid(getuid()) < 0)
+#endif
+#endif
+#ifdef USE_LIBSCHILY
+               comerr("Panic cannot set back effective uid.\n");
+#else
+       {
+               perror("Panic cannot set back effective uid.");
+               exit(1);
+       }
+#endif
+
+
+#ifdef no_more_needed
+#ifdef __NetBSD__
+       {
+               int             resource;
+               struct rlimit   rlp;
+
+               if (getrlimit(RLIMIT_DATA, &rlp) == -1)
+                       perror("Warning: getrlimit failed");
+               else {
+                       rlp.rlim_cur = 33554432;
+                       if (setrlimit(RLIMIT_DATA, &rlp) == -1)
+                               perror("Warning: setrlimit failed");
+               }
+       }
+#endif
+#endif /* no_more_needed */
+#ifdef HAVE_SBRK
+       mem_start = (unsigned long) sbrk(0);
+#endif
+
+       /*
+        * if the -hide-joliet option has been given, set the Joliet option
+        */
+       if (!use_Joliet && j_ishidden())
+               use_Joliet++;
+
+#ifdef APPLE_HYB
+       if (apple_hyb && apple_ext) {
+#ifdef USE_LIBSCHILY
+               comerrno(EX_BAD, "Can't have both -apple and -hfs options");
+#else
+               fprintf(stderr, "Can't have both -apple and -hfs options");
+               exit(1);
+#endif
+       }
+       /*
+        * if -probe, -macname, any hfs selection and/or mapping file is given,
+        * but no HFS option, then select apple_hyb
+        */
+       if (!apple_hyb && !apple_ext) {
+               if (*afpfile || probe || use_mac_name || hfs_select ||
+                               hfs_boot_file || magic_filename ||
+                               hfs_ishidden() || gen_pt || autoname ||
+                               afe_size || icon_pos || hfs_ct ||
+                               hfs_icharset || hfs_ocharset) {
+                       apple_hyb = 1;
+               }
+       }
+       if (apple_ext && hfs_boot_file) {
+#ifdef USE_LIBSCHILY
+               comerrno(EX_BAD, "Can't have -hfs-boot-file with -apple\n");
+#else
+               fprintf(stderr, "Can't have -hfs-boot-file with -apple\n");
+               exit(1);
+#endif
+       }
+       if (apple_ext && autoname) {
+#ifdef USE_LIBSCHILY
+               comerrno(EX_BAD, "Can't have -auto with -apple\n");
+#else
+               fprintf(stderr, "Can't have -auto with -apple\n");
+               exit(1);
+#endif
+       }
+       if (apple_hyb && (use_sparcboot || use_sunx86boot)) {
+#ifdef USE_LIBSCHILY
+               comerrno(EX_BAD, "Can't have -hfs with -sparc-boot/-sunx86-boot\n");
+#else
+               fprintf(stderr, "Can't have -hfs with -sparc-boot/-sunx86-boot\n");
+               exit(1);
+#endif
+       }
+       if (apple_hyb && use_genboot) {
+#ifdef USE_LIBSCHILY
+               comerrno(EX_BAD, "Can't have -hfs with -generic-boot\n");
+#else
+               fprintf(stderr, "Can't have -hfs with -generic-boot\n");
+               exit(1);
+#endif
+       }
+#ifdef PREP_BOOT
+       if (apple_ext && use_prep_boot) {
+#ifdef USE_LIBSCHILY
+               comerrno(EX_BAD, "Can't have -prep-boot with -apple\n");
+#else
+               fprintf(stderr, "Can't have -prep-boot with -apple\n");
+               exit(1);
+#endif
+       }
+#endif /* PREP_BOOT */
+
+       if (apple_hyb || apple_ext)
+               apple_both = 1;
+
+       if (probe)
+               /* we need to search for all types of Apple/Unix files */
+               hfs_select = ~0;
+
+       if (apple_both && verbose && !(hfs_select || *afpfile || magic_filename)) {
+#ifdef USE_LIBSCHILY
+               errmsgno(EX_BAD,
+               "Warning: no Apple/Unix files will be decoded/mapped\n");
+#else
+               fprintf(stderr,
+               "Warning: no Apple/Unix files will be decoded/mapped\n");
+#endif
+       }
+       if (apple_both && verbose && !afe_size &&
+                                       (hfs_select & (DO_FEU | DO_FEL))) {
+#ifdef USE_LIBSCHILY
+               errmsgno(EX_BAD,
+               "Warning: assuming PC Exchange cluster size of 512 bytes\n");
+#else
+               fprintf(stderr,
+               "Warning: assuming PC Exchange cluster size of 512 bytes\n");
+#endif
+               afe_size = 512;
+       }
+       if (apple_both) {
+               /* set up the TYPE/CREATOR mappings */
+               hfs_init(afpfile, 0, hfs_select);
+       }
+       if (apple_ext && !use_RockRidge) {
+#ifdef nonono
+               /* use RockRidge to set the SystemUse field ... */
+               use_RockRidge++;
+               rationalize_all++;
+#else
+               /* EMPTY */
+#endif
+       }
+       if (apple_ext && !(use_XA || use_RockRidge)) {
+               comerrno(EX_BAD, "Need either -XA/-xa or -R/-r for -apple to become active.\n");
+       }
+
+#endif /* APPLE_HYB */
+
+       if (rationalize_all) {
+               rationalize++;
+               rationalize_uid++;
+               rationalize_gid++;
+               rationalize_filemode++;
+               rationalize_dirmode++;
+       }
+
+       if (verbose > 1) {
+               fprintf(stderr, "%s (%s)\n", version_string, HOST_SYSTEM);
+       }
+       if (cdrecord_data == NULL && !check_session && merge_image != NULL) {
+#ifdef USE_LIBSCHILY
+               comerrno(EX_BAD,
+               "Multisession usage bug: Must specify -C if -M is used.\n");
+#else
+               fprintf(stderr,
+               "Multisession usage bug: Must specify -C if -M is used.\n");
+               exit(1);
+#endif
+       }
+       if (cdrecord_data != NULL && merge_image == NULL) {
+#ifdef USE_LIBSCHILY
+               errmsgno(EX_BAD,
+               "Warning: -C specified without -M: old session data will not be merged.\n");
+#else
+               fprintf(stderr,
+               "Warning: -C specified without -M: old session data will not be merged.\n");
+#endif
+       }
+#ifdef APPLE_HYB
+       if (merge_image != NULL && apple_hyb) {
+#ifdef USE_LIBSCHILY
+               errmsgno(EX_BAD,
+               "Warning: files from previous sessions will not be included in the HFS volume.\n");
+#else
+               fprintf(stderr,
+               "Warning: files from previous sessions will not be included in the HFS volume.\n");
+#endif
+       }
+#endif /* APPLE_HYB */
+
+       /*
+        * see if we have a list of pathnames to process
+        */
+       if (pathnames) {
+               /* "-" means take list from the standard input */
+               if (strcmp(pathnames, "-")) {
+                       if ((pfp = fopen(pathnames, "r")) == NULL) {
+#ifdef USE_LIBSCHILY
+                               comerr("Unable to open pathname list %s.\n",
+                                                               pathnames);
+#else
+                               fprintf(stderr,
+                                       "Unable to open pathname list %s.\n",
+                                                               pathnames);
+                               exit(1);
+#endif
+                       }
+               } else
+                       pfp = stdin;
+       }
+
+       /* The first step is to scan the directory tree, and take some notes */
+
+       if ((arg = get_pnames(argc, argv, optind, pname,
+                                       sizeof (pname), pfp)) == NULL) {
+               if (check_session == 0 && !stream_media_size) {
+#ifdef USE_LIBSCHILY
+                       errmsgno(EX_BAD, "Missing pathspec.\n");
+#endif
+                       susage(1);
+               }
+       }
+
+       /*
+        * if we don't have a pathspec, then save the pathspec found
+        * in the pathnames file (stored in pname) - we don't want
+        * to skip this pathspec when we read the pathnames file again
+        */
+       if (!have_cmd_line_pathspec && !stream_media_size) {
+               save_pname = 1;
+       }
+       if (stream_media_size) {
+               if (use_XA || use_RockRidge || use_udf || use_Joliet)
+                       comerrno(EX_BAD,
+                       "Cannot use XA, Rock Ridge, UDF or Joliet with -stream-media-size\n");
+               if (merge_image)
+                       comerrno(EX_BAD,
+                       "Cannot use multi session with -stream-media-size\n");
+               if (use_eltorito || use_sparcboot || use_sunx86boot ||
+                   use_genboot || use_prep_boot || hfs_boot_file)
+                       comerrno(EX_BAD,
+                       "Cannot use boot options with -stream-media-size\n");
+               if (apple_hyb)
+                       comerrno(EX_BAD,
+                       "Cannot use Apple hybrid options with -stream-media-size\n");
+       }
+
+       if (use_RockRidge) {
+               /* BEGIN CSTYLED */
+#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
+               /* END CSTYLED */
+       }
+       if (log_file) {
+               FILE            *lfp;
+               int             i;
+
+               /* open log file - test that we can open OK */
+               if ((lfp = fopen(log_file, "w")) == NULL) {
+#ifdef USE_LIBSCHILY
+                       comerr("Can't open logfile: '%s'.\n", log_file);
+#else
+                       fprintf(stderr, "Can't open logfile: '%s'.\n", log_file);
+                       exit(1);
+#endif
+               }
+               fclose(lfp);
+
+               /* redirect all stderr message to log_file */
+               fprintf(stderr, "re-directing all messages to %s\n", log_file);
+               fflush(stderr);
+
+               /* associate stderr with the log file */
+               if (freopen(log_file, "w", stderr) == NULL) {
+#ifdef USE_LIBSCHILY
+                       comerr("Can't open logfile: '%s'.\n", log_file);
+#else
+                       fprintf(stderr, "Can't open logfile: '%s'.\n", log_file);
+                       exit(1);
+#endif
+               }
+               if (verbose > 1) {
+                       for (i = 0; i < argc; i++)
+                               fprintf(stderr, "%s ", argv[i]);
+
+                       fprintf(stderr, "\n%s (%s)\n",
+                               version_string, HOST_SYSTEM);
+               }
+       }
+       /* Find name of root directory. */
+       if (arg != NULL)
+               node = findgequal(arg);
+       if (!use_graft_ptrs)
+               node = NULL;
+       if (node == NULL) {
+               if (use_graft_ptrs && arg != NULL)
+                       node = escstrcpy(nodename, arg);
+               else
+                       node = arg;
+       } else {
+               /*
+                * Remove '\\' escape chars which are located
+                * before '\\' and '=' chars
+                */
+               node = escstrcpy(nodename, ++node);
+       }
+
+       /*
+        * See if boot catalog file exists in root directory, if not we will
+        * create it.
+        */
+       if (use_eltorito)
+               init_boot_catalog(node);
+
+       /*
+        * Find the device and inode number of the root directory. Record this
+        * in the hash table so we don't scan it more than once.
+        */
+       stat_filter(node, &statbuf);
+       add_directory_hash(statbuf.st_dev, STAT_INODE(statbuf));
+
+       memset(&de, 0, sizeof (de));
+
+       /*
+        * PO:
+        * Isn't root NULL at this time anyway?
+        * I think it is created by the first call to
+        * find_or_create_directory() below.
+        */
+       de.filedir = root;      /* We need this to bootstrap */
+
+       if (cdrecord_data != NULL && merge_image == NULL) {
+               /*
+                * in case we want to add a new session, but don't want to
+                * merge old one
+                */
+               get_session_start(NULL);
+       }
+       if (merge_image != NULL) {
+               char    sector[SECTOR_SIZE];
+
+               errno = 0;
+               mrootp = merge_isofs(merge_image);
+               if (mrootp == NULL) {
+                       /* Complain and die. */
+#ifdef USE_LIBSCHILY
+                       if (errno == 0)
+                               errno = -1;
+                       comerr("Unable to find previous session PVD '%s'.\n",
+                               merge_image);
+#else
+                       fprintf(stderr,
+                               "Unable to find previous session PVD '%s'.\n",
+                               merge_image);
+                       exit(1);
+#endif
+               }
+               memcpy(de.isorec.extent, mrootp->extent, 8);
+
+               /*
+                * Look for RR Attributes in '.' entry of root dir.
+                * This is the first ISO directory entry in the root dir.
+                */
+               c = isonum_733((unsigned char *)mrootp->extent);
+#ifdef  USE_SCG
+               readsecs(c, sector, 1);
+#else
+    lseek(fileno(in_image), c*2048, SEEK_SET);
+    read(fileno(in_image), sector, sizeof (sector));
+#endif
+               c = rr_flags((struct iso_directory_record *)sector);
+               if (c & RR_FLAG_XA)
+                       fprintf(stderr, "XA signatures found\n");
+               if (c & RR_FLAG_AA)
+                       fprintf(stderr, "AA signatures found\n");
+               if (c & ~(RR_FLAG_XA|RR_FLAG_AA)) {
+                       if (c & RR_FLAG_SP) {
+                               fprintf(stderr, "Rock Ridge signatures found\n");
+                       } else {
+                               fprintf(stderr, "Bad Rock Ridge signatures found (SU record missing)\n");
+                               if (!force_rr)
+                                       no_rr++;
+                       }
+               } else {
+                       fprintf(stderr, "NO Rock Ridge present\n");
+                       if ((c & (RR_FLAG_XA|RR_FLAG_AA)) == 0) {
+                               if (!force_rr)
+                                       no_rr++;
+                       }
+               }
+               if (no_rr)
+                       fprintf(stderr, "Disabling Rock Ridge / XA / AA\n");
+       }
+       /*
+        * Create an empty root directory. If we ever scan it for real,
+        * we will fill in the contents.
+        */
+       find_or_create_directory(NULL, "", &de, TRUE, NULL);
+
+#ifdef APPLE_HYB
+       /* may need to set window layout of the volume */
+       if (root_info)
+               set_root_info(root_info);
+#endif /* APPLE_HYB */
+
+       if(optind < argc-1)
+               merge_warn_msg="NOTE: multiple source directories have been specified and merged into the root\n"
+                       "of the filesystem. Check your program arguments. genisoimage is not tar.\n";
+
+       /*
+        * Scan the actual directory (and any we find below it) for files to
+        * write out to the output image.  Note - we take multiple source
+        * directories and keep merging them onto the image.
+        */
+if (check_session == 0)
+       while ((arg = get_pnames(argc, argv, optind, pname,
+                                       sizeof (pname), pfp)) != NULL) {
+               struct directory *graft_dir;
+               struct stat     st;
+               char            *short_name;
+               int             status;
+               char            graft_point[PATH_MAX + 1];
+
+               /*
+                * We would like a syntax like:
+                *
+                *      /tmp=/usr/tmp/xxx
+                *
+                * where the user can specify a place to graft each component
+                * of the tree.  To do this, we may have to create directories
+                * along the way, of course. Secondly, I would like to allow
+                * the user to do something like:
+                *
+                *      /home/baz/RMAIL=/u3/users/baz/RMAIL
+                *
+                * so that normal files could also be injected into the tree
+                * at an arbitrary point.
+                *
+                * The idea is that the last component of whatever is being
+                * entered would take the name from the last component of
+                * whatever the user specifies.
+                *
+                * The default will be that the file is injected at the root of
+                * the image tree.
+                */
+               node = findgequal(arg);
+               if (!use_graft_ptrs)
+                       node = NULL;
+               /*
+                * Remove '\\' escape chars which are located
+                * before '\\' and '=' chars ---> below in escstrcpy()
+                */
+
+               short_name = NULL;
+
+               if (node != NULL || reloc_root) {
+                       char            *pnt;
+                       char            *xpnt;
+                       size_t          len;
+                       int             node_is_dir;
+
+                       /* insert -root prefix */
+                       if (reloc_root != NULL) {
+                               strcpy(graft_point, reloc_root);
+                               len = strlen(graft_point);
+                               if (graft_point[len] != '/') {
+                                       graft_point[len++] = '/';
+                                       graft_point[len] = '\0';
+                               }
+                       } else {
+                               len = 0;
+                       }
+
+                       if (node) {
+                               *node = '\0';
+                               escstrcpy(&graft_point[len], arg);
+                               *node = '=';
+                       }
+
+                       /*
+                        * Remove unwanted "./" & "/" sequences from start...
+                        */
+                       do {
+                               xpnt = graft_point;
+                               while (xpnt[0] == '.' && xpnt[1] == '/')
+                                       xpnt += 2;
+                               while (*xpnt == PATH_SEPARATOR) {
+                                       xpnt++;
+                               }
+                               memmove(graft_point, xpnt, strlen(xpnt)+1);
+                       } while (xpnt > graft_point);
+
+                       if (node) {
+                               node = escstrcpy(nodename, ++node);
+                       } else {
+                               node = arg;
+                       }
+
+                       graft_dir = root;
+                       xpnt = graft_point;
+
+                       /*
+                        * If "node" points to a directory, then graft_point
+                        * needs to point to a directory too.
+                        */
+                       if (follow_links)
+                               status = stat_filter(node, &st);
+                       else
+                               status = lstat_filter(node, &st);
+
+                       node_is_dir = S_ISDIR(st.st_mode);
+                       if (status == 0 && node_is_dir) {
+                               len = strlen(graft_point);
+
+                               if ((len <= (sizeof (graft_point) -1)) &&
+                                   graft_point[len-1] != '/') {
+                                       graft_point[len++] = '/';
+                                       graft_point[len] = '\0';
+                               }
+                       }
+                       if (debug)
+                               fprintf(stderr, "GRAFT:'%s'\n", xpnt);
+                       /*
+                        * Loop down deeper and deeper until we find the
+                        * correct insertion spot.
+                        * Canonicalize the filename while parsing it.
+                        */
+                       for (;;) {
+                               struct stat* stat_template;
+
+                               do {
+                                       while (xpnt[0] == '.' && xpnt[1] == '/')
+                                               xpnt += 2;
+                                       while (xpnt[0] == '/')
+                                               xpnt += 1;
+                                       if (xpnt[0] == '.' && xpnt[1] == '.' && xpnt[2] == '/') {
+                                               if (graft_dir && graft_dir != root) {
+                                                       graft_dir = graft_dir->parent;
+                                                       xpnt += 2;
+                                               }
+                                       }
+                               } while ((xpnt[0] == '/') || (xpnt[0] == '.' && xpnt[1] == '/'));
+                               pnt = strchr(xpnt, PATH_SEPARATOR);
+                               if (pnt == NULL) {
+                                       if (*xpnt != '\0') {
+                                               short_name = xpnt;
+                                       }
+                                       break;
+                               }
+                               *pnt = '\0';
+                               if (debug) {
+                                       fprintf(stderr, "GRAFT Point:'%s' in '%s : %s' (%s)\n",
+                                               xpnt,
+                                               graft_dir->whole_name,
+                                               graft_dir->de_name,
+                                               graft_point);
+                               }
+                               /*
+                                * If the node being grafted is a
+                                * directory, then we want the last
+                                * directory in this graft chain to have
+                                * the ownership and permissions of the
+                                * source node.  Other directories in the
+                                * chain get default ownership and
+                                * permissions.
+                                */
+                               stat_template = 
+                                 (pnt[1] == '\0' && node_is_dir) ? &st : 0;
+
+                               graft_dir = find_or_create_directory(graft_dir,
+                                       graft_point, NULL, TRUE, 
+                                       stat_template);
+
+                               *pnt = PATH_SEPARATOR;
+                               xpnt = pnt + 1;
+                       }
+               } else {
+                       graft_dir = root;
+                       if (use_graft_ptrs)
+                               node = escstrcpy(nodename, arg);
+                       else
+                               node = arg;
+               }
+
+               /*
+                * Get information on the node
+                */
+               if (follow_links)
+                       status = stat_filter(node, &st);
+               else
+                       status = lstat_filter(node, &st);
+               if (status != 0) {
+                       /*
+                        * This is a fatal error - the user won't be getting
+                        * what they want if we were to proceed.
+                        */
+#ifdef USE_LIBSCHILY
+                       comerr("Invalid node - '%s'.\n", node);
+#else
+                       fprintf(stderr, "Invalid node - '%s'.\n", node);
+                       exit(1);
+#endif
+               } else {
+                       /*
+                        * Now see whether the user wants to add a regular
+                        * file or a directory at this point.
+                        */
+                       if (S_ISDIR(st.st_mode)) {
+                               if (debug) {
+                                       fprintf(stderr, "graft_dir: '%s : %s', node: '%s', (scan)\n",
+                                               graft_dir->whole_name,
+                                               graft_dir->de_name, node);
+                               }
+                               if (!scan_directory_tree(graft_dir,
+                                                               node, &de)) {
+                                       exit(1);
+                               }
+                               if (debug) {
+                                       fprintf(stderr, "scan done\n");
+                               }
+                       } else {
+                               if (short_name == NULL) {
+                                       short_name = strrchr(node,
+                                                       PATH_SEPARATOR);
+                                       if (short_name == NULL ||
+                                                       short_name < node) {
+                                               short_name = node;
+                                       } else {
+                                               short_name++;
+                                       }
+                               }
+                               if (debug) {
+                                       fprintf(stderr, "graft_dir: '%s : %s', node: '%s', short_name: '%s'\n",
+                                               graft_dir->whole_name,
+                                               graft_dir->de_name, node,
+                                               short_name);
+                               }
+#ifdef APPLE_HYB
+                               if (!insert_file_entry(graft_dir, node,
+                                                               short_name, 0))
+#else
+                               if (!insert_file_entry(graft_dir, node,
+                                                               short_name))
+#endif /* APPLE_HYB */
+                               {
+                                       /*
+                                        * Should we ignore this?
+                                        */
+/*                                     exit(1);*/
+                                       /* EMPTY */
+                               }
+                       }
+               }
+
+               optind++;
+               no_path_names = 0;
+       }
+
+       if (pfp && pfp != stdin)
+               fclose(pfp);
+
+       /*
+        * exit if we don't have any pathnames to process
+        * - not going to happen at the moment as we have to have at least one
+        * path on the command line
+        */
+       if (no_path_names && !check_session && !stream_media_size) {
+#ifdef USE_LIBSCHILY
+               errmsgno(EX_BAD, "No pathnames found.\n");
+#endif
+               susage(1);
+       }
+       /*
+        * Now merge in any previous sessions.  This is driven on the source
+        * side, since we may need to create some additional directories.
+        */
+       if (merge_image != NULL) {
+               if (merge_previous_session(root, mrootp,
+                                       reloc_root, reloc_old_root) < 0) {
+#ifdef USE_LIBSCHILY
+                       comerrno(EX_BAD, "Cannot merge previous session.\n");
+#else
+                       fprintf(stderr, "Cannot merge previous session.\n");
+                       exit(1);
+#endif
+               }
+               close_merge_image();
+
+               /*
+                * set up parent_dir and filedir in relocated entries which
+                * were read from previous session so that
+                * finish_cl_pl_entries can do its job
+                */
+               match_cl_re_entries();
+       }
+#ifdef APPLE_HYB
+       /* free up any HFS filename mapping memory */
+       if (apple_both)
+               clean_hfs();
+#endif /* APPLE_HYB */
+
+       /* hide "./rr_moved" if all its contents have been hidden */
+       if (reloc_dir && i_ishidden())
+               hide_reloc_dir();
+
+       /* insert the boot catalog if required */
+       if (use_eltorito)
+               insert_boot_cat();
+
+       /*
+        * Free up any matching memory
+        */
+       for (n = 0; n < MAX_MAT; n++)
+               gen_del_match(n);
+
+#ifdef SORTING
+       del_sort();
+#endif /* SORTING */
+
+       /*
+        * Sort the directories in the required order (by ISO9660).  Also,
+        * choose the names for the 8.3 filesystem if required, and do any
+        * other post-scan work.
+        */
+       goof += sort_tree(root);
+
+       if (goof) {
+               fprintf(stderr, "ISO9660/Rock Ridge tree sort failed.\n");
+               if(merge_warn_msg)
+                       fprintf(stderr, merge_warn_msg);
+               exit(1);
+       }
+#ifdef UDF
+       if (use_Joliet || use_udf) {
+#else
+       if (use_Joliet) {
+#endif
+               goof += joliet_sort_tree(root);
+       }
+       if (goof) {
+               fprintf(stderr, "Joliet tree sort failed. The -joliet-long switch may help you.\n");
+               if(merge_warn_msg)
+                       fprintf(stderr, merge_warn_msg);
+               exit(1);
+       }
+       /*
+        * Fix a couple of things in the root directory so that everything is
+        * self consistent. Fix this up so that the path tables get done right.
+        */
+       root->self = root->contents;
+
+       /* OK, ready to write the file.  Open it up, and generate the thing. */
+       if (print_size) {
+               discimage = fopen("/dev/null", "wb");
+               if (!discimage) {
+#ifdef USE_LIBSCHILY
+                       comerr("Unable to open /dev/null\n");
+#else
+                       fprintf(stderr, "Unable to open /dev/null\n");
+                       exit(1);
+#endif
+               }
+       } else if (outfile && (strcmp (outfile, "-")) != 0) {
+               discimage = fopen(outfile, "wb");
+               if (!discimage) {
+#ifdef USE_LIBSCHILY
+                       comerr("Unable to open disc image file '%s'.\n", outfile);
+#else
+                       fprintf(stderr, "Unable to open disc image file '%s'.\n", outfile);
+                       exit(1);
+#endif
+               }
+               if (jtemplate_out || jjigdo_out) {
+                       if (!jtemplate_out || !jjigdo_out || !jmd5_list) {
+#ifdef USE_LIBSCHILY
+                               comerr("Bad options - need to specify output names for jigdo and template file, and also the md5-list input file!\n");
+#else
+                               fprintf(stderr, "Bad options - need to specify output names for jigdo and template file, and also the md5-list input file!\n");
+                               exit(1);
+#endif
+                       }
+                       jtjigdo = fopen(jjigdo_out, "wb");
+                       jttemplate = fopen(jtemplate_out, "wb");
+                       if (!jtjigdo || !jttemplate) {
+#ifdef USE_LIBSCHILY
+                               comerr("Unable to open jigdo template image file\n");
+#else
+                               fprintf(stderr, "Unable to open jigdo template image file\n");
+                               exit(1);
+#endif
+                       }
+                       write_jt_header(jttemplate, jtjigdo);
+               }
+       } else if ((outfile == NULL)
+               && isatty (fileno (stdout))) {
+               /* FIXME: a cleaner way to override this check? */
+               fputs (("image not written to a terminal.\n"
+                "Use -o - to force the output.\n"),
+                      stderr);
+               exit (1);
+       } else {
+               discimage = stdout;
+
+#ifdef NEED_O_BINARY
+               setmode(fileno(stdout), O_BINARY);
+#endif
+       }
+
+       /* Now assign addresses on the disc for the path table. */
+
+       path_blocks = ISO_BLOCKS(path_table_size);
+       if (path_blocks & 1)
+               path_blocks++;
+
+       jpath_blocks = ISO_BLOCKS(jpath_table_size);
+       if (jpath_blocks & 1)
+               jpath_blocks++;
+
+       /*
+        * Start to set up the linked list that we use to track the contents
+        * of the disc.
+        */
+#ifdef APPLE_HYB
+#ifdef PREP_BOOT
+       if (apple_hyb || use_prep_boot || use_chrp_boot)
+#else  /* PREP_BOOT */
+       if (apple_hyb)
+#endif /* PREP_BOOT */
+               outputlist_insert(&hfs_desc);
+#endif /* APPLE_HYB */
+       if (use_sparcboot || use_sunx86boot)
+               outputlist_insert(&sunlabel_desc);
+       if (use_alphaboot)
+               outputlist_insert(&alphaboot_desc);
+       if (use_hppaboot)
+               outputlist_insert(&hppaboot_desc);
+       if (use_alphaboot || use_hppaboot)
+               outputlist_insert(&alpha_hppa_boot_desc);
+       if (use_mipsboot)
+               outputlist_insert(&mipsboot_desc);
+       if (use_mipselboot)
+               outputlist_insert(&mipselboot_desc);
+       if (use_genboot)
+               outputlist_insert(&genboot_desc);
+       outputlist_insert(&startpad_desc);
+
+       /* PVD for disc. */
+       outputlist_insert(&voldesc_desc);
+
+       /* SVD for El Torito. MUST be immediately after the PVD! */
+       if (use_eltorito) {
+               outputlist_insert(&torito_desc);
+       }
+       /* Enhanced PVD for disc. neded if we write ISO-9660:1999 */
+       if (iso9660_level > 3)
+               outputlist_insert(&xvoldesc_desc);
+
+       /* SVD for Joliet. */
+       if (use_Joliet) {
+               outputlist_insert(&joliet_desc);
+       }
+       /* Finally the last volume descriptor. */
+       outputlist_insert(&end_vol);
+
+#ifdef UDF
+       if (use_udf) {
+               outputlist_insert(&udf_vol_recognition_area_frag);
+       }
+#endif
+
+       /* Insert the version descriptor. */
+       outputlist_insert(&version_desc);
+
+#ifdef UDF
+       if (use_udf) {
+               /*
+                * Most of the space before sector 256 is wasted when
+                * UDF is turned on. The waste could be reduced by
+                * putting the ISO9660/Joliet structures before the
+                * pad_to_sector_256; the problem is that they might
+                * overshoot sector 256, so there would have to be some
+                * ugly logic to detect this case and rearrange things
+                * appropriately. I don't know if it's worth it.
+                */
+               outputlist_insert(&udf_pad_to_sector_32_frag);
+               outputlist_insert(&udf_main_seq_frag);
+               outputlist_insert(&udf_main_seq_copy_frag);
+               outputlist_insert(&udf_integ_seq_frag);
+               outputlist_insert(&udf_pad_to_sector_256_frag);
+               outputlist_insert(&udf_anchor_vol_desc_frag);
+               outputlist_insert(&udf_file_set_desc_frag);
+               outputlist_insert(&udf_dirtree_frag);
+               outputlist_insert(&udf_file_entries_frag);
+       }
+#endif
+
+       /* Now start with path tables and directory tree info. */
+       if (!stream_media_size)
+               outputlist_insert(&pathtable_desc);
+       else
+               outputlist_insert(&strpath_desc);
+
+       if (use_Joliet) {
+               outputlist_insert(&jpathtable_desc);
+       }
+
+       if (!stream_media_size)
+               outputlist_insert(&dirtree_desc);
+
+       if (use_Joliet) {
+               outputlist_insert(&jdirtree_desc);
+       }
+       outputlist_insert(&dirtree_clean);
+
+       if (extension_record) {
+               outputlist_insert(&extension_desc);
+       }
+
+       if (!stream_media_size) {
+               outputlist_insert(&files_desc);
+       } else {
+               outputlist_insert(&strfile_desc);
+               outputlist_insert(&strdir_desc);
+       }
+
+       /*
+        * Allow room for the various headers we will be writing.
+        * There will always be a primary and an end volume descriptor.
+        */
+       last_extent = session_start;
+
+       /*
+        * Calculate the size of all of the components of the disc, and assign
+        * extent numbers.
+        */
+       for (opnt = out_list; opnt; opnt = opnt->of_next) {
+               opnt->of_start_extent = last_extent;
+               if (opnt->of_size != NULL) {
+                       (*opnt->of_size) (last_extent);
+               }
+       }
+
+       /*
+        * Generate the contents of any of the sections that we want to
+        * generate. Not all of the fragments will do anything here
+        * - most will generate the data on the fly when we get to the write
+        * pass.
+        */
+       for (opnt = out_list; opnt; opnt = opnt->of_next) {
+               if (opnt->of_generate != NULL) {
+                       (*opnt->of_generate) ();
+               }
+       }
+
+       /*
+        * Padding just after the ISO-9660 filesystem.
+        *
+        * files_desc does not have an of_size function. For this
+        * reason, we must insert us after the files content has been
+        * generated.
+        */
+#ifdef UDF
+       if (use_udf) {
+               /* Single anchor volume descriptor pointer at end */
+               outputlist_insert(&udf_end_anchor_vol_desc_frag);
+               if (udf_end_anchor_vol_desc_frag.of_size != NULL) {
+                       (*udf_end_anchor_vol_desc_frag.of_size) (last_extent);
+               }
+               if (dopad) {
+                       /*
+                        * Pad with anchor volume descriptor pointer
+                        * blocks instead of zeroes.
+                        */
+                       outputlist_insert(&udf_padend_avdp_frag);
+                       if (udf_padend_avdp_frag.of_size != NULL) {
+                               (*udf_padend_avdp_frag.of_size) (last_extent);
+                       }
+               }
+       } else
+#endif
+       if (dopad && !(use_sparcboot || use_sunx86boot)) {
+               outputlist_insert(&endpad_desc);
+               if (endpad_desc.of_size != NULL) {
+                       (*endpad_desc.of_size) (last_extent);
+               }
+       }
+       c = 0;
+       if (use_sparcboot) {
+               if (dopad) {
+                       /* Padding before the boot partitions. */
+                       outputlist_insert(&interpad_desc);
+                       if (interpad_desc.of_size != NULL) {
+                               (*interpad_desc.of_size) (last_extent);
+                       }
+               }
+               c = make_sun_label();
+               last_extent += c;
+               outputlist_insert(&sunboot_desc);
+               if (dopad) {
+                       outputlist_insert(&endpad_desc);
+                       if (endpad_desc.of_size != NULL) {
+                               (*endpad_desc.of_size) (last_extent);
+                       }
+               }
+       } else if (use_sunx86boot) {
+               if (dopad) {
+                       /* Padding before the boot partitions. */
+                       outputlist_insert(&interpad_desc);
+                       if (interpad_desc.of_size != NULL) {
+                               (*interpad_desc.of_size) (last_extent);
+                       }
+               }
+               c = make_sunx86_label();
+               last_extent += c;
+               outputlist_insert(&sunboot_desc);
+               if (dopad) {
+                       outputlist_insert(&endpad_desc);
+                       if (endpad_desc.of_size != NULL) {
+                               (*endpad_desc.of_size) (last_extent);
+                       }
+               }
+       }
+       if (print_size > 0) {
+               if (verbose > 0)
+                       fprintf(stderr,
+                       "Total extents scheduled to be written = %u\n",
+                       (last_extent - session_start));
+               printf("%u\n", (last_extent - session_start));
+               exit(0);
+       }
+       /*
+        * Now go through the list of fragments and write the data that
+        * corresponds to each one.
+        */
+       for (opnt = out_list; opnt; opnt = opnt->of_next) {
+               Uint    oext;
+
+               oext = last_extent_written;
+               if (opnt->of_start_extent != 0 &&
+                   opnt->of_start_extent != last_extent_written) {
+                       /*
+                        * Consistency check.
+                        * XXX Should make sure that all entries have
+                        * XXXX of_start_extent set up correctly.
+                        */
+                       comerrno(EX_BAD,
+                       "Implementation botch: %s should start at %u but starts at %u.\n",
+                       opnt->of_name, opnt->of_start_extent, last_extent_written);
+               }
+               if (opnt->of_write != NULL) {
+                       if (verbose > 1)
+                               fprintf(stderr, "Writing:   %-40sStart Block %u\n",
+                                       opnt->of_name, last_extent_written);
+                       (*opnt->of_write) (discimage);
+                       if (verbose > 1)
+                               fprintf(stderr, "Done with: %-40sBlock(s)    %u\n",
+                                       opnt->of_name, last_extent_written-oext);
+               }
+       }
+       if (last_extent != last_extent_written) {
+               comerrno(EX_BAD,
+               "Implementation botch: FS should end at %u but ends at %u.\n",
+                               last_extent, last_extent_written);
+       }
+
+       if (jttemplate) {
+               write_jt_footer();
+               fclose(jttemplate);
+       }
+       if (jtjigdo)
+               fclose(jtjigdo);
+
+       if (verbose > 0) {
+#ifdef HAVE_SBRK
+               fprintf(stderr, "Max brk space used %x\n",
+                       (unsigned int)(((unsigned long) sbrk(0)) - mem_start));
+#endif
+               fprintf(stderr, "%u extents written (%u MB)\n",
+                       last_extent, last_extent >> 9);
+       }
+#ifdef VMS
+       return (1);
+#else
+       return (0);
+#endif
+}
+
+/*
+ * Find unescaped equal sign in graft pointer string.
+ */
+char *
+findgequal(char *s)
+{
+       char    *p = s;
+
+       while ((p = strchr(p, '=')) != NULL) {
+               if (p > s && p[-1] != '\\')
+                       return (p);
+               p++;
+       }
+       return (NULL);
+}
+
+/*
+ * Find unescaped equal sign in string.
+ */
+static char *
+escstrcpy(char *to, char *from)
+{
+       char    *p = to;
+
+       if (debug)
+               fprintf(stderr, "FROM: '%s'\n", from);
+
+       while ((*p = *from++) != '\0') {
+               if (*p == '\\') {
+                       if ((*p = *from++) == '\0')
+                               break;
+                       if (*p != '\\' && *p != '=') {
+                               p[1] = p[0];
+                               *p++ = '\\';
+                       }
+               }
+               p++;
+       }
+       if (debug)
+               fprintf(stderr, "ESC:  '%s'\n", to);
+       return (to);
+}
+
+void *
+e_malloc(size_t size)
+{
+       void            *pt = 0;
+
+       if ((size > 0) && ((pt = malloc(size)) == NULL)) {
+#ifdef USE_LIBSCHILY
+               comerr("Not enough memory\n");
+#else
+               fprintf(stderr, "Not enough memory\n");
+               exit(1);
+#endif
+       }
+       /*
+        * Not all code is clean yet.
+        * Filling all allocated data with zeroes will help
+        * to avoid core dumps.
+        */
+  if (size > 0) /* a workaround for gcc bug gcc.gnu.org/PR25639 */
+     memset(pt, 0, size);
+       return (pt);
+}
diff --git a/genisoimage/genisoimage.h b/genisoimage/genisoimage.h
new file mode 100644 (file)
index 0000000..bbedfb0
--- /dev/null
@@ -0,0 +1,802 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)genisoimage.h   1.95 05/05/01 joerg */
+/*
+ * Header file genisoimage.h - assorted structure definitions and typecasts.
+ *
+ * Written by Eric Youngdale (1993).
+ *
+ * Copyright 1993 Yggdrasil Computing, Incorporated
+ * Copyright (c) 1999,2000-2003 J. Schilling
+ *
+ * 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.
+ */
+
+/* APPLE_HYB James Pearson j.pearson@ge.ucl.ac.uk 23/2/2000 */
+
+#define APPID_DEFAULT "GENISOIMAGE ISO 9660/HFS FILESYSTEM CREATOR (C) 1993 E.YOUNGDALE (C) 1997-2006 J.PEARSON/J.SCHILLING (C) 2006-2007 CDRKIT TEAM"
+
+
+#include <mconfig.h>   /* Must be before stdio.h for LARGEFILE support */
+#include <stdio.h>
+#include <statdefs.h>
+#include <stdxlib.h>
+#include <unixstd.h>   /* Needed for for LARGEFILE support */
+#include <strdefs.h>
+#include <dirdefs.h>
+#include <utypes.h>
+#include <standard.h>
+#include <libport.h>
+#include "scsi.h"
+#ifdef JIGDO_TEMPLATE
+#include "jte.h"
+#endif
+
+#ifdef DVD_VIDEO
+#ifndef        UDF
+#define        UDF
+#endif
+#endif
+
+/*#if  _LFS_LARGEFILE*/
+#ifdef HAVE_LARGEFILES
+/*
+ * XXX Hack until fseeko()/ftello() are available everywhere or until
+ * XXX we know a secure way to let autoconf ckeck for fseeko()/ftello()
+ * XXX without defining FILE_OFFSETBITS to 64 in confdefs.h
+ */
+#      define  fseek   fseeko
+#      define  ftell   ftello
+#endif
+
+#ifndef        HAVE_LSTAT
+#ifndef        VMS
+#define        lstat   stat
+#endif
+#endif
+
+#include "iso9660.h"
+#include "defaults.h"
+#include <unls.h>
+
+extern struct unls_table *in_nls;      /* input UNICODE conversion table */
+extern struct unls_table *out_nls;     /* output UNICODE conversion table */
+extern struct unls_table *hfs_inls;    /* input HFS UNICODE conversion table */
+extern struct unls_table *hfs_onls;    /* output HFS UNICODE conversion table */
+
+#ifdef APPLE_HYB
+#include "mactypes.h"
+#include "hfs.h"
+
+struct hfs_info {
+       unsigned char   finderinfo[32];
+       char            name[HFS_MAX_FLEN + 1];
+       /* should have fields for dates here as well */
+       char            *keyname;
+       struct hfs_info *next;
+};
+
+#endif /* APPLE_HYB */
+
+struct directory_entry {
+       struct directory_entry *next;
+       struct directory_entry *jnext;
+       struct iso_directory_record isorec;
+       unsigned int    starting_block;
+       off_t           size;
+       unsigned short  priority;
+       unsigned char   jreclen;        /* Joliet record len */
+       char            *name;
+       char            *table;
+       char            *whole_name;
+       struct directory *filedir;
+       struct directory_entry *parent_rec;
+       unsigned int    de_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;
+       unsigned int    got_rr_name;
+#ifdef APPLE_HYB
+       struct directory_entry *assoc;  /* entry has a resource fork */
+       hfsdirent       *hfs_ent;       /* HFS parameters */
+       off_t           hfs_off;        /* offset to real start of fork */
+       int             hfs_type;       /* type of HFS Unix file */
+#endif /* APPLE_HYB */
+#ifdef SORTING
+       int             sort;           /* sort weight for entry */
+#endif /* SORTING */
+#ifdef UDF
+       int             udf_file_entry_sector;  /* also used as UDF unique ID */
+#endif
+    uint64_t realsize;
+};
+
+struct file_hash {
+       struct file_hash *next;
+       ino_t           inode;          /* Used in the hash table */
+       dev_t           dev;            /* Used in the hash table */
+       nlink_t         nlink;          /* Used to compute new link count */
+       unsigned int    starting_block;
+       off_t           size;
+#ifdef SORTING
+       struct directory_entry *de;
+#endif /* SORTING */
+};
+
+
+/*
+ * This structure is used to control the output of fragments to the cdrom
+ * image.  Everything that will be written to the output image will eventually
+ * go through this structure.   There are two pieces - first is the sizing where
+ * we establish extent numbers for everything, and the second is when we actually
+ * generate the contents and write it to the output image.
+ *
+ * This makes it trivial to extend genisoimage to write special things in the image.
+ * All you need to do is hook an additional structure in the list, and the rest
+ * works like magic.
+ *
+ * The three passes each do the following:
+ *
+ * The 'size' pass determines the size of each component and assigns the extent number
+ * for that component.
+ *
+ * The 'generate' pass will adjust the contents and pointers as required now that extent
+ * numbers are assigned.  In some cases, the contents of the record are also generated.
+ *
+ * The 'write' pass actually writes the data to the disc.
+ */
+struct output_fragment {
+       struct output_fragment *of_next;
+       int             (*of_size)(int);
+       int             (*of_generate)(void);
+       int             (*of_write)(FILE *);
+       char            *of_name;                       /* Textual description */
+       unsigned int    of_start_extent;                /* For consist check */
+};
+
+extern struct output_fragment *out_list;
+extern struct output_fragment *out_tail;
+
+extern struct output_fragment startpad_desc;
+extern struct output_fragment voldesc_desc;
+extern struct output_fragment xvoldesc_desc;
+extern struct output_fragment joliet_desc;
+extern struct output_fragment torito_desc;
+extern struct output_fragment end_vol;
+extern struct output_fragment version_desc;
+extern struct output_fragment pathtable_desc;
+extern struct output_fragment jpathtable_desc;
+extern struct output_fragment dirtree_desc;
+extern struct output_fragment dirtree_clean;
+extern struct output_fragment jdirtree_desc;
+extern struct output_fragment extension_desc;
+extern struct output_fragment files_desc;
+extern struct output_fragment interpad_desc;
+extern struct output_fragment endpad_desc;
+extern struct output_fragment sunboot_desc;
+extern struct output_fragment sunlabel_desc;
+extern struct output_fragment genboot_desc;
+extern struct output_fragment strfile_desc;
+extern struct output_fragment strdir_desc;
+extern struct output_fragment strpath_desc;
+extern struct output_fragment alphaboot_desc;
+extern struct output_fragment hppaboot_desc;
+extern struct output_fragment alpha_hppa_boot_desc;
+extern struct output_fragment mipsboot_desc;
+extern struct output_fragment mipselboot_desc;
+
+#ifdef APPLE_HYB
+extern struct output_fragment hfs_desc;
+
+#endif /* APPLE_HYB */
+#ifdef DVD_VIDEO
+/*
+ * This structure holds the information necessary to create a valid
+ * DVD-Video image. Basically it's how much to pad the files so the
+ * file offsets described in the video_ts.ifo and vts_xx_0.ifo are
+ * the correct one in the image that we create.
+ */
+typedef struct {
+       int     realsize_ifo;
+       int     realsize_menu;
+       int     realsize_bup;
+       int     size_ifo;
+       int     size_menu;
+       int     size_title;
+       int     size_bup;
+       int     pad_ifo;
+       int     pad_menu;
+       int     pad_title;
+       int     pad_bup;
+       int     number_of_vob_files;
+       int     realsize_vob[10];
+} title_set_t;
+
+typedef struct {
+       int             num_titles;
+       title_set_t     *title_set;
+} title_set_info_t;
+#endif /* DVD_VIDEO */
+
+/*
+ * This structure describes one complete directory.  It has pointers
+ * to other directories in the overall tree so that it is clear where
+ * this directory lives in the tree, and it also must contain pointers
+ * to the contents of the directory.  Note that subdirectories of this
+ * directory exist twice in this stucture.  Once in the subdir chain,
+ * and again in the contents chain.
+ */
+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 *jcontents;
+       struct directory_entry *self;
+       char            *whole_name;    /* Entire path */
+       char            *de_name;       /* Entire path */
+       unsigned int    ce_bytes;       /* Number of bytes of CE entries read */
+                                       /* for this dir */
+       unsigned int    depth;
+       unsigned int    size;
+       unsigned int    extent;
+       unsigned int    jsize;
+       unsigned int    jextent;
+       unsigned int    path_index;
+       unsigned int    jpath_index;
+       unsigned short  dir_flags;
+       unsigned short  dir_nlink;
+#ifdef APPLE_HYB
+       hfsdirent       *hfs_ent;       /* HFS parameters */
+       struct hfs_info *hfs_info;      /* list of info for all entries in dir */
+#endif /* APPLE_HYB */
+#ifdef SORTING
+       int             sort;           /* sort weight for child files */
+#endif /* SORTING */
+};
+
+struct deferred_write {
+       struct deferred_write *next;
+       char            *table;
+       unsigned int    extent;
+       off_t           size;
+       char            *name;
+       struct directory_entry *s_entry;
+       unsigned int    pad;
+       off_t           off;
+};
+
+struct eltorito_boot_entry_info {
+       struct eltorito_boot_entry_info *next;
+       char            *boot_image;
+       int             not_bootable;
+       int             no_emul_boot;
+       int             hard_disk_boot;
+       int             boot_info_table;
+       int             load_size;
+       int             load_addr;
+};
+
+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 last_extent_written;
+extern unsigned int session_start;
+
+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 unsigned int jpath_table_size;
+extern unsigned int jpath_table[4];
+extern unsigned int jpath_blocks;
+extern char    *jpath_table_l;
+extern char    *jpath_table_m;
+
+extern struct iso_directory_record root_record;
+extern struct iso_directory_record jroot_record;
+
+extern int     check_oldnames;
+extern int     check_session;
+extern int     use_eltorito;
+extern int     hard_disk_boot;
+extern int     not_bootable;
+extern int     no_emul_boot;
+extern int     load_addr;
+extern int     load_size;
+extern int     boot_info_table;
+extern int     use_RockRidge;
+extern int     osecsize;
+extern int     use_XA;
+extern int     use_Joliet;
+extern int     rationalize;
+extern int     rationalize_uid;
+extern int     rationalize_gid;
+extern int     rationalize_filemode;
+extern int     rationalize_dirmode;
+extern uid_t   uid_to_use;
+extern gid_t   gid_to_use;
+extern int     filemode_to_use;
+extern int     dirmode_to_use;
+extern int     new_dir_mode;
+extern int     follow_links;
+extern int     cache_inodes;
+extern int     verbose;
+extern int     debug;
+extern int     gui;
+extern int     all_files;
+extern int     generate_tables;
+extern int     print_size;
+extern int     split_output;
+extern int     use_graft_ptrs;
+extern int     jhide_trans_tbl;
+extern int     hide_rr_moved;
+extern int     omit_period;
+extern int     omit_version_number;
+extern int     no_rr;
+extern int     transparent_compression;
+extern Uint    RR_relocation_depth;
+extern int     iso9660_level;
+extern int     iso9660_namelen;
+extern int     full_iso9660_filenames;
+extern int     relaxed_filenames;
+extern int     allow_lowercase;
+extern int     allow_multidot;
+extern int     iso_translate;
+extern int     allow_leading_dots;
+extern int     use_fileversion;
+extern int     split_SL_component;
+extern int     split_SL_field;
+extern char    *trans_tbl;
+char           *outfile;
+
+#define        JMAX            64      /* maximum Joliet file name length (spec) */
+#define        JLONGMAX        103     /* out of spec Joliet file name length */
+extern int     jlen;           /* selected maximum Joliet file name length */
+
+#ifdef DVD_VIDEO
+extern int     dvd_video;
+#endif /* DVD_VIDEO */
+
+
+#ifdef APPLE_HYB
+extern int     apple_hyb;      /* create HFS hybrid */
+extern int     apple_ext;      /* use Apple extensions */
+extern int     apple_both;     /* common flag (for above) */
+extern int     hfs_extra;      /* extra ISO extents (hfs_ce_size) */
+extern hce_mem *hce;           /* libhfs/genisoimage extras */
+extern int     use_mac_name;   /* use Mac name for ISO9660/Joliet/RR */
+extern int     create_dt;      /* create the Desktp files */
+extern char    *hfs_boot_file; /* name of HFS boot file */
+extern char    *magic_filename;        /* magic file for CREATOR/TYPE matching */
+extern int     hfs_last;       /* order in which to process map/magic files */
+extern char    *deftype;       /* default Apple TYPE */
+extern char    *defcreator;    /* default Apple CREATOR */
+extern int     gen_pt;         /* generate HFS partition table */
+extern char    *autoname;      /* Autostart filename */
+extern int     afe_size;       /* Apple File Exchange block size */
+extern char    *hfs_volume_id; /* HFS volume ID */
+extern int     icon_pos;       /* Keep Icon position */
+extern int     hfs_lock;       /* lock HFS volume (read-only) */
+extern char    *hfs_bless;     /* name of folder to 'bless' (System Folder) */
+extern char    *hfs_parms;     /* low level HFS parameters */
+
+#define        MAP_LAST        1       /* process magic then map file */
+#define        MAG_LAST        2       /* process map then magic file */
+
+#ifndef PREP_BOOT
+#define        PREP_BOOT
+#endif /* PREP_BOOT */
+
+#ifdef PREP_BOOT
+extern char    *prep_boot_image[4];
+extern int     use_prep_boot;
+extern int     use_chrp_boot;
+
+#endif /* PREP_BOOT */
+#endif /* APPLE_HYB */
+
+#ifdef SORTING
+extern int     do_sort;
+#endif /* SORTING */
+
+/* tree.c */
+extern int stat_filter(char *, struct stat *);
+extern int lstat_filter(char *, struct stat *);
+extern int sort_tree(struct directory *);
+extern struct directory *
+find_or_create_directory(struct directory *, const char *,
+                        struct directory_entry *self,
+                        int,
+                        struct stat *stat_template);
+extern void    finish_cl_pl_entries(void);
+extern int     scan_directory_tree(struct directory *this_dir, char *path,
+                                                                                 struct directory_entry *self);
+
+#ifdef APPLE_HYB
+extern int     insert_file_entry(struct directory *, char *, char *, int);
+#else
+extern int     insert_file_entry(struct directory *, char *, char *);
+#endif /* APPLE_HYB */
+
+extern void generate_iso9660_directories(struct directory *, FILE *);
+extern void dump_tree(struct directory * node);
+extern struct directory_entry *
+search_tree_file(struct directory * node, char *filename);
+extern void update_nlink_field(struct directory * node);
+extern void init_fstatbuf(void);
+extern struct stat root_statbuf;
+extern struct stat fstatbuf;
+
+/* eltorito.c */
+extern void init_boot_catalog(const char *path);
+extern void insert_boot_cat(void);
+extern void get_boot_entry(void);
+extern void new_boot_entry(void);
+
+/* boot.c */
+extern void sparc_boot_label(char *label);
+extern void sunx86_boot_label(char *label);
+extern void scan_sparc_boot(char *files);
+extern void scan_sunx86_boot(char *files);
+extern int make_sun_label(void);
+extern int make_sunx86_label(void);
+
+/* boot-alpha.c */
+extern int add_boot_alpha_filename(char *filename);
+
+/* boot-hppa.c */
+extern int add_boot_hppa_cmdline(char *cmdline);
+extern int add_boot_hppa_kernel_32(char *filename);
+extern int add_boot_hppa_kernel_64(char *filename);
+extern int add_boot_hppa_bootloader(char *filename);
+extern int add_boot_hppa_ramdisk(char *filename);
+
+/* boot-mips.c */
+extern int add_boot_mips_filename(char *filename);
+
+/* boot-mipsel.c */
+extern int add_boot_mipsel_filename(char *filename);
+
+/* rsync.c */
+extern unsigned long long rsync64(unsigned char *mem, size_t size);
+
+/* write.c */
+extern int get_731(char *);
+extern int get_732(char *);
+extern int get_733(char *);
+extern int isonum_733(unsigned char *);
+extern void set_723(char *, unsigned int);
+extern void set_731(char *, unsigned int);
+extern void set_721(char *, unsigned int);
+extern void set_733(char *, unsigned int);
+extern int sort_directory(struct directory_entry **, int);
+extern void generate_one_directory(struct directory *, FILE *);
+extern void memcpy_max(char *, char *, int);
+extern int oneblock_size(int starting_extent);
+extern struct iso_primary_descriptor vol_desc;
+extern void xfwrite(void *buffer, int size, int count, FILE *file, int submode,
+                                                 BOOL islast);
+extern void set_732(char *pnt, unsigned int i);
+extern void set_722(char *pnt, unsigned int i);
+extern void outputlist_insert(struct output_fragment * frag);
+
+#ifdef APPLE_HYB
+extern Ulong get_adj_size(int Csize);
+extern int adj_size(int Csize, int start_extent, int extra);
+extern void adj_size_other(struct directory * dpnt);
+extern int insert_padding_file(int size);
+extern int gen_mac_label(struct deferred_write *);
+
+#ifdef PREP_BOOT
+extern void gen_prepboot_label(unsigned char *);
+
+#endif /* PREP_BOOT */
+#endif /* APPLE_HYB */
+
+/* multi.c */
+
+extern FILE    *in_image;
+extern int open_merge_image(char *path);
+extern int close_merge_image(void);
+extern struct iso_directory_record *
+merge_isofs(char *path);
+extern unsigned char   *parse_xa(unsigned char *pnt, int *lenp,
+                                                                                struct directory_entry *dpnt);
+extern int     rr_flags(struct iso_directory_record *idr);
+extern int merge_previous_session(struct directory *, 
+                                                                                        struct iso_directory_record *, 
+                                                                                        char *, char *);
+extern int get_session_start(int *);
+
+/* joliet.c */
+#ifdef UDF
+#   ifdef USE_ICONV
+extern size_t  convert_to_unicode      (unsigned char *buffer,
+                       int size, char *source, struct unls_table *inls);
+#   else
+extern void    convert_to_unicode      (unsigned char *buffer,
+                       int size, char *source, struct unls_table *inls);
+#   endif
+extern int     joliet_strlen   (const char *string, struct unls_table *inls);
+#endif
+extern unsigned char conv_charset(unsigned char, struct unls_table *,
+                                                                                        struct unls_table *);
+extern int joliet_sort_tree(struct directory * node);
+
+/* match.c */
+extern int matches(char *);
+extern int add_match(char *);
+
+/* files.c */
+struct dirent  *readdir_add_files(char **, char *, DIR *);
+
+/* name.c */
+
+extern void iso9660_check(struct iso_directory_record *idr, 
+                                                                 struct directory_entry *ndr);
+extern int iso9660_file_length(const char *name, 
+                                                                                struct directory_entry *sresult, int flag);
+
+/* various */
+extern int iso9660_date(char *, time_t);
+extern void add_hash(struct directory_entry *);
+extern struct file_hash *find_hash(dev_t, ino_t);
+
+extern void flush_hash(void);
+extern void add_directory_hash(dev_t, ino_t);
+extern struct file_hash *find_directory_hash(dev_t, ino_t);
+extern void flush_file_hash(void);
+extern int delete_file_hash(struct directory_entry *);
+extern struct directory_entry *find_file_hash(char *);
+extern void add_file_hash(struct directory_entry *);
+
+extern int     generate_xa_rr_attributes(char *, char *, struct directory_entry *,
+                                                                                                 struct stat *, struct stat *, 
+                                                                                                 int deep_flag);
+extern char    *generate_rr_extension_record(char *id, char *descriptor,
+                                                                                                               char *source, int *size);
+
+extern int     check_prev_session(struct directory_entry **, int len, 
+                                                                                struct directory_entry *, struct stat *,
+                                                                                struct stat *, struct directory_entry **);
+
+extern void    match_cl_re_entries(void);
+extern void    finish_cl_pl_for_prev_session(void);
+extern char    *find_rr_attribute(unsigned char *pnt, int len, char *attr_type);
+
+#ifdef APPLE_HYB
+/* volume.c */
+extern int make_mac_volume(struct directory * dpnt, int start_extent);
+extern int write_fork(hfsfile * hfp, long tot);
+
+/* apple.c */
+
+extern void del_hfs_info(struct hfs_info *);
+extern int get_hfs_dir(char *, char *, struct directory_entry *);
+extern int get_hfs_info(char *, char *, struct directory_entry *);
+extern int get_hfs_rname(char *, char *, char *);
+extern int hfs_exclude(char *);
+extern void print_hfs_info(struct directory_entry *);
+extern void hfs_init(char *, unsigned short, unsigned int);
+extern void delete_rsrc_ent(struct directory_entry *);
+extern void clean_hfs(void);
+extern void perr(char *);
+extern void set_root_info(char *);
+
+/* desktop.c */
+
+extern int make_desktop(hfsvol *, int);
+
+/* mac_label.c */
+
+#ifdef _MAC_LABEL_H
+#ifdef PREP_BOOT
+extern void    gen_prepboot_label(MacLabel * mac_label);
+#endif
+extern int     gen_mac_label(defer *);
+#endif
+extern int     autostart(void);
+
+/* libfile */
+
+extern char    *get_magic_match(const char *);
+extern void    clean_magic(void);
+
+#endif /* APPLE_HYB */
+
+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 char    *boot_catalog;
+extern char    *boot_image;
+extern char    *genboot_image;
+extern int     ucs_level;
+extern int     volume_set_size;
+extern int     volume_sequence_number;
+
+extern struct eltorito_boot_entry_info *first_boot_entry;
+extern struct eltorito_boot_entry_info *last_boot_entry;
+extern struct eltorito_boot_entry_info *current_boot_entry;
+
+extern char    *findgequal(char *);
+extern void    *e_malloc(size_t);
+
+/*
+ * Note: always use these macros to avoid problems.
+ *
+ * ISO_ROUND_UP(X)     may cause an integer overflow and thus give
+ *                     incorrect results. So avoid it if possible.
+ *
+ * ISO_BLOCKS(X)       is overflow safe. Prefer this when ever it is possible.
+ */
+#define        SECTOR_SIZE     (2048)
+#define        ISO_ROUND_UP(X) (((X) + (SECTOR_SIZE - 1)) & ~(SECTOR_SIZE - 1))
+#define        ISO_BLOCKS(X)   (((X) / SECTOR_SIZE) + (((X)%SECTOR_SIZE)?1:0))
+
+#define        ROUND_UP(X, Y)  (((X + (Y - 1)) / Y) * Y)
+
+#ifdef APPLE_HYB
+/*
+ * ISO blocks == 2048, HFS blocks == 512
+ */
+#define        HFS_BLK_CONV    (SECTOR_SIZE/HFS_BLOCKSZ)
+
+#define        HFS_ROUND_UP(X) ISO_ROUND_UP(((X)*HFS_BLOCKSZ)) /* XXX ??? */
+#define        HFS_BLOCKS(X)   (ISO_BLOCKS(X) * HFS_BLK_CONV)
+
+#define        USE_MAC_NAME(E) (use_mac_name && ((E)->hfs_ent != NULL) && (E)->hfs_type)
+#endif /* APPLE_HYB */
+
+/*
+ * Rock Ridge defines
+ */
+#define        NEED_RE         1       /* Need Relocated Direcotry     */
+#define        NEED_PL         2       /* Need Parent link             */
+#define        NEED_CL         4       /* Need Child link              */
+#define        NEED_CE         8       /* Need Continuation Area       */
+#define        NEED_SP         16      /* Need SUSP record             */
+
+#define        RR_FLAG_PX      1       /* POSIX attributes             */
+#define        RR_FLAG_PN      2       /* POSIX device number          */
+#define        RR_FLAG_SL      4       /* Symlink                      */
+#define        RR_FLAG_NM      8       /* Alternate Name               */
+#define        RR_FLAG_CL      16      /* Child link                   */
+#define        RR_FLAG_PL      32      /* Parent link                  */
+#define        RR_FLAG_RE      64      /* Relocated Direcotry          */
+#define        RR_FLAG_TF      128     /* Time stamp                   */
+
+#define        RR_FLAG_SP      1024    /* SUSP record                  */
+#define        RR_FLAG_AA      2048    /* Apple Signature record       */
+#define        RR_FLAG_XA      4096    /* XA signature record          */
+
+#define        RR_FLAG_CE      8192    /* SUSP Continuation aerea      */
+#define        RR_FLAG_ER      16384   /* Extension record for RR signature */
+#define        RR_FLAG_RR      32768   /* RR Signature in every file   */
+#define        RR_FLAG_ZF      65535   /* Linux compression extension  */
+
+
+#define        PREV_SESS_DEV   (sizeof (dev_t) >= 4 ? 0x7ffffffd : 0x7ffd)
+#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
+
+/*
+ * When using multi-session, indicates that we can reuse the
+ * TRANS.TBL information for this directory entry. If this flag
+ * is set for all entries in a directory, it means we can just
+ * reuse the TRANS.TBL and not generate a new one.
+ */
+#define        SAFE_TO_REUSE_TABLE_ENTRY  0x01         /* de_flags only  */
+#define        DIR_HAS_DOT                0x02         /* dir_flags only */
+#define        DIR_HAS_DOTDOT             0x04         /* dir_flags only */
+#define        INHIBIT_JOLIET_ENTRY       0x08
+#define        INHIBIT_RR_ENTRY           0x10         /* not used       */
+#define        RELOCATED_DIRECTORY        0x20         /* de_flags only  */
+#define        INHIBIT_ISO9660_ENTRY      0x40
+#define        MEMORY_FILE                0x80         /* de_flags only  */
+#define        HIDDEN_FILE                0x100        /* de_flags only  */
+#define        DIR_WAS_SCANNED            0x200        /* dir_flags only */
+
+/*
+ * Volume sequence number to use in all of the iso directory records.
+ */
+#define        DEF_VSN         1
+
+/*
+ * Make sure we have a definition for this.  If not, take a very conservative
+ * guess.
+ * POSIX requires the max pathname component lenght to be defined in limits.h
+ * If variable, it may be undefined. If undefined, there should be
+ * a definition for _POSIX_NAME_MAX in limits.h or in unistd.h
+ * As _POSIX_NAME_MAX is defined to 14, we cannot use it.
+ * XXX Eric's wrong comment:
+ * XXX From what I can tell SunOS is the only one with this trouble.
+ */
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+#ifndef NAME_MAX
+#ifdef FILENAME_MAX
+#define        NAME_MAX        FILENAME_MAX
+#else
+#define        NAME_MAX        256
+#endif
+#endif
+
+#ifndef PATH_MAX
+#ifdef FILENAME_MAX
+#define        PATH_MAX        FILENAME_MAX
+#else
+#define        PATH_MAX        1024
+#endif
+#endif
+
+/*
+ * XXX JS: Some structures have odd lengths!
+ * Some compilers (e.g. on Sun3/mc68020) padd the structures to even length.
+ * For this reason, we cannot use sizeof (struct iso_path_table) or
+ * sizeof (struct iso_directory_record) to compute on disk sizes.
+ * Instead, we use offsetof(..., name) and add the name size.
+ * See iso9660.h
+ */
+#ifndef        offsetof
+#define        offsetof(TYPE, MEMBER)  ((size_t) &((TYPE *)0)->MEMBER)
+#endif
+
+/*
+ * EB: various shared stuff
+ */
+extern char            *merge_warn_msg;
diff --git a/genisoimage/genisoimagerc.5 b/genisoimage/genisoimagerc.5
new file mode 100644 (file)
index 0000000..71082b4
--- /dev/null
@@ -0,0 +1,144 @@
+.\" genisoimagerc.5 -*- nroff -*-
+.\" Derived from genisoimage.1
+.\" Copyright 1993-1998 by Yggdrasil Computing
+.\" Copyright 1996-1997 by Robert Leslie
+.\" Copyright 1997-2001 by James Pearson
+.\" Copyright 1999-2006 by Joerg Schilling
+.\" Copyright 2002-2003 by Jungshik Shin
+.\" Copyright 2003 by Jaakko Heinonen
+.\" Copyright 2006 by the Cdrkit maintainers
+.\"
+.TH GENISOIMAGERC 5 "13 Dec 2006"
+.\" ----------------------------------------
+.SH NAME
+genisoimagerc \- startup configuration file for genisoimage
+.SH DESCRIPTION
+.BR genisoimage (1)
+searches for a configuration file in several places; it uses the first
+one it is able to open.  First, if the
+.B GENISOIMAGERC
+environment variable is set, its value is used as the filename;
+likewise for the
+.B MKISOFSRC
+environment variable.  Next,
+.B genisoimage
+looks for files named
+.IR .genisoimagerc " or " .mkisofsrc ,
+first in the current working directory, then in the user's home
+directory.  Next, it looks for
+.IR /etc/genisoimagerc .
+Finally, it looks for a
+.I .genisoimagerc
+in the same directory as
+.B genisoimage
+itself is stored.
+.PP
+The
+.I .genisoimagerc
+file contains lines of the form
+.IP
+.BI TAG= value
+.PP
+where
+.B TAG
+is one of the settings defined below.  The case of the tag is not
+significant.  All settings have command-line equivalents; if the
+command-line parameter is specified, it takes priority over the
+configuration file.
+.PP
+Blank lines and lines beginning with `#' are ignored.
+.\" ----------------------------------------
+.SH "CONFIGURATION SETTINGS"
+.IP ABST
+The abstract information, typically the name of a file on the disc
+containing an abstract.  There is space for 37 characters.
+Equivalent to the
+.B \-abstract
+command-line option.
+.IP APPI
+The application identifier should describe the application that will be
+on the disc.  There is space for 128 characters.  Equivalent to the
+.B \-A
+command-line option.
+.IP BIBL
+The bibliographic information, often the name of a file on the disc
+containing a bibliography.  There is space for 37 characters.
+Equivalent to the
+.B \-biblio
+command-line option.
+.IP COPY
+The copyright information, typically the name of a file on the disc
+containing the copyright notice.  There is space for 37 characters.
+Equivalent to the
+.B \-copyright
+command-line option.
+.IP HFS_TYPE
+The default
+.B TYPE
+for Macintosh files. Must be exactly 4 characters.  Equivalent to the
+.B \-hfs\-type
+command-line option.  The default value is
+.IR TEXT .
+.IP HFS_CREATOR
+The default
+.B CREATOR
+for Macintosh files. Must be exactly 4 characters.  Equivalent to the
+.B \-hfs\-creator
+command-line option.  The default value is
+.IR Unix .
+.IP PREP
+This should describe the preparer of the CD-ROM, usually with a mailing
+address and phone number.  There is space for 128 characters.
+Equivalent to the
+.B \-p
+command-line option.
+.IP PUBL
+This should describe the publisher of the CD-ROM, usually with a
+mailing address and phone number.  There is space for 128 characters.
+Equivalent to the
+.B \-publisher
+command-line option.
+.IP SYSI
+The System Identifier.  There is space for 32 characters.
+Equivalent to the
+.B \-sysid
+command-line option.
+.IP VOLI
+The Volume Identifier.  There is space for 32 characters.
+Equivalent to the
+.B \-V
+command-line option.
+.IP VOLS
+The Volume Set Name.  There is space for 128 characters.
+Equivalent to the
+.B \-volset
+command-line option.
+.PP
+.B genisoimage
+can also be configured at compile time with defaults for many of these
+fields.  See the file
+.IR defaults.h .
+.\" ----------------------------------------
+.SH EXAMPLES
+The following file
+.IP
+.nf
+COPY=src/COPYING
+SYSI=Multics 75
+.fi
+.PP
+is equivalent to the
+.B genisoimage
+command-line parameters
+.IP
+.I "\-copyright src/COPYING \-sysid \(dqMultics 75\(dq"
+.\" ----------------------------------------
+.SH "SEE ALSO"
+.BR genisoimage (1).
+.\" ----------------------------------------
+.SH AUTHORS
+See the
+.BR genisoimage (1)
+manual page for credits for the
+.B genisoimage
+program and documentation.
diff --git a/genisoimage/getopt.c b/genisoimage/getopt.c
new file mode 100644 (file)
index 0000000..64fcb18
--- /dev/null
@@ -0,0 +1,790 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)getopt.c        1.6 03/03/09 joerg */
+/* Getopt for GNU.
+   NOTE: getopt is now part of the C library, so if you don't know what
+   "Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu
+   before changing it!
+
+   Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94, 95
+       Free Software Foundation, Inc.
+
+This file is part of the libiberty library.  This library 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 library 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 GNU CC; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+As a special exception, if you link this library with files
+compiled with a GNU compiler to produce an executable, this does not cause
+the resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why
+the executable file might be covered by the GNU General Public License. */
+\f
+/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>.
+   Ditto for AIX 3.2 and <stdlib.h>.  */
+/*
+ * XXX Never do it this way, it is FSF junk
+ */
+#ifndef _NO_PROTO
+/*#define _NO_PROTO*/
+#endif
+/*
+ * We do this instead:
+ */
+#undef getopt
+#define        getopt  __nothing__
+
+#ifdef HAVE_CONFIG_H
+#if defined (emacs) || defined (CONFIG_BROKETS)
+/* We use <config.h> instead of "config.h" so that a compilation
+   using -I. -I$srcdir will use ./config.h rather than $srcdir/config.h
+   (which it would do because it found this file in $srcdir).  */
+#include <config.h>
+#else
+#include "config.h"
+#endif
+#endif
+
+#ifndef __STDC__
+/* This is a separate conditional since some stdc systems
+   reject `defined (const)'.  */
+#ifndef const
+#define const
+#endif
+#endif
+
+#include <stdio.h>
+
+/* Comment out all this code if we are using the GNU C Library, and are not
+   actually compiling the library itself.  This code is part of the GNU C
+   Library, but also included in many other GNU distributions.  Compiling
+   and linking in this code is a waste when using the GNU C library
+   (especially if it is a shared library).  Rather than having every GNU
+   program understand `configure --with-gnu-libc' and omit the object files,
+   it is simpler to just do this in the source for each such file.  */
+/* Many versions of the Linux C library include older, broken versions
+   of these routines, which will break the linker's command-line
+   parsing.  */
+
+#if defined (_LIBC) || !defined (__GNU_LIBRARY__) || defined (__linux__)
+
+
+/* This needs to come after some library #include
+   to get __GNU_LIBRARY__ defined.  */
+#ifdef __GNU_LIBRARY__
+/* Don't include stdlib.h for non-GNU C libraries because some of them
+   contain conflicting prototypes for getopt.  */
+#include <stdlib.h>
+#define        __DID_STDLIB__          /* FSF rubbish compensation */
+#endif /* GNU C library.  */
+
+/* This version of `getopt' appears to the caller like standard Unix `getopt'
+   but it behaves differently for the user, since it allows the user
+   to intersperse the options with the other arguments.
+
+   As `getopt' works, it permutes the elements of ARGV so that,
+   when it is done, all the options precede everything else.  Thus
+   all application programs are extended to handle flexible argument order.
+
+   Setting the environment variable POSIXLY_CORRECT disables permutation.
+   Then the behavior is completely standard.
+
+   GNU application programs can use a third alternative mode in which
+   they can distinguish the relative order of options and other arguments.  */
+
+#include "getopt.h"
+
+static void            exchange(char **argv);
+static const char *_getopt_initialize(const char *optstring);
+
+/* For communication from `getopt' to the caller.
+   When `getopt' finds an option that takes an argument,
+   the argument value is returned here.
+   Also, when `ordering' is RETURN_IN_ORDER,
+   each non-option ARGV-element is returned here.  */
+
+char *optarg = NULL;
+
+/* Index in ARGV of the next element to be scanned.
+   This is used for communication to and from the caller
+   and for communication between successive calls to `getopt'.
+
+   On entry to `getopt', zero means this is the first call; initialize.
+
+   When `getopt' returns EOF, this is the index of the first of the
+   non-option elements that the caller should itself scan.
+
+   Otherwise, `optind' communicates from one call to the next
+   how much of ARGV has been scanned so far.  */
+
+/* XXX 1003.2 says this must be 1 before any call.  */
+int optind = 0;
+
+/* The next char to be scanned in the option-element
+   in which the last option character we returned was found.
+   This allows us to pick up the scan where we left off.
+
+   If this is zero, or a null string, it means resume the scan
+   by advancing to the next ARGV-element.  */
+
+static char *nextchar;
+
+/* Callers store zero here to inhibit the error message
+   for unrecognized options.  */
+
+int opterr = 1;
+
+/* Set to an option character which was unrecognized.
+   This must be initialized on some systems to avoid linking in the
+   system's own getopt implementation.  */
+
+int optopt = '?';
+
+/* Describe how to deal with options that follow non-option ARGV-elements.
+
+   If the caller did not specify anything,
+   the default is REQUIRE_ORDER if the environment variable
+   POSIXLY_CORRECT is defined, PERMUTE otherwise.
+
+   REQUIRE_ORDER means don't recognize them as options;
+   stop option processing when the first non-option is seen.
+   This is what Unix does.
+   This mode of operation is selected by either setting the environment
+   variable POSIXLY_CORRECT, or using `+' as the first character
+   of the list of option characters.
+
+   PERMUTE is the default.  We permute the contents of ARGV as we scan,
+   so that eventually all the non-options are at the end.  This allows options
+   to be given in any order, even with programs that were not written to
+   expect this.
+
+   RETURN_IN_ORDER is an option available to programs that were written
+   to expect options and other ARGV-elements in any order and that care about
+   the ordering of the two.  We describe each non-option ARGV-element
+   as if it were the argument of an option with character code 1.
+   Using `-' as the first character of the list of option characters
+   selects this mode of operation.
+
+   The special argument `--' forces an end of option-scanning regardless
+   of the value of `ordering'.  In the case of RETURN_IN_ORDER, only
+   `--' can cause `getopt' to return EOF with `optind' != ARGC.  */
+
+static enum
+{
+  REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
+} ordering;
+\f
+#ifdef __GNU_LIBRARY__
+/* We want to avoid inclusion of string.h with non-GNU libraries
+   because there are many ways it can cause trouble.
+   On some systems, it contains special magic macros that don't work
+   in GCC.  */
+#include <string.h>
+#define        my_index        strchr
+#else
+
+/* Avoid depending on library functions or files
+   whose names are inconsistent.  */
+
+char *getenv ();
+
+static char *my_index(const char *str, int chr);
+
+static char *
+my_index (const char *str, int chr)
+{
+  while (*str)
+    {
+      if (*str == chr)
+       return (char *) str;
+      str++;
+    }
+  return 0;
+}
+
+/* If using GCC, we can safely declare strlen this way.
+   If not using GCC, it is ok not to declare it.  */
+#ifdef __GNUC__
+/* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h.
+   That was relevant to code that was here before.  */
+#ifndef __STDC__
+/* gcc with -traditional declares the built-in strlen to return int,
+   and has done so at least since version 2.4.5. -- rms.  */
+extern int strlen (const char *);
+#endif /* not __STDC__ */
+#endif /* __GNUC__ */
+
+#endif /* not __GNU_LIBRARY__ */
+
+#ifndef        __DID_STDLIB__          /* FSF rubbish compensation */
+/*
+ *     This is the clean code using Schily constructs...
+ */
+#undef getopt
+#define        getopt  __nothing__
+#include <stdxlib.h>
+#endif
+#ifndef        my_index
+/*
+ * FSF rubbish compensation
+ * If GCC has problems with the system include files, it has to be fixed
+ */
+#include <strdefs.h>
+#endif
+#undef getopt
+\f
+/* Handle permutation of arguments.  */
+
+/* Describe the part of ARGV that contains non-options that have
+   been skipped.  `first_nonopt' is the index in ARGV of the first of them;
+   `last_nonopt' is the index after the last of them.  */
+
+static int first_nonopt;
+static int last_nonopt;
+
+/* Exchange two adjacent subsequences of ARGV.
+   One subsequence is elements [first_nonopt,last_nonopt)
+   which contains all the non-options that have been skipped so far.
+   The other is elements [last_nonopt,optind), which contains all
+   the options processed since those non-options were skipped.
+
+   `first_nonopt' and `last_nonopt' are relocated so that they describe
+   the new indices of the non-options in ARGV after they are moved.  */
+
+static void
+exchange (char **argv)
+{
+  int bottom = first_nonopt;
+  int middle = last_nonopt;
+  int top = optind;
+  char *tem;
+
+  /* Exchange the shorter segment with the far end of the longer segment.
+     That puts the shorter segment into the right place.
+     It leaves the longer segment in the right place overall,
+     but it consists of two parts that need to be swapped next.  */
+
+  while (top > middle && middle > bottom)
+    {
+      if (top - middle > middle - bottom)
+       {
+         /* Bottom segment is the short one.  */
+         int len = middle - bottom;
+         register int i;
+
+         /* Swap it with the top part of the top segment.  */
+         for (i = 0; i < len; i++)
+           {
+             tem = argv[bottom + i];
+             argv[bottom + i] = argv[top - (middle - bottom) + i];
+             argv[top - (middle - bottom) + i] = tem;
+           }
+         /* Exclude the moved bottom segment from further swapping.  */
+         top -= len;
+       }
+      else
+       {
+         /* Top segment is the short one.  */
+         int len = top - middle;
+         register int i;
+
+         /* Swap it with the bottom part of the bottom segment.  */
+         for (i = 0; i < len; i++)
+           {
+             tem = argv[bottom + i];
+             argv[bottom + i] = argv[middle + i];
+             argv[middle + i] = tem;
+           }
+         /* Exclude the moved top segment from further swapping.  */
+         bottom += len;
+       }
+    }
+
+  /* Update records for the slots the non-options now occupy.  */
+
+  first_nonopt += (optind - last_nonopt);
+  last_nonopt = optind;
+}
+
+/* Initialize the internal data when the first call is made.  */
+
+static const char *
+_getopt_initialize (const char *optstring)
+{
+  /* Start processing options with ARGV-element 1 (since ARGV-element 0
+     is the program name); the sequence of previously skipped
+     non-option ARGV-elements is empty.  */
+
+  first_nonopt = last_nonopt = optind = 1;
+
+  nextchar = NULL;
+
+  /* Determine how to handle the ordering of options and nonoptions.  */
+
+  if (optstring[0] == '-')
+    {
+      ordering = RETURN_IN_ORDER;
+      ++optstring;
+    }
+  else if (optstring[0] == '+')
+    {
+      ordering = REQUIRE_ORDER;
+      ++optstring;
+    }
+  else if (getenv ("POSIXLY_CORRECT") != NULL)
+    ordering = REQUIRE_ORDER;
+  else
+    ordering = PERMUTE;
+
+  return optstring;
+}
+\f
+/* Scan elements of ARGV (whose length is ARGC) for option characters
+   given in OPTSTRING.
+
+   If an element of ARGV starts with '-', and is not exactly "-" or "--",
+   then it is an option element.  The characters of this element
+   (aside from the initial '-') are option characters.  If `getopt'
+   is called repeatedly, it returns successively each of the option characters
+   from each of the option elements.
+
+   If `getopt' finds another option character, it returns that character,
+   updating `optind' and `nextchar' so that the next call to `getopt' can
+   resume the scan with the following option character or ARGV-element.
+
+   If there are no more option characters, `getopt' returns `EOF'.
+   Then `optind' is the index in ARGV of the first ARGV-element
+   that is not an option.  (The ARGV-elements have been permuted
+   so that those that are not options now come last.)
+
+   OPTSTRING is a string containing the legitimate option characters.
+   If an option character is seen that is not listed in OPTSTRING,
+   return '?' after printing an error message.  If you set `opterr' to
+   zero, the error message is suppressed but we still return '?'.
+
+   If a char in OPTSTRING is followed by a colon, that means it wants an arg,
+   so the following text in the same ARGV-element, or the text of the following
+   ARGV-element, is returned in `optarg'.  Two colons mean an option that
+   wants an optional arg; if there is text in the current ARGV-element,
+   it is returned in `optarg', otherwise `optarg' is set to zero.
+
+   If OPTSTRING starts with `-' or `+', it requests different methods of
+   handling the non-option ARGV-elements.
+   See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
+
+   Long-named options begin with `--' instead of `-'.
+   Their names may be abbreviated as long as the abbreviation is unique
+   or is an exact match for some defined option.  If they have an
+   argument, it follows the option name in the same ARGV-element, separated
+   from the option name by a `=', or else the in next ARGV-element.
+   When `getopt' finds a long-named option, it returns 0 if that option's
+   `flag' field is nonzero, the value of the option's `val' field
+   if the `flag' field is zero.
+
+   The elements of ARGV aren't really const, because we permute them.
+   But we pretend they're const in the prototype to be compatible
+   with other systems.
+
+   LONGOPTS is a vector of `struct option' terminated by an
+   element containing a name which is zero.
+
+   LONGIND returns the index in LONGOPT of the long-named option found.
+   It is only valid when a long-named option has been found by the most
+   recent call.
+
+   If LONG_ONLY is nonzero, '-' as well as '--' can introduce
+   long-named options.  */
+
+int
+_getopt_internal (int argc, char *const *argv, const char *optstring, 
+                                               const struct option *longopts, int *longind, int long_only)
+{
+  optarg = NULL;
+
+  if (optind == 0)
+    optstring = _getopt_initialize (optstring);
+
+  if (argc == 0)
+    return EOF;
+
+  if (nextchar == NULL || *nextchar == '\0')
+    {
+      /* Advance to the next ARGV-element.  */
+
+      if (ordering == PERMUTE)
+       {
+         /* If we have just processed some options following some non-options,
+            exchange them so that the options come first.  */
+
+         if (first_nonopt != last_nonopt && last_nonopt != optind)
+           exchange ((char **) argv);
+         else if (last_nonopt != optind)
+           first_nonopt = optind;
+
+         /* Skip any additional non-options
+            and extend the range of non-options previously skipped.  */
+
+         while (optind < argc
+                && (argv[optind][0] != '-' || argv[optind][1] == '\0'))
+           optind++;
+         last_nonopt = optind;
+       }
+
+      /* The special ARGV-element `--' means premature end of options.
+        Skip it like a null option,
+        then exchange with previous non-options as if it were an option,
+        then skip everything else like a non-option.  */
+
+      if (optind != argc && !strcmp (argv[optind], "--"))
+       {
+         optind++;
+
+         if (first_nonopt != last_nonopt && last_nonopt != optind)
+           exchange ((char **) argv);
+         else if (first_nonopt == last_nonopt)
+           first_nonopt = optind;
+         last_nonopt = argc;
+
+         optind = argc;
+       }
+
+      /* If we have done all the ARGV-elements, stop the scan
+        and back over any non-options that we skipped and permuted.  */
+
+      if (optind == argc)
+       {
+         /* Set the next-arg-index to point at the non-options
+            that we previously skipped, so the caller will digest them.  */
+         if (first_nonopt != last_nonopt)
+           optind = first_nonopt;
+         return EOF;
+       }
+
+      /* If we have come to a non-option and did not permute it,
+        either stop the scan or describe it to the caller and pass it by.  */
+
+      if ((argv[optind][0] != '-' || argv[optind][1] == '\0'))
+       {
+         if (ordering == REQUIRE_ORDER)
+           return EOF;
+         optarg = argv[optind++];
+         return 1;
+       }
+
+      /* We have found another option-ARGV-element.
+        Skip the initial punctuation.  */
+
+      nextchar = (argv[optind] + 1
+                 + (longopts != NULL && argv[optind][1] == '-'));
+    }
+
+  /* Decode the current option-ARGV-element.  */
+
+  /* Check whether the ARGV-element is a long option.
+
+     If long_only and the ARGV-element has the form "-f", where f is
+     a valid short option, don't consider it an abbreviated form of
+     a long option that starts with f.  Otherwise there would be no
+     way to give the -f short option.
+
+     On the other hand, if there's a long option "fubar" and
+     the ARGV-element is "-fu", do consider that an abbreviation of
+     the long option, just like "--fu", and not "-f" with arg "u".
+
+     This distinction seems to be the most useful approach.  */
+
+  if (longopts != NULL
+      && (argv[optind][1] == '-'
+         || (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1])))))
+    {
+      char *nameend;
+      const struct option *p;
+      const struct option *pfound = NULL;
+      int exact = 0;
+      int ambig = 0;
+      int indfound = 0;
+      int option_index;
+
+      for (nameend = nextchar; *nameend && *nameend != '='; nameend++)
+       /* Do nothing.  */ ;
+
+      /* Test all long options for either exact match
+        or abbreviated matches.  */
+      for (p = longopts, option_index = 0; p->name; p++, option_index++)
+       if (!strncmp (p->name, nextchar, nameend - nextchar))
+         {
+           if (nameend - nextchar == strlen (p->name))
+             {
+               /* Exact match found.  */
+               pfound = p;
+               indfound = option_index;
+               exact = 1;
+               break;
+             }
+           else if (pfound == NULL)
+             {
+               /* First nonexact match found.  */
+               pfound = p;
+               indfound = option_index;
+             }
+           else
+             /* Second or later nonexact match found.  */
+             ambig = 1;
+         }
+
+      if (ambig && !exact)
+       {
+         if (opterr)
+           fprintf (stderr, "%s: option `%s' is ambiguous\n",
+                    argv[0], argv[optind]);
+         nextchar += strlen (nextchar);
+         optind++;
+         return '?';
+       }
+
+      if (pfound != NULL)
+       {
+         option_index = indfound;
+         optind++;
+         if (*nameend)
+           {
+             /* Don't test has_arg with >, because some C compilers don't
+                allow it to be used on enums.  */
+             if (pfound->has_arg)
+               optarg = nameend + 1;
+             else
+               {
+                 if (opterr)
+                   {
+                     if (argv[optind - 1][1] == '-')
+                       /* --option */
+                       fprintf (stderr,
+                                "%s: option `--%s' doesn't allow an argument\n",
+                                argv[0], pfound->name);
+                     else
+                       /* +option or -option */
+                       fprintf (stderr,
+                            "%s: option `%c%s' doesn't allow an argument\n",
+                            argv[0], argv[optind - 1][0], pfound->name);
+                   }
+                 nextchar += strlen (nextchar);
+                 return '?';
+               }
+           }
+         else if (pfound->has_arg == 1)
+           {
+             if (optind < argc)
+               optarg = argv[optind++];
+             else
+               {
+                 if (opterr)
+                   fprintf (stderr, "%s: option `%s' requires an argument\n",
+                            argv[0], argv[optind - 1]);
+                 nextchar += strlen (nextchar);
+                 return optstring[0] == ':' ? ':' : '?';
+               }
+           }
+         nextchar += strlen (nextchar);
+         if (longind != NULL)
+           *longind = option_index;
+         if (pfound->flag)
+           {
+             *(pfound->flag) = pfound->val;
+             return 0;
+           }
+         return pfound->val;
+       }
+
+      /* Can't find it as a long option.  If this is not getopt_long_only,
+        or the option starts with '--' or is not a valid short
+        option, then it's an error.
+        Otherwise interpret it as a short option.  */
+      if (!long_only || argv[optind][1] == '-'
+         || my_index (optstring, *nextchar) == NULL)
+       {
+         if (opterr)
+           {
+             if (argv[optind][1] == '-')
+               /* --option */
+               fprintf (stderr, "%s: unrecognized option `--%s'\n",
+                        argv[0], nextchar);
+             else
+               /* +option or -option */
+               fprintf (stderr, "%s: unrecognized option `%c%s'\n",
+                        argv[0], argv[optind][0], nextchar);
+           }
+         nextchar = (char *) "";
+         optind++;
+         return '?';
+       }
+    }
+
+  /* Look at and handle the next short option-character.  */
+
+  {
+    char c = *nextchar++;
+    char *temp = my_index (optstring, c);
+
+    /* Increment `optind' when we start to process its last character.  */
+    if (*nextchar == '\0')
+      ++optind;
+
+    if (temp == NULL || c == ':')
+      {
+       if (opterr)
+         {
+           /* 1003.2 specifies the format of this message.  */
+           fprintf (stderr, "%s: illegal option -- %c\n", argv[0], c);
+         }
+       optopt = c;
+       return '?';
+      }
+    if (temp[1] == ':')
+      {
+       if (temp[2] == ':')
+         {
+           /* This is an option that accepts an argument optionally.  */
+           if (*nextchar != '\0')
+             {
+               optarg = nextchar;
+               optind++;
+             }
+           else
+             optarg = NULL;
+           nextchar = NULL;
+         }
+       else
+         {
+           /* This is an option that requires an argument.  */
+           if (*nextchar != '\0')
+             {
+               optarg = nextchar;
+               /* If we end this ARGV-element by taking the rest as an arg,
+                  we must advance to the next element now.  */
+               optind++;
+             }
+           else if (optind == argc)
+             {
+               if (opterr)
+                 {
+                   /* 1003.2 specifies the format of this message.  */
+                   fprintf (stderr, "%s: option requires an argument -- %c\n",
+                            argv[0], c);
+                 }
+               optopt = c;
+               if (optstring[0] == ':')
+                 c = ':';
+               else
+                 c = '?';
+             }
+           else
+             /* We already incremented `optind' once;
+                increment it again when taking next ARGV-elt as argument.  */
+             optarg = argv[optind++];
+           nextchar = NULL;
+         }
+      }
+    return c;
+  }
+}
+
+int
+getopt (int argc, char *const *argv, const char *optstring)
+{
+  return _getopt_internal (argc, argv, optstring,
+                          (const struct option *) 0,
+                          (int *) 0,
+                          0);
+}
+
+#endif /* _LIBC or not __GNU_LIBRARY__.  */
+\f
+#ifdef TEST
+
+/* Compile with -DTEST to make an executable for use in testing
+   the above definition of `getopt'.  */
+
+int
+main (int argc, char *argv[])
+{
+  int c;
+  int digit_optind = 0;
+
+  while (1)
+    {
+      int this_option_optind = optind ? optind : 1;
+
+      c = getopt (argc, argv, "abc:d:0123456789");
+      if (c == EOF)
+       break;
+
+      switch (c)
+       {
+       case '0':
+       case '1':
+       case '2':
+       case '3':
+       case '4':
+       case '5':
+       case '6':
+       case '7':
+       case '8':
+       case '9':
+         if (digit_optind != 0 && digit_optind != this_option_optind)
+           printf ("digits occur in two different argv-elements.\n");
+         digit_optind = this_option_optind;
+         printf ("option %c\n", c);
+         break;
+
+       case 'a':
+         printf ("option a\n");
+         break;
+
+       case 'b':
+         printf ("option b\n");
+         break;
+
+       case 'c':
+         printf ("option c with value `%s'\n", optarg);
+         break;
+
+       case '?':
+         break;
+
+       default:
+         printf ("?? getopt returned character code 0%o ??\n", c);
+       }
+    }
+
+  if (optind < argc)
+    {
+      printf ("non-option ARGV-elements: ");
+      while (optind < argc)
+       printf ("%s ", argv[optind++]);
+      printf ("\n");
+    }
+
+  exit (0);
+}
+
+#endif /* TEST */
diff --git a/genisoimage/getopt.h b/genisoimage/getopt.h
new file mode 100644 (file)
index 0000000..e2eb2b7
--- /dev/null
@@ -0,0 +1,148 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)getopt.h        1.3 03/03/06 eric */
+/* Declarations for getopt.
+   Copyright (C) 1989, 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library 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 Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+#ifndef _GETOPT_H
+#define _GETOPT_H 1
+
+#ifndef        _MCONFIG_H
+#include <mconfig.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* For communication from `getopt' to the caller.
+   When `getopt' finds an option that takes an argument,
+   the argument value is returned here.
+   Also, when `ordering' is RETURN_IN_ORDER,
+   each non-option ARGV-element is returned here.  */
+
+extern char *optarg;
+
+/* Index in ARGV of the next element to be scanned.
+   This is used for communication to and from the caller
+   and for communication between successive calls to `getopt'.
+
+   On entry to `getopt', zero means this is the first call; initialize.
+
+   When `getopt' returns EOF, this is the index of the first of the
+   non-option elements that the caller should itself scan.
+
+   Otherwise, `optind' communicates from one call to the next
+   how much of ARGV has been scanned so far.  */
+
+extern int optind;
+
+/* Callers store zero here to inhibit the error message `getopt' prints
+   for unrecognized options.  */
+
+extern int opterr;
+
+/* Set to an option character which was unrecognized.  */
+
+extern int optopt;
+
+/* Describe the long-named options requested by the application.
+   The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
+   of `struct option' terminated by an element containing a name which is
+   zero.
+
+   The field `has_arg' is:
+   no_argument         (or 0) if the option does not take an argument,
+   required_argument   (or 1) if the option requires an argument,
+   optional_argument   (or 2) if the option takes an optional argument.
+
+   If the field `flag' is not NULL, it points to a variable that is set
+   to the value given in the field `val' when the option is found, but
+   left unchanged if the option is not found.
+
+   To have a long-named option do something other than set an `int' to
+   a compiled-in constant, such as set a value from `optarg', set the
+   option's `flag' field to zero and its `val' field to a nonzero
+   value (the equivalent single-letter option character, if there is
+   one).  For long options that have a zero `flag' field, `getopt'
+   returns the contents of the `val' field.  */
+
+struct option
+{
+/*#if  __STDC__*/
+#ifdef PROTOTYPES
+  const char *name;
+#else
+  char *name;
+#endif
+  /* has_arg can't be an enum because some compilers complain about
+     type mismatches in all the code that assumes it is an int.  */
+  int has_arg;
+  int *flag;
+  int val;
+};
+
+/* Names for the values of the `has_arg' field of `struct option'.  */
+
+#define        no_argument             0
+#define required_argument      1
+#define optional_argument      2
+
+/*#if __STDC__*/
+#ifdef PROTOTYPES
+#if defined(__GNU_LIBRARY__)
+/* Many other libraries have conflicting prototypes for getopt, with
+   differences in the consts, in stdlib.h.  To avoid compilation
+   errors, only prototype getopt for the GNU C library.  */
+extern int getopt (int argc, char *const *argv, const char *shortopts);
+#else /* not __GNU_LIBRARY__ */
+extern int getopt ();
+#endif /* not __GNU_LIBRARY__ */
+extern int getopt_long (int argc, char *const *argv, const char *shortopts,
+                       const struct option *longopts, int *longind);
+extern int getopt_long_only (int argc, char *const *argv,
+                            const char *shortopts,
+                            const struct option *longopts, int *longind);
+
+/* Internal only.  Users should not call this directly.  */
+extern int _getopt_internal (int argc, char *const *argv,
+                            const char *shortopts,
+                            const struct option *longopts, int *longind,
+                            int long_only);
+#else /* not __STDC__ */
+extern int getopt ();
+extern int getopt_long ();
+extern int getopt_long_only ();
+
+extern int _getopt_internal ();
+#endif /* not __STDC__ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _GETOPT_H */
diff --git a/genisoimage/getopt1.c b/genisoimage/getopt1.c
new file mode 100644 (file)
index 0000000..9c51b0c
--- /dev/null
@@ -0,0 +1,193 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)getopt1.c       1.1 97/11/04 eric */
+/* getopt_long and getopt_long_only entry points for GNU getopt.
+   Copyright (C) 1987, 88, 89, 90, 91, 92, 1993
+       Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library 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 Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+\f
+#ifdef HAVE_CONFIG_H
+#if defined (emacs) || defined (CONFIG_BROKETS)
+/* We use <config.h> instead of "config.h" so that a compilation
+   using -I. -I$srcdir will use ./config.h rather than $srcdir/config.h
+   (which it would do because it found this file in $srcdir).  */
+#include <config.h>
+#else
+#include "config.h"
+#endif
+#endif
+
+#include "getopt.h"
+
+#ifndef __STDC__
+/* This is a separate conditional since some stdc systems
+   reject `defined (const)'.  */
+#ifndef const
+#define const
+#endif
+#endif
+
+#include <stdio.h>
+
+/* Comment out all this code if we are using the GNU C Library, and are not
+   actually compiling the library itself.  This code is part of the GNU C
+   Library, but also included in many other GNU distributions.  Compiling
+   and linking in this code is a waste when using the GNU C library
+   (especially if it is a shared library).  Rather than having every GNU
+   program understand `configure --with-gnu-libc' and omit the object files,
+   it is simpler to just do this in the source for each such file.  */
+/* Many versions of the Linux C library include older, broken versions
+   of these routines, which will break the linker's command-line
+   parsing.  */
+
+#if defined (_LIBC) || !defined (__GNU_LIBRARY__) || defined (__linux__)
+
+
+/* This needs to come after some library #include
+   to get __GNU_LIBRARY__ defined.  */
+#ifdef __GNU_LIBRARY__
+#include <stdlib.h>
+#else
+char *getenv ();
+#endif
+
+#ifndef        NULL
+#define NULL 0
+#endif
+
+int
+getopt_long (int argc, char *const *argv, const char *options, 
+                                const struct option *long_options, int *opt_index)
+{
+  return _getopt_internal (argc, argv, options, long_options, opt_index, 0);
+}
+
+/* Like getopt_long, but '-' as well as '--' can indicate a long option.
+   If an option that starts with '-' (not '--') doesn't match a long option,
+   but does match a short option, it is parsed as a short option
+   instead.  */
+
+int
+getopt_long_only (int argc, char *const *argv, const char *options, 
+                                               const struct option *long_options, int *opt_index)
+{
+  return _getopt_internal (argc, argv, options, long_options, opt_index, 1);
+}
+
+
+#endif /* _LIBC or not __GNU_LIBRARY__.  */
+\f
+#ifdef TEST
+
+#include <stdio.h>
+
+int
+main (int argc, char *argv[])
+{
+  int c;
+  int digit_optind = 0;
+
+  while (1)
+    {
+      int this_option_optind = optind ? optind : 1;
+      int option_index = 0;
+      static struct option long_options[] =
+      {
+       {"add", 1, 0, 0},
+       {"append", 0, 0, 0},
+       {"delete", 1, 0, 0},
+       {"verbose", 0, 0, 0},
+       {"create", 0, 0, 0},
+       {"file", 1, 0, 0},
+       {0, 0, 0, 0}
+      };
+
+      c = getopt_long (argc, argv, "abc:d:0123456789",
+                      long_options, &option_index);
+      if (c == EOF)
+       break;
+
+      switch (c)
+       {
+       case 0:
+         printf ("option %s", long_options[option_index].name);
+         if (optarg)
+           printf (" with arg %s", optarg);
+         printf ("\n");
+         break;
+
+       case '0':
+       case '1':
+       case '2':
+       case '3':
+       case '4':
+       case '5':
+       case '6':
+       case '7':
+       case '8':
+       case '9':
+         if (digit_optind != 0 && digit_optind != this_option_optind)
+           printf ("digits occur in two different argv-elements.\n");
+         digit_optind = this_option_optind;
+         printf ("option %c\n", c);
+         break;
+
+       case 'a':
+         printf ("option a\n");
+         break;
+
+       case 'b':
+         printf ("option b\n");
+         break;
+
+       case 'c':
+         printf ("option c with value `%s'\n", optarg);
+         break;
+
+       case 'd':
+         printf ("option d with value `%s'\n", optarg);
+         break;
+
+       case '?':
+         break;
+
+       default:
+         printf ("?? getopt returned character code 0%o ??\n", c);
+       }
+    }
+
+  if (optind < argc)
+    {
+      printf ("non-option ARGV-elements: ");
+      while (optind < argc)
+       printf ("%s ", argv[optind++]);
+      printf ("\n");
+    }
+
+  exit (0);
+}
+
+#endif /* TEST */
diff --git a/genisoimage/hash.c b/genisoimage/hash.c
new file mode 100644 (file)
index 0000000..054aea6
--- /dev/null
@@ -0,0 +1,404 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)hash.c  1.18 04/06/18 joerg */
+/* @(#)hash.c  1.23 06/10/04 joerg */
+/*
+ * File hash.c - generate hash tables for iso9660 filesystem.
+ *
+ * Written by Eric Youngdale (1993).
+ *
+ * Copyright 1993 Yggdrasil Computing, Incorporated
+ * Copyright (c) 1999,2000-2006 J. Schilling
+ *
+ * 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.
+ */
+
+/* APPLE_HYB James Pearson j.pearson@ge.ucl.ac.uk 23/2/2000 */
+
+/*
+ * From jb@danware.dk:
+ *
+ * Cygwin fakes inodes by hashing file info, actual collisions observed!
+ * This is documented in the cygwin source, look at winsup/cygwin/path.cc
+ * and search for the word 'Hash'.  On NT, cygwin ORs together the
+ * high and low 32 bits of the 64 bit genuine inode, look at fhandler.cc.
+ *
+ * Note:       Other operating systems which support the FAT filesystem may
+ *             have the same problem because FAT does not use the inode
+ *             concept.  For NTFS, genuine inode numbers exist, but they are
+ *             64 bits and available only through an open file handle.
+ *
+ * The solution is the new options -no-cache-inodes/-cache-inodes that
+ * allow to disable the genisoimage inode cache.
+ */
+
+#include <mconfig.h>
+#include "genisoimage.h"
+#include <schily.h>
+
+#define        NR_HASH (16*1024)
+
+#define        HASH_FN(DEV, INO)       ((DEV + INO  + (INO >> 8) + (INO << 16)) % NR_HASH)
+
+static struct file_hash *hash_table[NR_HASH];
+
+void           add_hash(struct directory_entry *spnt);
+struct file_hash *find_hash(dev_t dev, ino_t inode);
+void           flush_hash(void);
+void           add_directory_hash(dev_t dev, ino_t inode);
+struct file_hash *find_directory_hash(dev_t dev, ino_t inode);
+static unsigned int    name_hash(const char *name);
+void           add_file_hash(struct directory_entry *de);
+struct directory_entry *find_file_hash(char *name);
+static BOOL            isoname_endsok(char *name);
+int            delete_file_hash(struct directory_entry *de);
+void           flush_file_hash(void);
+
+void
+add_hash(struct directory_entry *spnt)
+{
+       struct file_hash *s_hash;
+       unsigned int    hash_number;
+
+       if (spnt->size == 0 || spnt->starting_block == 0)
+               if (spnt->size != 0 && spnt->starting_block == 0) {
+                       comerrno(EX_BAD,
+                       "Non zero-length file '%s' assigned zero extent.\n",
+                                                       spnt->name);
+               };
+
+       if (!cache_inodes)
+               return;
+       if (spnt->dev == UNCACHED_DEVICE &&
+           (spnt->inode == TABLE_INODE || spnt->inode == UNCACHED_INODE)) {
+               return;
+       }
+       hash_number = HASH_FN((unsigned int) spnt->dev,
+                                               (unsigned int) spnt->inode);
+
+#if 0
+       if (verbose > 1)
+               fprintf(stderr, "%s ", spnt->name);
+#endif
+       s_hash = (struct file_hash *) e_malloc(sizeof (struct file_hash));
+       s_hash->next = hash_table[hash_number];
+       s_hash->inode = spnt->inode;
+       s_hash->dev = spnt->dev;
+       s_hash->nlink = 0;
+       s_hash->starting_block = spnt->starting_block;
+       s_hash->size = spnt->size;
+#ifdef SORTING
+       s_hash->de = spnt;
+#endif /* SORTING */
+       hash_table[hash_number] = s_hash;
+}
+
+struct file_hash *
+find_hash(dev_t dev, ino_t inode)
+{
+       unsigned int    hash_number;
+       struct file_hash *spnt;
+
+       if (!cache_inodes)
+               return (NULL);
+       if (dev == UNCACHED_DEVICE &&
+           (inode == TABLE_INODE || inode == UNCACHED_INODE))
+               return (NULL);
+
+       hash_number = HASH_FN((unsigned int) dev, (unsigned int) inode);
+       spnt = hash_table[hash_number];
+       while (spnt) {
+               if (spnt->inode == inode && spnt->dev == dev)
+                       return (spnt);
+               spnt = spnt->next;
+       };
+       return (NULL);
+}
+
+/*
+ * based on flush_file_hash() below - needed as we want to re-use the
+ * file hash table.
+ */
+void
+flush_hash()
+{
+       struct file_hash        *fh;
+       struct file_hash        *fh1;
+       int                     i;
+
+       for (i = 0; i < NR_HASH; i++) {
+               fh = hash_table[i];
+               while (fh) {
+                       fh1 = fh->next;
+                       free(fh);
+                       fh = fh1;
+               }
+               hash_table[i] = NULL;
+       }
+}
+
+static struct file_hash *directory_hash_table[NR_HASH];
+
+void
+add_directory_hash(dev_t dev, ino_t inode)
+{
+       struct file_hash *s_hash;
+       unsigned int    hash_number;
+
+       if (!cache_inodes)
+               return;
+       if (dev == UNCACHED_DEVICE &&
+           (inode == TABLE_INODE || inode == UNCACHED_INODE))
+               return;
+
+       hash_number = HASH_FN((unsigned int) dev, (unsigned int) inode);
+
+       s_hash = (struct file_hash *) e_malloc(sizeof (struct file_hash));
+       s_hash->next = directory_hash_table[hash_number];
+       s_hash->inode = inode;
+       s_hash->dev = dev;
+       s_hash->nlink = 0;
+       directory_hash_table[hash_number] = s_hash;
+}
+
+struct file_hash *
+find_directory_hash(dev_t dev, ino_t inode)
+{
+       unsigned int    hash_number;
+       struct file_hash *spnt;
+
+       if (!cache_inodes)
+               return (NULL);
+       if (dev == UNCACHED_DEVICE &&
+           (inode == TABLE_INODE || inode == UNCACHED_INODE))
+               return (NULL);
+
+       hash_number = HASH_FN((unsigned int) dev, (unsigned int) inode);
+       spnt = directory_hash_table[hash_number];
+       while (spnt) {
+               if (spnt->inode == inode && spnt->dev == dev)
+                       return (spnt);
+               spnt = spnt->next;
+       };
+       return (NULL);
+}
+
+struct name_hash {
+       struct name_hash *next;
+       struct directory_entry *de;
+       int     sum;
+};
+
+#define        NR_NAME_HASH    (256*1024)
+
+static struct name_hash *name_hash_table[NR_NAME_HASH] = {0, };
+
+/*
+ * Find the hash bucket for this name.
+ */
+static unsigned int
+name_hash(const char *name)
+{
+       unsigned int    hash = 0;
+       const char      *p;
+
+       p = name;
+
+       while (*p) {
+               /*
+                * Don't hash the  iso9660 version number.
+                * This way we can detect duplicates in cases where we have
+                * directories (i.e. foo) and non-directories (i.e. foo;1).
+                */
+               if (*p == ';') {
+                       break;
+               }
+               hash = (hash << 15) + (hash << 3) + (hash >> 3) + (*p++ & 0xFF);
+       }
+       return (hash % NR_NAME_HASH);
+}
+
+void
+add_file_hash(struct directory_entry *de)
+{
+       struct name_hash        *new;
+       int                     hash;
+       Uchar                   *p;
+       int                     sum = 0;
+
+       new = (struct name_hash *) e_malloc(sizeof (struct name_hash));
+       new->de = de;
+       new->next = NULL;
+       for (p = (Uchar *)de->isorec.name; *p; p++) {
+               if (*p == ';')
+                       break;
+               sum += *p & 0xFF;
+       }
+       new->sum = sum;
+       hash = name_hash(de->isorec.name);
+
+       /* Now insert into the hash table */
+       new->next = name_hash_table[hash];
+       name_hash_table[hash] = new;
+}
+
+struct directory_entry *
+find_file_hash(register char *name)
+{
+       register char                   *p1;
+       register char                   *p2;
+       register struct name_hash       *nh;
+       register int                    sum = 0;
+
+       if (debug > 1)
+               fprintf(stderr, "find_hash('%s')\n", name);
+
+       for (p1 = name; *p1; p1++) {
+               if (*p1 == ';')
+                       break;
+               sum += *p1 & 0xFF;
+       }
+
+       for (nh = name_hash_table[name_hash(name)]; nh; nh = nh->next) {
+               if (nh->sum != sum)
+                       continue;
+
+               p1 = name;
+               p2 = nh->de->isorec.name;
+               if (debug > 1)
+                       fprintf(stderr, "Checking name '%s' isorec.name '%s'\n", p1, p2);
+
+               /* Look for end of string, or a mismatch. */
+               while (1 == 1) {
+                       if ((*p1 == '\0' || *p1 == ';') ||
+                           (*p2 == '\0' || *p2 == ';') ||
+                           (*p1 != *p2)) {
+                               break;
+                       }
+                       p1++;
+                       p2++;
+               }
+               if (!isoname_endsok(p1) || !isoname_endsok(p2)) {
+                       if (debug > 1) {
+                               if (!isoname_endsok(p1))
+                                       fprintf(stderr, "'%s' does NOT END OK\n", p1);
+                               if (!isoname_endsok(p2))
+                                       fprintf(stderr, "'%s' does NOT END OK\n", p2);
+                       }
+                       /*
+                        * If one file does not end with a valid version number
+                        * and the other name ends here, we found a miss match.
+                        */
+                       if (*p1 == '\0' || *p2 == '\0')
+                               continue;
+
+                       if (*p1 == ';' && *p2 == ';') {
+                               p1++;
+                               p2++;
+                               continue;
+                       }
+               }
+
+               /*
+                * If we are at the end of both strings, then we have a match.
+                */
+               if ((*p1 == '\0' || *p1 == ';') &&
+                   (*p2 == '\0' || *p2 == ';')) {
+                       return (nh->de);
+               }
+       }
+       return (NULL);
+}
+
+/*
+ * The macro 'eo' is just an idea on how one might speed up isoname_endsok()
+ */
+#define        eo(p)   (((p)[0] == '\0') || \
+               ((p)[0] == ';' && (p)[1] == '1' && (p)[2] == '\0') || \
+               isoname_endsok(p))
+
+static BOOL
+isoname_endsok(char *name)
+{
+       int     i;
+       char    *p;
+
+       if (*name == '\0')
+               return (TRUE);
+       if (*name != ';')
+               return (FALSE);
+
+       for (p = ++name, i = 0; *p && i < 5; p++, i++) {
+               if (*p < '0' || *p > '9')
+                       return (FALSE);
+       }
+       i = atoi(name);
+       if (i < 1 || i > 32767)
+               return (FALSE);
+       return (TRUE);
+}
+
+int
+delete_file_hash(struct directory_entry *de)
+{
+       struct name_hash        *nh;
+       struct name_hash        *prev;
+       int                     hash;
+
+       prev = NULL;
+       hash = name_hash(de->isorec.name);
+       for (nh = name_hash_table[hash]; nh; nh = nh->next) {
+               if (nh->de == de)
+                       break;
+               prev = nh;
+       }
+       if (!nh)
+               return (1);
+       if (!prev)
+               name_hash_table[hash] = nh->next;
+       else
+               prev->next = nh->next;
+       free(nh);
+       return (0);
+}
+
+void
+flush_file_hash()
+{
+       struct name_hash        *nh;
+       struct name_hash        *nh1;
+       int                     i;
+
+       for (i = 0; i < NR_NAME_HASH; i++) {
+               nh = name_hash_table[i];
+               while (nh) {
+                       nh1 = nh->next;
+                       free(nh);
+                       nh = nh1;
+               }
+               name_hash_table[i] = NULL;
+
+       }
+}
diff --git a/genisoimage/hdisk.pl b/genisoimage/hdisk.pl
new file mode 100755 (executable)
index 0000000..55ef66c
--- /dev/null
@@ -0,0 +1,65 @@
+#!/usr/bin/perl
+
+###############################################################################
+#
+# hfsutils - tools for reading and writing Macintosh HFS volumes
+# Copyright (C) 1996, 1997 Robert Leslie
+#
+# 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 of the License, 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.
+#
+###############################################################################
+
+die "Usage: $0 device-path\n" unless (@ARGV == 1);
+
+($disk) = @ARGV;
+
+format STDOUT_TOP =
+ # Partition Type                HFS Volume Name                Start    Length
+-------------------------------------------------------------------------------
+.
+
+format STDOUT =
+@# @<<<<<<<<<<<<<<<<<<<<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<<<< @####### @########
+$bnum, $pmParType, $drVN, $pmPyPartStart, $pmPartBlkCnt
+.
+
+open(DISK, $disk) || die "$disk: $!\n";
+
+$bnum = 1;
+
+do {
+    seek(DISK, 512 * $bnum, 0) || die "seek: $!\n";
+    read(DISK, $block, 512) || die "read: $!\n";
+
+    ($pmSig, $pmMapBlkCnt, $pmPyPartStart, $pmPartBlkCnt, $pmParType) =
+       (unpack('n2 N3 A32 A32 N10 A16', $block))[0, 2..4, 6];
+
+    die "$disk: unsupported partition map\n" if ($pmSig == 0x5453);
+    die "$disk: no partition map\n" unless ($pmSig == 0x504d);
+
+    if ($pmParType eq 'Apple_HFS') {
+       seek(DISK, 512 * ($pmPyPartStart + 2), 0) || die "seek: $!\n";
+       read(DISK, $block, 512) || die "read: $!\n";
+
+       ($len, $drVN) = (unpack('n N2 n5 N2 n N n c A27', $block))[13, 14];
+       $drVN = substr($drVN, 0, $len);
+    } else {
+       $drVN = '';
+    }
+
+    write;
+} while ($bnum++ < $pmMapBlkCnt);
+
+close(DISK);
diff --git a/genisoimage/ifo_read.c b/genisoimage/ifo_read.c
new file mode 100644 (file)
index 0000000..0173c47
--- /dev/null
@@ -0,0 +1,559 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)ifo_read.c      1.5 04/03/04 joerg */
+/*
+ * Copyright (C) 2002 Olaf Beck <olaf_sc@yahoo.com>
+ *                  Jörg Schilling <schilling@fokus.gmd.de>
+ *                  (making the code portable)
+ *
+ * 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 of the License, 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ * NOTE: This is a cut down version of libdvdread for genisoimage, due
+ * to portability issues with the current libdvdread according to
+ * the maintainer of genisoimage.
+ * This cut down version only reads from a harddisk file structure
+ * and it only implements the functions necessary inorder to make
+ * genisoimage produce valid DVD-Video images.
+ * DON'T USE THIS LIBRARY IN ANY OTHER PROGRAM GET THE REAL
+ * LIBDVDREAD INSTEAD
+ */
+#ifdef DVD_VIDEO
+
+#include <mconfig.h>
+#include "genisoimage.h"
+#include <fctldefs.h>
+#include <utypes.h>
+#include <schily.h>
+
+#include "ifo_read.h"
+#include "bswap.h"
+
+#define MSGEREAD "Failed to read VIDEO_TS.IFO\n"
+#define MSGESEEK "Failed to seek VIDEO_TS.IFO\n"
+#define MSGEOPEN "Failed to open VIDEO_TS.IFO\n"
+
+static ifo_handle_t *ifoReadVTSI(int file, ifo_handle_t * ifofile);
+static ifo_handle_t *ifoReadVGMI(int file, ifo_handle_t * ifofile);
+ifo_handle_t *ifoOpen(dvd_reader_t *dvd, int title);
+static void            ifoFree_TT_SRPT(ifo_handle_t *ifofile);
+void           ifoClose(ifo_handle_t * ifofile);
+
+
+static ifo_handle_t *
+ifoReadVTSI(int file, ifo_handle_t *ifofile)
+{
+       off_t offset;
+       UInt32_t sector;
+
+       vtsi_mat_t * vtsi_mat;
+
+       /* Make the VMG part NULL */
+       ifofile->vmgi_mat = NULL;
+       ifofile->tt_srpt = NULL;
+
+       vtsi_mat = (vtsi_mat_t *)e_malloc(sizeof (vtsi_mat_t));
+       if (!vtsi_mat) {
+/*             fprintf(stderr, "Memmory allocation error\n");*/
+               free(ifofile);
+               return (0);
+       }
+
+       ifofile->vtsi_mat = vtsi_mat;
+
+       /* Last sector of VTS i.e. last sector of BUP */
+
+       offset = 12;
+
+       if (lseek(file, offset, SEEK_SET) != offset) {
+#ifdef USE_LIBSCHILY
+               errmsg(MSGESEEK);
+#else
+               printf(stderr, MSGESEEK);
+#endif
+               ifoClose(ifofile);
+               return (0);
+       }
+
+       if (read(file, &sector, sizeof (sector)) != sizeof (sector)) {
+#ifdef USE_LIBSCHILY
+               errmsg(MSGEREAD);
+#else
+               printf(stderr, MSGEREAD);
+#endif
+               ifoClose(ifofile);
+               return (0);
+       }
+
+       B2N_32(sector);
+
+       vtsi_mat->vts_last_sector = sector;
+
+       /* Last sector of IFO */
+
+       offset = 28;
+
+       if (lseek(file, offset, SEEK_SET) != offset) {
+#ifdef USE_LIBSCHILY
+               errmsg(MSGESEEK);
+#else
+               printf(stderr, MSGESEEK);
+#endif
+               ifoClose(ifofile);
+               return (0);
+       }
+
+       if (read(file, &sector, sizeof (sector)) != sizeof (sector)) {
+#ifdef USE_LIBSCHILY
+               errmsg(MSGEREAD);
+#else
+               printf(stderr, MSGEREAD);
+#endif
+               ifoClose(ifofile);
+               return (0);
+       }
+
+       B2N_32(sector);
+
+       vtsi_mat->vtsi_last_sector = sector;
+
+
+       /* Star sector of VTS Menu VOB */
+
+       offset = 192;
+
+       if (lseek(file, offset, SEEK_SET) != offset) {
+#ifdef USE_LIBSCHILY
+               errmsg(MSGESEEK);
+#else
+               printf(stderr, MSGESEEK);
+#endif
+               ifoClose(ifofile);
+               return (0);
+       }
+
+
+       if (read(file, &sector, sizeof (sector)) != sizeof (sector)) {
+#ifdef USE_LIBSCHILY
+               errmsg(MSGEREAD);
+#else
+               printf(stderr, MSGEREAD);
+#endif
+               ifoClose(ifofile);
+               return (0);
+       }
+
+       B2N_32(sector);
+
+       vtsi_mat->vtsm_vobs = sector;
+
+
+       /* Start sector of VTS Title VOB */
+
+       offset = 196;
+
+       if (lseek(file, offset, SEEK_SET) != offset) {
+#ifdef USE_LIBSCHILY
+               errmsg(MSGESEEK);
+#else
+               printf(stderr, MSGESEEK);
+#endif
+               ifoClose(ifofile);
+               return (0);
+       }
+
+
+       if (read(file, &sector, sizeof (sector)) != sizeof (sector)) {
+#ifdef USE_LIBSCHILY
+               errmsg(MSGEREAD);
+#else
+               printf(stderr, MSGEREAD);
+#endif
+               ifoClose(ifofile);
+               return (0);
+       }
+
+       B2N_32(sector);
+
+       vtsi_mat->vtstt_vobs = sector;
+
+       return (ifofile);
+}
+
+
+static ifo_handle_t *
+ifoReadVGMI(int file, ifo_handle_t *ifofile)
+{
+       off_t   offset;
+       Uint    counter;
+       UInt32_t sector;
+       UInt16_t titles;
+
+       vmgi_mat_t *vmgi_mat;
+       tt_srpt_t *tt_srpt;
+
+       /* Make the VTS part null */
+       ifofile->vtsi_mat = NULL;
+
+       vmgi_mat = (vmgi_mat_t *)e_malloc(sizeof (vmgi_mat_t));
+       if (!vmgi_mat) {
+/*             fprintf(stderr, "Memmory allocation error\n");*/
+               free(ifofile);
+               return (0);
+       }
+
+       ifofile->vmgi_mat = vmgi_mat;
+
+       /* Last sector of VMG i.e. last sector of BUP */
+
+       offset = 12;
+
+       if (lseek(file, offset, SEEK_SET) != offset) {
+#ifdef USE_LIBSCHILY
+               errmsg(MSGESEEK);
+#else
+               printf(stderr, MSGESEEK);
+#endif
+               ifoClose(ifofile);
+               return (0);
+       }
+
+       if (read(file, &sector, sizeof (sector)) != sizeof (sector)) {
+#ifdef USE_LIBSCHILY
+               errmsg(MSGEREAD);
+#else
+               printf(stderr, MSGEREAD);
+#endif
+               ifoClose(ifofile);
+               return (0);
+       }
+
+       B2N_32(sector);
+
+       vmgi_mat->vmg_last_sector = sector;
+
+       /* Last sector of IFO */
+
+       offset = 28;
+
+       if (lseek(file, offset, SEEK_SET) != offset) {
+#ifdef USE_LIBSCHILY
+               errmsg(MSGESEEK);
+#else
+               printf(stderr, MSGESEEK);
+#endif
+               ifoClose(ifofile);
+               return (0);
+       }
+
+
+       if (read(file, &sector, sizeof (sector)) != sizeof (sector)) {
+#ifdef USE_LIBSCHILY
+               errmsg(MSGEREAD);
+#else
+               printf(stderr, MSGEREAD);
+#endif
+               ifoClose(ifofile);
+               return (0);
+       }
+
+       B2N_32(sector);
+
+       vmgi_mat->vmgi_last_sector = sector;
+
+
+       /* Number of VTS i.e. title sets */
+
+       offset = 62;
+
+       if (lseek(file, offset, SEEK_SET) != offset) {
+#ifdef USE_LIBSCHILY
+               errmsg(MSGESEEK);
+#else
+               printf(stderr, MSGESEEK);
+#endif
+               ifoClose(ifofile);
+               return (0);
+       }
+
+
+       if (read(file, &titles, sizeof (titles)) != sizeof (titles)) {
+#ifdef USE_LIBSCHILY
+               errmsg(MSGEREAD);
+#else
+               printf(stderr, MSGEREAD);
+#endif
+               ifoClose(ifofile);
+               return (0);
+       }
+
+       B2N_16(titles);
+
+       vmgi_mat->vmg_nr_of_title_sets = titles;
+
+
+       /* Star sector of VMG Menu VOB */
+
+       offset = 192;
+
+       if (lseek(file, offset, SEEK_SET) != offset) {
+#ifdef USE_LIBSCHILY
+               errmsg(MSGESEEK);
+#else
+               printf(stderr, MSGESEEK);
+#endif
+               ifoClose(ifofile);
+               return (0);
+       }
+
+
+       if (read(file, &sector, sizeof (sector)) != sizeof (sector)) {
+#ifdef USE_LIBSCHILY
+               errmsg(MSGEREAD);
+#else
+               printf(stderr, MSGEREAD);
+#endif
+               ifoClose(ifofile);
+               return (0);
+       }
+
+       B2N_32(sector);
+
+       vmgi_mat->vmgm_vobs = sector;
+
+
+       /* Sector offset to TT_SRPT */
+
+       offset = 196;
+
+       if (lseek(file, offset, SEEK_SET) != offset) {
+#ifdef USE_LIBSCHILY
+               errmsg(MSGESEEK);
+#else
+               printf(stderr, MSGESEEK);
+#endif
+               ifoClose(ifofile);
+               return (0);
+       }
+
+
+       if (read(file, &sector, sizeof (sector)) != sizeof (sector)) {
+#ifdef USE_LIBSCHILY
+               errmsg(MSGEREAD);
+#else
+               printf(stderr, MSGEREAD);
+#endif
+               ifoClose(ifofile);
+               return (0);
+       }
+
+       B2N_32(sector);
+
+       vmgi_mat->tt_srpt = sector;
+
+       tt_srpt = (tt_srpt_t *)e_malloc(sizeof (tt_srpt_t));
+       if (!tt_srpt) {
+/*             fprintf(stderr, "Memmory allocation error\n");*/
+               ifoClose(ifofile);
+               return (0);
+       }
+
+       ifofile->tt_srpt = tt_srpt;
+
+
+       /* Number of titles in TT_SRPT */
+
+       offset = 2048 * vmgi_mat->tt_srpt;
+
+       if (lseek(file, offset, SEEK_SET) != offset) {
+#ifdef USE_LIBSCHILY
+               errmsg(MSGESEEK);
+#else
+               printf(stderr, MSGESEEK);
+#endif
+               return (0);
+       }
+
+       if (read(file, &titles, sizeof (titles)) != sizeof (titles)) {
+#ifdef USE_LIBSCHILY
+               errmsg(MSGEREAD);
+#else
+               printf(stderr, MSGEREAD);
+#endif
+               return (0);
+       }
+
+       B2N_16(titles);
+
+       tt_srpt->nr_of_srpts = titles;
+
+       tt_srpt->title = (title_info_t *)e_malloc(sizeof (title_info_t) * tt_srpt->nr_of_srpts);
+       if (!tt_srpt->title) {
+/*             fprintf(stderr, "Memmory allocation error\n");*/
+               ifoClose(ifofile);
+               return (0);
+       }
+
+       /* Start sector of each title in TT_SRPT */
+
+       for (counter = 0; counter < tt_srpt->nr_of_srpts; counter++) {
+               offset = (2048 * vmgi_mat->tt_srpt) + 8 + (counter * 12) + 8;
+               if (lseek(file, offset, SEEK_SET) != offset) {
+#ifdef USE_LIBSCHILY
+                       errmsg(MSGESEEK);
+#else
+                       printf(stderr, MSGESEEK);
+#endif
+                       ifoClose(ifofile);
+                       return (0);
+               }
+
+               if (read(file, &sector, sizeof (sector)) != sizeof (sector)) {
+#ifdef USE_LIBSCHILY
+                       errmsg(MSGEREAD);
+#else
+                       printf(stderr, MSGEREAD);
+#endif
+                       ifoClose(ifofile);
+                       return (0);
+               }
+
+               B2N_32(sector);
+
+               tt_srpt->title[counter].title_set_sector = sector;
+
+       }
+       return (ifofile);
+}
+
+ifo_handle_t *
+ifoOpen(dvd_reader_t *dvd, int title)
+{
+       /* The main ifofile structure */
+       ifo_handle_t *ifofile;
+
+       /* File handles and offset */
+       int file;
+       off_t offset;
+       char full_path[ PATH_MAX + 1 ];
+
+       /* Identifier of the IFO */
+       char identifier[13];
+
+       identifier[0] = '\0';
+
+       ifofile = (ifo_handle_t *)e_malloc(sizeof (ifo_handle_t));
+
+       memset(ifofile, 0, sizeof (ifo_handle_t));
+
+       if (title) {
+               snprintf(full_path, sizeof (full_path),
+                               "%s/VIDEO_TS/VTS_%02d_0.IFO", dvd->path_root, title);
+       } else {
+               snprintf(full_path, sizeof (full_path),
+                               "%s/VIDEO_TS/VIDEO_TS.IFO", dvd->path_root);
+       }
+
+       if ((file = open(full_path, O_RDONLY | O_BINARY)) == -1) {
+#ifdef USE_LIBSCHILY
+               errmsg(MSGEOPEN);
+#else
+               printf(stderr, MSGEOPEN);
+#endif
+               free(ifofile);
+               return (0);
+       }
+
+       offset = 0;
+
+       /* Determine if we have a VMGI or VTSI */
+
+       if (read(file, identifier, sizeof (identifier)) != sizeof (identifier)) {
+#ifdef USE_LIBSCHILY
+               errmsg(MSGEREAD);
+#else
+               printf(stderr, MSGEREAD);
+#endif
+               return (0);
+       }
+
+       if ((strstr("DVDVIDEO-VMG", identifier) != 0) && (title == 0)) {
+               ifofile = ifoReadVGMI(file, ifofile);
+               close(file);
+               return (ifofile);
+       } else if ((strstr("DVDVIDEO-VTS", identifier) != 0) && (title != 0)) {
+               ifofile = ifoReadVTSI(file, ifofile);
+               close(file);
+               return (ifofile);
+       } else {
+#ifdef USE_LIBSCHILY
+               errmsgno(EX_BAD, "Giving up this is not a valid IFO file\n");
+#else
+               fprintf(stderr, "Giving up this is not a valid IFO file\n");
+#endif
+               close(file);
+               free(ifofile);
+               ifofile = 0;
+               return (0);
+       }
+}
+
+static void
+ifoFree_TT_SRPT(ifo_handle_t *ifofile)
+{
+       if (!ifofile)
+               return;
+
+       if (ifofile->tt_srpt) {
+               if (ifofile->tt_srpt->title) {
+                       free(ifofile->tt_srpt->title);
+               }
+               free(ifofile->tt_srpt);
+               ifofile->tt_srpt = 0;
+       }
+}
+
+void
+ifoClose(ifo_handle_t *ifofile)
+{
+
+       if (!ifofile)
+               return;
+
+       ifoFree_TT_SRPT(ifofile);
+
+       if (ifofile->vmgi_mat) {
+               free(ifofile->vtsi_mat);
+       }
+
+       if (ifofile->vtsi_mat) {
+               free(ifofile->vtsi_mat);
+       }
+
+       free(ifofile);
+       ifofile = 0;
+}
+#endif /* DVD_VIDEO */
diff --git a/genisoimage/ifo_read.h b/genisoimage/ifo_read.h
new file mode 100644 (file)
index 0000000..b8fa009
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)ifo_read.h      1.2 04/03/02 joerg */
+
+#ifndef        _IFO_READ_H
+#define        _IFO_READ_H
+
+/*
+ * Copyright (C) 2000, 2001, 2002 Björn Englund <d4bjorn@dtek.chalmers.se>,
+ *                               HÃ¥kan Hjort <d95hjort@dtek.chalmers.se
+ *                               Olaf Beck <olaf_sc@yahoo.com>
+ *                               (I only did the cut down no other contribs)
+ *                               Jörg Schilling <schilling@fokus.gmd.de>
+ *                               (making the code portable)
+ * 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 of the License, 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ * NOTE: This is a cut down version of libdvdread for genisoimage, due
+ * to portability issues with the current libdvdread according to
+ * the maintainer of genisoimage.
+ * This cut down version only reads from a harddisk file structure
+ * and it only implements the functions necessary inorder to make
+ * genisoimage produce valid DVD-Video images.
+ * DON'T USE THIS LIBRARY IN ANY OTHER PROGRAM GET THE REAL
+ * LIBDVDREAD INSTEAD
+ */
+
+
+
+#include "ifo_types.h"
+#include "dvd_reader.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/*
+ * handle = ifoOpen(dvd, title);
+ *
+ * Opens an IFO and reads a tiny fraction of the data for the IFO file
+ * corresponding to the given title set. If title 0 is given, the video
+ * manager IFO file is read.
+ * Returns a handle to a tiny parsed fraction of a IFO strcuture
+ */
+extern ifo_handle_t *ifoOpen(dvd_reader_t *, int);
+
+
+/*
+ * ifoClose(ifofile);
+ * Cleans up the IFO information. This will free all data allocated.
+ */
+extern void ifoClose(ifo_handle_t *);
+
+#ifdef __cplusplus
+};
+#endif
+#endif /* _IFO_READ_H */
diff --git a/genisoimage/ifo_types.h b/genisoimage/ifo_types.h
new file mode 100644 (file)
index 0000000..00b3bde
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)ifo_types.h     1.2 04/03/02 joerg */
+
+#ifndef        _IFO_TYPES_H
+#define        _IFO_TYPES_H
+/*
+ * Copyright (C) 2001, 2002 Billy Biggs <vektor@dumbterm.net>,
+ *                         HÃ¥kan Hjort <d95hjort@dtek.chalmers.se>,
+ *                         Olaf Beck <olaf_sc@yahoo.com>
+ *                         (I only did the cut down no other contribs)
+ *                         Jörg Schilling <schilling@fokus.gmd.de>
+ *                         (making the code portable)
+ * 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 of the License, 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ * NOTE: This is a cut down version of libdvdread for genisoimage, due
+ * to portability issues with the current libdvdread according to
+ * the maintainer of genisoimage.
+ * This cut down version only reads from a harddisk file structure
+ * and it only implements the functions necessary inorder to make
+ * genisoimage produce valid DVD-Video images.
+ * DON'T USE THIS LIBRARY IN ANY OTHER PROGRAM GET THE REAL
+ * LIBDVDREAD INSTEAD
+ */
+
+#include "dvd_reader.h"
+
+
+typedef struct {
+       UInt32_t        title_set_sector;       /* sector */
+} title_info_t;
+
+
+typedef struct {
+       UInt16_t        nr_of_srpts;
+       title_info_t *  title;                  /* array of title info */
+} tt_srpt_t;
+
+typedef struct {
+       UInt32_t        vmg_last_sector;        /*sector */
+       UInt32_t        vmgi_last_sector;       /* sector */
+       UInt16_t        vmg_nr_of_title_sets;
+       UInt32_t        vmgm_vobs;              /* sector */
+       UInt32_t        tt_srpt;                /* sector */
+} vmgi_mat_t;
+
+
+
+typedef struct {
+       UInt32_t        vts_last_sector;        /* sector */
+       UInt32_t        vtsi_last_sector;       /* sector */
+       UInt32_t        vtsm_vobs;              /* sector */
+       UInt32_t        vtstt_vobs;             /* sector */
+} vtsi_mat_t;
+
+
+typedef struct {
+       /* VMGI */
+       vmgi_mat_t *    vmgi_mat;
+       tt_srpt_t  *    tt_srpt;
+
+       /* VTSI */
+       vtsi_mat_t *    vtsi_mat;
+} ifo_handle_t;
+
+
+#endif /* _IFO_TYPES_H */
diff --git a/genisoimage/iso9660.h b/genisoimage/iso9660.h
new file mode 100644 (file)
index 0000000..c74c2a9
--- /dev/null
@@ -0,0 +1,359 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)iso9660.h       1.19 04/03/02 joerg */
+/*
+ * Header file iso9660.h - assorted structure definitions and typecasts.
+ * specific to iso9660 filesystem.
+ *
+ * Written by Eric Youngdale (1993).
+ *
+ * Copyright 1993 Yggdrasil Computing, Incorporated
+ * Copyright (c) 1999,2000-2004 J. Schilling
+ *
+ * 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.
+ */
+#ifndef        _ISOFS_FS_H
+#define        _ISOFS_FS_H
+
+/*
+ * The isofs filesystem constants/structures
+ */
+
+/* This part borrowed from the bsd386 isofs */
+#define        ISODCL(from, to) (to - from + 1)
+
+struct iso_volume_descriptor {
+       char type       [ISODCL(1, 1)]; /* 711 */
+       char id         [ISODCL(2, 6)];
+       char version    [ISODCL(7, 7)];
+       char data       [ISODCL(8, 2048)];
+};
+
+/* volume descriptor types */
+#define        ISO_VD_PRIMARY          1
+#define        ISO_VD_SUPPLEMENTARY    2       /* Used by Joliet */
+#define        ISO_VD_END              255
+
+#define        ISO_STANDARD_ID         "CD001"
+
+#define        EL_TORITO_ID            "EL TORITO SPECIFICATION"
+#define        EL_TORITO_ARCH_x86      0
+#define        EL_TORITO_ARCH_PPC      1
+#define        EL_TORITO_ARCH_MAC      2
+
+#define        EL_TORITO_BOOTABLE      0x88
+#define        EL_TORITO_NOT_BOOTABLE  0
+
+#define        EL_TORITO_MEDIA_NOEMUL  0
+#define        EL_TORITO_MEDIA_12FLOP  1
+#define        EL_TORITO_MEDIA_144FLOP 2
+#define        EL_TORITO_MEDIA_288FLOP 3
+#define        EL_TORITO_MEDIA_HD      4
+
+struct iso_primary_descriptor {
+       char type                       [ISODCL(1,    1)]; /* 711 */
+       char id                         [ISODCL(2,    6)];
+       char version                    [ISODCL(7,    7)]; /* 711 */
+       char unused1                    [ISODCL(8,    8)];
+       char system_id                  [ISODCL(9,   40)]; /* achars */
+       char volume_id                  [ISODCL(41,  72)]; /* dchars */
+       char unused2                    [ISODCL(73,  80)];
+       char volume_space_size          [ISODCL(81,  88)]; /* 733 */
+       char escape_sequences           [ISODCL(89, 120)];
+       char volume_set_size            [ISODCL(121, 124)]; /* 723 */
+       char volume_sequence_number     [ISODCL(125, 128)]; /* 723 */
+       char logical_block_size         [ISODCL(129, 132)]; /* 723 */
+       char path_table_size            [ISODCL(133, 140)]; /* 733 */
+       char type_l_path_table          [ISODCL(141, 144)]; /* 731 */
+       char opt_type_l_path_table      [ISODCL(145, 148)]; /* 731 */
+       char type_m_path_table          [ISODCL(149, 152)]; /* 732 */
+       char opt_type_m_path_table      [ISODCL(153, 156)]; /* 732 */
+       char root_directory_record      [ISODCL(157, 190)]; /* 9.1 */
+       char volume_set_id              [ISODCL(191, 318)]; /* dchars */
+       char publisher_id               [ISODCL(319, 446)]; /* achars */
+       char preparer_id                [ISODCL(447, 574)]; /* achars */
+       char application_id             [ISODCL(575, 702)]; /* achars */
+       char copyright_file_id          [ISODCL(703, 739)]; /* 7.5 dchars */
+       char abstract_file_id           [ISODCL(740, 776)]; /* 7.5 dchars */
+       char bibliographic_file_id      [ISODCL(777, 813)]; /* 7.5 dchars */
+       char creation_date              [ISODCL(814, 830)]; /* 8.4.26.1 */
+       char modification_date          [ISODCL(831, 847)]; /* 8.4.26.1 */
+       char expiration_date            [ISODCL(848, 864)]; /* 8.4.26.1 */
+       char effective_date             [ISODCL(865, 881)]; /* 8.4.26.1 */
+       char file_structure_version     [ISODCL(882, 882)]; /* 711 */
+       char unused4                    [ISODCL(883, 883)];
+       char application_data           [ISODCL(884, 1395)];
+       char unused5                    [ISODCL(1396, 2048)];
+};
+
+/*
+ * Supplementary or enhanced volume descriptor
+ */
+struct iso_enhanced_descriptor {
+       char type                       [ISODCL(1,    1)]; /* 711 */
+       char id                         [ISODCL(2,    6)];
+       char version                    [ISODCL(7,    7)]; /* 711 */
+       char flags                      [ISODCL(8,    8)];
+       char system_id                  [ISODCL(9,   40)]; /* achars */
+       char volume_id                  [ISODCL(41,  72)]; /* dchars */
+       char unused2                    [ISODCL(73,  80)];
+       char volume_space_size          [ISODCL(81,  88)]; /* 733 */
+       char escape_sequences           [ISODCL(89, 120)];
+       char volume_set_size            [ISODCL(121, 124)]; /* 723 */
+       char volume_sequence_number     [ISODCL(125, 128)]; /* 723 */
+       char logical_block_size         [ISODCL(129, 132)]; /* 723 */
+       char path_table_size            [ISODCL(133, 140)]; /* 733 */
+       char type_l_path_table          [ISODCL(141, 144)]; /* 731 */
+       char opt_type_l_path_table      [ISODCL(145, 148)]; /* 731 */
+       char type_m_path_table          [ISODCL(149, 152)]; /* 732 */
+       char opt_type_m_path_table      [ISODCL(153, 156)]; /* 732 */
+       char root_directory_record      [ISODCL(157, 190)]; /* 9.1 */
+       char volume_set_id              [ISODCL(191, 318)]; /* dchars */
+       char publisher_id               [ISODCL(319, 446)]; /* achars */
+       char preparer_id                [ISODCL(447, 574)]; /* achars */
+       char application_id             [ISODCL(575, 702)]; /* achars */
+       char copyright_file_id          [ISODCL(703, 739)]; /* 7.5 dchars */
+       char abstract_file_id           [ISODCL(740, 776)]; /* 7.5 dchars */
+       char bibliographic_file_id      [ISODCL(777, 813)]; /* 7.5 dchars */
+       char creation_date              [ISODCL(814, 830)]; /* 8.4.26.1 */
+       char modification_date          [ISODCL(831, 847)]; /* 8.4.26.1 */
+       char expiration_date            [ISODCL(848, 864)]; /* 8.4.26.1 */
+       char effective_date             [ISODCL(865, 881)]; /* 8.4.26.1 */
+       char file_structure_version     [ISODCL(882, 882)]; /* 711 */
+       char unused4                    [ISODCL(883, 883)];
+       char application_data           [ISODCL(884, 1395)];
+       char unused5                    [ISODCL(1396, 2048)];
+};
+
+/* El Torito Boot Record Volume Descriptor */
+struct eltorito_boot_descriptor {
+       char type                       [ISODCL(1,    1)]; /* 711 */
+       char id                         [ISODCL(2,    6)];
+       char version                    [ISODCL(7,    7)]; /* 711 */
+       char system_id                  [ISODCL(8,   39)];
+       char unused2                    [ISODCL(40,  71)];
+       char bootcat_ptr                [ISODCL(72,  75)];
+       char unused5                    [ISODCL(76, 2048)];
+};
+
+/* Validation entry for El Torito */
+struct eltorito_validation_entry {
+       char headerid                   [ISODCL(1,    1)]; /* 711 */
+       char arch                       [ISODCL(2,    2)];
+       char pad1                       [ISODCL(3,    4)]; /* 711 */
+       char id                         [ISODCL(5,   28)]; /* CD devel/man*/
+       char cksum                      [ISODCL(29,  30)];
+       char key1                       [ISODCL(31,  31)];
+       char key2                       [ISODCL(32,  32)];
+};
+
+/* El Torito initial/default entry in boot catalog */
+struct eltorito_defaultboot_entry {
+       char boot_id                    [ISODCL(1,    1)]; /* 711 */
+       char boot_media                 [ISODCL(2,    2)];
+       char loadseg                    [ISODCL(3,    4)]; /* 711 */
+       char sys_type                   [ISODCL(5,    5)];
+       char pad1                       [ISODCL(6,    6)];
+       char nsect                      [ISODCL(7,    8)];
+       char bootoff                    [ISODCL(9,   12)];
+       char pad2                       [ISODCL(13,  32)];
+};
+
+/*
+ * XXX JS: The next two structures have odd lengths!
+ * Some compilers (e.g. on Sun3/mc68020) padd the structures to even length.
+ * For this reason, we cannot use sizeof (struct iso_path_table) or
+ * sizeof (struct iso_directory_record) to compute on disk sizes.
+ * Instead, we use offsetof(..., name) and add the name size.
+ * See genisoimage.h
+ */
+
+/* We use this to help us look up the parent inode numbers. */
+
+struct iso_path_table {
+       unsigned char  name_len[2];     /* 721 */
+       char extent[4];                 /* 731 */
+       char  parent[2];                /* 721 */
+       char name[1];
+};
+
+/*
+ * A ISO filename is: "abcde.eee;1" -> <filename> '.' <ext> ';' <version #>
+ *
+ * The maximum needed string length is:
+ *     30 chars (filename + ext)
+ * +    2 chars ('.' + ';')
+ * +      strlen("32767")
+ * +      null byte
+ * ================================
+ * =   38 chars
+ *
+ * We currently do not support CD-ROM-XA entension records, but we must honor
+ * the needed space for ISO-9660:1999 (Version 2).
+ *
+ * XXX If we ever will start to support XA records, we will need to take care
+ * XXX that the the maximum ISO-9660 name length will be reduced by another
+ * XXX 14 bytes resulting in a new total of 179 Bytes.
+ */
+#define        LEN_ISONAME             31
+#define        MAX_ISONAME_V1          37
+#define        MAX_ISONAME_V2          207             /* 254 - 33 - 14 (XA Record) */
+#define        MAX_ISONAME_V2_RR       193             /* 254 - 33 - 28 (CE Record) */
+#define        MAX_ISONAME_V2_RR_XA    179             /* 254 - 33 - 14 - 28       */
+#define        MAX_ISONAME             MAX_ISONAME_V2  /* Used for array space defs */
+#define        MAX_ISODIR              254             /* Must be even and <= 255   */
+
+struct iso_directory_record {
+       unsigned char length            [ISODCL(1,  1)];  /* 711 */
+       char ext_attr_length            [ISODCL(2,  2)];  /* 711 */
+       char extent                     [ISODCL(3,  10)]; /* 733 */
+       char size                       [ISODCL(11, 18)]; /* 733 */
+       char date                       [ISODCL(19, 25)]; /* 7 by 711 */
+       char flags                      [ISODCL(26, 26)];
+       char file_unit_size             [ISODCL(27, 27)]; /* 711 */
+       char interleave                 [ISODCL(28, 28)]; /* 711 */
+       char volume_sequence_number     [ISODCL(29, 32)]; /* 723 */
+       unsigned char name_len          [ISODCL(33, 33)]; /* 711 */
+       char name                       [MAX_ISONAME+1]; /* Not really, but we need something here */
+};
+
+
+/*
+ * Iso directory flags.
+ */
+#define        ISO_FILE        0       /* Not really a flag...                 */
+#define        ISO_EXISTENCE   1       /* Do not make existence known (hidden) */
+#define        ISO_DIRECTORY   2       /* This file is a directory             */
+#define        ISO_ASSOCIATED  4       /* This file is an assiciated file      */
+#define        ISO_RECORD      8       /* Record format in extended attr. != 0 */
+#define        ISO_PROTECTION  16      /* No read/execute perm. in ext. attr.  */
+#define        ISO_DRESERVED1  32      /* Reserved bit 5                       */
+#define        ISO_DRESERVED2  64      /* Reserved bit 6                       */
+#define        ISO_MULTIEXTENT 128     /* Not final entry of a mult. ext. file */
+
+
+struct iso_ext_attr_record {
+       char owner                      [ISODCL(1, 4)];     /* 723 */
+       char group                      [ISODCL(5, 8)];     /* 723 */
+       char permissions                [ISODCL(9, 10)];    /* 16 bits */
+       char creation_date              [ISODCL(11, 27)];   /* 8.4.26.1 */
+       char modification_date          [ISODCL(28, 44)];   /* 8.4.26.1 */
+       char expiration_date            [ISODCL(45, 61)];   /* 8.4.26.1 */
+       char effective_date             [ISODCL(62, 78)];   /* 8.4.26.1 */
+       char record_format              [ISODCL(79, 79)];   /* 711 */
+       char record_attributes          [ISODCL(80, 80)];   /* 711 */
+       char record_length              [ISODCL(81, 84)];   /* 723 */
+       char system_id                  [ISODCL(85, 116)];  /* achars */
+       char system_use                 [ISODCL(117, 180)];
+       char ext_attr_version           [ISODCL(181, 181)]; /* 711 */
+       char esc_seq_len                [ISODCL(182, 182)]; /* 711 */
+       char reserved                   [ISODCL(183, 246)]; /* for future use */
+       char appl_use_len               [ISODCL(247, 250)]; /* 723 */
+       char appl_use[1];               /* really more */
+/*     char esc_seq[];                 escape sequences recorded after appl_use */
+};
+
+/*
+ * Iso extended attribute permissions.
+ */
+#define        ISO_GS_READ             0x0001  /* System Group Read */
+#define        ISO_BIT_1               0x0002
+#define        ISO_GS_EXEC             0x0004  /* System Group Execute */
+#define        ISO_BIT_3               0x0008
+
+#define        ISO_O_READ              0x0010  /* Owner Read */
+#define        ISO_BIT_5               0x0020
+#define        ISO_O_EXEC              0x0040  /* Owner Exexute */
+#define        ISO_BIT_7               0x0080
+
+#define        ISO_G_READ              0x0100  /* Group Read */
+#define        ISO_BIT_9               0x0200
+#define        ISO_G_EXEC              0x0400  /* Group Execute */
+#define        ISO_BIT_11              0x0800
+
+#define        ISO_W_READ              0x1000  /* World (other) Read */
+#define        ISO_BIT_13              0x2000
+#define        ISO_W_EXEC              0x4000  /* World (other) Execute */
+#define        ISO_BIT_15              0x8000
+
+#define        ISO_MB_ONE              (ISO_BIT_1|ISO_BIT_3|ISO_BIT_5|ISO_BIT_7| \
+                               ISO_BIT_9|ISO_BIT_11|ISO_BIT_13|ISO_BIT_15)
+
+/*
+ * Extended Attributes record according to Yellow Book.
+ */
+struct iso_xa_dir_record {
+       char group_id                   [ISODCL(1, 2)];
+       char user_id                    [ISODCL(3, 4)];
+       char attributes                 [ISODCL(5, 6)];
+       char signature                  [ISODCL(7, 8)];
+       char file_number                [ISODCL(9, 9)];
+       char reserved                   [ISODCL(10, 14)];
+};
+
+/*
+ * Definitions for XA attributes
+ */
+#define        XA_O_READ       0x0001  /* Owner Read                           */
+#define        XA_O_RES        0x0002  /* Owner Reserved (write ?)             */
+#define        XA_O_EXEC       0x0004  /* Owner Execute                        */
+#define        XA_O_RES2       0x0008  /* Owner Reserved                       */
+#define        XA_G_READ       0x0010  /* Group Read                           */
+#define        XA_G_RES        0x0020  /* Group Reserved (write ?)             */
+#define        XA_G_EXEC       0x0040  /* Group Execute                        */
+#define        XA_G_RES2       0x0080  /* Group Reserved                       */
+#define        XA_W_READ       0x0100  /* World Read                           */
+#define        XA_W_RES        0x0200  /* World Reserved (write ?)             */
+#define        XA_W_EXEC       0x0400  /* World Execute                        */
+
+#define        XA_FORM1        0x0800  /* File contains Form 1 sector          */
+#define        XA_FORM2        0x1000  /* File contains Form 2 sector          */
+#define        XA_INTERLEAVED  0x2000  /* File contains interleaved sectors    */
+#define        XA_CDDA         0x4000  /* File contains audio data             */
+#define        XA_DIR          0x8000  /* This is a directory                  */
+
+/*
+ * Definitions for CD-ROM XA-Mode-2-form-1/2 sector sub-headers
+ */
+struct xa_subhdr {
+       Uchar   file_number;            /* Identifies file for block    */
+       Uchar   channel_number;         /* Playback channel selection   */
+       Uchar   sub_mode;               /* See bit definitions below    */
+       Uchar   coding;                 /* Coding information           */
+};
+
+/*
+ * Sub mode bit definitions
+ */
+#define        XA_SUBH_EOR             0x01    /* End-Of-Record                */
+#define        XA_SUBH_VIDEO           0x02    /* Video Block                  */
+#define        XA_SUBH_AUDIO           0x04    /* Audio Block (not CD-DA)      */
+#define        XA_SUBH_DATA            0x08    /* Data Block                   */
+#define        XA_SUBH_TRIGGER         0x10    /* Trigger Block                */
+#define        XA_SUBH_FORM2           0x20    /* 0 == Form1, 1 == Form2       */
+#define        XA_SUBH_REALTIME        0x40    /* Real Time Block              */
+#define        XA_SUBH_EOF             0x80    /* End-Of-File                  */
+
+#endif /* _ISOFS_FS_H */
diff --git a/genisoimage/joliet.c b/genisoimage/joliet.c
new file mode 100644 (file)
index 0000000..b36f8f7
--- /dev/null
@@ -0,0 +1,1456 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)joliet.c        1.38 05/05/01 joerg */
+/*
+ * File joliet.c - handle Win95/WinNT long file/unicode extensions for iso9660.
+ *
+ * Copyright 1997 Eric Youngdale.
+ * APPLE_HYB James Pearson j.pearson@ge.ucl.ac.uk 22/2/2000
+ * Copyright (c) 1999,2000,2001 J. Schilling
+ *
+ * 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.
+ */
+
+/*
+ * Joliet extensions for ISO9660.  These are spottily documented by
+ * Microsoft.  In their infinite stupidity, they completely ignored
+ * the possibility of using an SUSP record with the long filename
+ * in it, and instead wrote out a duplicate directory tree with the
+ * long filenames in it.
+ *
+ * I am not sure why they did this.  One reason is that they get the path
+ * tables with the long filenames in them.
+ *
+ * There are two basic principles to Joliet, and the non-Unicode variant
+ * known as Romeo.  Long filenames seem to be the main one, and the second
+ * is that the character set and a few other things is substantially relaxed.
+ *
+ * The SVD is identical to the PVD, except:
+ *
+ *     Id is 2, not 1 (indicates SVD).
+ *     escape_sequences contains UCS-2 indicator (levels 1, 2 or 3).
+ *     The root directory record points to a different extent (with different
+ *             size).
+ *     There are different path tables for the two sets of directory trees.
+ *
+ * The Unicode level is coded in the SVD as follows:
+ *
+ *     Standard        Level   ASCII escape code
+ *     UCS-2           Level-1 %/@
+ *     UCS-2           Level-2 %/C
+ *     UCS-2           Level-3 %/E
+ *
+ * The following fields are recorded in Unicode:
+ *     system_id
+ *     volume_id
+ *     volume_set_id
+ *     publisher_id
+ *     preparer_id
+ *     application_id
+ *     copyright_file_id
+ *     abstract_file_id
+ *     bibliographic_file_id
+ *
+ * Unicode strings are always encoded in big-endian format.
+ *
+ * In a directory record, everything is the same as with iso9660, except
+ * that the name is recorded in unicode.  The name length is specified in
+ * total bytes, not in number of unicode characters.
+ *
+ * The character set used for the names is different with UCS - the
+ * restrictions are that the following are not allowed:
+ *
+ *     Characters (00)(00) through (00)(1f) (control chars)
+ *     (00)(2a) '*'
+ *     (00)(2f) '/'
+ *     (00)(3a) ':'
+ *     (00)(3b) ';'
+ *     (00)(3f) '?'
+ *     (00)(5c) '\'
+ */
+#include <mconfig.h>
+#include "genisoimage.h"
+#include <timedefs.h>
+#include <utypes.h>
+#include <intcvt.h>
+#include <unls.h>      /* For UNICODE translation */
+#include <schily.h>
+#include <string.h>
+
+#ifdef USE_ICONV
+#include <iconv.h>
+#include <errno.h>
+#endif
+
+static Uint    jpath_table_index;
+static struct directory **jpathlist;
+static int     next_jpath_index = 1;
+static int     jsort_goof;
+
+static char    ucs_codes[] = {
+               '\0',           /* UCS-level 0 is illegal       */
+               '@',            /* UCS-level 1                  */
+               'C',            /* UCS-level 2                  */
+               'E',            /* UCS-level 3                  */
+};
+
+#ifdef UDF
+#ifdef USE_ICONV
+size_t
+#else
+void
+#endif
+convert_to_unicode(unsigned char *buffer, int size, char *source, 
+                                                struct unls_table *inls);
+int    joliet_strlen(const char *string, struct unls_table *inls);
+#else
+#ifdef USE_ICONV
+static size_t
+#else
+static void
+#endif
+convert_to_unicode(unsigned char *buffer, int size, char *source, 
+                                                struct unls_table *inls);
+static int     joliet_strlen(const char *string, struct nls_table *inls);
+#endif
+static void    get_joliet_vol_desc(struct iso_primary_descriptor *jvol_desc);
+static void    assign_joliet_directory_addresses(struct directory *node);
+static void    build_jpathlist(struct directory *node);
+static int     joliet_compare_paths(void const *r, void const *l);
+static int     generate_joliet_path_tables(void);
+static void    generate_one_joliet_directory(struct directory *dpnt, 
+                                                                                                               FILE *outfile);
+static int     joliet_sort_n_finish(struct directory *this_dir);
+static int     joliet_compare_dirs(const void *rr, const void *ll);
+static int     joliet_sort_directory(struct directory_entry **sort_dir);
+int    joliet_sort_tree(struct directory *node);
+static void    generate_joliet_directories(struct directory *node, FILE *outfile);
+static int     jpathtab_write(FILE *outfile);
+static int     jdirtree_size(int starting_extent);
+static int     jroot_gen(void);
+static int     jdirtree_write(FILE *outfile);
+static int     jvd_write(FILE *outfile);
+static int     jpathtab_size(int starting_extent);
+
+/*
+ *     conv_charset: convert to/from charsets via Unicode.
+ *
+ *     Any unknown character is set to '_'
+ *
+ */
+unsigned char
+conv_charset(unsigned char c,
+       struct unls_table *inls,
+       struct unls_table *onls)
+{
+       unsigned char   uh;
+       unsigned char   ul;
+       unsigned char   uc;
+       unsigned char   *up;
+
+       /* if we have a null mapping, just return the input character */
+       if (inls == onls)
+               return (c);
+
+#ifdef USE_ICONV
+       if(inls->unls_cs2uni == NULL || onls->unls_uni2cs == NULL) {
+               /*
+                * This shouldn't be reached
+                */
+               static BOOL iconv_warned = FALSE;
+               if(!iconv_warned) {
+                       fprintf(stderr, "Warning: Iconv conversion not supported in conv_charset.\n");
+                       iconv_warned = TRUE;
+               }
+               return (c);
+       }
+#endif
+
+       /* get high and low UNICODE bytes */
+       uh = inls->unls_cs2uni[c].unls_high;
+       ul = inls->unls_cs2uni[c].unls_low;
+
+       /* get the backconverted page from the output charset */
+       up = onls->unls_uni2cs[uh];
+
+       /* if the page exists, get the backconverted character */
+       if (up == NULL)
+               uc = '\0';
+       else
+               uc = up[ul];
+
+       /* return the backconverted, if it's not NULL */
+       return (uc ? uc : '_');
+}
+
+/*
+ * Function:           convert_to_unicode
+ *
+ * Purpose:            Perform a unicode conversion on a text string
+ *                     using the supplied input character set.
+ *
+ * Notes:
+ */
+#ifdef USE_ICONV
+#      if      UDF
+size_t
+#      else
+static size_t
+#      endif
+#else
+#      if      UDF
+void
+#      else
+static void
+#      endif
+#endif
+convert_to_unicode(unsigned char *buffer, int size, char *source, 
+                                                struct unls_table *inls)
+{
+       unsigned char   *tmpbuf;
+       int             i;
+       int             j;
+       unsigned char   uh,
+                       ul,
+                       uc,
+                       *up;
+
+       /*
+        * If we get a NULL pointer for the source, it means we have an
+        * inplace copy, and we need to make a temporary working copy first.
+        */
+       if (source == NULL) {
+               tmpbuf = (Uchar *) e_malloc(size+1);
+               memcpy(tmpbuf, buffer, size);
+               tmpbuf[size] = 0;
+       } else {
+               tmpbuf = (Uchar *) source;
+       }
+
+#ifdef USE_ICONV
+       if (inls->iconv_d && inls->unls_cs2uni==NULL &&
+                       inls->unls_uni2cs==NULL) {
+               char *inptr = (char *)tmpbuf;
+               char *outptr = (char *)buffer;
+               size_t inleft = strlen((char *)tmpbuf);
+               size_t inlen = inleft;
+               size_t outleft = size;
+
+               iconv(inls->iconv_d, NULL, NULL, NULL, NULL);
+               if(iconv(inls->iconv_d, &inptr, &inleft, &outptr, &outleft) ==
+                               (size_t)-1 && errno == EILSEQ) {
+                       fprintf(stderr, "Incorrectly encoded string (%s) "
+                               "encountered.\nPossibly creating an invalid "
+                               "Joliet extension. Aborting.\n", source);
+                       exit(1);
+               }
+
+               for (i = 0; (i + 1) < size - outleft; i += 2) { /* Size may be odd!!!*/
+                       if (buffer[i]=='\0') {
+                               switch (buffer[i+1]) {   /* Invalid characters for Joliet */
+                                       case '*':
+                                       case '/':
+                                       case ':':
+                                       case ';':
+                                       case '?':
+                                       case '\\':
+                                               buffer[i+1]='_';
+                                       default:
+                                               if (buffer[i+1] == 0x7f ||
+                                                           buffer[i+1] < 0x20)
+                                                       buffer[i+1]='_';
+                               }
+                       }
+               }
+               if (size & 1) { /* beautification */
+                       buffer[size - 1] = 0;
+               }
+               if (source == NULL) {
+                       free(tmpbuf);
+               }
+               return (inlen - inleft);
+       }
+#endif
+
+       /*
+        * Now start copying characters.  If the size was specified to be 0,
+        * then assume the input was 0 terminated.
+        */
+       j = 0;
+       for (i = 0; (i + 1) < size; i += 2, j++) {      /* Size may be odd! */
+               /*
+                * JS integrated from: Achim_Kaiser@t-online.de
+                * SGE modified according to Linux kernel source
+                * Let all valid unicode characters pass
+                * through (according to charset). Others are set to '_' .
+                */
+               uc = tmpbuf[j];                 /* temporary copy */
+               if (uc != '\0') {               /* must be converted */
+                       uh = inls->unls_cs2uni[uc].unls_high;   /* convert forward:  */
+                                                               /*   hibyte...  */
+                       ul = inls->unls_cs2uni[uc].unls_low;    /* ...lobyte    */
+                       up = inls->unls_uni2cs[uh];             /* convert backward: */
+                                                               /*   page...    */
+                       if (up == NULL)
+                               uc = '\0';      /* wrong unicode page      */
+                       else
+                               uc = up[ul];    /* backconverted character */
+                       if (uc != tmpbuf[j])
+                               uc = '\0';      /* should be identical */
+                       if (uc <= 0x1f || uc == 0x7f)
+                               uc = '\0';      /* control char */
+                       switch (uc) {           /* test special characters */
+
+                       case '*':
+                       case '/':
+                       case ':':
+                       case ';':
+                       case '?':
+                       case '\\':
+                       case '\0':              /* illegal char mark */
+                               /*
+                                * Even Joliet has some standards as to what is
+                                * allowed in a pathname. Pretty tame in
+                                * comparison to what DOS restricts you to.
+                                */
+                               uc = '_';
+                       }
+               }
+               buffer[i] = inls->unls_cs2uni[uc].unls_high; /* final UNICODE */
+                                                           /* conversion */
+               buffer[i + 1] = inls->unls_cs2uni[uc].unls_low;
+       }
+
+       if (size & 1) { /* beautification */
+               buffer[size - 1] = 0;
+       }
+       if (source == NULL) {
+               free(tmpbuf);
+       }
+#ifdef USE_ICONV
+       return j;
+#endif
+}
+
+/*
+ * Function:   joliet_strlen
+ *
+ * Purpose:    Return length in bytes of string after conversion to unicode.
+ *
+ * Notes:      This is provided mainly as a convenience so that when more
+ *             intelligent Unicode conversion for either Multibyte or 8-bit
+ *             codes is available that we can easily adapt.
+ */
+#ifdef UDF
+int
+#else
+static int
+#endif
+joliet_strlen(const char *string, struct unls_table *inls)
+{
+       int             rtn;
+
+#ifdef USE_ICONV
+       if (inls->iconv_d && inls->unls_cs2uni==NULL &&
+                       inls->unls_uni2cs==NULL) {
+               /*
+                * we const-cast since we're sure iconv won't change
+                * the string itself
+                */
+               char *string_ptr = (char *)string;
+               size_t string_len = strlen(string);
+
+               /*
+                * iconv has no way of finding out the required size
+                * in the target
+                */
+
+               char *tmp, *tmp_ptr;
+               /* we assume that the maximum length is 2 * jlen */
+               size_t tmp_len = (size_t)jlen * 2 + 1;
+               tmp = e_malloc(tmp_len);
+               tmp_ptr = tmp;
+
+               iconv(inls->iconv_d, NULL, NULL, NULL, NULL);
+               iconv(inls->iconv_d, &string_ptr, &string_len, &tmp_ptr,
+                       &tmp_len);
+
+               /*
+                * iconv advanced the tmp pointer with as many chars
+                * as it has written to it, so we add up the delta
+                */
+               rtn = (tmp_ptr - tmp);
+
+               free(tmp);
+       } else {
+               rtn = strlen(string) << 1;
+       }
+#else
+       rtn = strlen(string) << 1;
+#endif
+
+       /*
+        * We do clamp the maximum length of a Joliet string to be the
+        * maximum path size.  This helps to ensure that we don't completely
+        * bolix things up with very long paths.    The Joliet specs say that
+        * the maximum length is 128 bytes, or 64 unicode characters.
+        */
+       if (rtn > 2*jlen) {
+               rtn = 2*jlen;
+       }
+       return (rtn);
+}
+
+/*
+ * Function:           get_joliet_vol_desc
+ *
+ * Purpose:            generate a Joliet compatible volume desc.
+ *
+ * Notes:              Assume that we have the non-joliet vol desc
+ *                     already present in the buffer.  Just modifiy the
+ *                     appropriate fields.
+ */
+static void
+get_joliet_vol_desc(struct iso_primary_descriptor *jvol_desc)
+{
+       jvol_desc->type[0] = ISO_VD_SUPPLEMENTARY;
+       jvol_desc->version[0] = 1;
+       jvol_desc->file_structure_version[0] = 1;
+
+       /*
+        * For now, always do Unicode level 3.
+        * I don't really know what 1 and 2 are - perhaps a more limited
+        * Unicode set.
+        * FIXME(eric) - how does Romeo fit in here?
+        */
+       sprintf(jvol_desc->escape_sequences, "%%/%c", ucs_codes[ucs_level]);
+
+       /* Until we have Unicode path tables, leave these unset. */
+       set_733((char *) jvol_desc->path_table_size, jpath_table_size);
+       set_731(jvol_desc->type_l_path_table, jpath_table[0]);
+       set_731(jvol_desc->opt_type_l_path_table, jpath_table[1]);
+       set_732(jvol_desc->type_m_path_table, jpath_table[2]);
+       set_732(jvol_desc->opt_type_m_path_table, jpath_table[3]);
+
+       /* Set this one up. */
+       memcpy(jvol_desc->root_directory_record, &jroot_record,
+               offsetof(struct iso_directory_record, name[0]) + 1);
+
+       /*
+        * Finally, we have a bunch of strings to convert to Unicode.
+        * FIXME(eric) - I don't know how to do this in general,
+        * so we will just be really lazy and do a char -> short conversion.
+        *  We probably will want to filter any characters >= 0x80.
+        */
+       convert_to_unicode((Uchar *) jvol_desc->system_id,
+                       sizeof (jvol_desc->system_id), NULL, in_nls);
+       convert_to_unicode((Uchar *) jvol_desc->volume_id,
+                       sizeof (jvol_desc->volume_id), NULL, in_nls);
+       convert_to_unicode((Uchar *) jvol_desc->volume_set_id,
+                       sizeof (jvol_desc->volume_set_id), NULL, in_nls);
+       convert_to_unicode((Uchar *) jvol_desc->publisher_id,
+                       sizeof (jvol_desc->publisher_id), NULL, in_nls);
+       convert_to_unicode((Uchar *) jvol_desc->preparer_id,
+                       sizeof (jvol_desc->preparer_id), NULL, in_nls);
+       convert_to_unicode((Uchar *) jvol_desc->application_id,
+                       sizeof (jvol_desc->application_id), NULL, in_nls);
+       convert_to_unicode((Uchar *) jvol_desc->copyright_file_id,
+                       sizeof (jvol_desc->copyright_file_id), NULL, in_nls);
+       convert_to_unicode((Uchar *) jvol_desc->abstract_file_id,
+                       sizeof (jvol_desc->abstract_file_id), NULL, in_nls);
+       convert_to_unicode((Uchar *) jvol_desc->bibliographic_file_id,
+                       sizeof (jvol_desc->bibliographic_file_id), NULL, in_nls);
+}
+
+static void
+assign_joliet_directory_addresses(struct directory *node)
+{
+       int             dir_size;
+       struct directory *dpnt;
+
+       dpnt = node;
+
+       while (dpnt) {
+               if ((dpnt->dir_flags & INHIBIT_JOLIET_ENTRY) == 0) {
+                       /*
+                        * If we already have an extent for this
+                        * (i.e. it came from a multisession disc), then
+                        * don't reassign a new extent.
+                        */
+                       dpnt->jpath_index = next_jpath_index++;
+                       if (dpnt->jextent == 0) {
+                               dpnt->jextent = last_extent;
+                               dir_size = ISO_BLOCKS(dpnt->jsize);
+                               last_extent += dir_size;
+                       }
+               }
+               /* skip if hidden - but not for the rr_moved dir */
+               if (dpnt->subdir && (!(dpnt->dir_flags & INHIBIT_JOLIET_ENTRY) || dpnt == reloc_dir)) {
+                       assign_joliet_directory_addresses(dpnt->subdir);
+               }
+               dpnt = dpnt->next;
+       }
+}
+
+static void
+build_jpathlist(struct directory *node)
+{
+       struct directory        *dpnt;
+
+       dpnt = node;
+
+       while (dpnt) {
+               if ((dpnt->dir_flags & INHIBIT_JOLIET_ENTRY) == 0) {
+                       jpathlist[dpnt->jpath_index] = dpnt;
+               }
+               if (dpnt->subdir)
+                       build_jpathlist(dpnt->subdir);
+               dpnt = dpnt->next;
+       }
+}/* build_jpathlist(... */
+
+static int
+joliet_compare_paths(void const *r, void const *l)
+{
+       struct directory const *ll = *(struct directory * const *) l;
+       struct directory const *rr = *(struct directory * const *) r;
+       int             rparent,
+                       lparent;
+       char            *rpnt,
+                       *lpnt;
+       unsigned char   rtmp[2],
+                       ltmp[2];
+       struct unls_table *rinls, *linls;
+
+       /* make sure root directory is first */
+       if (rr == root)
+               return (-1);
+
+       if (ll == root)
+               return (1);
+
+       rparent = rr->parent->jpath_index;
+       lparent = ll->parent->jpath_index;
+       if (rr->parent == reloc_dir) {
+               rparent = rr->self->parent_rec->filedir->jpath_index;
+       }
+       if (ll->parent == reloc_dir) {
+               lparent = ll->self->parent_rec->filedir->jpath_index;
+       }
+       if (rparent < lparent) {
+               return (-1);
+       }
+       if (rparent > lparent) {
+               return (1);
+       }
+#ifdef APPLE_HYB
+       /*
+        * we may be using the HFS name - so select the correct input
+        * charset
+        */
+       if (USE_MAC_NAME(rr->self)) {
+               rpnt = rr->self->hfs_ent->name;
+               rinls = hfs_inls;
+       } else {
+               rpnt = rr->self->name;
+               rinls = in_nls;
+       }
+
+       if (USE_MAC_NAME(ll->self)) {
+               lpnt = ll->self->hfs_ent->name;
+               linls = hfs_inls;
+       } else {
+               lpnt = ll->self->name;
+               linls = in_nls;
+       }
+#else
+       rpnt = rr->self->name;
+       lpnt = ll->self->name;
+       linls = rinls = in_nls;
+#endif /* APPLE_HYB */
+
+       /* compare the Unicode names */
+
+       while (*rpnt && *lpnt) {
+#ifdef USE_ICONV
+               size_t ri, li;
+
+               ri = convert_to_unicode(rtmp, 2, rpnt, rinls);
+               li = convert_to_unicode(ltmp, 2, lpnt, linls);
+               rpnt += ri;
+               lpnt += li;
+               if(!ri && !li)
+                       return (0);
+               else if(ri && !li)
+                       return (1);
+               else if(!ri && li)
+                       return (-1);
+#else
+               convert_to_unicode(rtmp, 2, rpnt, rinls);
+               convert_to_unicode(ltmp, 2, lpnt, linls);
+#endif
+
+               if (a_to_u_2_byte(rtmp) < a_to_u_2_byte(ltmp))
+                       return (-1);
+               if (a_to_u_2_byte(rtmp) > a_to_u_2_byte(ltmp))
+                       return (1);
+
+#ifndef USE_ICONV
+               rpnt++;
+               lpnt++;
+#endif
+       }
+
+       if (*rpnt)
+               return (1);
+       if (*lpnt)
+               return (-1);
+
+       return (0);
+
+}/* compare_paths(... */
+
+static int
+generate_joliet_path_tables()
+{
+       struct directory_entry *de;
+       struct directory *dpnt;
+       int             fix;
+       int             j;
+       int             namelen;
+       char            *npnt;
+       char            *npnt1;
+       int             tablesize;
+
+       /* First allocate memory for the tables and initialize the memory */
+       tablesize = jpath_blocks << 11;
+       jpath_table_m = (char *) e_malloc(tablesize);
+       jpath_table_l = (char *) e_malloc(tablesize);
+       memset(jpath_table_l, 0, tablesize);
+       memset(jpath_table_m, 0, tablesize);
+
+       /* Now start filling in the path tables.  Start with root directory */
+       jpath_table_index = 0;
+       jpathlist = (struct directory **) e_malloc(sizeof (struct directory *)
+               * next_jpath_index);
+       memset(jpathlist, 0, sizeof (struct directory *) * next_jpath_index);
+       build_jpathlist(root);
+
+       do {
+               fix = 0;
+#ifdef PROTOTYPES
+               qsort(&jpathlist[1], next_jpath_index - 1, sizeof (struct directory *),
+                       (int (*) (const void *, const void *)) joliet_compare_paths);
+#else
+               qsort(&jpathlist[1], next_jpath_index - 1, sizeof (struct directory *),
+                       joliet_compare_paths);
+#endif
+
+               for (j = 1; j < next_jpath_index; j++) {
+                       if (jpathlist[j]->jpath_index != j) {
+                               jpathlist[j]->jpath_index = j;
+                               fix++;
+                       }
+               }
+       } while (fix);
+
+       for (j = 1; j < next_jpath_index; j++) {
+               dpnt = jpathlist[j];
+               if (!dpnt) {
+#ifdef USE_LIBSCHILY
+                       comerrno(EX_BAD, "Entry %d not in path tables\n", j);
+#else
+                       fprintf(stderr, "Entry %d not in path tables\n", j);
+                       exit(1);
+#endif
+               }
+               npnt = dpnt->de_name;
+
+               npnt1 = strrchr(npnt, PATH_SEPARATOR);
+               if (npnt1) {
+                       npnt = npnt1 + 1;
+               }
+               de = dpnt->self;
+               if (!de) {
+#ifdef USE_LIBSCHILY
+                       comerrno(EX_BAD,
+                       "Fatal Joliet goof - directory has amnesia\n");
+#else
+                       fprintf(stderr,
+                       "Fatal Joliet goof - directory has amnesia\n");
+                       exit(1);
+#endif
+               }
+#ifdef APPLE_HYB
+               if (USE_MAC_NAME(de))
+                       namelen = joliet_strlen(de->hfs_ent->name, hfs_inls);
+               else
+#endif /* APPLE_HYB */
+                       namelen = joliet_strlen(de->name, in_nls);
+
+               if (dpnt == root) {
+                       jpath_table_l[jpath_table_index] = 1;
+                       jpath_table_m[jpath_table_index] = 1;
+               } else {
+                       jpath_table_l[jpath_table_index] = namelen;
+                       jpath_table_m[jpath_table_index] = namelen;
+               }
+               jpath_table_index += 2;
+
+               set_731(jpath_table_l + jpath_table_index, dpnt->jextent);
+               set_732(jpath_table_m + jpath_table_index, dpnt->jextent);
+               jpath_table_index += 4;
+
+               if (dpnt->parent->jpath_index > 0xffff) {
+#ifdef USE_LIBSCHILY
+                       comerrno(EX_BAD,
+                       "Unable to generate sane path tables - too many directories (%d)\n",
+                               dpnt->parent->jpath_index);
+#else
+                       fprintf(stderr,
+                       "Unable to generate sane path tables - too many directories (%d)\n",
+                               dpnt->parent->jpath_index);
+                       exit(1);
+#endif
+               }
+
+               if (dpnt->parent != reloc_dir) {
+                       set_721(jpath_table_l + jpath_table_index,
+                               dpnt->parent->jpath_index);
+                       set_722(jpath_table_m + jpath_table_index,
+                               dpnt->parent->jpath_index);
+               } else {
+                       set_721(jpath_table_l + jpath_table_index,
+                               dpnt->self->parent_rec->filedir->jpath_index);
+                       set_722(jpath_table_m + jpath_table_index,
+                               dpnt->self->parent_rec->filedir->jpath_index);
+               }
+
+               jpath_table_index += 2;
+
+               /*
+                * The root directory is still represented in non-unicode
+                * fashion.
+                */
+               if (dpnt == root) {
+                       jpath_table_l[jpath_table_index] = 0;
+                       jpath_table_m[jpath_table_index] = 0;
+                       jpath_table_index++;
+               } else {
+#ifdef APPLE_HYB
+                       if (USE_MAC_NAME(de)) {
+                               convert_to_unicode((Uchar *) jpath_table_l +
+                                       jpath_table_index,
+                                       namelen, de->hfs_ent->name, hfs_inls);
+                               convert_to_unicode((Uchar *) jpath_table_m +
+                                       jpath_table_index,
+                                       namelen, de->hfs_ent->name, hfs_inls);
+                       } else {
+#endif /* APPLE_HYB */
+                               convert_to_unicode((Uchar *) jpath_table_l +
+                                       jpath_table_index,
+                                       namelen, de->name, in_nls);
+                               convert_to_unicode((Uchar *) jpath_table_m +
+                                       jpath_table_index,
+                                       namelen, de->name, in_nls);
+#ifdef APPLE_HYB
+                       }
+#endif /* APPLE_HYB */
+
+                       jpath_table_index += namelen;
+               }
+
+               if (jpath_table_index & 1) {
+                       jpath_table_index++;    /* For odd lengths we pad */
+               }
+       }
+
+       free(jpathlist);
+       if (jpath_table_index != jpath_table_size) {
+#ifdef USE_LIBSCHILY
+               errmsgno(EX_BAD,
+               "Joliet path table lengths do not match %d expected: %d\n",
+                       jpath_table_index,
+                       jpath_table_size);
+#else
+               fprintf(stderr,
+               "Joliet path table lengths do not match %d expected: %d\n",
+                       jpath_table_index,
+                       jpath_table_size);
+#endif
+       }
+       return (0);
+}/* generate_path_tables(... */
+
+static void
+generate_one_joliet_directory(struct directory *dpnt, FILE *outfile)
+{
+       unsigned int            dir_index;
+       char                    *directory_buffer;
+       int                     new_reclen;
+       struct directory_entry *s_entry;
+       struct directory_entry *s_entry1;
+       struct iso_directory_record jrec;
+       unsigned int    total_size;
+       int                     cvt_len;
+       struct directory        *finddir;
+
+       total_size = ISO_ROUND_UP(dpnt->jsize);
+       directory_buffer = (char *) e_malloc(total_size);
+       memset(directory_buffer, 0, total_size);
+       dir_index = 0;
+
+       s_entry = dpnt->jcontents;
+       while (s_entry) {
+               if (s_entry->de_flags & INHIBIT_JOLIET_ENTRY) {
+                       s_entry = s_entry->jnext;
+                       continue;
+               }
+               /*
+                * If this entry was a directory that was relocated,
+                * we have a bit of trouble here.  We need to dig out the real
+                * thing and put it back here.  In the Joliet tree, there is
+                * no relocated rock ridge, as there are no depth limits to a
+                * directory tree.
+                */
+               if ((s_entry->de_flags & RELOCATED_DIRECTORY) != 0) {
+                       for (s_entry1 = reloc_dir->contents; s_entry1;
+                                               s_entry1 = s_entry1->next) {
+                               if (s_entry1->parent_rec == s_entry) {
+                                       break;
+                               }
+                       }
+                       if (s_entry1 == NULL) {
+                               /* We got trouble. */
+#ifdef USE_LIBSCHILY
+                               comerrno(EX_BAD,
+                               "Unable to locate relocated directory\n");
+#else
+                               fprintf(stderr,
+                               "Unable to locate relocated directory\n");
+                               exit(1);
+#endif
+                       }
+               } else {
+                       s_entry1 = 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_entry1->jreclen;
+               if ((dir_index & (SECTOR_SIZE - 1)) + new_reclen >= SECTOR_SIZE) {
+                       dir_index = ISO_ROUND_UP(dir_index);
+               }
+               memcpy(&jrec, &s_entry1->isorec, offsetof(struct iso_directory_record, name[0]));
+
+#ifdef APPLE_HYB
+               /* Use the HFS name if it exists */
+               if (USE_MAC_NAME(s_entry1))
+                       cvt_len = joliet_strlen(s_entry1->hfs_ent->name, hfs_inls);
+               else
+#endif /* APPLE_HYB */
+                       cvt_len = joliet_strlen(s_entry1->name, in_nls);
+
+               /*
+                * Fix the record length
+                * - this was the non-Joliet version we were seeing.
+                */
+               jrec.name_len[0] = cvt_len;
+               jrec.length[0] = s_entry1->jreclen;
+
+               /*
+                * If this is a directory,
+                * fix the correct size and extent number.
+                */
+               if ((jrec.flags[0] & ISO_DIRECTORY) != 0) {
+                       if (strcmp(s_entry1->name, ".") == 0) {
+                               jrec.name_len[0] = 1;
+                               set_733((char *) jrec.extent, dpnt->jextent);
+                               set_733((char *) jrec.size, ISO_ROUND_UP(dpnt->jsize));
+                       } else if (strcmp(s_entry1->name, "..") == 0) {
+                               jrec.name_len[0] = 1;
+                               if (dpnt->parent == reloc_dir) {
+                                       set_733((char *)jrec.extent, dpnt->self->parent_rec->filedir->jextent);
+                                       set_733((char *)jrec.size, ISO_ROUND_UP(dpnt->self->parent_rec->filedir->jsize));
+                               } else {
+                                       set_733((char *)jrec.extent, dpnt->parent->jextent);
+                                       set_733((char *)jrec.size, ISO_ROUND_UP(dpnt->parent->jsize));
+                               }
+                       } else {
+                               if ((s_entry->de_flags & RELOCATED_DIRECTORY) != 0) {
+                                       finddir = reloc_dir->subdir;
+                               } else {
+                                       finddir = dpnt->subdir;
+                               }
+                               while (1 == 1) {
+                                       if (finddir->self == s_entry1)
+                                               break;
+                                       finddir = finddir->next;
+                                       if (!finddir) {
+#ifdef USE_LIBSCHILY
+                                               comerrno(EX_BAD, "Fatal goof - unable to find directory location\n");
+#else
+                                               fprintf(stderr, "Fatal goof - unable to find directory location\n");
+                                               exit(1);
+#endif
+                                       }
+                               }
+                               set_733((char *)jrec.extent, finddir->jextent);
+                               set_733((char *)jrec.size,
+                                               ISO_ROUND_UP(finddir->jsize));
+                       }
+               }
+               memcpy(directory_buffer + dir_index, &jrec,
+                       offsetof(struct iso_directory_record, name[0]));
+
+               dir_index += offsetof(struct iso_directory_record, name[0]);
+
+               /*
+                * Finally dump the Unicode version of the filename.
+                * Note - . and .. are the same as with non-Joliet discs.
+                */
+               if ((jrec.flags[0] & ISO_DIRECTORY) != 0 &&
+                       strcmp(s_entry1->name, ".") == 0) {
+                       directory_buffer[dir_index++] = 0;
+               } else if ((jrec.flags[0] & ISO_DIRECTORY) != 0 &&
+                       strcmp(s_entry1->name, "..") == 0) {
+                       directory_buffer[dir_index++] = 1;
+               } else {
+#ifdef APPLE_HYB
+                       if (USE_MAC_NAME(s_entry1)) {
+                               /* Use the HFS name if it exists */
+                               convert_to_unicode(
+                                       (Uchar *) directory_buffer+dir_index,
+                                       cvt_len,
+                                       s_entry1->hfs_ent->name, hfs_inls);
+                       } else
+#endif /* APPLE_HYB */
+                       {
+                               convert_to_unicode(
+                                       (Uchar *) directory_buffer+dir_index,
+                                       cvt_len,
+                                       s_entry1->name, in_nls);
+                       }
+                       dir_index += cvt_len;
+               }
+
+               if (dir_index & 1) {
+                       directory_buffer[dir_index++] = 0;
+               }
+               s_entry = s_entry->jnext;
+       }
+
+       if (dpnt->jsize != dir_index) {
+#ifdef USE_LIBSCHILY
+               errmsgno(EX_BAD,
+               "Unexpected joliet directory length %d expected: %d '%s'\n",
+                       dpnt->jsize,
+                       dir_index, dpnt->de_name);
+#else
+               fprintf(stderr,
+               "Unexpected joliet directory length %d expected: %d '%s'\n",
+                       dpnt->jsize,
+                       dir_index, dpnt->de_name);
+#endif
+       }
+       jtwrite(directory_buffer, total_size, 1, 0, FALSE);
+       xfwrite(directory_buffer, total_size, 1, outfile, 0, FALSE);
+       last_extent_written += total_size >> 11;
+       free(directory_buffer);
+}/* generate_one_joliet_directory(... */
+
+static int
+joliet_sort_n_finish(struct directory *this_dir)
+{
+       struct directory_entry  *s_entry;
+       int                     status = 0;
+
+       /*
+        * don't want to skip this directory if it's the reloc_dir
+        * at the moment
+        */
+       if (this_dir != reloc_dir &&
+                               this_dir->dir_flags & INHIBIT_JOLIET_ENTRY) {
+               return (0);
+       }
+       for (s_entry = this_dir->contents; s_entry; s_entry = s_entry->next) {
+               /* skip hidden entries */
+               if ((s_entry->de_flags & INHIBIT_JOLIET_ENTRY) != 0) {
+                       continue;
+               }
+               /*
+                * First update the path table sizes for directories.
+                *
+                * Finally, set the length of the directory entry if Joliet is
+                * used. The name is longer, but no Rock Ridge is ever used
+                * here, so depending upon the options the entry size might
+                * turn out to be about the same.  The Unicode name is always
+                * a multiple of 2 bytes, so we always add 1 to make it an
+                * even number.
+                */
+               if (s_entry->isorec.flags[0] & ISO_DIRECTORY) {
+                       if (strcmp(s_entry->name, ".") != 0 &&
+                                       strcmp(s_entry->name, "..") != 0) {
+#ifdef APPLE_HYB
+                               if (USE_MAC_NAME(s_entry))
+                                       /* Use the HFS name if it exists */
+                                       jpath_table_size +=
+                                               joliet_strlen(s_entry->hfs_ent->name, hfs_inls) +
+                                               offsetof(struct iso_path_table, name[0]);
+                               else
+#endif /* APPLE_HYB */
+                                       jpath_table_size +=
+                                               joliet_strlen(s_entry->name, in_nls) +
+                                               offsetof(struct iso_path_table, name[0]);
+                               if (jpath_table_size & 1) {
+                                       jpath_table_size++;
+                               }
+                       } else {
+                               if (this_dir == root &&
+                                               strlen(s_entry->name) == 1) {
+
+                                       jpath_table_size += 1 + offsetof(struct iso_path_table, name[0]);
+                                       if (jpath_table_size & 1)
+                                               jpath_table_size++;
+                               }
+                       }
+               }
+               if (strcmp(s_entry->name, ".") != 0 &&
+                                       strcmp(s_entry->name, "..") != 0) {
+#ifdef APPLE_HYB
+                       if (USE_MAC_NAME(s_entry))
+                               /* Use the HFS name if it exists */
+                               s_entry->jreclen =
+                               offsetof(struct iso_directory_record, name[0])
+                                       + joliet_strlen(s_entry->hfs_ent->name, hfs_inls)
+                                       + 1;
+                       else
+#endif /* APPLE_HYB */
+                               s_entry->jreclen =
+                               offsetof(struct iso_directory_record, name[0])
+                                       + joliet_strlen(s_entry->name, in_nls)
+                                       + 1;
+               } else {
+                       /*
+                        * Special - for '.' and '..' we generate the same
+                        * records we did for non-Joliet discs.
+                        */
+                       s_entry->jreclen =
+                       offsetof(struct iso_directory_record, name[0])
+                               + 1;
+               }
+
+
+       }
+
+       if ((this_dir->dir_flags & INHIBIT_JOLIET_ENTRY) != 0) {
+               return (0);
+       }
+       this_dir->jcontents = this_dir->contents;
+       status = joliet_sort_directory(&this_dir->jcontents);
+
+       /*
+        * Now go through the directory and figure out how large this one will
+        * be. Do not split a directory entry across a sector boundary
+        */
+       s_entry = this_dir->jcontents;
+       /*
+        * XXX Is it ok to comment this out?
+        */
+/*XXX JS  this_dir->ce_bytes = 0;*/
+       for (s_entry = this_dir->jcontents; s_entry;
+                                               s_entry = s_entry->jnext) {
+               int     jreclen;
+
+               if ((s_entry->de_flags & INHIBIT_JOLIET_ENTRY) != 0) {
+                       continue;
+               }
+               jreclen = s_entry->jreclen;
+
+               if ((this_dir->jsize & (SECTOR_SIZE - 1)) + jreclen >=
+                                                               SECTOR_SIZE) {
+                       this_dir->jsize = ISO_ROUND_UP(this_dir->jsize);
+               }
+               this_dir->jsize += jreclen;
+       }
+       return (status);
+}
+
+/*
+ * Similar to the iso9660 case,
+ * except here we perform a full sort based upon the
+ * regular name of the file, not the 8.3 version.
+ */
+static int
+joliet_compare_dirs(const void *rr, const void *ll)
+{
+       char            *rpnt,
+                       *lpnt;
+       struct directory_entry **r,
+                       **l;
+       unsigned char   rtmp[2],
+                       ltmp[2];
+       struct unls_table *linls, *rinls;
+
+       r = (struct directory_entry **) rr;
+       l = (struct directory_entry **) ll;
+
+#ifdef APPLE_HYB
+       /*
+        * we may be using the HFS name - so select the correct input
+        * charset
+        */
+       if (USE_MAC_NAME(*r)) {
+               rpnt = (*r)->hfs_ent->name;
+               rinls = hfs_inls;
+       } else {
+               rpnt = (*r)->name;
+               rinls = in_nls;
+       }
+
+       if (USE_MAC_NAME(*l)) {
+               lpnt = (*l)->hfs_ent->name;
+               linls = hfs_inls;
+       } else {
+               lpnt = (*l)->name;
+               linls = in_nls;
+       }
+#else
+       rpnt = (*r)->name;
+       lpnt = (*l)->name;
+       rinls = linls = in_nls;
+#endif /* APPLE_HYB */
+
+       /*
+        * If the entries are the same, this is an error.
+        * Joliet specs allow for a maximum of 64 characters.
+        */
+       if (strncmp(rpnt, lpnt, jlen) == 0) {
+#ifdef USE_LIBSCHILY
+               errmsgno(EX_BAD,
+                       "Error: %s and %s have the same Joliet name\n",
+                       (*r)->whole_name, (*l)->whole_name);
+#else
+               fprintf(stderr,
+                       "Error: %s and %s have the same Joliet name\n",
+                       (*r)->whole_name, (*l)->whole_name);
+#endif
+               jsort_goof++;
+       }
+       /*
+        * Put the '.' and '..' entries on the head of the sorted list.
+        * For normal ASCII, this always happens to be the case, but out of
+        * band characters cause this not to be the case sometimes.
+        */
+       if (strcmp(rpnt, ".") == 0)
+               return (-1);
+       if (strcmp(lpnt, ".") == 0)
+               return (1);
+
+       if (strcmp(rpnt, "..") == 0)
+               return (-1);
+       if (strcmp(lpnt, "..") == 0)
+               return (1);
+
+#ifdef DVD_VIDEO
+       /*
+        * There're rumors claiming that some players assume VIDEO_TS.IFO
+        * to be the first file in VIDEO_TS/ catalog. Well, it's basically
+        * the only file a player has to actually look for, as the whole
+        * video content can be "rolled down" from this file alone.
+        *                              <appro@fy.chalmers.se>
+        */
+       /*
+        * XXX This code has to be moved from the Joliet implementation
+        * XXX to the UDF implementation if we implement decent UDF support
+        * XXX with a separate name space for the UDF file tree.
+        */
+       if (dvd_video) {
+               if (strcmp(rpnt, "VIDEO_TS.IFO") == 0)
+                       return (-1);
+               if (strcmp(lpnt, "VIDEO_TS.IFO") == 0)
+                       return (1);
+       }
+#endif
+
+       while (*rpnt && *lpnt) {
+#ifdef USE_ICONV
+               size_t ri, li;
+#endif
+               if (*rpnt == ';' && *lpnt != ';')
+                       return (-1);
+               if (*rpnt != ';' && *lpnt == ';')
+                       return (1);
+
+               if (*rpnt == ';' && *lpnt == ';')
+                       return (0);
+
+               /*
+                * Extensions are not special here.
+                * Don't treat the dot as something that must be bumped to
+                * the start of the list.
+                */
+#if 0
+               if (*rpnt == '.' && *lpnt != '.')
+                       return (-1);
+               if (*rpnt != '.' && *lpnt == '.')
+                       return (1);
+#endif
+
+#ifdef USE_ICONV
+
+               ri = convert_to_unicode(rtmp, 2, rpnt, rinls);
+               li = convert_to_unicode(ltmp, 2, lpnt, linls);
+               rpnt += ri;
+               lpnt += li;
+               if(!ri && !li)
+                       return (0);
+               else if(ri && !li)
+                       return (1);
+               else if(!ri && li)
+                       return (-1);
+#else
+               convert_to_unicode(rtmp, 2, rpnt, rinls);
+               convert_to_unicode(ltmp, 2, lpnt, linls);
+#endif
+
+               if (a_to_u_2_byte(rtmp) < a_to_u_2_byte(ltmp))
+                       return (-1);
+               if (a_to_u_2_byte(rtmp) > a_to_u_2_byte(ltmp))
+                       return (1);
+
+#ifndef USE_ICONV
+               rpnt++;
+               lpnt++;
+#endif
+       }
+       if (*rpnt)
+               return (1);
+       if (*lpnt)
+               return (-1);
+       return (0);
+}
+
+
+/*
+ * Function:           sort_directory
+ *
+ * Purpose:            Sort the directory in the appropriate ISO9660
+ *                     order.
+ *
+ * Notes:              Returns 0 if OK, returns > 0 if an error occurred.
+ */
+static int
+joliet_sort_directory(struct directory_entry **sort_dir)
+{
+       int                     dcount = 0;
+       int                     i;
+       struct directory_entry  *s_entry;
+       struct directory_entry  **sortlist;
+
+       s_entry = *sort_dir;
+       while (s_entry) {
+               /* skip hidden entries */
+               if (!(s_entry->de_flags & INHIBIT_JOLIET_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) {
+       /* skip hidden entries */
+               if (!(s_entry->de_flags & INHIBIT_JOLIET_ENTRY)) {
+                       sortlist[dcount] = s_entry;
+                       dcount++;
+               }
+               s_entry = s_entry->next;
+       }
+
+       jsort_goof = 0;
+#ifdef PROTOTYPES
+       qsort(sortlist, dcount, sizeof (struct directory_entry *),
+               (int (*) (const void *, const void *)) joliet_compare_dirs);
+#else
+       qsort(sortlist, dcount, sizeof (struct directory_entry *),
+               joliet_compare_dirs);
+#endif
+
+       /* Now reassemble the linked list in the proper sorted order */
+       for (i = 0; i < dcount - 1; i++) {
+               sortlist[i]->jnext = sortlist[i + 1];
+       }
+
+       sortlist[dcount - 1]->jnext = NULL;
+       *sort_dir = sortlist[0];
+
+       free(sortlist);
+       return (jsort_goof);
+}
+
+int
+joliet_sort_tree(struct directory *node)
+{
+       struct directory        *dpnt;
+       int                     ret = 0;
+
+       dpnt = node;
+
+       while (dpnt) {
+               ret = joliet_sort_n_finish(dpnt);
+               if (ret) {
+                       break;
+               }
+               if (dpnt->subdir)
+                       ret = joliet_sort_tree(dpnt->subdir);
+               if (ret) {
+                       break;
+               }
+               dpnt = dpnt->next;
+       }
+       return (ret);
+}
+
+static void
+generate_joliet_directories(struct directory *node, FILE *outfile)
+{
+       struct directory *dpnt;
+
+       dpnt = node;
+
+       while (dpnt) {
+               if ((dpnt->dir_flags & INHIBIT_JOLIET_ENTRY) == 0) {
+                       /*
+                        * In theory we should never reuse a directory, so this
+                        * doesn't make much sense.
+                        */
+                       if (dpnt->jextent > session_start) {
+                               generate_one_joliet_directory(dpnt, outfile);
+                       }
+               }
+               /* skip if hidden - but not for the rr_moved dir */
+               if (dpnt->subdir &&
+                   (!(dpnt->dir_flags & INHIBIT_JOLIET_ENTRY) ||
+                   dpnt == reloc_dir)) {
+                       generate_joliet_directories(dpnt->subdir, outfile);
+               }
+               dpnt = dpnt->next;
+       }
+}
+
+
+/*
+ * Function to write the EVD for the disc.
+ */
+static int
+jpathtab_write(FILE *outfile)
+{
+       /* Next we write the path tables */
+       jtwrite(jpath_table_l, jpath_blocks << 11, 1, 0, FALSE);
+       xfwrite(jpath_table_l, jpath_blocks << 11, 1, outfile, 0, FALSE);
+       last_extent_written += jpath_blocks;
+       jtwrite(jpath_table_m, jpath_blocks << 11, 1, 0, FALSE);
+       xfwrite(jpath_table_m, jpath_blocks << 11, 1, outfile, 0, FALSE);
+       last_extent_written += jpath_blocks;
+       free(jpath_table_l);
+       free(jpath_table_m);
+       jpath_table_l = NULL;
+       jpath_table_m = NULL;
+       return (0);
+}
+
+static int
+jdirtree_size(int starting_extent)
+{
+       assign_joliet_directory_addresses(root);
+       return (0);
+}
+
+static int
+jroot_gen()
+{
+       jroot_record.length[0] =
+                       1 + offsetof(struct iso_directory_record, name[0]);
+       jroot_record.ext_attr_length[0] = 0;
+       set_733((char *) jroot_record.extent, root->jextent);
+       set_733((char *) jroot_record.size, ISO_ROUND_UP(root->jsize));
+       iso9660_date(jroot_record.date, root_statbuf.st_mtime);
+       jroot_record.flags[0] = ISO_DIRECTORY;
+       jroot_record.file_unit_size[0] = 0;
+       jroot_record.interleave[0] = 0;
+       set_723(jroot_record.volume_sequence_number, volume_sequence_number);
+       jroot_record.name_len[0] = 1;
+       return (0);
+}
+
+static int
+jdirtree_write(FILE *outfile)
+{
+       generate_joliet_directories(root, outfile);
+       return (0);
+}
+
+/*
+ * Function to write the EVD for the disc.
+ */
+static int
+jvd_write(FILE *outfile)
+{
+       struct iso_primary_descriptor jvol_desc;
+
+       /* Next we write out the boot volume descriptor for the disc */
+       jvol_desc = vol_desc;
+       get_joliet_vol_desc(&jvol_desc);
+       jtwrite(&jvol_desc, SECTOR_SIZE, 1, 0, FALSE);
+       xfwrite(&jvol_desc, SECTOR_SIZE, 1, outfile, 0, FALSE);
+       last_extent_written++;
+       return (0);
+}
+
+/*
+ * Functions to describe padding block at the start of the disc.
+ */
+static int
+jpathtab_size(int starting_extent)
+{
+       jpath_table[0] = starting_extent;
+       jpath_table[1] = 0;
+       jpath_table[2] = jpath_table[0] + jpath_blocks;
+       jpath_table[3] = 0;
+
+       last_extent += 2 * jpath_blocks;
+       return (0);
+}
+
+struct output_fragment joliet_desc = {NULL, oneblock_size, jroot_gen, jvd_write, "Joliet Volume Descriptor" };
+struct output_fragment jpathtable_desc = {NULL, jpathtab_size, generate_joliet_path_tables, jpathtab_write, "Joliet path table" };
+struct output_fragment jdirtree_desc = {NULL, jdirtree_size, NULL, jdirtree_write, "Joliet directory tree" };
diff --git a/genisoimage/jte.c b/genisoimage/jte.c
new file mode 100644 (file)
index 0000000..0dff289
--- /dev/null
@@ -0,0 +1,1042 @@
+/*
+ * jte.c
+ *
+ * Copyright (c) 2004-2006 Steve McIntyre <steve@einval.com>
+ *
+ * Implementation of the Jigdo Template Engine - make jigdo files
+ * directly when making ISO images
+ *
+ * GNU GPL v2
+ */
+
+#include <mconfig.h>
+#include "genisoimage.h"
+#include <timedefs.h>
+#include <fctldefs.h>
+#include <zlib.h>
+#include <bzlib.h>
+#include <regex.h>
+#ifdef SORTING
+#include "match.h"
+#endif /* SORTING */
+#include <errno.h>
+#include <schily.h>
+#ifdef DVD_VIDEO
+#include "dvd_reader.h"
+#include "dvd_file.h"
+#include "ifo_read.h"
+#include "endianconv.h"
+#include "checksum.h"
+#endif
+#ifdef APPLE_HYB
+#include <ctype.h>
+#endif
+
+#ifdef VMS
+#include "vms.h"
+#endif
+
+/* Different types used in building our state list below */
+#define JTET_FILE_MATCH 1
+#define JTET_NOMATCH    2
+
+#define JTE_VER_MAJOR     0x0001
+#define JTE_VER_MINOR     0x0013
+#define JTE_NAME          "JTE"
+#define JTE_COMMENT       "JTE at http://www.einval.com/~steve/software/JTE/ ; jigdo at http://atterer.org/jigdo/"
+
+#define JIGDO_TEMPLATE_VERSION "1.1"
+
+/*     
+       Simple list to hold the results of -jigdo-exclude and
+       -jigdo-force-match command line options. Seems easiest to do this
+       using regexps.
+*/
+struct path_match
+{
+    regex_t  match_pattern;
+    char    *match_rule;
+    struct path_match *next;
+};
+
+/* List of mappings e.g. Debian=/mirror/debian */
+struct path_mapping
+{
+    char                *from;
+    char                *to;
+    struct path_mapping *next;
+};
+
+FILE   *jtjigdo = NULL;       /* File handle used throughout for the jigdo file */
+FILE   *jttemplate = NULL;    /* File handle used throughout for the template file */
+char    *jjigdo_out = NULL;    /* Output name for jigdo .jigdo file; NULL means don't do it */
+char    *jtemplate_out = NULL; /* Output name for jigdo template file; NULL means don't do it */
+char    *jmd5_list = NULL;     /* Name of file to use for MD5 checking */
+int      jte_min_size = MIN_JIGDO_FILE_SIZE;
+jtc_t    jte_template_compression = JTE_TEMP_GZIP;
+struct  path_match *exclude_list = NULL;
+struct  path_match *include_list = NULL;
+struct  path_mapping  *map_list = NULL;
+unsigned long long template_size = 0;
+unsigned long long image_size = 0;
+int checksum_algo_iso = (CHECK_MD5_USED | \
+                         CHECK_SHA1_USED | \
+                         CHECK_SHA256_USED | \
+                         CHECK_SHA512_USED);
+int checksum_algo_tmpl = CHECK_MD5_USED;
+
+static checksum_context_t *iso_context = NULL;
+static checksum_context_t *template_context = NULL;
+
+/* List of files that we've seen, ready to write into the template and
+   jigdo files */
+typedef struct _file_entry
+{
+    unsigned char       md5[16];
+    off_t               file_length;
+    unsigned long long  rsyncsum;
+    char               *filename;
+} file_entry_t;
+
+typedef struct _unmatched_entry
+{
+    off_t uncompressed_length;
+} unmatched_entry_t;    
+
+typedef struct _entry
+{
+    int entry_type; /* JTET_TYPE as above */
+    struct _entry *next;
+    union
+    {
+        file_entry_t      file;
+        unmatched_entry_t chunk;
+    } data;
+} entry_t;
+
+typedef struct _jigdo_file_entry
+{
+    unsigned char type;
+    unsigned char fileLen[6];
+    unsigned char fileRsync[8];
+    unsigned char fileMD5[16];
+} jigdo_file_entry_t;
+
+typedef struct _jigdo_chunk_entry
+{
+    unsigned char type;
+    unsigned char skipLen[6];
+} jigdo_chunk_entry_t;
+
+typedef struct _jigdo_image_entry
+{
+    unsigned char type;
+    unsigned char imageLen[6];
+    unsigned char imageMD5[16];
+    unsigned char blockLen[4];
+} jigdo_image_entry_t;
+
+typedef struct _md5_list_entry
+{
+    struct _md5_list_entry *next;
+    unsigned char       MD5[16];
+    unsigned long long  size;
+    char               *filename;
+} md5_list_entry_t;
+    
+entry_t *entry_list = NULL;
+entry_t *entry_last = NULL;
+FILE    *t_file = NULL;
+FILE    *j_file = NULL;
+int      num_matches = 0;
+int      num_chunks = 0;
+md5_list_entry_t *md5_list = NULL;
+md5_list_entry_t *md5_last = NULL;
+
+/* Grab the file component from a full path */
+static char *file_base_name(char *path)
+{
+    char *endptr = path;
+    char *ptr = path;
+    
+    while (*ptr != '\0')
+    {
+        if ('/' == *ptr)
+            endptr = ++ptr;
+        else
+            ++ptr;
+    }
+    return endptr;
+}
+
+/* Build the list of exclusion regexps */
+extern int jte_add_exclude(char *pattern)
+{
+    struct path_match *new = NULL;
+    
+    new = malloc(sizeof *new);
+    if (!new)
+        return ENOMEM;    
+    
+    regcomp(&new->match_pattern, pattern, REG_NEWLINE);
+       new->match_rule = pattern;
+
+    /* Order on the exclude list doesn't matter! */
+       new->next = exclude_list;
+
+    exclude_list = new;
+    return 0;
+}
+
+/* Check if the file should be excluded because of a filename match. 1
+   means exclude, 0 means not */
+static int check_exclude_by_name(char *filename, char **matched)
+{
+    struct path_match *ptr = exclude_list;
+    regmatch_t pmatch[1];
+    int i = 0;
+
+    while (ptr)
+    {
+        if (!regexec(&ptr->match_pattern, filename, 1, pmatch, 0))
+        {
+            *matched = ptr->match_rule;
+            return 1;
+        }
+        ptr = ptr->next;
+    }
+    
+    /* Not matched, so return 0 */
+    return 0;
+}
+
+/* Build the list of required inclusion regexps */
+extern int jte_add_include(char *pattern)
+{
+    struct path_match *new = NULL;
+    
+    new = malloc(sizeof *new);
+    if (!new)
+        return ENOMEM;    
+    
+    regcomp(&new->match_pattern, pattern, REG_NEWLINE);
+       new->match_rule = pattern;
+
+    /* Order on the include list doesn't matter! */
+       new->next = include_list;
+
+    include_list = new;
+    return 0;
+}
+
+/* Check if a file has to be MD5-matched to be valid. If we get called
+   here, we've failed to match any of the MD5 entries we were
+   given. If the path to the filename matches one of the paths in our
+   list, clearly it must have been corrupted. Abort with an error. */
+static void check_md5_file_match(char *filename)
+{
+    struct path_match *ptr = include_list;
+    regmatch_t pmatch[1];
+    int i = 0;
+
+    while (ptr)
+    {
+        if (!regexec(&ptr->match_pattern, filename, 1, pmatch, 0))
+        {
+#ifdef USE_LIBSCHILY
+                       comerr("File %s should have matched an MD5 entry, but didn't! (Rule '%s')\n", filename, ptr->match_rule);
+#else
+                       fprintf(stderr, "File %s should have matched an MD5 entry, but didn't! (Rule '%s')\n", filename, ptr->match_rule);
+                       exit(1);
+#endif
+               }
+        ptr = ptr->next;
+    }
+}    
+
+/* Should we list a file separately in the jigdo output, or should we
+   just dump it into the template file as binary data? Three things
+   cases to look for here:
+
+   1. Small files are better simply folded in, as they take less space that way.
+
+   2. Files in /doc (for example) may change in the archive all the
+      time and it's better to not have to fetch snapshot copies if we
+      can avoid it.      
+
+   3. Files living in specified paths *must* match an entry in the
+      md5-list, or they must have been corrupted. If we find a corrupt
+      file, bail out with an error.
+
+*/
+extern int list_file_in_jigdo(char *filename, off_t size, char **realname, unsigned char md5[16])
+{
+    char *matched_rule;
+    md5_list_entry_t *entry = md5_list;
+    int md5sum_done = 0;
+    
+    if (!jtemplate_out)
+        return 0;
+
+    memset(md5, 0, sizeof(md5));
+
+    /* Cheaper to check file size first */
+    if (size < jte_min_size)
+    {
+        if (verbose > 1)
+            fprintf(stderr, "Jigdo-ignoring file %s; it's too small\n", filename);
+        return 0;
+    }
+    
+    /* Now check the excluded list by name */
+    if (check_exclude_by_name(filename, &matched_rule))
+    {
+        if (verbose > 1)
+            fprintf(stderr, "Jigdo-ignoring file %s; it's covered in the exclude list by \"%s\"\n", filename, matched_rule);
+        return 0;
+    }
+
+    /* Check to see if the file is in our md5 list. Check three things:
+       
+       1. the size
+       2. the filename
+       3. (only if the first 2 match) the md5sum
+
+       If we get a match for all three, include the file and return
+       the full path to the file that we have gleaned from the mirror.
+    */
+
+    while (entry)
+    {
+        if (size == entry->size)
+        {
+            if (!strcmp(file_base_name(filename), file_base_name(entry->filename)))
+            {
+                if (!md5sum_done)
+                {
+                    calculate_md5sum(filename, size, md5);
+                    md5sum_done = 1;
+                }
+                if (!memcmp(md5, entry->MD5, sizeof(entry->MD5)))
+                {
+                    *realname = entry->filename;
+                    return 1;
+                }
+            }
+        }
+        entry = entry->next;
+    }
+
+    /* We haven't found an entry in our MD5 list to match this
+     * file. If we should have done, complain and bail out. */
+    check_md5_file_match(filename);
+    return 0;
+}
+
+/* Add a mapping of pathnames (e.g. Debian=/mirror/debian). We should
+   be passed TO=FROM here */
+extern int jte_add_mapping(char *arg)
+{
+    int error = 0;
+    struct path_mapping *new = NULL;
+    struct path_mapping *entry = NULL;
+    char *p = arg;
+    char *from = NULL;
+    char *to = NULL;
+
+    /* Find the "=" in the string passed. Set it to NULL and we can
+       use the string in-place */
+    while (*p)
+    {
+        if ('=' == *p)
+        {
+            *p = 0;
+            p++;
+            to = arg;
+            from = p;
+        }
+        p++;
+    }
+    if (!from || !strlen(from) || !to || !strlen(to))
+        return EINVAL;
+    
+    new = malloc(sizeof(*new));
+    if (!new)
+        return ENOMEM;
+    
+    new->from = from;
+    new->to = to;
+    new->next = NULL;
+
+    if (verbose > 0)
+        fprintf(stderr, "Adding mapping from %s to %s for the jigdo file\n", from, to);
+    if (!map_list)
+        map_list = new;
+    else
+    {
+        /* Order is important; add to the end of the list */
+        entry = map_list;
+        while (NULL != entry->next)
+            entry = entry->next;
+        entry->next = new;
+    }
+    return 0;
+}
+
+/* Check if the filename should be remapped; if so map it, otherwise
+   return the original name. */
+static char *remap_filename(char *filename)
+{
+    char *new_name = filename;
+    struct path_mapping *entry = map_list;
+    
+    while (entry)
+    {
+        if (!strncmp(filename, entry->from, strlen(entry->from)))
+        {
+            new_name = calloc(1, 2 + strlen(filename) + strlen(entry->to) - strlen(entry->from));
+            if (!new_name)
+            {
+                fprintf(stderr, "Failed to malloc new filename; abort!\n");
+                exit(1);
+            }
+            sprintf(new_name, "%s:%s", entry->to, &filename[strlen(entry->from)]);
+            return new_name;
+        }
+        entry = entry->next;
+    }
+
+    /* No mapping in effect */
+    return strdup(filename);
+}    
+
+/* Write data to the template file and update the MD5 sum */
+static size_t template_fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)
+{
+    checksum_update(template_context, ptr, size * nmemb);
+    template_size += (unsigned long long)size * nmemb;
+    return fwrite(ptr, size, nmemb, stream);
+}
+
+/* Create a new template file and initialise it */
+static void write_template_header()
+{
+    char buf[2048];
+    int i = 0;
+    char *p = buf;
+
+    memset(buf, 0, sizeof(buf));
+
+    template_context = checksum_init_context(checksum_algo_tmpl, "template");
+    if (!template_context)
+    {
+#ifdef USE_LIBSCHILY
+        comerr("cannot allocate template checksum contexts\n");
+#else
+        fprintf(stderr, "cannot allocate template checksum contexts\n");
+        exit(1);
+#endif
+    }
+    
+    i += sprintf(p, "JigsawDownload template %s %s/%d.%d \r\n",
+                 JIGDO_TEMPLATE_VERSION, JTE_NAME, JTE_VER_MAJOR, JTE_VER_MINOR);
+    p = &buf[i];
+
+    i += sprintf(p, "%s \r\n", JTE_COMMENT);
+    p = &buf[i];
+
+    i += sprintf(p, "\r\n");
+    template_fwrite(buf, i, 1, t_file);
+}
+
+/* Read the MD5 list and build a list in memory for us to use later */
+static void add_md5_entry(unsigned char *md5, unsigned long long size, char *filename)
+{
+    int error = 0;
+    md5_list_entry_t *new = NULL;
+    
+    new = calloc(1, sizeof(md5_list_entry_t));
+    memcpy(new->MD5, md5, sizeof(new->MD5));
+    new->size = size;
+    new->filename = strdup(filename);
+    
+    /* Add to the end of the list */
+    if (NULL == md5_last)
+    {
+        md5_last = new;
+        md5_list = new;
+    }
+    else
+    {
+        md5_last->next = new;
+        md5_last = new;
+    }
+}
+
+/* Parse a 12-digit decimal number */
+static unsigned long long parse_number(unsigned char in[12])
+{
+    unsigned long long size = 0;
+    int i = 0;
+    
+    for (i = 0; i < 12; i++)
+    {
+        size *= 10;
+        if (isdigit(in[i]))
+            size += (in[i] - '0');
+    }
+
+    return size;
+}
+    
+/* Read the MD5 list and build a list in memory for us to use later
+   MD5 list format:
+
+   <---MD5--->  <--Size-->  <--Filename-->
+       32          12          remaining
+*/
+static void parse_md5_list(void)
+{
+    FILE *md5_file = NULL;
+    unsigned char buf[1024];
+    unsigned char md5[16];
+    char *filename = NULL;
+    unsigned char *numbuf = NULL;
+    int num_files = 0;
+    unsigned long long size = 0;
+
+    md5_file = fopen(jmd5_list, "rb");
+    if (!md5_file)
+    {
+#ifdef USE_LIBSCHILY
+        comerr("cannot read from MD5 list file '%s'\n", jmd5_list);
+#else
+        fprintf(stderr, "cannot read from MD5 list file '%s'\n", jmd5_list);
+        exit(1);
+#endif
+    }
+
+    memset(buf, 0, sizeof(buf));
+    while (fgets((char *)buf, sizeof(buf), md5_file))
+    {
+        numbuf = &buf[34];
+        filename = (char *)&buf[48];
+        /* Lose the trailing \n from the fgets() call */
+        if (buf[strlen((char *)buf)-1] == '\n')
+         buf[strlen((char *)buf)-1] = 0;
+
+        if (mk_MD5Parse(buf, md5))
+        {
+#ifdef USE_LIBSCHILY
+            comerr("cannot parse MD5 file '%s'\n", jmd5_list);
+#else
+            fprintf(stderr, "cannot parse MD5 file '%s'\n", jmd5_list);
+            exit(1);
+#endif
+        }
+        size = parse_number(numbuf);
+        add_md5_entry(md5, size, filename);
+        memset(buf, 0, sizeof(buf));
+        num_files++;
+    }
+    if (verbose > 0)
+        fprintf(stderr, "parse_md5_list: added MD5 checksums for %d files\n", num_files);
+    fclose(md5_file);
+}
+
+/* Initialise state and start the jigdo template file */
+void write_jt_header(FILE *template_file, FILE *jigdo_file)
+{
+    t_file = template_file;
+    j_file = jigdo_file;
+
+    /* Start checksum work for the image */
+    iso_context = checksum_init_context(checksum_algo_iso, "iso");
+    if (!iso_context)
+    {
+#ifdef USE_LIBSCHILY
+        comerr("cannot allocate iso checksum contexts\n");
+#else
+        fprintf(stderr, "cannot allocate iso checksum contexts\n");
+        exit(1);
+#endif
+    }
+
+    /* Start the template file */
+    write_template_header();
+
+    /* Load up the MD5 list if we've been given one */
+    if (jmd5_list)
+        parse_md5_list();
+}
+
+/* Compress and flush out a buffer full of template data */
+static void flush_gzip_chunk(void *buffer, off_t size)
+{
+    z_stream c_stream; /* compression stream */
+    unsigned char comp_size_out[6];
+    unsigned char uncomp_size_out[6];
+    off_t compressed_size_out = 0;
+    int err = 0;
+    unsigned char *comp_buf = NULL;
+
+    c_stream.zalloc = NULL;
+    c_stream.zfree = NULL;
+    c_stream.opaque = NULL;
+
+    err = deflateInit(&c_stream, Z_BEST_COMPRESSION);
+    comp_buf = malloc(2 * size); /* Worst case */
+    c_stream.next_out = comp_buf;
+    c_stream.avail_out = 2 * size;
+    c_stream.next_in = buffer;
+    c_stream.avail_in = size;
+    
+    err = deflate(&c_stream, Z_NO_FLUSH);
+    err = deflate(&c_stream, Z_FINISH);
+    
+    compressed_size_out = c_stream.total_out + 16;
+    err = deflateEnd(&c_stream);
+
+    template_fwrite("DATA", 4, 1, t_file);
+
+    write_le48(compressed_size_out, &comp_size_out[0]);
+    template_fwrite(comp_size_out, sizeof(comp_size_out), 1, t_file);
+
+    write_le48(size, &uncomp_size_out[0]);
+    template_fwrite(uncomp_size_out, sizeof(uncomp_size_out), 1, t_file);
+    
+    template_fwrite(comp_buf, c_stream.total_out, 1, t_file);
+    free(comp_buf);
+}
+
+/* Compress and flush out a buffer full of template data */
+static void flush_bz2_chunk(void *buffer, off_t size)
+{
+    bz_stream c_stream; /* compression stream */
+    unsigned char comp_size_out[6];
+    unsigned char uncomp_size_out[6];
+    off_t compressed_size_out = 0;
+    int err = 0;
+    unsigned char *comp_buf = NULL;
+
+    c_stream.bzalloc = NULL;
+    c_stream.bzfree = NULL;
+    c_stream.opaque = NULL;
+
+    err = BZ2_bzCompressInit(&c_stream, 9, 0, 0);
+    comp_buf = malloc(2 * size); /* Worst case */
+    c_stream.next_out = comp_buf;
+    c_stream.avail_out = 2 * size;
+    c_stream.next_in = buffer;
+    c_stream.avail_in = size;
+    
+    err = BZ2_bzCompress(&c_stream, BZ_FINISH);
+    
+    compressed_size_out = c_stream.total_out_lo32 + 16;
+    err = BZ2_bzCompressEnd(&c_stream);
+
+    template_fwrite("BZIP", 4, 1, t_file);
+
+    write_le48(compressed_size_out, &comp_size_out[0]);
+    template_fwrite(comp_size_out, sizeof(comp_size_out), 1, t_file);
+
+    write_le48(size, &uncomp_size_out[0]);
+    template_fwrite(uncomp_size_out, sizeof(uncomp_size_out), 1, t_file);
+    
+    template_fwrite(comp_buf, c_stream.total_out_lo32, 1, t_file);
+    free(comp_buf);
+}
+
+static void flush_compressed_chunk(void *buffer, off_t size)
+{
+    if (jte_template_compression == JTE_TEMP_BZIP2)
+        flush_bz2_chunk(buffer, size);
+    else
+        flush_gzip_chunk(buffer, size);
+}
+
+/* Append to an existing data buffer, and compress/flush it if
+   necessary */
+static void write_compressed_chunk(unsigned char *buffer, size_t size)
+{
+    static unsigned char *uncomp_buf = NULL;
+       static size_t uncomp_size = 0;
+    static size_t uncomp_buf_used = 0;
+
+       if (!uncomp_buf)
+       {
+               if (jte_template_compression == JTE_TEMP_BZIP2)
+                       uncomp_size = 900 * 1024;
+               else
+                       uncomp_size = 1024 * 1024;
+               uncomp_buf = malloc(uncomp_size);
+               if (!uncomp_buf)
+               {
+#ifdef USE_LIBSCHILY
+            comerr("failed to allocate %d bytes for template compression buffer\n", uncomp_size);
+#else
+            fprintf(stderr, "failed to allocate %d bytes for template compression buffer\n", uncomp_size);
+            exit(1);
+#endif
+               }
+       }
+
+    if ((uncomp_buf_used + size) > uncomp_size)
+    {
+        flush_compressed_chunk(uncomp_buf, uncomp_buf_used);
+        uncomp_buf_used = 0;
+    }
+
+    if (!size) /* Signal a flush before we start writing the DESC entry */
+    {
+        flush_compressed_chunk(uncomp_buf, uncomp_buf_used);
+        return;
+    }
+    
+    if (!uncomp_buf_used)
+        memset(uncomp_buf, 0, uncomp_size);
+
+    while (size > uncomp_size)
+    {
+        flush_compressed_chunk(buffer, uncomp_size);
+        buffer += uncomp_size;
+        size -= uncomp_size;
+    }
+    memcpy(&uncomp_buf[uncomp_buf_used], buffer, size);
+    uncomp_buf_used += size;
+}
+
+/* Loop through the list of DESC entries that we've built up and
+   append them to the template file */
+static void write_template_desc_entries(off_t image_len)
+{
+    entry_t *entry = entry_list;
+    off_t desc_len = 0;
+    unsigned char out_len[6];
+    jigdo_image_entry_t jimage;
+
+    desc_len = 16 /* DESC + length twice */
+        + (sizeof(jigdo_file_entry_t) * num_matches)
+        + (sizeof(jigdo_chunk_entry_t) * num_chunks)
+        + sizeof(jigdo_image_entry_t);
+
+    write_le48(desc_len, &out_len[0]);
+    write_compressed_chunk(NULL, 0);
+    template_fwrite("DESC", 4, 1, t_file);
+    template_fwrite(out_len, sizeof(out_len), 1, t_file);
+    
+    while (entry)
+    {
+        switch (entry->entry_type)
+        {
+            case JTET_FILE_MATCH:
+            {
+                jigdo_file_entry_t jfile;
+                jfile.type = 6; /* Matched file */
+                write_le48(entry->data.file.file_length, &jfile.fileLen[0]);
+                write_le64(entry->data.file.rsyncsum, &jfile.fileRsync[0]);
+                memcpy(jfile.fileMD5, entry->data.file.md5, sizeof(jfile.fileMD5));
+                template_fwrite(&jfile, sizeof(jfile), 1, t_file);
+                break;
+            }
+            case JTET_NOMATCH:
+            {
+                jigdo_chunk_entry_t jchunk;
+                               jchunk.type = 2; /* Raw data, compressed */
+                write_le48(entry->data.chunk.uncompressed_length, &jchunk.skipLen[0]);
+                template_fwrite(&jchunk, sizeof(jchunk), 1, t_file);
+                break;
+            }
+        }
+        entry = entry->next;
+    }
+
+    jimage.type = 5;
+    write_le48(image_len, &jimage.imageLen[0]);
+    checksum_copy(iso_context, CHECK_MD5, &jimage.imageMD5[0]);
+    write_le32(MIN_JIGDO_FILE_SIZE, &jimage.blockLen[0]);
+    template_fwrite(&jimage, sizeof(jimage), 1, t_file);    
+    template_fwrite(out_len, sizeof(out_len), 1, t_file);
+}
+
+/* Dump a buffer in jigdo-style "base64" */
+static char *base64_dump(unsigned char *buf, size_t buf_size)
+{
+    const char *b64_enc = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
+    int value = 0;
+    unsigned int i;
+    int bits = 0;
+    static char output_buffer[2048];
+    char *p = output_buffer;
+
+    memset(output_buffer, 0, sizeof(output_buffer));
+    if (buf_size >= (sizeof(output_buffer) * 6/8))
+    {
+        fprintf(stderr, "base64_dump: Buffer too small!\n");
+        exit(1);
+    }
+
+    for (i = 0; i < buf_size ; i++)
+    {
+        value = (value << 8) | buf[i];
+        bits += 2;
+        p += sprintf(p, "%c", b64_enc[(value >> bits) & 63U]);
+        if (bits >= 6) {
+            bits -= 6;
+            p += sprintf(p, "%c", b64_enc[(value >> bits) & 63U]);
+        }
+    }
+    if (bits > 0)
+    {
+        value <<= 6 - bits;
+        p += sprintf(p, "%c", b64_enc[value & 63U]);
+    }
+    return output_buffer;
+}
+
+/* Write the .jigdo file to match the .template we've just finished. */
+static void write_jigdo_file(void)
+{
+    unsigned char template_md5sum[16];
+    entry_t *entry = entry_list;
+    struct path_mapping *map = map_list;
+    int i = 0;
+    struct checksum_info *info = NULL;
+
+    checksum_final(template_context);
+    checksum_copy(template_context, CHECK_MD5, &template_md5sum[0]);
+
+    fprintf(j_file, "# JigsawDownload\n");
+    fprintf(j_file, "# See <http://atterer.org/jigdo/> for details about jigdo\n");
+    fprintf(j_file, "# See <http://www.einval.com/~steve/software/CD/JTE/> for details about JTE\n\n");
+    
+    fprintf(j_file, "[Jigdo]\n");
+    fprintf(j_file, "Version=%s\n", JIGDO_TEMPLATE_VERSION);
+    fprintf(j_file, "Generator=%s/%d.%d\n\n", JTE_NAME, JTE_VER_MAJOR, JTE_VER_MINOR);
+
+    fprintf(j_file, "[Image]\n");
+    fprintf(j_file, "Filename=%s\n", file_base_name(outfile));
+    fprintf(j_file, "Template=http://localhost/%s\n", jtemplate_out);
+
+    fprintf(j_file, "Template-MD5Sum=%s \n",
+            base64_dump(&template_md5sum[0], sizeof(template_md5sum)));
+
+    for (i = 0; i < NUM_CHECKSUMS; i++)
+    {
+        if (checksum_algo_tmpl & (1 << i))
+        {
+            info = checksum_information(i);
+            fprintf(j_file, "# Template Hex %sSum %s\n", info->name, checksum_hex(template_context, i));
+        }
+    }
+    fprintf(j_file, "# Template size %lld bytes\n", template_size);
+
+    for (i = 0; i < NUM_CHECKSUMS; i++)
+    {
+        if (checksum_algo_iso & (1 << i))
+        {
+            info = checksum_information(i);
+            fprintf(j_file, "# Image Hex %sSum %s\n", info->name, checksum_hex(iso_context, i));
+        }
+    }
+
+    fprintf(j_file, "# Image size %lld bytes\n\n", image_size);
+
+    fprintf(j_file, "[Parts]\n");
+    while (entry)
+    {
+        if (JTET_FILE_MATCH == entry->entry_type)
+        {
+            char *new_name = remap_filename(entry->data.file.filename);
+            fprintf(j_file, "%s=%s\n",
+                    base64_dump(&entry->data.file.md5[0], sizeof(entry->data.file.md5)),
+                    new_name);
+            free(new_name);
+        }
+        entry = entry->next;
+    }
+
+    fprintf(j_file, "\n[Servers]\n");
+    fflush(j_file);
+}
+
+/* Finish and flush state; for now:
+   
+   1. Dump the DESC blocks and the footer information in the jigdo template file
+   2. Write the jigdo .jigdo file containing file pointers
+*/
+void write_jt_footer(void)
+{
+    /* Finish calculating the image's checksum */
+    checksum_final(iso_context);
+
+    /* And calculate the image size */
+    image_size = (unsigned long long)SECTOR_SIZE * last_extent_written;
+
+    write_template_desc_entries(image_size);
+
+    write_jigdo_file();
+}
+
+/* Add a raw data entry to the list of extents; no file to match */
+static void add_unmatched_entry(int uncompressed_length)
+{
+    entry_t *new_entry = NULL;
+
+    /* Can we extend a previous non-match entry? */
+    if (entry_last && (JTET_NOMATCH == entry_last->entry_type))
+    {
+        entry_last->data.chunk.uncompressed_length += uncompressed_length;
+        return;
+    }
+
+    new_entry = calloc(1, sizeof(entry_t));
+    new_entry->entry_type = JTET_NOMATCH;
+    new_entry->next = NULL;
+    new_entry->data.chunk.uncompressed_length = uncompressed_length;
+
+    /* Add to the end of the list */
+    if (NULL == entry_last)
+    {
+        entry_last = new_entry;
+        entry_list = new_entry;
+    }
+    else
+    {
+        entry_last->next = new_entry;
+        entry_last = new_entry;
+    }
+    num_chunks++;
+}
+
+/* Add a file match entry to the list of extents */
+static void add_file_entry(char *filename, off_t size, unsigned char *md5,
+                           unsigned long long rsyncsum)
+{
+    entry_t *new_entry = NULL;
+
+    new_entry = calloc(1, sizeof(entry_t));
+    new_entry->entry_type = JTET_FILE_MATCH;
+    new_entry->next = NULL;
+    memcpy(new_entry->data.file.md5, md5, sizeof(new_entry->data.file.md5));
+    new_entry->data.file.file_length = size;
+    new_entry->data.file.rsyncsum = rsyncsum;
+    new_entry->data.file.filename = strdup(filename);
+
+    /* Add to the end of the list */
+    if (NULL == entry_last)
+    {
+        entry_last = new_entry;
+        entry_list = new_entry;
+    }
+    else
+    {
+        entry_last->next = new_entry;
+        entry_last = new_entry;
+    }
+    num_matches++;
+}    
+
+/* Cope with an unmatched block in the .iso file:
+
+   1. Write a compressed data chunk in the jigdo template file
+   2. Add an entry in our list of unmatched chunks for later */
+void jtwrite(buffer, size, count, submode, islast)
+       void    *buffer;
+       int     size;
+       int     count;
+       int     submode;
+       BOOL    islast;
+{
+#ifdef JTWRITE_DEBUG
+       if (count != 1 || (size % 2048) != 0)
+               error("Count: %d, size: %d\n", count, size);
+#endif
+
+    if (!jtemplate_out)
+        return;
+
+    /* Update the global image checksum */
+    checksum_update(iso_context, buffer, size * count);
+//    mk_MD5Update(&iso_context, buffer, size*count);
+
+    /* Write a compressed version of the data to the template file,
+       and add a reference on the state list so we can write that
+       later. */
+    write_compressed_chunk(buffer, size*count);
+    add_unmatched_entry(size*count);
+}
+
+/* Cope with a file entry in the .iso file:
+
+   1. Read the file for the image's md5 checksum
+   2. Add an entry in our list of files to be written into the .jigdo later
+*/
+void write_jt_match_record(char *filename, char *mirror_name, int sector_size, off_t size, unsigned char md5[16])
+{
+    unsigned long long  tmp_size = 0;
+    char                buf[32768];
+    off_t               remain = size;
+       FILE               *infile = NULL;
+       int                     use = 0;
+    unsigned long long  rsync64_sum = 0;
+    int first_block = 1;
+
+    memset(buf, 0, sizeof(buf));
+
+    if ((infile = fopen(filename, "rb")) == NULL) {
+#ifdef USE_LIBSCHILY
+               comerr("cannot open '%s'\n", filename);
+#else
+#ifndef        HAVE_STRERROR
+               fprintf(stderr, "cannot open '%s': (%d)\n",
+                               filename, errno);
+#else
+               fprintf(stderr, "cannot open '%s': %s\n",
+                               filename, strerror(errno));
+#endif
+               exit(1);
+#endif
+       }
+
+    while (remain > 0)
+    {
+        use = remain;
+        if (remain > sizeof(buf))
+            use = sizeof(buf);
+               if (fread(buf, 1, use, infile) == 0)
+        {
+#ifdef USE_LIBSCHILY
+                       comerr("cannot read from '%s'\n", filename);
+#else
+                       fprintf(stderr, "cannot read from '%s'\n", filename);
+                       exit(1);
+#endif
+               }
+        if (first_block)
+            rsync64_sum = rsync64(buf, MIN_JIGDO_FILE_SIZE);
+        checksum_update(iso_context, buf, use);
+//        mk_MD5Update(&iso_context, buf, use);
+        remain -= use;
+        first_block = 0;
+    }
+
+    fclose(infile);
+    
+    /* Update the image checksum with any necessary padding data */
+    if (size % sector_size)
+    {
+        int pad_size = sector_size - (size % sector_size);
+        memset(buf, 0, pad_size);
+        checksum_update(iso_context, buf, pad_size);
+//        mk_MD5Update(&iso_context, buf, pad_size);
+    }
+
+    add_file_entry(mirror_name, size, &md5[0], rsync64_sum);
+    if (size % sector_size)
+    {
+        int pad_size = sector_size - (size % sector_size);
+        write_compressed_chunk(buf, pad_size);
+        add_unmatched_entry(pad_size);
+    }        
+}
diff --git a/genisoimage/jte.h b/genisoimage/jte.h
new file mode 100644 (file)
index 0000000..4469452
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * jte.c
+ *
+ * Copyright (c) 2004-2006 Steve McIntyre <steve@einval.com>
+ *
+ * Prototypes and declarations for JTE
+ *
+ * GNU GPL v2
+ */
+
+extern char *jtemplate_out;
+extern char *jjigdo_out;
+extern char *jmd5_list;
+extern FILE    *jthelper;
+extern FILE *jtjigdo;
+extern FILE *jttemplate;
+extern int  jte_min_size;
+extern int  checksum_algo_iso;
+extern int  checksum_algo_tmpl;
+
+extern void write_jt_header(FILE *template_file, FILE *jigdo_file);
+extern void write_jt_footer(void);
+extern void jtwrite(void *buffer, int size, int count, int submode, BOOL islast);
+extern void write_jt_match_record(char *filename, char *mirror_name, int sector_size, off_t size, unsigned char md5[16]);
+extern int  list_file_in_jigdo(char *filename, off_t size, char **realname, unsigned char md5[16]);
+extern int  jte_add_exclude(char *pattern);
+extern int  jte_add_include(char *pattern);
+extern int  jte_add_mapping(char *arg);
+
+typedef enum _jtc_e
+{
+    JTE_TEMP_GZIP = 0,
+    JTE_TEMP_BZIP2
+} jtc_t;
+
+extern jtc_t jte_template_compression;
+
+
+#define MIN_JIGDO_FILE_SIZE 1024
diff --git a/genisoimage/mac_label.c b/genisoimage/mac_label.c
new file mode 100644 (file)
index 0000000..f43aafc
--- /dev/null
@@ -0,0 +1,425 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)mac_label.c     1.9 04/03/05 joerg, Copyright 1997, 1998, 1999, 2000 James Pearson */
+/*
+ *      Copyright (c) 1997, 1998, 1999, 2000 James Pearson
+ *
+ * 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; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ *     mac_label.c: generate Mactintosh partition maps and label
+ *
+ *     Taken from "mkisofs 1.05 PLUS" by Andy Polyakov <appro@fy.chalmers.se>
+ *     (see http://fy.chalmers.se/~appro/mkisofs_plus.html for details)
+ *
+ *     The format of the HFS driver file:
+ *
+ *     HFS CD Label Block                              512 bytes
+ *     Driver Partition Map (for 2048 byte blocks)     512 bytes
+ *     Driver Partition Map (for 512 byte blocks)      512 bytes
+ *     Empty                                           512 bytes
+ *     Driver Partition                                N x 2048 bytes
+ *     HFS Partition Boot Block                        1024 bytes
+ *
+ *     File of the above format can be extracted from a CD using
+ *     apple_driver.c
+ *
+ *     James Pearson 16/5/98
+ */
+
+/* PREP_BOOT Troy Benjegerdes 2/4/99 */
+
+#include <mconfig.h>
+#include "genisoimage.h"
+#include "mac_label.h"
+#include "apple.h"
+
+#ifdef PREP_BOOT
+void   gen_prepboot_label(unsigned char *ml);
+
+#endif /* PREP_BOOT */
+int    gen_mac_label(defer * mac_boot);
+int    autostart(void);
+
+#ifdef PREP_BOOT
+void
+gen_prepboot_label(unsigned char *ml)
+{
+       struct directory_entry *de;
+       int             i = 0;
+       int             block;
+       int             size;
+       MacLabel        *mac_label = (MacLabel *) ml;
+
+       if (verbose > 1) {
+               fprintf(stderr, "Creating %d PReP boot partition(s)\n",
+                                               use_prep_boot + use_chrp_boot);
+       }
+       mac_label->fdiskMagic[0] = fdiskMagic0;
+       mac_label->fdiskMagic[1] = fdiskMagic1;
+
+       if (use_chrp_boot) {
+               fprintf(stderr, "CHRP boot partition 1\n");
+
+               mac_label->image[i].boot = 0x80;
+
+               mac_label->image[i].CHSstart[0] = 0xff;
+               mac_label->image[i].CHSstart[1] = 0xff;
+               mac_label->image[i].CHSstart[2] = 0xff;
+
+               mac_label->image[i].type = chrpPartType;        /* 0x96 */
+
+               mac_label->image[i].CHSend[0] = 0xff;
+               mac_label->image[i].CHSend[1] = 0xff;
+               mac_label->image[i].CHSend[2] = 0xff;
+
+               mac_label->image[i].startSect[0] = 0;
+               mac_label->image[i].startSect[1] = 0;
+               mac_label->image[i].startSect[2] = 0;
+               mac_label->image[i].startSect[3] = 0;
+
+               size = (last_extent - session_start) * 2048 / 512;
+               mac_label->image[i].size[0] = size & 0xff;
+               mac_label->image[i].size[1] = (size >> 8) & 0xff;
+               mac_label->image[i].size[2] = (size >> 16) & 0xff;
+               mac_label->image[i].size[3] = (size >> 24) & 0xff;
+
+               i++;
+       }
+
+       for (; i < use_prep_boot + use_chrp_boot; i++) {
+               de = search_tree_file(root, prep_boot_image[i - use_chrp_boot]);
+               if (!de) {
+                       fprintf(stderr,
+                               "Uh oh, I cant find the boot image \"%s\"!\n",
+                               prep_boot_image[i - use_chrp_boot]);
+                       exit(1);
+               }
+               /* get size and block in 512-byte blocks */
+               block = get_733(de->isorec.extent) * 2048 / 512;
+               size = get_733(de->isorec.size) / 512 + 1;
+               fprintf(stderr, "PReP boot partition %d is \"%s\"\n",
+                       i + 1, prep_boot_image[i - use_chrp_boot]);
+
+               mac_label->image[i].boot = 0x80;
+
+               mac_label->image[i].CHSstart[0] = 0xff;
+               mac_label->image[i].CHSstart[1] = 0xff;
+               mac_label->image[i].CHSstart[2] = 0xff;
+
+               mac_label->image[i].type = prepPartType;        /* 0x41 */
+
+               mac_label->image[i].CHSend[0] = 0xff;
+               mac_label->image[i].CHSend[1] = 0xff;
+               mac_label->image[i].CHSend[2] = 0xff;
+
+               /* deal with  endianess */
+               mac_label->image[i].startSect[0] = block & 0xff;
+               mac_label->image[i].startSect[1] = (block >> 8) & 0xff;
+               mac_label->image[i].startSect[2] = (block >> 16) & 0xff;
+               mac_label->image[i].startSect[3] = (block >> 24) & 0xff;
+
+               mac_label->image[i].size[0] = size & 0xff;
+               mac_label->image[i].size[1] = (size >> 8) & 0xff;
+               mac_label->image[i].size[2] = (size >> 16) & 0xff;
+               mac_label->image[i].size[3] = (size >> 24) & 0xff;
+       }
+       for (; i < 4; i++) {
+               mac_label->image[i].CHSstart[0] = 0xff;
+               mac_label->image[i].CHSstart[1] = 0xff;
+               mac_label->image[i].CHSstart[2] = 0xff;
+
+               mac_label->image[i].CHSend[0] = 0xff;
+               mac_label->image[i].CHSend[1] = 0xff;
+               mac_label->image[i].CHSend[2] = 0xff;
+       }
+}
+
+#endif /* PREP_BOOT */
+
+int
+gen_mac_label(defer *mac_boot)
+{
+       FILE            *fp;
+       MacLabel        *mac_label;
+       MacPart         *mac_part;
+       char            *buffer = (char *) hce->hfs_map;
+       int             block_size;
+       int             have_hfs_boot = 0;
+       char            tmp[SECTOR_SIZE];
+       struct stat     stat_buf;
+       mac_partition_table mpm[2];
+       int             mpc = 0;
+       int             i;
+
+       /* If we have a boot file, then open and check it */
+       if (mac_boot->name) {
+               if (stat(mac_boot->name, &stat_buf) < 0) {
+                       sprintf(hce->error, "unable to stat HFS boot file %s",
+                                                               mac_boot->name);
+                       return (-1);
+               }
+               if ((fp = fopen(mac_boot->name, "rb")) == NULL) {
+                       sprintf(hce->error, "unable to open HFS boot file %s",
+                                                               mac_boot->name);
+                       return (-1);
+               }
+               if (fread(tmp, 1, SECTOR_SIZE, fp) != SECTOR_SIZE) {
+                       sprintf(hce->error, "unable to read HFS boot file %s",
+                                                               mac_boot->name);
+                       return (-1);
+               }
+               /* check we have a bootable partition */
+               mac_part = (MacPart *) (tmp + HFS_BLOCKSZ);
+
+               if (!(IS_MAC_PART(mac_part) &&
+                   strncmp((char *) mac_part->pmPartType, pmPartType_2, 12) == 0)) {
+                       sprintf(hce->error, "%s is not a HFS boot file",
+                                                               mac_boot->name);
+                       return (-1);
+               }
+               /* check we have a boot block as well - last 2 blocks of file */
+
+               if (fseek(fp, (off_t)-2 * HFS_BLOCKSZ, SEEK_END) != 0) {
+                       sprintf(hce->error, "unable to seek HFS boot file %s",
+                                                               mac_boot->name);
+                       return (-1);
+               }
+               /* overwrite (empty) boot block for our HFS volume */
+               if (fread(hce->hfs_hdr, 2, HFS_BLOCKSZ, fp) != HFS_BLOCKSZ) {
+                       sprintf(hce->error, "unable to read HFS boot block %s",
+                                                               mac_boot->name);
+                       return (-1);
+               }
+               fclose(fp);
+
+               /* check boot block is valid */
+               if (d_getw((unsigned char *) hce->hfs_hdr) != HFS_BB_SIGWORD) {
+                       sprintf(hce->error,
+                               "%s does not contain a valid boot block",
+                                                               mac_boot->name);
+                       return (-1);
+               }
+               /*
+                * collect info about boot file for later user
+                * - skip over the bootfile header
+                */
+               mac_boot->size = stat_buf.st_size - SECTOR_SIZE - 2*HFS_BLOCKSZ;
+               mac_boot->off = SECTOR_SIZE;
+               mac_boot->pad = 0;
+
+               /*
+                * get size in SECTOR_SIZE blocks
+                * - shouldn't need to round up
+                */
+               mpm[mpc].size = ISO_BLOCKS(mac_boot->size);
+
+               mpm[mpc].ntype = PM2;
+               mpm[mpc].type = (char *) mac_part->pmPartType;
+               mpm[mpc].start = mac_boot->extent = last_extent;
+               mpm[mpc].name = 0;
+
+               /* flag that we have a boot file */
+               have_hfs_boot++;
+
+               /* add boot file size to the total size */
+               last_extent += mpm[mpc].size;
+               hfs_extra += mpm[mpc].size;
+
+               mpc++;
+       }
+       /* set info about our hybrid volume */
+       mpm[mpc].ntype = PM4;
+       mpm[mpc].type = pmPartType_4;
+       mpm[mpc].start = hce->hfs_map_size / HFS_BLK_CONV;
+       mpm[mpc].size = last_extent - mpm[mpc].start -
+                       ISO_BLOCKS(mac_boot->size);
+       mpm[mpc].name = volume_id;
+
+       mpc++;
+
+       if (verbose > 1)
+               fprintf(stderr, "Creating HFS Label %s %s\n", mac_boot->name ?
+                       "with boot file" : "",
+                       mac_boot->name ? mac_boot->name : "");
+
+       /* for a bootable CD, block size is SECTOR_SIZE */
+       block_size = have_hfs_boot ? SECTOR_SIZE : HFS_BLOCKSZ;
+
+       /* create the CD label */
+       mac_label = (MacLabel *) buffer;
+       mac_label->sbSig[0] = 'E';
+       mac_label->sbSig[1] = 'R';
+       set_722((char *) mac_label->sbBlkSize, block_size);
+       set_732((char *) mac_label->sbBlkCount,
+                               last_extent * (SECTOR_SIZE / block_size));
+       set_722((char *) mac_label->sbDevType, 1);
+       set_722((char *) mac_label->sbDevId, 1);
+
+       /* create the partition map entry */
+       mac_part = (MacPart *) (buffer + block_size);
+       mac_part->pmSig[0] = 'P';
+       mac_part->pmSig[1] = 'M';
+       set_732((char *) mac_part->pmMapBlkCnt, mpc + 1);
+       set_732((char *) mac_part->pmPyPartStart, 1);
+       set_732((char *) mac_part->pmPartBlkCnt, mpc + 1);
+       strncpy((char *) mac_part->pmPartName, "Apple",
+                                               sizeof (mac_part->pmPartName));
+       strncpy((char *) mac_part->pmPartType, "Apple_partition_map",
+                                               sizeof (mac_part->pmPartType));
+       set_732((char *) mac_part->pmLgDataStart, 0);
+       set_732((char *) mac_part->pmDataCnt, mpc + 1);
+       set_732((char *) mac_part->pmPartStatus, PM_STAT_DEFAULT);
+
+       /* create partition map entries for our partitions */
+       for (i = 0; i < mpc; i++) {
+               mac_part = (MacPart *) (buffer + (i + 2) * block_size);
+               if (mpm[i].ntype == PM2) {
+                       /* get driver label and patch it */
+                       memcpy((char *) mac_label, tmp, HFS_BLOCKSZ);
+                       set_732((char *) mac_label->sbBlkCount,
+                               last_extent * (SECTOR_SIZE / block_size));
+                       set_732((char *) mac_label->ddBlock,
+                               (mpm[i].start) * (SECTOR_SIZE / block_size));
+                       memcpy((char *) mac_part, tmp + HFS_BLOCKSZ,
+                                                               HFS_BLOCKSZ);
+                       set_732((char *) mac_part->pmMapBlkCnt, mpc + 1);
+                       set_732((char *) mac_part->pmPyPartStart,
+                               (mpm[i].start) * (SECTOR_SIZE / block_size));
+               } else {
+                       mac_part->pmSig[0] = 'P';
+                       mac_part->pmSig[1] = 'M';
+                       set_732((char *) mac_part->pmMapBlkCnt, mpc + 1);
+                       set_732((char *) mac_part->pmPyPartStart,
+                               mpm[i].start * (SECTOR_SIZE / HFS_BLOCKSZ));
+                       set_732((char *) mac_part->pmPartBlkCnt,
+                               mpm[i].size * (SECTOR_SIZE / HFS_BLOCKSZ));
+                       strncpy((char *) mac_part->pmPartName, mpm[i].name,
+                               sizeof (mac_part->pmPartName));
+                       strncpy((char *) mac_part->pmPartType, mpm[i].type,
+                               sizeof (mac_part->pmPartType));
+                       set_732((char *) mac_part->pmLgDataStart, 0);
+                       set_732((char *) mac_part->pmDataCnt,
+                               mpm[i].size * (SECTOR_SIZE / HFS_BLOCKSZ));
+                       set_732((char *) mac_part->pmPartStatus,
+                               PM_STAT_DEFAULT);
+               }
+       }
+
+       if (have_hfs_boot) {    /* generate 512 partition table as well */
+               mac_part = (MacPart *) (buffer + HFS_BLOCKSZ);
+               if (mpc < 3) {  /* don't have to interleave with 2048 table */
+                       mac_part->pmSig[0] = 'P';
+                       mac_part->pmSig[1] = 'M';
+                       set_732((char *) mac_part->pmMapBlkCnt, mpc + 1);
+                       set_732((char *) mac_part->pmPyPartStart, 1);
+                       set_732((char *) mac_part->pmPartBlkCnt, mpc + 1);
+                       strncpy((char *) mac_part->pmPartName, "Apple",
+                                       sizeof (mac_part->pmPartName));
+                       strncpy((char *) mac_part->pmPartType,
+                                       "Apple_partition_map",
+                                       sizeof (mac_part->pmPartType));
+                       set_732((char *) mac_part->pmLgDataStart, 0);
+                       set_732((char *) mac_part->pmDataCnt, mpc + 1);
+                       set_732((char *) mac_part->pmPartStatus,
+                                                       PM_STAT_DEFAULT);
+                       mac_part++;     /* +HFS_BLOCKSZ */
+               }
+               for (i = 0; i < mpc; i++, mac_part++) {
+                       if (mac_part == (MacPart *) (buffer + SECTOR_SIZE))
+                               mac_part++;     /* jump over 2048 partition */
+                                               /* entry */
+                       if (mpm[i].ntype == PM2) {
+                               memcpy((char *) mac_part, tmp + HFS_BLOCKSZ * 2,
+                                                       HFS_BLOCKSZ);
+                               if (!IS_MAC_PART(mac_part)) {
+                                       mac_part--;
+                                       continue;
+                               }
+                               set_732((char *) mac_part->pmMapBlkCnt, mpc+1);
+                               set_732((char *) mac_part->pmPyPartStart,
+                                   mpm[i].start * (SECTOR_SIZE / HFS_BLOCKSZ));
+                       } else {
+                               mac_part->pmSig[0] = 'P';
+                               mac_part->pmSig[1] = 'M';
+                               set_732((char *) mac_part->pmMapBlkCnt, mpc+1);
+                               set_732((char *) mac_part->pmPyPartStart,
+                                   mpm[i].start * (SECTOR_SIZE / HFS_BLOCKSZ));
+                               set_732((char *) mac_part->pmPartBlkCnt,
+                                   mpm[i].size * (SECTOR_SIZE / HFS_BLOCKSZ));
+                               strncpy((char *) mac_part->pmPartName,
+                                   mpm[i].name, sizeof (mac_part->pmPartName));
+                               strncpy((char *) mac_part->pmPartType,
+                                   mpm[i].type, sizeof (mac_part->pmPartType));
+                               set_732((char *) mac_part->pmLgDataStart, 0);
+                               set_732((char *) mac_part->pmDataCnt,
+                                   mpm[i].size * (SECTOR_SIZE / HFS_BLOCKSZ));
+                               set_732((char *) mac_part->pmPartStatus,
+                                                       PM_STAT_DEFAULT);
+                       }
+               }
+       }
+       return (0);
+}
+
+/*
+ *     autostart: make the HFS CD use the QuickTime 2.0 Autostart feature.
+ *
+ *     based on information from Eric Eisenhart <eric@sonic.net> and
+ *     http://developer.apple.com/qa/qtpc/qtpc12.html and
+ *     http://developer.apple.com/dev/techsupport/develop/issue26/macqa.html
+ *
+ *     The name of the AutoStart file is stored in the area allocated for
+ *     the Clipboard name. This area begins 106 bytes into the sector of
+ *     block 0, with the first four bytes at that offset containing the
+ *     hex value 0x006A7068. This value indicates that an AutoStart
+ *     filename follows. After this 4-byte tag, 12 bytes remain, starting
+ *     at offset 110. In these 12 bytes, the name of the AutoStart file is
+ *     stored as a Pascal string, giving you up to 11 characters to identify
+ *     the file. The file must reside in the root directory of the HFS
+ *     volume or partition.
+ */
+
+int
+autostart()
+{
+       int     len;
+       int     i;
+
+       if ((len = strlen(autoname)) > 11)
+               return (-1);
+
+       hce->hfs_hdr[106] = 0x00;
+       hce->hfs_hdr[107] = 0x6A;
+       hce->hfs_hdr[108] = 0x70;
+       hce->hfs_hdr[109] = 0x68;
+       hce->hfs_hdr[110] = len;
+
+       for (i = 0; i < len; i++)
+               hce->hfs_hdr[111 + i] = autoname[i];
+
+       return (0);
+}
diff --git a/genisoimage/mac_label.h b/genisoimage/mac_label.h
new file mode 100644 (file)
index 0000000..ada860f
--- /dev/null
@@ -0,0 +1,169 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)mac_label.h     1.3 04/03/01 joerg, Copyright 1997, 1998, 1999, 2000 James Pearson */
+/*
+ *      Copyright (c) 1997, 1998, 1999, 2000 James Pearson
+ *
+ * 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; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ *     mac_label.h: defines Macintosh partition maps and label
+ *
+ *     Taken from "genisoimage 1.05 PLUS" by Andy Polyakov <appro@fy.chalmers.se>
+ *     (see http://fy.chalmers.se/~appro/genisoimage_plus.html for details)
+ *
+ *     Much of this is already defined in the libhfs code, but to keep
+ *     things simple we stick with these.
+ */
+
+#ifndef        _MAC_LABEL_H
+#define        _MAC_LABEL_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef PREP_BOOT
+struct fdiskPartition {
+#define        prepPartType 0x41
+#define        chrpPartType 0x96
+       unsigned char   boot;           /* bootable flag; not used */
+       unsigned char   CHSstart[3];    /* start CHS; not used */
+       unsigned char   type;           /* Partition type, = 0x41 (PReP bootable) */
+       unsigned char   CHSend[3];      /* end CHS; not used */
+       unsigned char   startSect[4];   /* start sector (really start of boot image on CD */
+       unsigned char   size[4];        /* size of partition (or boot image ;) ) */
+};
+typedef struct fdiskPartition fdiskPartition;
+#endif
+
+/* Driver Descriptor Map */
+#define        sbSigMagic      "ER"
+struct MacLabel {
+       unsigned char   sbSig[2];       /* unique value for SCSI block 0 */
+       unsigned char   sbBlkSize[2];   /* block size of device */
+       unsigned char   sbBlkCount[4];  /* number of blocks on device */
+       unsigned char   sbDevType[2];   /* device type */
+       unsigned char   sbDevId[2];     /* device id */
+       unsigned char   sbData[4];      /* not used */
+       unsigned char   sbDrvrCount[2]; /* driver descriptor count */
+       unsigned char   ddBlock[4];     /* 1st driver's starting block */
+       unsigned char   ddSize[2];      /* size of 1st driver (512-byte blks) */
+       unsigned char   ddType[2];      /* system type (1 for Mac+) */
+#ifndef PREP_BOOT
+       unsigned char   ddPad[486];     /* ARRAY[0..242] OF INTEGER; not used */
+#else
+#define        fdiskMagic0 0x55
+#define        fdiskMagic1 0xAA
+       unsigned char   pad1[420];      /* not used */
+       fdiskPartition  image[4];       /* heh heh heh, we can have up to 4 */
+                                       /* different boot images */
+       unsigned char   fdiskMagic[2];  /* PReP uses fdisk partition map */
+#endif /* PREP_BOOT */
+};
+typedef struct MacLabel MacLabel;
+
+#define        IS_MAC_LABEL(d)         (((MacLabel*)(d))->sbSig[0] == 'E' && \
+                               ((MacLabel*)(d))->sbSig[1] == 'R')
+
+/* Partition Map Entry */
+#define        pmSigMagic      "PM"
+
+#define        pmPartType_1    "Apple_partition_map"
+#define        pmPartName_11   "Apple"
+
+#define        pmPartType_2    "Apple_Driver"
+#define        pmPartType_21   "Apple_Driver43"
+
+#define        pmPartType_3    "Apple_UNIX_SVR2"
+#define        pmPartName_31   "A/UX Root"
+#define        pmPartName_32   "A/UX Usr"
+#define        pmPartName_33   "Random A/UX fs"
+#define        pmPartName_34   "Swap"
+
+#define        pmPartType_4    "Apple_HFS"
+#define        pmPartName_41   "MacOS"
+
+#define        pmPartType_5    "Apple_Free"
+#define        pmPartName_51   "Extra"
+
+#define        PM2     2
+#define        PM4     4
+
+struct MacPart {
+       unsigned char   pmSig[2];       /* unique value for map entry blk */
+       unsigned char   pmSigPad[2];    /* currently unused */
+       unsigned char   pmMapBlkCnt[4]; /* # of blks in partition map */
+       unsigned char   pmPyPartStart[4]; /* physical start blk of partition */
+       unsigned char   pmPartBlkCnt[4];  /* # of blks in this partition */
+       unsigned char   pmPartName[32];   /* ASCII partition name */
+       unsigned char   pmPartType[32];   /* ASCII partition type */
+       unsigned char   pmLgDataStart[4]; /* log. # of partition's 1st data blk */
+       unsigned char   pmDataCnt[4];     /* # of blks in partition's data area */
+       unsigned char   pmPartStatus[4];  /* bit field for partition status */
+       unsigned char   pmLgBootStart[4]; /* log. blk of partition's boot code */
+       unsigned char   pmBootSize[4];  /* number of bytes in boot code */
+       unsigned char   pmBootAddr[4];  /* memory load address of boot code */
+       unsigned char   pmBootAddr2[4]; /* currently unused */
+       unsigned char   pmBootEntry[4]; /* entry point of boot code */
+       unsigned char   pmBootEntry2[4]; /* currently unused */
+       unsigned char   pmBootCksum[4];  /* checksum of boot code */
+       unsigned char   pmProcessor[16]; /* ASCII for the processor type */
+       unsigned char   pmPad[376];      /* ARRAY[0..187] OF INTEGER; not used */
+};
+typedef struct MacPart MacPart;
+
+#define        IS_MAC_PART(d)          (((MacPart*)(d))->pmSig[0] == 'P' && \
+                               ((MacPart*)(d))->pmSig[1] == 'M')
+
+#define        PM_STAT_VALID           0x01    /* Set if a valid partition map entry */
+#define        PM_STAT_ALLOC           0x02    /* Set if partition is already allocated; clear if available */
+#define        PM_STAT_INUSE           0x04    /* Set if partition is in use; may be cleared after a system reset */
+#define        PM_STAT_BOOTABLE        0x08    /* Set if partition contains valid boot information */
+#define        PM_STAT_READABLE        0x10    /* Set if partition allows reading */
+#define        PM_STAT_WRITABLE        0x20    /* Set if partition allows writing */
+#define        PM_STAT_BOOT_PIC        0x40    /* Set if boot code is position-independent */
+#define        PM_STAT_UNUSED          0x80    /* Unused */
+#define        PM_STAT_DEFAULT         PM_STAT_VALID|PM_STAT_ALLOC|PM_STAT_READABLE|PM_STAT_WRITABLE
+
+typedef struct {
+       char *name;                     /* Partition name */
+       char *type;                     /* Partition type */
+       int   ntype;                    /* Partition type (numeric) */
+       int   start;                    /* start extent (SECTOR_SIZE blocks) */
+       int   size;                     /* extents (SECTOR_SIZE blocks) */
+} mac_partition_table;
+
+/* from libhfs */
+#define        HFS_BB_SIGWORD          0x4c4b
+
+typedef struct deferred_write defer;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _MAC_LABEL_H */
diff --git a/genisoimage/mactypes.h b/genisoimage/mactypes.h
new file mode 100644 (file)
index 0000000..01e1085
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)mactypes.h      1.3 04/03/01 joerg */
+
+#ifndef        _MACTYPES_H
+#define        _MACTYPES_H
+
+/*
+ * Various types of HFS files stored on Unix systems
+ */
+#define        TYPE_NONE       0       /* Unknown file type (ordinary Unix file) */
+#define        TYPE_CAP        1       /* AUFS CAP */
+#define        TYPE_NETA       2       /* Netatalk */
+#define        TYPE_DBL        3       /* AppleDouble */
+#define        TYPE_ESH        4       /* Helios EtherShare */
+#define        TYPE_FEU        5       /* PC Exchange (Upper case) */
+#define        TYPE_FEL        6       /* PC Exchange (Lower case) */
+#define        TYPE_SGI        7       /* SGI */
+#define        TYPE_MBIN       8       /* MacBinary */
+#define        TYPE_SGL        9       /* AppleSingle */
+#define        TYPE_DAVE       10      /* DAVE (AppleDouble type) */
+#define        TYPE_SFM        11      /* NTFS Services for Macintosh */
+#define        TYPE_XDBL       12      /* MacOS X AppleDouble */
+#define        TYPE_XHFS       13      /* MacOS X HFS */
+
+/*
+ * above encoded in a bit map
+ */
+#define        DO_NONE         (1 << TYPE_NONE)
+#define        DO_CAP          (1 << TYPE_CAP)
+#define        DO_NETA         (1 << TYPE_NETA)
+#define        DO_DBL          (1 << TYPE_DBL)
+#define        DO_ESH          (1 << TYPE_ESH)
+#define        DO_FEU          (1 << TYPE_FEU)
+#define        DO_FEL          (1 << TYPE_FEL)
+#define        DO_SGI          (1 << TYPE_SGI)
+#define        DO_MBIN         (1 << TYPE_MBIN)
+#define        DO_SGL          (1 << TYPE_SGL)
+#define        DO_DAVE         (1 << TYPE_DAVE)
+#define        DO_SFM          (1 << TYPE_SFM)
+#define        DO_XDBL         (1 << TYPE_XDBL)
+#define        DO_XHFS         (1 << TYPE_XHFS)
+
+/*
+ * flags describing how the data/rsrc/info files are stored
+ * in the whole file name
+ */
+#define        INSERT          0x0     /* rsrc/info is inserted in name (default) */
+#define        PROBE           0x1     /* need to probe file for type */
+#define        NOPEND          0x2     /* info data in one file for all files */
+#define        APPEND          0x4     /* rsrc/info appended to file name */
+#define        NORSRC          0x8     /* rsrc for file may not exist */
+#define        NOINFO          0x10    /* info file dosen't exist */
+
+#endif /* _MACTYPES_H */
diff --git a/genisoimage/magic b/genisoimage/magic
new file mode 100644 (file)
index 0000000..387727c
--- /dev/null
@@ -0,0 +1,81 @@
+#
+# Example magic file for mkhybrid
+#
+# The "message" for the offset MUST be 4 characters for the CREATOR
+# and 4 characters for the TYPE - white space is optional between them.
+# Any other characters on this line are ignored. Continuation lines (starting
+# with '>') are also ignored i.e. only the initial offset lines are used.
+#
+# The continuation lines are given here, but they do not need to exist.
+
+#
+# James Pearson 20/5/98
+
+# off  type            test            message
+
+# GIF
+0      string          GIF8            8BIM GIFf
+>4     string          7a              \b, version 8%s,
+>4     string          9a              \b, version 8%s,
+>6     leshort         >0              %hd x
+>8     leshort         >0              %hd,
+#>10   byte            &0x80           color mapped,
+#>10   byte&0x07       =0x00           2 colors
+#>10   byte&0x07       =0x01           4 colors
+#>10   byte&0x07       =0x02           8 colors
+#>10   byte&0x07       =0x03           16 colors
+#>10   byte&0x07       =0x04           32 colors
+#>10   byte&0x07       =0x05           64 colors
+#>10   byte&0x07       =0x06           128 colors
+#>10   byte&0x07       =0x07           256 colors
+
+# JPEG images
+#
+0      ubeshort                0xffd8          8BIM JPEG  image data
+
+# StuffIt
+#
+0      string          SIT!            SIT!SIT!
+
+# standard unix compress
+0      string          \037\235        LZIV ZIVU
+>2     byte&0x80       >0              block compressed
+>2     byte&0x1f       x               %d bits
+
+# gzip (GNU zip, not to be confused with Info-ZIP or PKWARE zip archiver)
+0       string          \037\213        GNUz ZIVU gzip compressed data
+>2      byte            <8              \b, reserved method,
+>2      byte            8               \b, deflated,
+>3     byte            &0x01           ASCII,
+>3     byte            &0x02           continuation,
+>3     byte            &0x04           extra field,
+>3     byte            &0x08           original filename,
+>3     byte            &0x10           comment,
+>3     byte            &0x20           encrypted,
+>4     ledate          x               last modified: %s,
+>8     byte            2               max compression,
+>8     byte            4               max speed,
+>9     byte            =0x00           os: MS-DOS
+>9     byte            =0x01           os: Amiga
+>9     byte            =0x02           os: VMS
+>9     byte            =0x03           os: Unix
+>9     byte            =0x05           os: Atari
+>9     byte            =0x06           os: OS/2
+>9     byte            =0x07           os: MacOS
+>9     byte            =0x0A           os: Tops/20
+>9     byte            =0x0B           os: Win/32
+
+# Postscript
+0      string          %!              ASPSTEXT
+>2     string          PS-Adobe-       conforming
+>>11   string          >\0             at level %.3s
+>>>15  string          EPS             - type %s
+>>>15  string          Query           - type %s
+>>>15  string          ExitServer      - type %s
+# Some PCs have the annoying habit of adding a ^D as a document separator
+0      string          \004%!          ASPS TEXT PostScript document text
+>3     string          PS-Adobe-       conforming
+>>12   string          >\0             at level %.3s
+>>>16  string          EPS             - type %s
+>>>16  string          Query           - type %s
+>>>16  string          ExitServer      - type %s
diff --git a/genisoimage/mapping b/genisoimage/mapping
new file mode 100644 (file)
index 0000000..c108a44
--- /dev/null
@@ -0,0 +1,8 @@
+# Example filename mapping file
+#
+# EXTN   XLate   CREATOR   TYPE     Comment
+.tif     Raw     '8BIM'    'TIFF'   "Photoshop TIFF image"
+.hqx     Ascii   'BnHq'    'TEXT'   "BinHex file"
+.doc     Raw     'MSWD'    'WDBN'   "Word file"
+.mov     Raw     'TVOD'    'MooV'   "QuickTime Movie"
+*        Ascii   'ttxt'    'TEXT'   "Text file"
diff --git a/genisoimage/match.c b/genisoimage/match.c
new file mode 100644 (file)
index 0000000..6762e89
--- /dev/null
@@ -0,0 +1,290 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)match.c 1.18 04/05/23 joerg */
+/*
+ * 27-Mar-96: Jan-Piet Mens <jpm@mens.de>
+ * added 'match' option (-m) to specify regular expressions NOT to be included
+ * in the CD image.
+ *
+ * Re-written 13-Apr-2000 James Pearson
+ * now uses a generic set of routines
+ */
+
+#include <mconfig.h>
+#include <stdio.h>
+#include <stdxlib.h>
+#include <unixstd.h>
+#include <strdefs.h>
+#include <standard.h>
+#include <schily.h>
+#include <libport.h>
+#include "match.h"
+
+struct match {
+       struct match *next;
+       char     *name;
+};
+
+typedef struct match match;
+
+static match *mats[MAX_MAT];
+
+static char *mesg[MAX_MAT] = {
+       "excluded",
+       "excluded ISO-9660",
+       "excluded Joliet",
+       "hidden attribute ISO-9660",
+#ifdef APPLE_HYB
+       "excluded HFS",
+#endif /* APPLE_HYB */
+};
+
+#ifdef SORTING
+struct sort_match {
+       struct sort_match       *next;
+       char                    *name;
+       int                     val;
+};
+
+typedef struct sort_match sort_match;
+
+static sort_match      *s_mats;
+
+int
+add_sort_match(char *fn, int val)
+{
+       sort_match *s_mat;
+
+       s_mat = (sort_match *)malloc(sizeof (sort_match));
+       if (s_mat == NULL) {
+#ifdef USE_LIBSCHILY
+               errmsg("Can't allocate memory for sort filename\n");
+#else
+               fprintf(stderr, "Can't allocate memory for sort filename\n");
+#endif
+               return (0);
+       }
+
+       if ((s_mat->name = strdup(fn)) == NULL) {
+#ifdef USE_LIBSCHILY
+               errmsg("Can't allocate memory for sort filename\n");
+#else
+               fprintf(stderr, "Can't allocate memory for sort filename\n");
+#endif
+               return (0);
+       }
+
+       /* need to reserve the minimum value for other uses */
+       if (val == NOT_SORTED)
+               val++;
+
+       s_mat->val = val;
+       s_mat->next = s_mats;
+       s_mats = s_mat;
+
+       return (1);
+}
+
+void
+add_sort_list(char *file)
+{
+       FILE    *fp;
+       char    name[4096];
+       char    *p;
+       int     val;
+
+       if ((fp = fopen(file, "r")) == NULL) {
+#ifdef USE_LIBSCHILY
+               comerr("Can't open sort file list %s\n", file);
+#else
+               fprintf(stderr, "Can't open hidden/exclude file list %s\n", file);
+               exit(1);
+#endif
+       }
+
+       while (fgets(name, sizeof (name), fp) != NULL) {
+               /*
+                * look for the last space or tab character
+                */
+               if ((p = strrchr(name, ' ')) == NULL)
+                       p = strrchr(name, '\t');
+               else if (strrchr(p, '\t') != NULL)      /* Tab after space? */
+                       p = strrchr(p, '\t');
+
+               if (p == NULL) {
+#ifdef USE_LIBSCHILY
+                       comerrno(EX_BAD, "Incorrect sort file format\n\t%s", name);
+#else
+                       fprintf(stderr, "Incorrect sort file format\n\t%s", name);
+#endif
+                       continue;
+               } else {
+                       *p = '\0';
+                       val = atoi(++p);
+               }
+               if (!add_sort_match(name, val)) {
+                       fclose(fp);
+                       return;
+               }
+       }
+
+       fclose(fp);
+}
+
+int
+sort_matches(char *fn, int val)
+{
+       register sort_match     *s_mat;
+
+       for (s_mat = s_mats; s_mat; s_mat = s_mat->next) {
+               if (fnmatch(s_mat->name, fn, FNM_FILE_NAME) != FNM_NOMATCH) {
+                       return (s_mat->val); /* found sort value */
+               }
+       }
+       return (val); /* not found - default sort value */
+}
+
+void
+del_sort()
+{
+       register sort_match * s_mat, *s_mat1;
+
+       s_mat = s_mats;
+       while (s_mat) {
+               s_mat1 = s_mat->next;
+
+               free(s_mat->name);
+               free(s_mat);
+
+               s_mat = s_mat1;
+       }
+
+       s_mats = 0;
+}
+
+#endif /* SORTING */
+
+
+int
+gen_add_match(char *fn, int n)
+{
+       match   *mat;
+
+       if (n >= MAX_MAT)
+               return (0);
+
+       mat = (match *)malloc(sizeof (match));
+       if (mat == NULL) {
+#ifdef USE_LIBSCHILY
+               errmsg("Can't allocate memory for %s filename\n", mesg[n]);
+#else
+               fprintf(stderr, "Can't allocate memory for %s filename\n", mesg[n]);
+#endif
+               return (0);
+       }
+
+       if ((mat->name = strdup(fn)) == NULL) {
+#ifdef USE_LIBSCHILY
+               errmsg("Can't allocate memory for %s filename\n", mesg[n]);
+#else
+               fprintf(stderr, "Can't allocate memory for %s filename\n", mesg[n]);
+#endif
+               return (0);
+       }
+
+       mat->next = mats[n];
+       mats[n] = mat;
+
+       return (1);
+}
+
+void
+gen_add_list(char *file, int n)
+{
+       FILE    *fp;
+       char    name[4096];
+       int     len;
+
+       if ((fp = fopen(file, "r")) == NULL) {
+#ifdef USE_LIBSCHILY
+               comerr("Can't open %s file list %s\n", mesg[n], file);
+#else
+               fprintf(stderr, "Can't open %s file list %s\n", mesg[n], file);
+               exit(1);
+#endif
+       }
+
+       while (fgets(name, sizeof (name), fp) != NULL) {
+               /*
+                * strip of '\n'
+                */
+               len = strlen(name);
+               if (name[len - 1] == '\n') {
+                       name[len - 1] = '\0';
+               }
+               if (!gen_add_match(name, n)) {
+                       fclose(fp);
+                       return;
+               }
+       }
+
+       fclose(fp);
+}
+
+int
+gen_matches(char *fn, int n)
+{
+       register match * mat;
+
+       if (n >= MAX_MAT)
+               return (0);
+
+       for (mat = mats[n]; mat; mat = mat->next) {
+               if (fnmatch(mat->name, fn, FNM_FILE_NAME) != FNM_NOMATCH) {
+                       return (1);     /* found -> excluded filename */
+               }
+       }
+       return (0);                     /* not found -> not excluded */
+}
+
+int
+gen_ishidden(int n)
+{
+       if (n >= MAX_MAT)
+               return (0);
+
+       return ((int)(mats[n] != 0));
+}
+
+void
+gen_del_match(int n)
+{
+       register match  *mat;
+       register match  *mat1;
+
+       if (n >= MAX_MAT)
+               return;
+
+       mat = mats[n];
+
+       while (mat) {
+               mat1 = mat->next;
+
+               free(mat->name);
+               free(mat);
+
+               mat = mat1;
+       }
+
+       mats[n] = 0;
+}
diff --git a/genisoimage/match.h b/genisoimage/match.h
new file mode 100644 (file)
index 0000000..2894af9
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)match.h 1.9 04/05/23 joerg */
+/*
+ * 27th March 1996. Added by Jan-Piet Mens for matching regular expressions
+ *                  in paths.
+ *
+ */
+
+#include "fnmatch.h"
+
+#ifdef SORTING
+#include <limits.h>
+#define        NOT_SORTED INT_MIN
+
+#ifdef MAX                             /* May be defined in param.h */
+#undef MAX
+#endif
+#define        MAX(A, B)       (A) > (B) ? (A) : (B)
+#endif
+
+#define        EXCLUDE         0               /* Exclude file completely */
+#define        I_HIDE          1               /* ISO9660/Rock Ridge hide */
+#define        J_HIDE          2               /* Joliet hide */
+#define        H_HIDE          3               /* ISO9660 hidden bit set */
+
+#ifdef APPLE_HYB
+#define        HFS_HIDE        4               /* HFS hide */
+#define        MAX_MAT         5
+#else
+#define        MAX_MAT         4
+#endif /* APPLE_HYB */
+
+extern int     gen_add_match(char *fn, int n);
+extern int     gen_matches(char *fn, int n);
+extern void    gen_add_list(char *fn, int n);
+extern int     gen_ishidden(int n);
+extern void    gen_del_match(int n);
+
+#ifdef SORTING
+extern int     add_sort_match(char *fn, int val);
+extern void    add_sort_list(char *fn);
+extern int     sort_matches(char *fn, int val);
+extern void    del_sort(void);
+#endif /* SORTING */
+
+/*
+ * The following are for compatiblity with the separate routines - the
+ * main code should be changed to call the generic routines directly
+ */
+
+/* filenames to be excluded */
+#define        add_match(FN)   gen_add_match((FN), EXCLUDE)
+#define        add_list(FN)    gen_add_list((FN), EXCLUDE)
+#define        matches(FN)     gen_matches((FN), EXCLUDE)
+
+/* ISO9660/Rock Ridge filenames to be hidden */
+#define        i_add_match(FN) gen_add_match((FN), I_HIDE)
+#define        i_add_list(FN)  gen_add_list((FN), I_HIDE)
+#define        i_matches(FN)   gen_matches((FN), I_HIDE)
+#define        i_ishidden()    gen_ishidden(I_HIDE)
+
+/* Joliet filenames to be hidden */
+#define        j_add_match(FN) gen_add_match((FN), J_HIDE)
+#define        j_add_list(FN)  gen_add_list((FN), J_HIDE)
+#define        j_matches(FN)   gen_matches((FN), J_HIDE)
+#define        j_ishidden()    gen_ishidden(J_HIDE)
+
+/* ISO9660 "hidden" files */
+#define        h_add_match(FN) gen_add_match((FN), H_HIDE)
+#define        h_add_list(FN)  gen_add_list((FN), H_HIDE)
+#define        h_matches(FN)   gen_matches((FN), H_HIDE)
+#define        h_ishidden()    gen_ishidden(H_HIDE)
+
+#ifdef APPLE_HYB
+/* HFS filenames to be hidden */
+#define        hfs_add_match(FN) gen_add_match((FN), HFS_HIDE)
+#define        hfs_add_list(FN)  gen_add_list((FN), HFS_HIDE)
+#define        hfs_matches(FN)   gen_matches((FN), HFS_HIDE)
+#define        hfs_ishidden()    gen_ishidden(HFS_HIDE)
+#endif /* APPLE_HYB */
diff --git a/genisoimage/md5.c b/genisoimage/md5.c
new file mode 100644 (file)
index 0000000..353ae5a
--- /dev/null
@@ -0,0 +1,401 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/*
+ * This code implements the MD5 message-digest algorithm.
+ * The algorithm is due to Ron Rivest.  This code was
+ * written by Colin Plumb in 1993, no copyright is claimed.
+ * This code is in the public domain; do with it what you wish.
+ *
+ * Equivalent code is available from RSA Data Security, Inc.
+ * This code has been tested against that, and is equivalent,
+ * except that you don't need to include two pages of legalese
+ * with every copy.
+ *
+ * To compute the message digest of a chunk of bytes, declare an
+ * MD5Context structure, pass it to MD5Init, call MD5Update as
+ * needed on buffers full of bytes, and then call MD5Final, which
+ * will fill a supplied 16-byte array with the digest.
+ */
+
+/* This code was modified in 1997 by Jim Kingdon of Cyclic Software to
+   not require an integer type which is exactly 32 bits.  This work
+   draws on the changes for the same purpose by Tatu Ylonen
+   <ylo@cs.hut.fi> as part of SSH, but since I didn't actually use
+   that code, there is no copyright issue.  I hereby disclaim
+   copyright in any changes I have made; this code remains in the
+   public domain.  */
+
+/* Note regarding cvs_* namespace: this avoids potential conflicts
+   with libraries such as some versions of Kerberos.  No particular
+   need to worry about whether the system supplies an MD5 library, as
+   this file is only about 3k of object code.  */
+
+/* Steve McIntyre, 2004/05/31: borrowed this code from the CVS
+   library. s/cvs_/mk_/ across the source */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>    /* for memcpy() and memset() */
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+
+#include "md5.h"
+
+/* Little-endian byte-swapping routines.  Note that these do not
+   depend on the size of datatypes such as mk_uint32, nor do they require
+   us to detect the endianness of the machine we are running on.  It
+   is possible they should be macros for speed, but I would be
+   surprised if they were a performance bottleneck for MD5.  */
+
+static mk_uint32
+getu32 (const unsigned char *addr)
+{
+       return (((((unsigned long)addr[3] << 8) | addr[2]) << 8)
+               | addr[1]) << 8 | addr[0];
+}
+
+static void
+putu32 (mk_uint32 data, unsigned char *addr)
+{
+       addr[0] = (unsigned char)data;
+       addr[1] = (unsigned char)(data >> 8);
+       addr[2] = (unsigned char)(data >> 16);
+       addr[3] = (unsigned char)(data >> 24);
+}
+
+/*
+ * Start MD5 accumulation.  Set bit count to 0 and buffer to mysterious
+ * initialization constants.
+ */
+void
+mk_MD5Init (struct mk_MD5Context *ctx)
+{
+       ctx->buf[0] = 0x67452301;
+       ctx->buf[1] = 0xefcdab89;
+       ctx->buf[2] = 0x98badcfe;
+       ctx->buf[3] = 0x10325476;
+
+       ctx->bits[0] = 0;
+       ctx->bits[1] = 0;
+}
+
+/*
+ * Update context to reflect the concatenation of another buffer full
+ * of bytes.
+ */
+void
+mk_MD5Update (struct mk_MD5Context *ctx, unsigned char const *buf, unsigned len)
+{
+       mk_uint32 t;
+
+       /* Update bitcount */
+
+       t = ctx->bits[0];
+       if ((ctx->bits[0] = (t + ((mk_uint32)len << 3)) & 0xffffffff) < t)
+               ctx->bits[1]++; /* Carry from low to high */
+       ctx->bits[1] += len >> 29;
+
+       t = (t >> 3) & 0x3f;    /* Bytes already in shsInfo->data */
+
+       /* Handle any leading odd-sized chunks */
+
+       if ( t ) {
+               unsigned char *p = ctx->in + t;
+
+               t = 64-t;
+               if (len < t) {
+                       memcpy(p, buf, len);
+                       return;
+               }
+               memcpy(p, buf, t);
+               mk_MD5Transform (ctx->buf, ctx->in);
+               buf += t;
+               len -= t;
+       }
+
+       /* Process data in 64-byte chunks */
+
+       while (len >= 64) {
+               memcpy(ctx->in, buf, 64);
+               mk_MD5Transform (ctx->buf, ctx->in);
+               buf += 64;
+               len -= 64;
+       }
+
+       /* Handle any remaining bytes of data. */
+
+       memcpy(ctx->in, buf, len);
+}
+
+/*
+ * Final wrapup - pad to 64-byte boundary with the bit pattern 
+ * 1 0* (64-bit count of bits processed, MSB-first)
+ */
+void
+mk_MD5Final (unsigned char digest[16], struct mk_MD5Context *ctx)
+{
+       unsigned count;
+       unsigned char *p;
+
+       /* Compute number of bytes mod 64 */
+       count = (ctx->bits[0] >> 3) & 0x3F;
+
+       /* Set the first char of padding to 0x80.  This is safe since there is
+          always at least one byte free */
+       p = ctx->in + count;
+       *p++ = 0x80;
+
+       /* Bytes of padding needed to make 64 bytes */
+       count = 64 - 1 - count;
+
+       /* Pad out to 56 mod 64 */
+       if (count < 8) {
+               /* Two lots of padding:  Pad the first block to 64 bytes */
+               memset(p, 0, count);
+               mk_MD5Transform (ctx->buf, ctx->in);
+
+               /* Now fill the next block with 56 bytes */
+               memset(ctx->in, 0, 56);
+       } else {
+               /* Pad block to 56 bytes */
+               memset(p, 0, count-8);
+       }
+
+       /* Append length in bits and transform */
+       putu32(ctx->bits[0], ctx->in + 56);
+       putu32(ctx->bits[1], ctx->in + 60);
+
+       mk_MD5Transform (ctx->buf, ctx->in);
+       putu32(ctx->buf[0], digest);
+       putu32(ctx->buf[1], digest + 4);
+       putu32(ctx->buf[2], digest + 8);
+       putu32(ctx->buf[3], digest + 12);
+       memset(ctx, 0, sizeof(ctx));    /* In case it's sensitive */
+}
+
+/* The four core functions - F1 is optimized somewhat */
+
+/* #define F1(x, y, z) (x & y | ~x & z) */
+#define F1(x, y, z) (z ^ (x & (y ^ z)))
+#define F2(x, y, z) F1(z, x, y)
+#define F3(x, y, z) (x ^ y ^ z)
+#define F4(x, y, z) (y ^ (x | ~z))
+
+/* This is the central step in the MD5 algorithm. */
+#define MD5STEP(f, w, x, y, z, data, s) \
+       ( w += f(x, y, z) + data, w &= 0xffffffff, w = w<<s | w>>(32-s), w += x )
+
+/*
+ * The core of the MD5 algorithm, this alters an existing MD5 hash to
+ * reflect the addition of 16 longwords of new data.  MD5Update blocks
+ * the data and converts bytes into longwords for this routine.
+ */
+void
+mk_MD5Transform (mk_uint32 buf[4], const unsigned char inraw[64])
+{
+       register mk_uint32 a, b, c, d;
+       mk_uint32 in[16];
+       int i;
+
+       for (i = 0; i < 16; ++i)
+               in[i] = getu32 (inraw + 4 * i);
+
+       a = buf[0];
+       b = buf[1];
+       c = buf[2];
+       d = buf[3];
+
+       MD5STEP(F1, a, b, c, d, in[ 0]+0xd76aa478,  7);
+       MD5STEP(F1, d, a, b, c, in[ 1]+0xe8c7b756, 12);
+       MD5STEP(F1, c, d, a, b, in[ 2]+0x242070db, 17);
+       MD5STEP(F1, b, c, d, a, in[ 3]+0xc1bdceee, 22);
+       MD5STEP(F1, a, b, c, d, in[ 4]+0xf57c0faf,  7);
+       MD5STEP(F1, d, a, b, c, in[ 5]+0x4787c62a, 12);
+       MD5STEP(F1, c, d, a, b, in[ 6]+0xa8304613, 17);
+       MD5STEP(F1, b, c, d, a, in[ 7]+0xfd469501, 22);
+       MD5STEP(F1, a, b, c, d, in[ 8]+0x698098d8,  7);
+       MD5STEP(F1, d, a, b, c, in[ 9]+0x8b44f7af, 12);
+       MD5STEP(F1, c, d, a, b, in[10]+0xffff5bb1, 17);
+       MD5STEP(F1, b, c, d, a, in[11]+0x895cd7be, 22);
+       MD5STEP(F1, a, b, c, d, in[12]+0x6b901122,  7);
+       MD5STEP(F1, d, a, b, c, in[13]+0xfd987193, 12);
+       MD5STEP(F1, c, d, a, b, in[14]+0xa679438e, 17);
+       MD5STEP(F1, b, c, d, a, in[15]+0x49b40821, 22);
+
+       MD5STEP(F2, a, b, c, d, in[ 1]+0xf61e2562,  5);
+       MD5STEP(F2, d, a, b, c, in[ 6]+0xc040b340,  9);
+       MD5STEP(F2, c, d, a, b, in[11]+0x265e5a51, 14);
+       MD5STEP(F2, b, c, d, a, in[ 0]+0xe9b6c7aa, 20);
+       MD5STEP(F2, a, b, c, d, in[ 5]+0xd62f105d,  5);
+       MD5STEP(F2, d, a, b, c, in[10]+0x02441453,  9);
+       MD5STEP(F2, c, d, a, b, in[15]+0xd8a1e681, 14);
+       MD5STEP(F2, b, c, d, a, in[ 4]+0xe7d3fbc8, 20);
+       MD5STEP(F2, a, b, c, d, in[ 9]+0x21e1cde6,  5);
+       MD5STEP(F2, d, a, b, c, in[14]+0xc33707d6,  9);
+       MD5STEP(F2, c, d, a, b, in[ 3]+0xf4d50d87, 14);
+       MD5STEP(F2, b, c, d, a, in[ 8]+0x455a14ed, 20);
+       MD5STEP(F2, a, b, c, d, in[13]+0xa9e3e905,  5);
+       MD5STEP(F2, d, a, b, c, in[ 2]+0xfcefa3f8,  9);
+       MD5STEP(F2, c, d, a, b, in[ 7]+0x676f02d9, 14);
+       MD5STEP(F2, b, c, d, a, in[12]+0x8d2a4c8a, 20);
+
+       MD5STEP(F3, a, b, c, d, in[ 5]+0xfffa3942,  4);
+       MD5STEP(F3, d, a, b, c, in[ 8]+0x8771f681, 11);
+       MD5STEP(F3, c, d, a, b, in[11]+0x6d9d6122, 16);
+       MD5STEP(F3, b, c, d, a, in[14]+0xfde5380c, 23);
+       MD5STEP(F3, a, b, c, d, in[ 1]+0xa4beea44,  4);
+       MD5STEP(F3, d, a, b, c, in[ 4]+0x4bdecfa9, 11);
+       MD5STEP(F3, c, d, a, b, in[ 7]+0xf6bb4b60, 16);
+       MD5STEP(F3, b, c, d, a, in[10]+0xbebfbc70, 23);
+       MD5STEP(F3, a, b, c, d, in[13]+0x289b7ec6,  4);
+       MD5STEP(F3, d, a, b, c, in[ 0]+0xeaa127fa, 11);
+       MD5STEP(F3, c, d, a, b, in[ 3]+0xd4ef3085, 16);
+       MD5STEP(F3, b, c, d, a, in[ 6]+0x04881d05, 23);
+       MD5STEP(F3, a, b, c, d, in[ 9]+0xd9d4d039,  4);
+       MD5STEP(F3, d, a, b, c, in[12]+0xe6db99e5, 11);
+       MD5STEP(F3, c, d, a, b, in[15]+0x1fa27cf8, 16);
+       MD5STEP(F3, b, c, d, a, in[ 2]+0xc4ac5665, 23);
+
+       MD5STEP(F4, a, b, c, d, in[ 0]+0xf4292244,  6);
+       MD5STEP(F4, d, a, b, c, in[ 7]+0x432aff97, 10);
+       MD5STEP(F4, c, d, a, b, in[14]+0xab9423a7, 15);
+       MD5STEP(F4, b, c, d, a, in[ 5]+0xfc93a039, 21);
+       MD5STEP(F4, a, b, c, d, in[12]+0x655b59c3,  6);
+       MD5STEP(F4, d, a, b, c, in[ 3]+0x8f0ccc92, 10);
+       MD5STEP(F4, c, d, a, b, in[10]+0xffeff47d, 15);
+       MD5STEP(F4, b, c, d, a, in[ 1]+0x85845dd1, 21);
+       MD5STEP(F4, a, b, c, d, in[ 8]+0x6fa87e4f,  6);
+       MD5STEP(F4, d, a, b, c, in[15]+0xfe2ce6e0, 10);
+       MD5STEP(F4, c, d, a, b, in[ 6]+0xa3014314, 15);
+       MD5STEP(F4, b, c, d, a, in[13]+0x4e0811a1, 21);
+       MD5STEP(F4, a, b, c, d, in[ 4]+0xf7537e82,  6);
+       MD5STEP(F4, d, a, b, c, in[11]+0xbd3af235, 10);
+       MD5STEP(F4, c, d, a, b, in[ 2]+0x2ad7d2bb, 15);
+       MD5STEP(F4, b, c, d, a, in[ 9]+0xeb86d391, 21);
+
+       buf[0] += a;
+       buf[1] += b;
+       buf[2] += c;
+       buf[3] += d;
+}
+
+/* Read in a hex-dumped MD5 sum and parse it */
+int mk_MD5Parse(unsigned char in[33], unsigned char out[16])
+{
+    int i = 0;
+
+    for (i = 0; i < 16; i++)
+    {
+        if (in[2*i] >= '0' && in[2*i] <= '9')
+            in[2*i] -= '0';
+        else if (in[2*i] >= 'A' && in[2*i] <= 'F')
+            in[2*i] += 10 - 'A';
+        else if (in[2*i] >= 'a' && in[2*i] <= 'f')
+            in[2*i] += 10 - 'a';
+        else
+            return 1;
+        if (in[1+(2*i)] >= '0' && in[1+(2*i)] <= '9')
+            in[1+(2*i)] -= '0';
+        else if (in[1+(2*i)] >= 'A' && in[1+(2*i)] <= 'F')
+            in[1+(2*i)] += 10 - 'A';
+        else if (in[1+(2*i)] >= 'a' && in[1+(2*i)] <= 'f')
+            in[1+(2*i)] += 10 - 'a';
+        else
+            return 1;
+        out[i] = in[2*i] << 4 | in[1+(2*i)];
+    }
+    return 0;
+}
+
+/* Calculate the MD5sum of the specified file */
+int calculate_md5sum(char *filename, unsigned long long size, unsigned char out[16])
+{
+       char            buffer[32768];
+    int i = 0;
+    FILE *infile = NULL;
+    unsigned long long remain = 0;
+    int                use;
+    struct mk_MD5Context file_context;
+
+    /* Start MD5 work for the file */
+    mk_MD5Init(&file_context);
+
+    infile = fopen(filename, "rb");
+    if (!infile)
+    {
+#ifndef        HAVE_STRERROR
+               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 > sizeof(buffer) ? sizeof(buffer) : remain);
+       if (fread(buffer, 1, use, infile) == 0)
+       {
+               fprintf(stderr, "cannot read from '%s'\n", filename);
+               exit(1);
+       }
+       /* Update the checksum */
+       mk_MD5Update(&file_context, (unsigned char *)buffer, use);
+       remain -= use;
+    }
+    fclose(infile);
+    mk_MD5Final(&out[0], &file_context);
+
+    return 0;
+}
+
+
+#ifdef TEST
+/* Simple test program.  Can use it to manually run the tests from
+   RFC1321 for example.  */
+#include <stdio.h>
+
+int
+main (int argc, char *argv[])
+{
+       struct mk_MD5Context context;
+       unsigned char checksum[16];
+       int i;
+       int j;
+
+       if (argc < 2)
+       {
+               fprintf (stderr, "usage: %s string-to-hash\n", argv[0]);
+               exit (1);
+       }
+       for (j = 1; j < argc; ++j)
+       {
+               printf ("MD5 (\"%s\") = ", argv[j]);
+               mk_MD5Init (&context);
+               mk_MD5Update (&context, argv[j], strlen (argv[j]));
+               mk_MD5Final (checksum, &context);
+               for (i = 0; i < 16; i++)
+               {
+                       printf ("%02x", (unsigned int) checksum[i]);
+               }
+               printf ("\n");
+       }
+       return 0;
+}
+#endif /* TEST */
diff --git a/genisoimage/md5.h b/genisoimage/md5.h
new file mode 100644 (file)
index 0000000..b48c05c
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* See md5.c for explanation and copyright information.  */
+
+#ifndef MD5_H
+#define MD5_H
+
+/* Unlike previous versions of this code, uint32 need not be exactly
+   32 bits, merely 32 bits or more.  Choosing a data type which is 32
+   bits instead of 64 is not important; speed is considerably more
+   important.  ANSI guarantees that "unsigned long" will be big enough,
+   and always using it seems to have few disadvantages.  */
+typedef unsigned long mk_uint32;
+
+struct mk_MD5Context {
+       mk_uint32 buf[4];
+       mk_uint32 bits[2];
+       unsigned char in[64];
+};
+
+void mk_MD5Init (struct mk_MD5Context *context);
+void mk_MD5Update (struct mk_MD5Context *context,
+                          unsigned char const *buf, unsigned len);
+void mk_MD5Final (unsigned char digest[16],
+                         struct mk_MD5Context *context);
+void mk_MD5Transform (mk_uint32 buf[4], const unsigned char in[64]);
+int mk_MD5Parse(unsigned char in[33], unsigned char out[16]);
+int calculate_md5sum(char *filename, unsigned long long size, unsigned char out[16]);
+
+
+#endif /* !MD5_H */
diff --git a/genisoimage/mkhybrid.8 b/genisoimage/mkhybrid.8
new file mode 100644 (file)
index 0000000..075bc0a
--- /dev/null
@@ -0,0 +1,2 @@
+.so man8/genisoimage.8
+.\" %Z%%M%     %I% %E% joerg
diff --git a/genisoimage/more.mapping b/genisoimage/more.mapping
new file mode 100644 (file)
index 0000000..a18daa3
--- /dev/null
@@ -0,0 +1,282 @@
+#
+# Mapping file converted from Internet Config
+# by Bob Nestor <rnestor@metronet.com>
+#
+# EXTN   Xlate Creator Type  Application - description (mime type)
+#
+.1st     Ascii 'ttxt' 'TEXT' "SimpleText - Text Readme (application/text)"
+.669     Raw   'SNPL' '6669' "PlayerPro - 669 MOD Music"
+.8med    Raw   'SCPL' 'STrk' "SoundApp - Amiga OctaMed music"
+.8svx    Raw   'SCPL' '8SVX' "SoundApp - Amiga 8-bit sound"
+.a       Ascii 'MPS ' 'TEXT' "MPW Shell - Assembly Source"
+.aif     Raw   'SCPL' 'AIFF' "SoundApp - AIFF Sound (audio/x-aiff)"
+.aifc    Raw   'SCPL' 'AIFC' "SoundApp - AIFF Sound Compressed (audio/x-aiff)"
+.aiff    Raw   'SCPL' 'AIFF' "SoundApp - AIFF Sound (audio/x-aiff)"
+.al      Raw   'SCPL' 'ALAW' "SoundApp - ALAW Sound"
+.ani     Raw   'GKON' 'ANIi' "GraphicConverter - Animated NeoChrome"
+.apd     Ascii 'ALD3' 'TEXT' "Aldus PageMaker - Aldus Printer Description"
+.arc     Raw   'arc*' 'mArc' "ArcMac - PC ARChive"
+.arj     Raw   'DArj' 'BINA' "DeArj - ARJ Archive"
+.arr     Raw   'GKON' 'ARR ' "GraphicConverter - Amber ARR image"
+.art     Raw   'GKON' 'ART ' "GraphicConverter - First Publisher"
+.asc     Ascii 'ttxt' 'TEXT' "SimpleText - ASCII Text (text/plain)"
+.ascii   Ascii 'ttxt' 'TEXT' "SimpleText - ASCII Text (text/plain)"
+.asm     Ascii 'MPS ' 'TEXT' "MPW Shell - Assembly Source"
+.au      Raw   'SCPL' 'ULAW' "SoundApp - Sun Sound (audio/basic)"
+.avi     Raw   'AVIC' 'VfW ' "AVI to QT Utility - AVI Movie (video/avi)"
+.bar     Raw   'S691' 'BARF' "SunTar - Unix BAR Archive"
+.bas     Ascii 'TBB6' 'TEXT' "TexEdit - BASIC Source"
+.bat     Ascii 'ttxt' 'TEXT' "SimpleText - MS-DOS Batch File"
+.bga     Raw   'JVWR' 'BMPp' "JPEGView - OS/2 Bitmap"
+.bib     Ascii '*TEX' 'TEXT' "Textures - BibTex Bibliography"
+.bin     Raw   'MB2P' 'BINA' "MacBinary II+ - MacBinary (application/macbinary)"
+.binary  Raw   'hDmp' 'BINA' "HexEdit - Untyped Binary Data (application/octet-stream)"
+.bmp     Raw   'JVWR' 'BMPp' "JPEGView - Windows Bitmap"
+.boo     Ascii 'TBB6' 'TEXT' "TexEdit - BOO encoded"
+.bst     Ascii '*TEX' 'TEXT' "Textures - BibTex Style"
+.bw      Raw   'GKON' 'SGI ' "GraphicConverter - SGI Image"
+.c       Ascii 'CWIE' 'TEXT' "CodeWarrior - C Source"
+.cgm     Raw   'GKON' 'CGMm' "GraphicConverter - Computer Graphics Meta"
+.class   Raw   'CWIE' 'Clss' "CodeWarrior - Java Class File"
+.clp     Raw   'GKON' 'CLPp' "GraphicConverter - Windows Clipboard"
+.cmd     Ascii 'ttxt' 'TEXT' "SimpleText - OS/2 Batch File"
+.com     Raw   'SWIN' 'PCFA' "SoftWindows - MS-DOS Executable"
+.cp      Ascii 'CWIE' 'TEXT' "CodeWarrior - C++ Source"
+.cpp     Ascii 'CWIE' 'TEXT' "CodeWarrior - C++ Source"
+.cpt     Raw   'CPCT' 'PACT' "Compact Pro - Compact Pro Archive"
+.csv     Ascii 'XCEL' 'TEXT' "Excel - Comma Separated Vars"
+.ct      Raw   'GKON' '..CT' "GraphicConverter - Scitex-CT"
+.cut     Raw   'GKON' 'Halo' "GraphicConverter - Dr Halo Image"
+.cvs     Raw   'DAD2' 'drw2' "Canvas - Canvas Drawing"
+.dbf     Raw   'FOX+' 'COMP' "FoxBase+ - DBase Document"
+.dcx     Raw   'GKON' 'DCXx' "GraphicConverter - Some PCX Images"
+.dif     Ascii 'XCEL' 'TEXT' "Excel - Data Interchange Format"
+.diz     Ascii 'TBB6' 'TEXT' "TexEdit - BBS Descriptive Text"
+.dl      Raw   'AnVw' 'DL  ' "MacAnim Viewer - DL Animation"
+.dll     Raw   'SWIN' 'PCFL' "SoftWindows - Windows DLL"
+.doc     Raw   'MSWD' 'WDBN' "Microsoft Word - Word Document (application/msword)"
+.dot     Raw   'MSWD' 'sDBN' "Microsoft Word - Word for Windows Template"
+.dvi     Raw   'OTEX' 'ODVI' "OzTeX - TeX DVI Document (application/x-dvi)"
+.dxf     Ascii 'SWVL' 'TEXT' "Swivel Pro - AutoCAD 3D Data"
+.eps     Raw   'vgrd' 'EPSF' "LaserWriter 8 - Postscript (application/postscript)"
+.epsf    Raw   'vgrd' 'EPSF' "LaserWriter 8 - Postscript (application/postscript)"
+.etx     Ascii 'ezVu' 'TEXT' "Easy View - SEText (text/x-setext)"
+.evy     Raw   'ENVY' 'EVYD' "Envoy - Envoy Document"
+.exe     Raw   'SWIN' 'PCFA' "SoftWindows - MS-DOS Executable"
+.faq     Ascii 'TBB6' 'TEXT' "TexEdit - ASCII Text (text/x-usenet-faq)"
+.fit     Raw   'GKON' 'FITS' "GraphicConverter - Flexible Image Transport (image/x-fits)"
+.flc     Raw   'AnVw' 'FLI ' "MacAnim Viewer - FLIC Animation"
+.fli     Raw   'AnVw' 'FLI ' "MacAnim Viewer - FLI Animation"
+.fm      Raw   'FMPR' 'FMPR' "FileMaker Pro - FileMaker Pro Database"
+.for     Ascii 'MPS ' 'TEXT' "MPW Shell - Fortran Source"
+.fts     Raw   'GKON' 'FITS' "GraphicConverter - Flexible Image Transport"
+.gem     Raw   'GKON' 'GEM-' "GraphicConverter - GEM Metafile"
+.gif     Raw   'JVWR' 'GIFf' "JPEGView - GIF Picture (image/gif)"
+.gl      Raw   'AnVw' 'GL  ' "MacAnim Viewer - GL Animation"
+.grp     Raw   'GKON' 'GRPp' "GraphicConverter - GRP Image"
+.gz      Raw   'Gzip' 'Gzip' "MacGzip - Gnu ZIP Archive (application/x-gzip)"
+.h       Ascii 'CWIE' 'TEXT' "CodeWarrior - C Include File"
+.hcom    Raw   'SCPL' 'FSSD' "SoundApp - SoundEdit Sound ex SOX"
+.hp      Ascii 'CWIE' 'TEXT' "CodeWarrior - C Include File"
+.hpgl    Raw   'GKON' 'HPGL' "GraphicConverter - HP GL/2"
+.hpp     Ascii 'CWIE' 'TEXT' "CodeWarrior - C Include File"
+.hqx     Ascii 'TBB6' 'TEXT' "TexEdit - BinHex (application/mac-binhex40)"
+.htm     Ascii 'Um\816' 'TEXT' "HTML Pro - HyperText (text/html)"
+.html    Ascii 'Um\816' 'TEXT' "HTML Pro - HyperText (text/html)"
+.i3      Ascii 'TBB6' 'TEXT' "TexEdit - Modula 3 Interface"
+.ic1     Raw   'GKON' 'IMAG' "GraphicConverter - Atari Image"
+.ic2     Raw   'GKON' 'IMAG' "GraphicConverter - Atari Image"
+.ic3     Raw   'GKON' 'IMAG' "GraphicConverter - Atari Image"
+.icn     Raw   'GKON' 'ICO ' "GraphicConverter - Windows Icon"
+.ico     Raw   'GKON' 'ICO ' "GraphicConverter - Windows Icon"
+.ief     Raw   'GKON' 'IEF ' "GraphicConverter - IEF image (image/ief)"
+.iff     Raw   'GKON' 'ILBM' "GraphicConverter - Amiga IFF Image"
+.ilbm    Raw   'GKON' 'ILBM' "GraphicConverter - Amiga ILBM Image"
+.image   Raw   'dCpy' 'dImg' "DiskCopy - Apple DiskCopy Image"
+.img     Raw   'GKON' 'IMGg' "GraphicConverter - GEM bit image/XIMG"
+.img     Raw   'GKON' 'KONT' "GraphicConverter - KONTRON Image"
+.ini     Ascii 'ttxt' 'TEXT' "SimpleText - Windows INI File"
+.java    Ascii 'CWIE' 'TEXT' "CodeWarrior - Java Source File"
+.jfif    Raw   'JVWR' 'JFIF' "JPEGView - JFIF Image"
+.jpe     Raw   'JVWR' 'JPEG' "JPEGView - JPEG Picture (image/jpeg)"
+.jpeg    Raw   'JVWR' 'JPEG' "JPEGView - JPEG Picture (image/jpeg)"
+.jpg     Raw   'JVWR' 'JPEG' "JPEGView - JPEG Picture (image/jpeg)"
+.latex   Ascii 'OTEX' 'TEXT' "OzTex - Latex (application/x-latex)"
+.lbm     Raw   'GKON' 'ILBM' "GraphicConverter - Amiga IFF Image"
+.lha     Raw   'LARC' 'LHA ' "MacLHA - LHArc Archive"
+.lzh     Raw   'LARC' 'LHA ' "MacLHA - LHArc Archive"
+.m1a     Raw   'KAU1' 'MPEG' "MPEG/CD - MPEG-1 audiostream (audio/x-mpeg)"
+.m1s     Raw   'MPsp' 'MPEG' "MPEGSplitter - MPEG-1 systemstream"
+.m1v     Raw   'mMPG' 'M1V ' "Sparkle - MPEG-1 IPB videostream (video/mpeg)"
+.m2      Ascii 'TBB6' 'TEXT' "TexEdit - Modula 2 Source"
+.m2v     Raw   'MPG2' 'MPG2' "MPEG2decoder - MPEG-2 IPB videostream"
+.m3      Ascii 'TBB6' 'TEXT' "TexEdit - Modula 3 Source"
+.mac     Raw   'ttxt' 'PICT' "SimpleText - PICT Picture (image/x-pict)"
+.mak     Ascii 'TBB6' 'TEXT' "TexEdit - Makefile"
+.mcw     Raw   'MSWD' 'WDBN' "Microsoft Word - Mac Word Document"
+.me      Ascii 'ttxt' 'TEXT' "SimpleText - Text Readme"
+.med     Raw   'SCPL' 'STrk' "SoundApp - Amiga MED Sound"
+.mf      Ascii '*MF*' 'TEXT' "Metafont - Metafont"
+.mid     Raw   'ttxt' 'Midi' "SimpleText - MIDI Music"
+.midi    Raw   'ttxt' 'Midi' "SimpleText - MIDI Music"
+.mif     Ascii 'Fram' 'TEXT' "FrameMaker - FrameMaker MIF (application/x-mif)"
+.mif     Ascii 'Fram' 'TEXT' "FrameMaker - FrameMaker MIF (application/x-framemaker)"
+.mime    Ascii 'mPAK' 'TEXT' "Mpack - MIME Message (message/rfc822)"
+.ml      Ascii 'TBB6' 'TEXT' "TexEdit - ML Source"
+.mod     Raw   'SCPL' 'STrk' "SoundApp - MOD Music"
+.mol     Ascii 'RSML' 'TEXT' "RasMac - MDL Molfile"
+.moov    Raw   'ttxt' 'MooV' "SimpleText - QuickTime Movie (video/quicktime)"
+.mov     Raw   'ttxt' 'MooV' "SimpleText - QuickTime Movie (video/quicktime)"
+.mp2     Raw   'KAU1' 'MPEG' "MPEG/CD - MPEG-1 audiostream (audio/x-mpeg)"
+.mpa     Raw   'KAU1' 'MPEG' "MPEG/CD - MPEG-1 audiostream (audio/x-mpeg)"
+.mpe     Raw   'mMPG' 'MPEG' "Sparkle - MPEG Movie of some sort (video/mpeg)"
+.mpeg    Raw   'mMPG' 'MPEG' "Sparkle - MPEG Movie of some sort (video/mpeg)"
+.mpg     Raw   'mMPG' 'MPEG' "Sparkle - MPEG Movie of some sort (video/mpeg)"
+.msp     Raw   'GKON' 'MSPp' "GraphicConverter - Microsoft Paint"
+.mtm     Raw   'SNPL' 'MTM ' "PlayerPro - MultiMOD Music"
+.mw      Raw   'MWII' 'MW2D' "MacWrite II - MacWrite Document (application/macwriteii)"
+.mwii    Raw   'MWII' 'MW2D' "MacWrite II - MacWrite Document (application/macwriteii)"
+.neo     Raw   'GKON' 'NeoC' "GraphicConverter - Atari NeoChrome"
+.nfo     Ascii 'ttxt' 'TEXT' "SimpleText - Info Text (application/text)"
+.nst     Raw   'SCPL' 'STrk' "SoundApp - MOD Music"
+.obj     Raw   'SWIN' 'PCFL' "SoftWindows - Object (DOS/Windows)"
+.oda     Raw   'ODA ' 'ODIF' "MacODA XTND Translator - ODA Document (application/oda)"
+.okt     Raw   'SCPL' 'OKTA' "SoundApp - Oktalyser MOD Music"
+.out     Raw   'hDmp' 'BINA' "HexEdit - Output File"
+.ovl     Raw   'SWIN' 'PCFL' "SoftWindows - Overlay (DOS/Windows)"
+.p       Ascii 'CWIE' 'TEXT' "CodeWarrior - Pascal Source"
+.pac     Raw   'GKON' 'STAD' "GraphicConverter - Atari STAD Image"
+.pas     Ascii 'CWIE' 'TEXT' "CodeWarrior - Pascal Source"
+.pbm     Raw   'GKON' 'PPGM' "GraphicConverter - Portable Bitmap (image/x-pbm)"
+.pbm     Raw   'GKON' 'PPGM' "GraphicConverter - Portable Bitmap (image/x-portable-bitmap)"
+.pc1     Raw   'GKON' 'Dega' "GraphicConverter - Atari Degas Image"
+.pc2     Raw   'GKON' 'Dega' "GraphicConverter - Atari Degas Image"
+.pc3     Raw   'GKON' 'Dega' "GraphicConverter - Atari Degas Image"
+.pcs     Raw   'GKON' 'PICS' "GraphicConverter - Animated PICTs"
+.pct     Raw   'ttxt' 'PICT' "SimpleText - PICT Picture (image/x-pict)"
+.pcx     Raw   'GKON' 'PCXx' "GraphicConverter - PC PaintBrush"
+.pdb     Ascii 'RSML' 'TEXT' "RasMac - Brookhaven PDB file"
+.pdf     Raw   'CARO' 'PDF ' "Acrobat Reader - Portable Document Format (application/pdf)"
+.pdx     Ascii 'ALD5' 'TEXT' "PageMaker - Printer Description"
+.pgm     Raw   'GKON' 'PPGM' "GraphicConverter - Portable Graymap (image/x-pgm)"
+.pgm     Raw   'GKON' 'PPGM' "GraphicConverter - Portable Graymap (image/x-portable-graymap)"
+.pi1     Raw   'GKON' 'Dega' "GraphicConverter - Atari Degas Image"
+.pi2     Raw   'GKON' 'Dega' "GraphicConverter - Atari Degas Image"
+.pi3     Raw   'GKON' 'Dega' "GraphicConverter - Atari Degas Image"
+.pic     Raw   'ttxt' 'PICT' "SimpleText - PICT Picture (image/x-pict)"
+.pict    Raw   'ttxt' 'PICT' "SimpleText - PICT Picture (image/x-macpict)"
+.pit     Raw   'SITx' 'PIT ' "StuffIt Expander - PackIt Archive"
+.pkg     Raw   'GEOL' 'HBSF' "AppleLink - AppleLink Package"
+.pl      Ascii 'McPL' 'TEXT' "MacPerl - Perl Source"
+.plt     Raw   'GKON' 'HPGL' "GraphicConverter - HP GL/2"
+.pm      Raw   'GKON' 'PMpm' "GraphicConverter - Bitmap from xv"
+.pm3     Raw   'ALD3' 'ALB3' "PageMaker - PageMaker 3 Document"
+.pm4     Raw   'ALD4' 'ALB4' "PageMaker - PageMaker 4 Document"
+.pm5     Raw   'ALD5' 'ALB5' "PageMaker - PageMaker 5 Document"
+.png     Raw   'GKON' 'PNG ' "GraphicConverter - Portable Network Graphic"
+.pntg    Raw   'GKON' 'PNTG' "GraphicConverter - Macintosh Painting"
+.ppd     Ascii 'ALD5' 'TEXT' "PageMaker - Printer Description"
+.ppm     Raw   'GKON' 'PPGM' "GraphicConverter - Portable Pixmap (image/x-ppm)"
+.ppm     Raw   'GKON' 'PPGM' "GraphicConverter - Portable Pixmap (image/x-portable-pixmap)"
+.prn     Ascii 'TBB6' 'TEXT' "TexEdit - Printer Output File"
+.ps      Ascii 'vgrd' 'TEXT' "LaserWriter 8 - PostScript (application/postscript)"
+.psd     Raw   '8BIM' '8BPS' "Photoshop - PhotoShop Document"
+.pt4     Raw   'ALD4' 'ALT4' "PageMaker - PageMaker 4 Template"
+.pt5     Raw   'ALD5' 'ALT5' "PageMaker - PageMaker 5 Template"
+.pxr     Raw   '8BIM' 'PXR ' "Photoshop - Pixar Image"
+.qdv     Raw   'GKON' 'QDVf' "GraphicConverter - QDV image"
+.qt      Raw   'ttxt' 'MooV' "SimpleText - QuickTime Movie (video/quicktime)"
+.qxd     Raw   'XPR3' 'XDOC' "QuarkXpress - QuarkXpress Document"
+.qxt     Raw   'XPR3' 'XTMP' "QuarkXpress - QuarkXpress Template"
+.ram     Ascii '????' 'TEXT' "Unknown - Real Audio (audio/x-pn-realaudio)"
+.raw     Raw   'GKON' 'BINA' "GraphicConverter - Raw Image"
+.readme  Ascii 'TBB6' 'TEXT' "TexEdit - Text Readme (application/text)"
+.rgb     Raw   'GKON' 'SGI ' "GraphicConverter - SGI Image (image/x-rgb)"
+.rgba    Raw   'GKON' 'SGI ' "GraphicConverter - SGI Image (image/x-rgb)"
+.rib     Ascii 'RINI' 'TEXT' "Renderman - Renderman 3D Data"
+.rif     Raw   'GKON' 'RIFF' "GraphicConverter - RIFF Graphic"
+.rle     Raw   'GKON' 'RLE ' "GraphicConverter - RLE image"
+.rme     Ascii 'ttxt' 'TEXT' "SimpleText - Text Readme"
+.rpl     Raw   'REP!' 'FRL!' "Replica - Replica Document"
+.rsc     Raw   'RSED' 'rsrc' "ResEdit - Resource File"
+.rsrc    Raw   'RSED' 'rsrc' "ResEdit - Resource File"
+.rtf     Ascii 'MSWD' 'TEXT' "Microsoft Word - Rich Text Format (application/rtf)"
+.rtx     Ascii 'TBB6' 'TEXT' "TexEdit - Rich Text (text/richtext)"
+.s3m     Raw   'SNPL' 'S3M ' "PlayerPro - ScreamTracker 3 MOD"
+.scc     Raw   'GKON' 'MSX ' "GraphicConverter - MSX pitcure"
+.usal     Raw   'GKON' 'RIX3' "GraphicConverter - ColoRIX"
+.sci     Raw   'GKON' 'RIX3' "GraphicConverter - ColoRIX"
+.scp     Raw   'GKON' 'RIX3' "GraphicConverter - ColoRIX"
+.scr     Raw   'GKON' 'RIX3' "GraphicConverter - ColoRIX"
+.scu     Raw   'GKON' 'RIX3' "GraphicConverter - ColoRIX"
+.sea     Raw   '????' 'APPL' "Self Extracting Archive - Self-Extracting Archive"
+.sf      Raw   'SDHK' 'IRCM' "SoundHack - IRCAM Sound"
+.sgi     Raw   'GKON' 'SGI ' "GraphicConverter - SGI Image"
+.sha     Ascii 'UnSh' 'TEXT' "UnShar - Unix Shell Archive (application/x-shar)"
+.shar    Ascii 'UnSh' 'TEXT' "UnShar - Unix Shell Archive (application/x-shar)"
+.shp     Raw   'GKON' 'SHPp' "GraphicConverter - Printmaster Icon Library"
+.sit     Raw   'SIT!' 'SITD' "StuffIt - StuffIt Archive"
+.sithqx  Ascii 'TBB6' 'TEXT' "TexEdit - BinHexed StuffIt Archive (application/mac-binhex40)"
+.six     Raw   'GKON' 'SIXE' "GraphicConverter - SIXEL image"
+.slk     Ascii 'XCEL' 'TEXT' "Excel - SYLK Spreadsheet"
+.snd     Raw   'SCPL' 'BINA' "SoundApp - Sound of various types"
+.spc     Raw   'GKON' 'Spec' "GraphicConverter - Atari Spectrum 512"
+.sr      Raw   'GKON' 'SUNn' "GraphicConverter - Sun Raster Image"
+.sty     Ascii '*TEX' 'TEXT' "Textures - TeX Style"
+.sun     Raw   'GKON' 'SUNn' "GraphicConverter - Sun Raster Image"
+.sup     Raw   'GKON' 'SCRN' "GraphicConverter - StartupScreen"
+.svx     Raw   'SCPL' '8SVX' "SoundApp - Amiga IFF Sound"
+.syk     Ascii 'XCEL' 'TEXT' "Excel - SYLK Spreadsheet"
+.sylk    Ascii 'XCEL' 'TEXT' "Excel - SYLK Spreadsheet"
+.tar     Raw   'S691' 'TARF' "SunTar - Unix Tape ARchive (application/x-tar)"
+.targa   Raw   'GKON' 'TPIC' "GraphicConverter - Truevision Image"
+.taz     Raw   'SITx' 'ZIVU' "StuffIt Expander - Compressed Tape ARchive (application/x-compress)"
+.tex     Ascii 'OTEX' 'TEXT' "OzTeX - TeX Document (application/x-tex)"
+.texi    Ascii 'OTEX' 'TEXT' "OzTeX - TeX Document"
+.texinfo Ascii 'OTEX' 'TEXT' "OzTeX - TeX Document (application/x-texinfo)"
+.text    Ascii 'ttxt' 'TEXT' "SimpleText - ASCII Text (text/plain)"
+.tga     Raw   'GKON' 'TPIC' "GraphicConverter - Truevision Image"
+.tgz     Raw   'Gzip' 'Gzip' "MacGzip - Gnu ZIPed Tape ARchive (application/x-gzip)"
+.tif     Raw   'JVWR' 'TIFF' "JPEGView - TIFF Picture (image/tiff)"
+.tiff    Raw   'JVWR' 'TIFF' "JPEGView - TIFF Picture (image/tiff)"
+.tny     Raw   'GKON' 'TINY' "GraphicConverter - Atari TINY Bitmap"
+.tsv     Ascii 'XCEL' 'TEXT' "Excel - Tab Separated Values (text/tab-separated-values)"
+.tx8     Ascii 'ttxt' 'TEXT' "SimpleText - 8-bit ASCII Text"
+.txt     Ascii 'ttxt' 'TEXT' "SimpleText - ASCII Text (text/plain)"
+.ul      Raw   'SCPL' 'ULAW' "SoundApp - Mu-Law Sound (audio/basic)"
+.url     Raw   'Arch' 'AURL' "Anarchie - URL Bookmark (message/external-body)"
+.uu      Ascii 'TBB6' 'TEXT' "TexEdit - UUEncode"
+.uue     Ascii 'TBB6' 'TEXT' "TexEdit - UUEncode"
+.vff     Raw   'GKON' 'VFFf' "GraphicConverter - DESR VFF Greyscale Image"
+.vga     Raw   'JVWR' 'BMPp' "JPEGView - OS/2 Bitmap"
+.voc     Raw   'SCPL' 'VOC ' "SoundApp - VOC Sound"
+.w51     Raw   'WPC2' '.WP5' "WordPerfect - WordPerfect PC 5.1 Doc (application/wordperfect5.1)"
+.wav     Raw   'SCPL' 'WAVE' "SoundApp - Windows WAV Sound (audio/x-wav)"
+.wk1     Raw   'XCEL' 'XLBN' "Excel - Lotus Spreadsheet r2.1"
+.wks     Raw   'XCEL' 'XLBN' "Excel - Lotus Spreadsheet r1.x"
+.wmf     Raw   'GKON' 'WMF ' "GraphicConverter - Windows Metafile"
+.wp      Raw   'WPC2' '.WP5' "WordPerfect - WordPerfect PC 5.1 Doc (application/wordperfect5.1)"
+.wp4     Raw   'WPC2' '.WP4' "WordPerfect - WordPerfect PC 4.2 Doc"
+.wp5     Raw   'WPC2' '.WP5' "WordPerfect - WordPerfect PC 5.x Doc (application/wordperfect5.1)"
+.wp6     Raw   'WPC2' '.WP6' "WordPerfect - WordPerfect PC 6.x Doc"
+.wpg     Raw   'GKON' 'WPGf' "GraphicConverter - WordPerfect Graphic"
+.wpm     Raw   'WPC2' 'WPD1' "WordPerfect - WordPerfect Mac"
+.wri     Raw   'MSWD' 'WDBN' "Microsoft Word - MS Write/Windows"
+.wve     Raw   'SCPL' 'BINA' "SoundApp - PSION sound"
+.x10     Raw   'GKON' 'XWDd' "GraphicConverter - X-Windows Dump (image/x-xwd)"
+.x11     Raw   'GKON' 'XWDd' "GraphicConverter - X-Windows Dump (image/x-xwd)"
+.xbm     Raw   'GKON' 'XBM ' "GraphicConverter - X-Windows Bitmap (image/x-xbm)"
+.xbm     Raw   'GKON' 'XBM ' "GraphicConverter - X-Windows Bitmap (image/x-xbitmap)"
+.xl      Raw   'XCEL' 'XLS ' "Excel - Excel Spreadsheet"
+.xlc     Raw   'XCEL' 'XLC ' "Excel - Excel Chart"
+.xlm     Raw   'XCEL' 'XLM ' "Excel - Excel Macro"
+.xls     Raw   'XCEL' 'XLS ' "Excel - Excel Spreadsheet"
+.xlw     Raw   'XCEL' 'XLW ' "Excel - Excel Workspace"
+.xm      Raw   'SNPL' 'XM  ' "PlayerPro - FastTracker MOD Music"
+.xpm     Raw   'GKON' 'XPM ' "GraphicConverter - X-Windows Pixmap (image/x-xpm)"
+.xpm     Raw   'GKON' 'XPM ' "GraphicConverter - X-Windows Pixmap (image/x-xpixmap)"
+.xwd     Raw   'GKON' 'XWDd' "GraphicConverter - X-Windows Dump (image/x-xwd)"
+#
+# Add the default translation for anything not recognized
+#
+*        Ascii 'ttxt' 'TEXT' "SimpleText - Text file"
diff --git a/genisoimage/multi.c b/genisoimage/multi.c
new file mode 100644 (file)
index 0000000..e069c91
--- /dev/null
@@ -0,0 +1,1912 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)multi.c 1.68 05/05/15 joerg */
+/*
+ * File multi.c - scan existing iso9660 image and merge into
+ * iso9660 filesystem.  Used for multisession support.
+ *
+ * Written by Eric Youngdale (1996).
+ * Copyright (c) 1999-2003 J. Schilling
+ *
+ * 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 <mconfig.h>
+#include "genisoimage.h"
+#include <timedefs.h>
+#include <errno.h>
+#include <utypes.h>
+#include <schily.h>
+#include <ctype.h>                     /* Needed for printasc()        */
+
+#ifdef VMS
+
+#include <sys/file.h>
+#include <vms/fabdef.h>
+#include "vms.h"
+#endif
+
+#ifndef howmany
+#define        howmany(x, y)   (((x)+((y)-1))/(y))
+#endif
+#ifndef roundup
+#define        roundup(x, y)   ((((x)+((y)-1))/(y))*(y))
+#endif
+
+/*
+ * Cannot debug memset() with gdb on Linux, so use fillbytes()
+ */
+/*#define      memset(s, c, n) fillbytes(s, n, c)*/
+
+#define        TF_CREATE 1
+#define        TF_MODIFY 2
+#define        TF_ACCESS 4
+#define        TF_ATTRIBUTES 8
+
+static int     isonum_711(unsigned char *p);
+static int     isonum_721(unsigned char *p);
+static int     isonum_723(unsigned char *p);
+static int     isonum_731(unsigned char *p);
+
+static void    printasc(char *txt, unsigned char *p, int len);
+static void    prbytes(char *txt, unsigned char *p, int len);
+unsigned char  *parse_xa(unsigned char *pnt, int *lenp,
+                                                                struct directory_entry *dpnt);
+int    rr_flags(struct iso_directory_record *idr);
+static int     parse_rrflags(Uchar *pnt, int len, int cont_flag);
+static BOOL    find_rr(struct iso_directory_record *idr, Uchar **pntp, 
+                                                         int *lenp);
+static  int    parse_rr(unsigned char *pnt, int len, 
+                                                               struct directory_entry *dpnt);
+static int     check_rr_dates(struct directory_entry *dpnt,
+                                                                               struct directory_entry *current,
+                                                                               struct stat *statbuf,
+                                                                               struct stat *lstatbuf);
+static struct directory_entry **
+               read_merging_directory(struct iso_directory_record *, int *);
+static int     free_mdinfo(struct directory_entry **, int len);
+static void    free_directory_entry(struct directory_entry * dirp);
+static void    merge_remaining_entries(struct directory *,
+                                                                                                       struct directory_entry **, int);
+
+static int     merge_old_directory_into_tree(struct directory_entry *,
+                                                                                                                       struct directory *);
+static void    check_rr_relocation(struct directory_entry *de);
+
+static int
+isonum_711(unsigned char *p)
+{
+       return (*p & 0xff);
+}
+
+static int
+isonum_721(unsigned char *p)
+{
+       return ((p[0] & 0xff) | ((p[1] & 0xff) << 8));
+}
+
+static int
+isonum_723(unsigned char *p)
+{
+#if 0
+       if (p[0] != p[3] || p[1] != p[2]) {
+#ifdef USE_LIBSCHILY
+               comerrno(EX_BAD, "invalid format 7.2.3 number\n");
+#else
+               fprintf(stderr, "invalid format 7.2.3 number\n");
+               exit(1);
+#endif
+       }
+#endif
+       return (isonum_721(p));
+}
+
+static int
+isonum_731(unsigned 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));
+}
+
+FILE   *in_image = NULL;
+
+#ifndef        USE_SCG
+/*
+ * Don't define readsecs if genisoimage is linked with
+ * the SCSI library.
+ * readsecs() will be implemented as SCSI command in this case.
+ *
+ * Use global var in_image directly in readsecs()
+ * the SCSI equivalent will not use a FILE* for I/O.
+ *
+ * The main point of this pointless abstraction is that Solaris won't let
+ * you read 2K sectors from the cdrom driver.  The fact that 99.9% of the
+ * discs out there have a 2K sectorsize doesn't seem to matter that much.
+ * Anyways, this allows the use of a scsi-generics type of interface on
+ * Solaris.
+ */
+static int
+readsecs(int startsecno, void *buffer, int sectorcount)
+{
+       int             f = fileno(in_image);
+
+       if (lseek(f, (off_t) startsecno * SECTOR_SIZE, SEEK_SET) == (off_t) - 1) {
+#ifdef USE_LIBSCHILY
+               comerr(" Seek error on old image\n");
+#else
+               fprintf(stderr, " Seek error on old image\n");
+               exit(10);
+#endif
+       }
+       if (read(f, buffer, (sectorcount * SECTOR_SIZE))
+               != (sectorcount * SECTOR_SIZE)) {
+#ifdef USE_LIBSCHILY
+               comerr(" Read error on old image\n");
+#else
+               fprintf(stderr, " Read error on old image\n");
+               exit(10);
+#endif
+       }
+       return (sectorcount * SECTOR_SIZE);
+}
+
+#endif
+
+static void
+printasc(char *txt, unsigned char *p, int len)
+{
+       int             i;
+
+       fprintf(stderr, "%s ", txt);
+       for (i = 0; i < len; i++) {
+               if (isprint(p[i]))
+                       fprintf(stderr, "%c", p[i]);
+               else
+                       fprintf(stderr, ".");
+       }
+       fprintf(stderr, "\n");
+}
+
+static void
+prbytes(char *txt, register Uchar *p, register int len)
+{
+       fprintf(stderr, "%s", txt);
+       while (--len >= 0)
+               fprintf(stderr, " %02X", *p++);
+       fprintf(stderr, "\n");
+}
+
+unsigned char *
+parse_xa(unsigned char *pnt, int *lenp, struct directory_entry *dpnt)
+{
+       struct iso_xa_dir_record *xadp;
+       int             len = *lenp;
+static int             did_xa = 0;
+
+/*fprintf(stderr, "len: %d\n", len);*/
+
+       if (len >= 14) {
+               xadp = (struct iso_xa_dir_record *)pnt;
+
+/*             if (dpnt) prbytes("XA ", pnt, len);*/
+               if (xadp->signature[0] == 'X' && xadp->signature[1] == 'A' &&
+                               xadp->reserved[0] == '\0') {
+                       len -= 14;
+                       pnt += 14;
+                       *lenp = len;
+                       if (!did_xa) {
+                               did_xa = 1;
+                               errmsgno(EX_BAD, "Found XA directory extension record.\n");
+                       }
+               } else if (pnt[2] == 0) {
+                       char *cp = NULL;
+
+                       if (dpnt)
+                               cp = (char *)&dpnt->isorec;
+                       if (cp) {
+                               prbytes("ISOREC:", (Uchar *)cp, 33+cp[32]);
+                               printasc("ISOREC:", (Uchar *)cp, 33+cp[32]);
+                               prbytes("XA REC:", pnt, len);
+                               printasc("XA REC:", pnt, len);
+                       }
+                       if (no_rr == 0) {
+                               errmsgno(EX_BAD, "Disabling RR / XA / AA.\n");
+                               no_rr = 1;
+                       }
+                       *lenp = 0;
+                       if (cp) {
+                               errmsgno(EX_BAD, "Problems with old ISO directory entry for file: '%s'.\n", &cp[33]);
+                       }
+                       errmsgno(EX_BAD, "Illegal extended directory attributes found (bad XA disk?).\n");
+/*                     errmsgno(EX_BAD, "Disabling Rock Ridge for old session.\n");*/
+                       comerrno(EX_BAD, "Try again using the -no-rr option.\n");
+               }
+       }
+       if (len >= 4 && pnt[3] != 1 && pnt[3] != 2) {
+               prbytes("BAD RR ATTRIBUTES:", pnt, len);
+               printasc("BAD RR ATTRIBUTES:", pnt, len);
+       }
+       return (pnt);
+}
+
+static BOOL
+find_rr(struct iso_directory_record *idr, Uchar **pntp, int *lenp)
+{
+       struct iso_xa_dir_record *xadp;
+       int             len;
+       unsigned char   *pnt;
+       BOOL            ret = FALSE;
+
+       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--;
+       }
+       if (len >= 14) {
+               xadp = (struct iso_xa_dir_record *)pnt;
+
+               if (xadp->signature[0] == 'X' && xadp->signature[1] == 'A' &&
+                               xadp->reserved[0] == '\0') {
+                       len -= 14;
+                       pnt += 14;
+                       ret = TRUE;
+               }
+       }
+       *pntp = pnt;
+       *lenp = len;
+       return (ret);
+}
+
+static int
+parse_rrflags(Uchar *pnt, int len, int cont_flag)
+{
+       int     ncount;
+       int     cont_extent;
+       int     cont_offset;
+       int     cont_size;
+       int     flag1;
+       int     flag2;
+
+       cont_extent = cont_offset = cont_size = 0;
+
+       ncount = 0;
+       flag1 = flag2 = 0;
+       while (len >= 4) {
+               if (pnt[3] != 1 && pnt[3] != 2) {
+#ifdef USE_LIBSCHILY
+                       errmsgno(EX_BAD,
+                               "**BAD RRVERSION (%d) for %c%c\n",
+                               pnt[3], pnt[0], pnt[1]);
+#else
+                       fprintf(stderr,
+                               "**BAD RRVERSION (%d) for %c%c\n",
+                               pnt[3], pnt[0], pnt[1]);
+#endif
+                       return (0);     /* JS ??? Is this right ??? */
+               }
+               ncount++;
+               if (pnt[0] == 'R' && pnt[1] == 'R')
+                       flag1 = pnt[4] & 0xff;
+
+               if (strncmp((char *) pnt, "PX", 2) == 0)        /* POSIX attributes */
+                       flag2 |= 1;
+               if (strncmp((char *) pnt, "PN", 2) == 0)        /* POSIX device number */
+                       flag2 |= 2;
+               if (strncmp((char *) pnt, "SL", 2) == 0)        /* Symlink */
+                       flag2 |= 4;
+               if (strncmp((char *) pnt, "NM", 2) == 0)        /* Alternate Name */
+                       flag2 |= 8;
+               if (strncmp((char *) pnt, "CL", 2) == 0)        /* Child link */
+                       flag2 |= 16;
+               if (strncmp((char *) pnt, "PL", 2) == 0)        /* Parent link */
+                       flag2 |= 32;
+               if (strncmp((char *) pnt, "RE", 2) == 0)        /* Relocated Direcotry */
+                       flag2 |= 64;
+               if (strncmp((char *) pnt, "TF", 2) == 0)        /* Time stamp */
+                       flag2 |= 128;
+               if (strncmp((char *) pnt, "SP", 2) == 0) {      /* SUSP record */
+                       flag2 |= 1024;
+/*                     su_version = pnt[3] & 0xff;*/
+               }
+               if (strncmp((char *) pnt, "AA", 2) == 0) {      /* Apple Signature record */
+                       flag2 |= 2048;
+/*                     aa_version = pnt[3] & 0xff;*/
+               }
+
+               if (strncmp((char *)pnt, "CE", 2) == 0) {       /* Continuation Area */
+                       cont_extent = isonum_733(pnt+4);
+                       cont_offset = isonum_733(pnt+12);
+                       cont_size = isonum_733(pnt+20);
+               }
+
+               len -= pnt[2];
+               pnt += pnt[2];
+               if (len <= 3 && cont_extent) {
+                       unsigned char   sector[SECTOR_SIZE];
+
+                       readsecs(cont_extent, sector, 1);
+                       flag2 |= parse_rrflags(&sector[cont_offset], cont_size, 1);
+               }
+       }
+       return (flag2);
+}
+
+int
+rr_flags(struct iso_directory_record *idr)
+{
+       int             len;
+       unsigned char   *pnt;
+       int             ret = 0;
+
+       if (find_rr(idr, &pnt, &len))
+               ret |= 4096;
+       ret |= parse_rrflags(pnt, len, 0);
+       return (ret);
+}
+
+/*
+ * Parse the RR attributes so we can find the file name.
+ */
+static int
+parse_rr(unsigned char *pnt, int len, struct directory_entry *dpnt)
+{
+       int             cont_extent;
+       int             cont_offset;
+       int             cont_size;
+       char            name_buf[256];
+
+       cont_extent = cont_offset = cont_size = 0;
+
+       pnt = parse_xa(pnt, &len, dpnt /* 0 */);
+
+       while (len >= 4) {
+               if (pnt[3] != 1 && pnt[3] != 2) {
+#ifdef USE_LIBSCHILY
+                       errmsgno(EX_BAD,
+                               "**BAD RRVERSION (%d) for %c%c\n",
+                               pnt[3], pnt[0], pnt[1]);
+#else
+                       fprintf(stderr,
+                               "**BAD RRVERSION (%d) for %c%c\n",
+                               pnt[3], pnt[0], pnt[1]);
+#endif
+                       return (-1);
+               }
+               if (strncmp((char *) pnt, "NM", 2) == 0) {
+                       strncpy(name_buf, (char *) pnt + 5, pnt[2] - 5);
+                       name_buf[pnt[2] - 5] = 0;
+                       if (dpnt->name) {
+                               size_t nlen = strlen(dpnt->name);
+
+                               /*
+                                * append to name from previous NM records
+                                */
+                               dpnt->name = realloc(dpnt->name, nlen +
+                                                       strlen(name_buf) + 1);
+                               strcpy(dpnt->name + nlen, name_buf);
+                       } else {
+                               dpnt->name = strdup(name_buf);
+                               dpnt->got_rr_name = 1;
+                       }
+                       /* continue searching for more NM records */
+               } else if (strncmp((char *) pnt, "CE", 2) == 0) {
+                       cont_extent = isonum_733(pnt + 4);
+                       cont_offset = isonum_733(pnt + 12);
+                       cont_size = isonum_733(pnt + 20);
+               }
+
+               len -= pnt[2];
+               pnt += pnt[2];
+               if (len <= 3 && cont_extent) {
+                       unsigned char   sector[SECTOR_SIZE];
+
+                       readsecs(cont_extent, sector, 1);
+                       if (parse_rr(&sector[cont_offset],
+                                                       cont_size, dpnt) == -1)
+                               return (-1);
+               }
+       }
+
+       /* Fall back to the iso name if no RR name found */
+       if (dpnt->name == NULL) {
+               char    *cp;
+
+               strcpy(name_buf, dpnt->isorec.name);
+               cp = strchr(name_buf, ';');
+               if (cp != NULL) {
+                       *cp = '\0';
+               }
+               dpnt->name = strdup(name_buf);
+       }
+       return (0);
+}/* parse_rr */
+
+
+/*
+ * Returns 1 if the two files are identical
+ * Returns 0 if the two files differ
+ */
+static int
+check_rr_dates(struct directory_entry *dpnt, 
+                                       struct directory_entry *current, 
+                                       struct stat *statbuf, 
+                                       struct stat *lstatbuf)
+{
+       int             cont_extent;
+       int             cont_offset;
+       int             cont_size;
+       int             offset;
+       unsigned char   *pnt;
+       int             len;
+       int             same_file;
+       int             same_file_type;
+       mode_t          mode;
+       char            time_buf[7];
+
+
+       cont_extent = cont_offset = cont_size = 0;
+       same_file = 1;
+       same_file_type = 1;
+
+       pnt = dpnt->rr_attributes;
+       len = dpnt->rr_attr_size;
+       /*
+        * We basically need to parse the rr attributes again, and dig out the
+        * dates and file types.
+        */
+       pnt = parse_xa(pnt, &len, /* dpnt */ 0);
+       while (len >= 4) {
+               if (pnt[3] != 1 && pnt[3] != 2) {
+#ifdef USE_LIBSCHILY
+                       errmsgno(EX_BAD,
+                               "**BAD RRVERSION (%d) for %c%c\n",
+                               pnt[3], pnt[0], pnt[1]);
+#else
+                       fprintf(stderr,
+                               "**BAD RRVERSION (%d) for %c%c\n",
+                               pnt[3], pnt[0], pnt[1]);
+#endif
+                       return (-1);
+               }
+
+               /*
+                * If we have POSIX file modes, make sure that the file type is
+                * the same.  If it isn't, then we must always write the new
+                * file.
+                */
+               if (strncmp((char *) pnt, "PX", 2) == 0) {
+                       mode = isonum_733(pnt + 4);
+                       if ((lstatbuf->st_mode & S_IFMT) != (mode & S_IFMT)) {
+                               same_file_type = 0;
+                               same_file = 0;
+                       }
+               }
+               if (strncmp((char *) pnt, "TF", 2) == 0) {
+                       offset = 5;
+                       if (pnt[4] & TF_CREATE) {
+                               iso9660_date((char *) time_buf,
+                                                       lstatbuf->st_ctime);
+                               if (memcmp(time_buf, pnt + offset, 7) != 0)
+                                       same_file = 0;
+                               offset += 7;
+                       }
+                       if (pnt[4] & TF_MODIFY) {
+                               iso9660_date((char *) time_buf,
+                                                       lstatbuf->st_mtime);
+                               if (memcmp(time_buf, pnt + offset, 7) != 0)
+                                       same_file = 0;
+                               offset += 7;
+                       }
+               }
+               if (strncmp((char *) pnt, "CE", 2) == 0) {
+                       cont_extent = isonum_733(pnt + 4);
+                       cont_offset = isonum_733(pnt + 12);
+                       cont_size = isonum_733(pnt + 20);
+               }
+
+               len -= pnt[2];
+               pnt += pnt[2];
+               if (len <= 3 && cont_extent) {
+                       unsigned char   sector[SECTOR_SIZE];
+
+                       readsecs(cont_extent, sector, 1);
+                       /*
+                        * Continue to scan the extension record.
+                        * Note that this has not been tested yet, but it is
+                        * definitely more correct that calling parse_rr()
+                        * as done in Eric's old code.
+                        */
+                       pnt = &sector[cont_offset];
+                       len = cont_size;
+                       /*
+                        * Clear the "pending extension record" state as
+                        * we did already read it now.
+                        */
+                       cont_extent = cont_offset = cont_size = 0;
+               }
+       }
+
+       /*
+        * If we have the same fundamental file type, then it is clearly safe
+        * to reuse the TRANS.TBL entry.
+        */
+       if (same_file_type) {
+               current->de_flags |= SAFE_TO_REUSE_TABLE_ENTRY;
+       }
+       return (same_file);
+}
+
+static struct directory_entry **
+read_merging_directory(struct iso_directory_record *mrootp, int *nentp)
+{
+       unsigned char   *cpnt;
+       unsigned char   *cpnt1;
+       char            *p;
+       char            *dirbuff;
+       int             i;
+       struct iso_directory_record *idr;
+       int             len;
+       int             nbytes;
+       int             nent;
+       struct directory_entry **pnt;
+       int             rlen;
+       struct directory_entry **rtn;
+       int             seen_rockridge;
+       unsigned char   *tt_buf;
+       int             tt_extent;
+       int             tt_size;
+
+       static int      warning_given = 0;
+
+       /*
+        * This is the number of sectors we will need to read.  We need to
+        * round up to get the last fractional sector - we are asking for the
+        * data in terms of a number of sectors.
+        */
+       nbytes = roundup(isonum_733((unsigned char *) mrootp->size),
+                                                               SECTOR_SIZE);
+
+       /*
+        * First, allocate a buffer large enough to read in the entire
+        * directory.
+        */
+       dirbuff = (char *) e_malloc(nbytes);
+
+       readsecs(isonum_733((unsigned char *) mrootp->extent), dirbuff,
+               nbytes / SECTOR_SIZE);
+
+       /*
+        * Next look over the directory, and count up how many entries we have.
+        */
+       len = isonum_733((unsigned char *) mrootp->size);
+       i = 0;
+       *nentp = 0;
+       nent = 0;
+       while (i < len) {
+               idr = (struct iso_directory_record *) & dirbuff[i];
+               if (idr->length[0] == 0) {
+                       i = ISO_ROUND_UP(i);
+                       continue;
+               }
+               nent++;
+               i += idr->length[0];
+       }
+
+       /*
+        * Now allocate the buffer which will hold the array we are about to
+        * return.
+        */
+       rtn = (struct directory_entry **) e_malloc(nent * sizeof (*rtn));
+
+       /*
+        * Finally, scan the directory one last time, and pick out the relevant
+        * bits of information, and store it in the relevant bits of the
+        * structure.
+        */
+       i = 0;
+       pnt = rtn;
+       tt_extent = 0;
+       seen_rockridge = 0;
+       tt_size = 0;
+       while (i < len) {
+               idr = (struct iso_directory_record *) & dirbuff[i];
+               if (idr->length[0] == 0) {
+                       i = ISO_ROUND_UP(i);
+                       continue;
+               }
+               *pnt = (struct directory_entry *) e_malloc(sizeof (**rtn));
+               (*pnt)->next = NULL;
+#ifdef DEBUG
+               fprintf(stderr, "IDR name: '%s' ist: %d soll: %d\n",
+                       idr->name, strlen(idr->name), idr->name_len[0]);
+#endif
+               (*pnt)->isorec = *idr;
+               (*pnt)->starting_block =
+                               isonum_733((unsigned char *) idr->extent);
+               (*pnt)->size = isonum_733((unsigned char *) idr->size);
+               (*pnt)->priority = 0;
+               (*pnt)->name = NULL;
+               (*pnt)->got_rr_name = 0;
+               (*pnt)->table = NULL;
+               (*pnt)->whole_name = NULL;
+               (*pnt)->filedir = NULL;
+               (*pnt)->parent_rec = NULL;
+               /*
+                * Set this information so that we correctly cache previous
+                * session bits of information.
+                */
+               (*pnt)->inode = (*pnt)->starting_block;
+               (*pnt)->dev = PREV_SESS_DEV;
+               (*pnt)->rr_attributes = NULL;
+               (*pnt)->rr_attr_size = 0;
+               (*pnt)->total_rr_attr_size = 0;
+               (*pnt)->de_flags = SAFE_TO_REUSE_TABLE_ENTRY;
+#ifdef APPLE_HYB
+               (*pnt)->assoc = NULL;
+               (*pnt)->hfs_ent = NULL;
+#endif /* APPLE_HYB */
+
+               /*
+                * Check for and parse any RR attributes for the file. All we
+                * are really looking for here is the original name of the
+                * file.
+                */
+               rlen = idr->length[0] & 0xff;
+               cpnt = (unsigned char *) idr;
+
+               rlen -= offsetof(struct iso_directory_record, name[0]);
+               cpnt += offsetof(struct iso_directory_record, name[0]);
+
+               rlen -= idr->name_len[0];
+               cpnt += idr->name_len[0];
+
+               if ((idr->name_len[0] & 1) == 0) {
+                       cpnt++;
+                       rlen--;
+               }
+
+               if (no_rr)
+                       rlen = 0;
+               if (rlen > 0) {
+                       (*pnt)->total_rr_attr_size =
+                                               (*pnt)->rr_attr_size = rlen;
+                       (*pnt)->rr_attributes = e_malloc(rlen);
+                       memcpy((*pnt)->rr_attributes, cpnt, rlen);
+                       seen_rockridge = 1;
+               }
+#ifdef DEBUG
+               fprintf(stderr, "INT name: '%s' ist: %d soll: %d\n",
+                       (*pnt)->isorec.name, strlen((*pnt)->isorec.name),
+                       idr->name_len[0]);
+#endif
+
+               if (idr->name_len[0] < sizeof ((*pnt)->isorec.name)) {
+                       /*
+                        * Now zero out the remainder of the name field.
+                        */
+                       cpnt = (unsigned char *) (*pnt)->isorec.name;
+                       cpnt += idr->name_len[0];
+                       memset(cpnt, 0,
+                               sizeof ((*pnt)->isorec.name) - idr->name_len[0]);
+               } else {
+                       /*
+                        * Simple sanity work to make sure that we have no
+                        * illegal data structures in our tree.
+                        */
+                       (*pnt)->isorec.name[MAX_ISONAME] = '\0';
+                       (*pnt)->isorec.name_len[0] = MAX_ISONAME;
+               }
+               /*
+                * If the filename len from the old session is more
+                * then 31 chars, there is a high risk of hard violations
+                * if the ISO9660 standard.
+                * Run it through our name canonication machine....
+                */
+               if (idr->name_len[0] > LEN_ISONAME || check_oldnames) {
+                       iso9660_check(idr, *pnt);
+               }
+
+               if (parse_rr((*pnt)->rr_attributes, rlen, *pnt) == -1) {
+#ifdef USE_LIBSCHILY
+                       comerrno(EX_BAD,
+                           "Cannot parse Rock Ridge attributes for '%s'.\n",
+                                                               idr->name);
+#else
+                       fprintf(stderr,
+                           "Cannot parse Rock Ridge attributes for '%s'.\n",
+                                                               idr->name);
+                       exit(1);
+#endif
+               }
+               if (((*pnt)->isorec.name_len[0] == 1) &&
+                   (((*pnt)->isorec.name[0] == 0) ||   /* "."  entry */
+                   ((*pnt)->isorec.name[0] == 1))) {   /* ".." entry */
+
+                       if ((*pnt)->name != NULL) {
+                               free((*pnt)->name);
+                       }
+                       if ((*pnt)->whole_name != NULL) {
+                               free((*pnt)->whole_name);
+                       }
+                       if ((*pnt)->isorec.name[0] == 0) {
+                               (*pnt)->name = strdup(".");
+                       } else {
+                               (*pnt)->name = strdup("..");
+                       }
+               }
+#ifdef DEBUG
+               fprintf(stderr, "got DE name: %s\n", (*pnt)->name);
+#endif
+
+               if (strncmp(idr->name, trans_tbl, strlen(trans_tbl)) == 0) {
+                       if ((*pnt)->name != NULL) {
+                               free((*pnt)->name);
+                       }
+                       if ((*pnt)->whole_name != NULL) {
+                               free((*pnt)->whole_name);
+                       }
+/*                     (*pnt)->name = strdup("<translation table>");*/
+                       (*pnt)->name = strdup(trans_tbl);
+                       tt_extent = isonum_733((unsigned char *) idr->extent);
+                       tt_size = isonum_733((unsigned char *) idr->size);
+                       if (tt_extent == 0)
+                               tt_size = 0;
+               }
+               pnt++;
+               i += idr->length[0];
+       }
+#ifdef APPLE_HYB
+       /*
+        * If we find an associated file, check if there is a file
+        * with same ISO name and link it to this entry
+        */
+       for (pnt = rtn, i = 0; i < nent; i++, pnt++) {
+               int     j;
+
+               rlen = isonum_711((*pnt)->isorec.name_len);
+               if ((*pnt)->isorec.flags[0] & ISO_ASSOCIATED) {
+                       for (j = 0; j < nent; j++) {
+                               if (strncmp(rtn[j]->isorec.name,
+                                   (*pnt)->isorec.name, rlen) == 0 &&
+                                   (rtn[j]->isorec.flags[0] & ISO_ASSOCIATED) == 0) {
+                                       rtn[j]->assoc = *pnt;
+
+                                       /*
+                                        * don't want this entry to be
+                                        * in the Joliet tree
+                                        */
+                                       (*pnt)->de_flags |= INHIBIT_JOLIET_ENTRY;
+
+                                       /*
+                                        * as we have associated files, then
+                                        * assume we are are dealing with
+                                        * Apple's extensions - if not already
+                                        * set
+                                        */
+                                       if (apple_both == 0) {
+                                               apple_both = apple_ext = 1;
+                                       }
+                                       break;
+                               }
+                       }
+               }
+       }
+#endif /* APPLE_HYB */
+
+       /*
+        * If there was a TRANS.TBL;1 entry, then grab it, read it, and use it
+        * to get the filenames of the files.  Also, save the table info, just
+        * in case we need to use it.
+        *
+        * The entries look something like: F ISODUMP.;1 isodump
+        */
+       if (tt_extent != 0 && tt_size != 0) {
+               nbytes = roundup(tt_size, SECTOR_SIZE);
+               tt_buf = (unsigned char *) e_malloc(nbytes);
+               readsecs(tt_extent, tt_buf, nbytes / SECTOR_SIZE);
+
+               /*
+                * Loop through the file, examine each entry, and attempt to
+                * attach it to the correct entry.
+                */
+               cpnt = tt_buf;
+               cpnt1 = tt_buf;
+               while (cpnt - tt_buf < tt_size) {
+                       /* Skip to a line terminator, or end of the file. */
+                       while ((cpnt1 - tt_buf < tt_size) &&
+                               (*cpnt1 != '\n') &&
+                               (*cpnt1 != '\0')) {
+                               cpnt1++;
+                       }
+                       /* Zero terminate this particular line. */
+                       if (cpnt1 - tt_buf < tt_size) {
+                               *cpnt1 = '\0';
+                       }
+                       /*
+                        * Now dig through the actual directories, and try and
+                        * find the attachment for this particular filename.
+                        */
+                       for (pnt = rtn, i = 0; i < nent; i++, pnt++) {
+                               rlen = isonum_711((*pnt)->isorec.name_len);
+
+                               /*
+                                * If this filename is so long that it would
+                                * extend past the end of the file, it cannot
+                                * be the one we want.
+                                */
+                               if (cpnt + 2 + rlen - tt_buf >= tt_size) {
+                                       continue;
+                               }
+                               /*
+                                * Now actually compare the name, and make sure
+                                * that the character at the end is a ' '.
+                                */
+                               if (strncmp((char *) cpnt + 2,
+                                       (*pnt)->isorec.name, rlen) == 0 &&
+                                       cpnt[2 + rlen] == ' ' &&
+                                       (p = strchr((char *)&cpnt[2 + rlen], '\t'))) {
+                                       p++;
+                                       /*
+                                        * This is a keeper. Now determine the
+                                        * correct table entry that we will
+                                        * use on the new image.
+                                        */
+                                       if (strlen(p) > 0) {
+                                               (*pnt)->table =
+                                                   e_malloc(strlen(p) + 4);
+                                               sprintf((*pnt)->table,
+                                                       "%c\t%s\n",
+                                                       *cpnt, p);
+                                       }
+                                       if (!(*pnt)->got_rr_name) {
+                                               if ((*pnt)->name != NULL) {
+                                                       free((*pnt)->name);
+                                               }
+                                               (*pnt)->name = strdup(p);
+                                       }
+                                       break;
+                               }
+                       }
+                       cpnt = cpnt1 + 1;
+                       cpnt1 = cpnt;
+               }
+
+               free(tt_buf);
+       } else if (!seen_rockridge && !warning_given) {
+               /*
+                * Warn the user that iso-9660 names were used because neither
+                * Rock Ridge (-R) nor TRANS.TBL (-T) name translations were
+                * found.
+                */
+               fprintf(stderr,
+                   "Warning: Neither Rock Ridge (-R) nor TRANS.TBL (-T) \n");
+               fprintf(stderr,
+                   "name translations were found on previous session.\n");
+               fprintf(stderr,
+                   "ISO-9660 file names have been used instead.\n");
+               warning_given = 1;
+       }
+       if (dirbuff != NULL) {
+               free(dirbuff);
+       }
+       *nentp = nent;
+       return (rtn);
+}/* read_merging_directory */
+
+/*
+ * Free any associated data related to the structures.
+ */
+static int
+free_mdinfo(struct directory_entry **ptr, int len)
+{
+       int             i;
+       struct directory_entry **p;
+
+       p = ptr;
+       for (i = 0; i < len; i++, p++) {
+               /*
+                * If the tree-handling code decided that it needed an entry, it
+                * will have removed it from the list.  Thus we must allow for
+                * null pointers here.
+                */
+               if (*p == NULL) {
+                       continue;
+               }
+               free_directory_entry(*p);
+       }
+
+       free(ptr);
+       return (0);
+}
+
+static void
+free_directory_entry(struct directory_entry *dirp)
+{
+       if (dirp->name != NULL)
+               free(dirp->name);
+
+       if (dirp->whole_name != NULL)
+               free(dirp->whole_name);
+
+       if (dirp->rr_attributes != NULL)
+               free(dirp->rr_attributes);
+
+       if (dirp->table != NULL)
+               free(dirp->table);
+
+       free(dirp);
+}
+
+/*
+ * Search the list to see if we have any entries from the previous
+ * session that match this entry.  If so, copy the extent number
+ * over so we don't bother to write it out to the new session.
+ */
+int
+check_prev_session(struct directory_entry **ptr, int len, 
+                                                struct directory_entry *curr_entry, 
+                                                struct stat *statbuf, 
+                                                struct stat *lstatbuf, 
+                                                struct directory_entry **odpnt)
+{
+       int             i;
+       int             rr;
+       int             retcode = 0;    /* Default not found */
+
+       for (i = 0; i < len; i++) {
+               if (ptr[i] == NULL) {   /* Used or empty entry skip */
+                       continue;
+               }
+#if 0
+               if (ptr[i]->name != NULL && ptr[i]->isorec.name_len[0] == 1 &&
+                   ptr[i]->name[0] == '\0') {
+                       continue;
+               }
+               if (ptr[i]->name != NULL && ptr[i]->isorec.name_len[0] == 1 &&
+                   ptr[i]->name[0] == 1) {
+                       continue;
+               }
+#else
+               if (ptr[i]->name != NULL && strcmp(ptr[i]->name, ".") == 0) {
+                       continue;
+               }
+               if (ptr[i]->name != NULL && strcmp(ptr[i]->name, "..") == 0) {
+                       continue;
+               }
+#endif
+
+               if (ptr[i]->name != NULL &&
+                   strcmp(ptr[i]->name, curr_entry->name) != 0) {
+                       /* Not the same name continue */
+                       continue;
+               }
+               /*
+                * It's a directory so we must always merge it with the new
+                * session. Never ever reuse directory extents.  See comments
+                * in tree.c for an explaination of why this must be the case.
+                */
+               if ((curr_entry->isorec.flags[0] & ISO_DIRECTORY) != 0) {
+                       retcode = 2;    /* Flag directory case */
+                       goto found_it;
+               }
+               /*
+                * We know that the files have the same name.  If they also
+                * have the same file type (i.e. file, dir, block, etc), then
+                * we can safely reuse the TRANS.TBL entry for this file. The
+                * check_rr_dates() function will do this for us.
+                *
+                * Verify that the file type and dates are consistent. If not,
+                * we probably have a different file, and we need to write it
+                * out again.
+                */
+               retcode = 1;    /* We found a non directory */
+
+               if (ptr[i]->rr_attributes != NULL) {
+                       if ((rr = check_rr_dates(ptr[i], curr_entry, statbuf,
+                                                       lstatbuf)) == -1)
+                               return (-1);
+
+                       if (rr == 0) {  /* Different files */
+                               goto found_it;
+                       }
+               }
+               /*
+                * Verify size and timestamp.  If rock ridge is in use, we
+                * need to compare dates from RR too.  Directories are special,
+                * we calculate their size later.
+                */
+               if (ptr[i]->size != curr_entry->size) {
+                       /* Different files */
+                       goto found_it;
+               }
+               if (memcmp(ptr[i]->isorec.date,
+                                       curr_entry->isorec.date, 7) != 0) {
+                       /* Different files */
+                       goto found_it;
+               }
+               /* We found it and we can reuse the extent */
+               memcpy(curr_entry->isorec.extent, ptr[i]->isorec.extent, 8);
+               curr_entry->starting_block = isonum_733((unsigned char *)ptr[i]->isorec.extent);
+               curr_entry->de_flags |= SAFE_TO_REUSE_TABLE_ENTRY;
+               goto found_it;
+       }
+       return (retcode);
+
+found_it:
+       if (odpnt != NULL) {
+               *odpnt = ptr[i];
+       } else {
+               free(ptr[i]);
+       }
+       ptr[i] = NULL;
+       return (retcode);
+}
+
+/*
+ * open_merge_image:  Open an existing image.
+ */
+int
+open_merge_image(char *path)
+{
+#ifndef        USE_SCG
+       in_image = fopen(path, "rb");
+       if (in_image == NULL) {
+               return (-1);
+       }
+#else
+       in_image = fopen(path, "rb");
+       if (in_image == NULL) {
+               if (scsidev_open(path) < 0)
+                       return (-1);
+       }
+#endif
+       return (0);
+}
+
+/*
+ * close_merge_image:  Close an existing image.
+ */
+int
+close_merge_image()
+{
+#ifdef USE_SCG
+       return (scsidev_close());
+#else
+       return (fclose(in_image));
+#endif
+}
+
+/*
+ * merge_isofs:  Scan an existing image, and return a pointer
+ * to the root directory for this image.
+ */
+struct iso_directory_record *
+merge_isofs(char *path)
+{
+       char            buffer[SECTOR_SIZE];
+       int             file_addr;
+       int             i;
+       struct iso_primary_descriptor *pri = NULL;
+       struct iso_directory_record *rootp;
+       struct iso_volume_descriptor *vdp;
+
+       /*
+        * Start by searching for the volume header. Ultimately, we need to
+        * search for volume headers in multiple places because we might be
+        * starting with a multisession image. FIXME(eric).
+        */
+       get_session_start(&file_addr);
+
+       for (i = 0; i < 100; i++) {
+               if (readsecs(file_addr, buffer,
+                               sizeof (buffer) / SECTOR_SIZE) != sizeof (buffer)) {
+#ifdef USE_LIBSCHILY
+                       comerr(" Read error on old image %s\n", path);
+#else
+                       fprintf(stderr, " Read error on old image %s\n", path);
+                       exit(10);
+#endif
+               }
+               vdp = (struct iso_volume_descriptor *) buffer;
+
+               if ((strncmp(vdp->id, ISO_STANDARD_ID, sizeof (vdp->id)) == 0) &&
+                   (isonum_711((unsigned char *) vdp->type) == ISO_VD_PRIMARY)) {
+                       break;
+               }
+               file_addr += 1;
+       }
+
+       if (i == 100) {
+               return (NULL);
+       }
+       pri = (struct iso_primary_descriptor *) vdp;
+
+       /* Check the blocksize of the image to make sure it is compatible. */
+       if (isonum_723((unsigned char *) pri->logical_block_size) != SECTOR_SIZE) {
+               errmsgno(EX_BAD,
+                       "Previous session has incompatible sector size %d.\n",
+                       isonum_723((unsigned char *) pri->logical_block_size));
+               return (NULL);
+       }
+       if (isonum_723((unsigned char *) pri->volume_set_size) != 1) {
+               errmsgno(EX_BAD,
+                       "Previous session has volume set size %d (must be 1).\n",
+                       isonum_723((unsigned char *) pri->volume_set_size));
+               return (NULL);
+       }
+       /* Get the location and size of the root directory. */
+       rootp = (struct iso_directory_record *)
+               e_malloc(sizeof (struct iso_directory_record));
+
+       memcpy(rootp, pri->root_directory_record, sizeof (*rootp));
+
+       return (rootp);
+}
+
+static void
+merge_remaining_entries(struct directory *this_dir, 
+                                                               struct directory_entry **pnt, int n_orig)
+{
+       int             i;
+       struct directory_entry *s_entry;
+       unsigned int    ttbl_extent = 0;
+       unsigned int    ttbl_index = 0;
+       char            whole_path[PATH_MAX];
+
+       /*
+        * Whatever is leftover in the list needs to get merged back into the
+        * directory.
+        */
+       for (i = 0; i < n_orig; i++) {
+               if (pnt[i] == NULL) {
+                       continue;
+               }
+               if (pnt[i]->name != NULL && pnt[i]->whole_name == NULL) {
+                       /* Set the name for this directory. */
+                       strcpy(whole_path, this_dir->de_name);
+                       strcat(whole_path, SPATH_SEPARATOR);
+                       strcat(whole_path, pnt[i]->name);
+
+                       pnt[i]->whole_name = strdup(whole_path);
+               }
+               if (pnt[i]->name != NULL &&
+/*                     strcmp(pnt[i]->name, "<translation table>") == 0 )*/
+                       strcmp(pnt[i]->name, trans_tbl) == 0) {
+                       ttbl_extent =
+                           isonum_733((unsigned char *)pnt[i]->isorec.extent);
+                       ttbl_index = i;
+                       continue;
+               }
+
+               /*
+                * Skip directories for now - these need to be treated
+                * differently.
+                */
+               if ((pnt[i]->isorec.flags[0] & ISO_DIRECTORY) != 0) {
+                       /*
+                        * FIXME - we need to insert this directory into the
+                        * tree, so that the path tables we generate will be
+                        * correct.
+                        */
+                       if ((strcmp(pnt[i]->name, ".") == 0) ||
+                               (strcmp(pnt[i]->name, "..") == 0)) {
+                               free_directory_entry(pnt[i]);
+                               pnt[i] = NULL;
+                               continue;
+                       } else {
+                               merge_old_directory_into_tree(pnt[i], this_dir);
+                       }
+               }
+               pnt[i]->next = this_dir->contents;
+               pnt[i]->filedir = this_dir;
+               this_dir->contents = pnt[i];
+               pnt[i] = NULL;
+       }
+
+
+       /*
+        * If we don't have an entry for the translation table, then don't
+        * bother trying to copy the starting extent over. Note that it is
+        * possible that if we are copying the entire directory, the entry for
+        * the translation table will have already been inserted into the
+        * linked list and removed from the old entries list, in which case we
+        * want to leave the extent number as it was before.
+        */
+       if (ttbl_extent == 0) {
+               return;
+       }
+       /*
+        * Finally, check the directory we are creating to see whether there
+        * are any new entries in it.  If there are not, we can reuse the same
+        * translation table.
+        */
+       for (s_entry = this_dir->contents; s_entry; s_entry = s_entry->next) {
+               /*
+                * Don't care about '.' or '..'.  They are never in the table
+                * anyways.
+                */
+               if (s_entry->name != NULL && strcmp(s_entry->name, ".") == 0) {
+                       continue;
+               }
+               if (s_entry->name != NULL && strcmp(s_entry->name, "..") == 0) {
+                       continue;
+               }
+/*             if (strcmp(s_entry->name, "<translation table>") == 0)*/
+               if (strcmp(s_entry->name, trans_tbl) == 0) {
+                       continue;
+               }
+               if ((s_entry->de_flags & SAFE_TO_REUSE_TABLE_ENTRY) == 0) {
+                       return;
+               }
+       }
+
+       /*
+        * Locate the translation table, and re-use the same extent. It isn't
+        * clear that there should ever be one in there already so for now we
+        * try and muddle through the best we can.
+        */
+       for (s_entry = this_dir->contents; s_entry; s_entry = s_entry->next) {
+/*             if (strcmp(s_entry->name, "<translation table>") == 0)*/
+               if (strcmp(s_entry->name, trans_tbl) == 0) {
+                       fprintf(stderr, "Should never get here\n");
+                       set_733(s_entry->isorec.extent, ttbl_extent);
+                       return;
+               }
+       }
+
+       pnt[ttbl_index]->next = this_dir->contents;
+       pnt[ttbl_index]->filedir = this_dir;
+       this_dir->contents = pnt[ttbl_index];
+       pnt[ttbl_index] = NULL;
+}
+
+
+/*
+ * Here we have a case of a directory that has completely disappeared from
+ * the face of the earth on the tree we are mastering from.  Go through and
+ * merge it into the tree, as well as everything beneath it.
+ *
+ * Note that if a directory has been moved for some reason, this will
+ * incorrectly pick it up and attempt to merge it back into the old
+ * location.  FIXME(eric).
+ */
+static int
+merge_old_directory_into_tree(struct directory_entry *dpnt, 
+                                                                               struct directory *parent)
+{
+       struct directory_entry **contents = NULL;
+       int             i;
+       int             n_orig;
+       struct directory *this_dir,
+                       *next_brother;
+       char            whole_path[PATH_MAX];
+
+       this_dir = (struct directory *) e_malloc(sizeof (struct directory));
+       memset(this_dir, 0, sizeof (struct directory));
+       this_dir->next = NULL;
+       this_dir->subdir = NULL;
+       this_dir->self = dpnt;
+       this_dir->contents = NULL;
+       this_dir->size = 0;
+       this_dir->extent = 0;
+       this_dir->depth = parent->depth + 1;
+       this_dir->parent = parent;
+       if (!parent->subdir)
+               parent->subdir = this_dir;
+       else {
+               next_brother = parent->subdir;
+               while (next_brother->next)
+                       next_brother = next_brother->next;
+               next_brother->next = this_dir;
+       }
+
+       /* Set the name for this directory. */
+       strcpy(whole_path, parent->de_name);
+       strcat(whole_path, SPATH_SEPARATOR);
+       strcat(whole_path, dpnt->name);
+       this_dir->de_name = strdup(whole_path);
+       this_dir->whole_name = strdup(whole_path);
+
+       /*
+        * Now fill this directory using information from the previous session.
+        */
+       contents = read_merging_directory(&dpnt->isorec, &n_orig);
+       /*
+        * Start by simply copying the '.', '..' and non-directory entries to
+        * this directory.  Technically we could let merge_remaining_entries
+        * handle this, but it gets rather confused by the '.' and '..' entries
+        */
+       for (i = 0; i < n_orig; i++) {
+               /*
+                * We can always reuse the TRANS.TBL in this particular case.
+                */
+               contents[i]->de_flags |= SAFE_TO_REUSE_TABLE_ENTRY;
+
+               if (((contents[i]->isorec.flags[0] & ISO_DIRECTORY) != 0) &&
+                                                       (i >= 2)) {
+                       continue;
+               }
+               /* If we have a directory, don't reuse the extent number. */
+               if ((contents[i]->isorec.flags[0] & ISO_DIRECTORY) != 0) {
+                       memset(contents[i]->isorec.extent, 0, 8);
+
+                       if (strcmp(contents[i]->name, ".") == 0)
+                               this_dir->dir_flags |= DIR_HAS_DOT;
+
+                       if (strcmp(contents[i]->name, "..") == 0)
+                               this_dir->dir_flags |= DIR_HAS_DOTDOT;
+               }
+               /*
+                * for regilar files, we do it here.
+                * If it has CL or RE attributes, remember its extent
+                */
+               check_rr_relocation(contents[i]);
+
+               /*
+                * Set the whole name for this file.
+                */
+               strcpy(whole_path, this_dir->whole_name);
+               strcat(whole_path, SPATH_SEPARATOR);
+               strcat(whole_path, contents[i]->name);
+
+               contents[i]->whole_name = strdup(whole_path);
+
+               contents[i]->next = this_dir->contents;
+               contents[i]->filedir = this_dir;
+               this_dir->contents = contents[i];
+               contents[i] = NULL;
+       }
+
+       /*
+        * and for directories, we do it here.
+        * If it has CL or RE attributes, remember its extent
+        */
+       check_rr_relocation(dpnt);
+
+       /*
+        * Zero the extent number for ourselves.
+        */
+       memset(dpnt->isorec.extent, 0, 8);
+
+       /*
+        * Anything that is left are other subdirectories that need to be
+        * merged.
+        */
+       merge_remaining_entries(this_dir, contents, n_orig);
+       free_mdinfo(contents, n_orig);
+#if 0
+       /*
+        * This is no longer required.  The post-scan sort will handle all of
+        * this for us.
+        */
+       sort_n_finish(this_dir);
+#endif
+
+       return (0);
+}
+
+
+char   *cdrecord_data = NULL;
+
+int
+get_session_start(int *file_addr)
+{
+       char            *pnt;
+
+#ifdef CDRECORD_DETERMINES_FIRST_WRITABLE_ADDRESS
+       /*
+        * FIXME(eric).  We need to coordinate with cdrecord to obtain the
+        * parameters.  For now, we assume we are writing the 2nd session, so
+        * we start from the session that starts at 0.
+        */
+       if (file_addr != NULL)
+               *file_addr = 16;
+
+       /*
+        * We need to coordinate with cdrecord to get the next writable address
+        * from the device.  Here is where we use it.
+        */
+       session_start = last_extent = last_extent_written = cdrecord_result();
+#else
+
+       if (file_addr != NULL)
+               *file_addr = 0L;
+       session_start = last_extent = last_extent_written = 0L;
+       if (check_session && cdrecord_data == NULL)
+               return (0);
+
+       if (cdrecord_data == NULL) {
+#ifdef USE_LIBSCHILY
+               comerrno(EX_BAD,
+                   "Special parameters for cdrecord not specified with -C\n");
+#else
+               fprintf(stderr,
+                   "Special parameters for cdrecord not specified with -C\n");
+               exit(1);
+#endif
+       }
+       /*
+        * Next try and find the ',' in there which delimits the two numbers.
+        */
+       pnt = strchr(cdrecord_data, ',');
+       if (pnt == NULL) {
+#ifdef USE_LIBSCHILY
+               comerrno(EX_BAD, "Malformed cdrecord parameters\n");
+#else
+               fprintf(stderr, "Malformed cdrecord parameters\n");
+               exit(1);
+#endif
+       }
+
+       *pnt = '\0';
+       if (file_addr != NULL) {
+               *file_addr = atol(cdrecord_data);
+       }
+       pnt++;
+
+       session_start = last_extent = last_extent_written = atol(pnt);
+
+       pnt--;
+       *pnt = ',';
+
+#endif
+       return (0);
+}
+
+/*
+ * This function scans the directory tree, looking for files, and it makes
+ * note of everything that is found.  We also begin to construct the ISO9660
+ * directory entries, so that we can determine how large each directory is.
+ */
+int
+merge_previous_session(struct directory *this_dir, 
+                                                         struct iso_directory_record *mrootp, 
+                                                         char *reloc_root, 
+                                                         char *reloc_old_root)
+{
+       struct directory_entry **orig_contents = NULL;
+       struct directory_entry *odpnt = NULL;
+       int             n_orig;
+       struct directory_entry *s_entry;
+       int             status;
+       int             lstatus;
+       struct stat     statbuf,
+                       lstatbuf;
+       int             retcode;
+
+       /* skip leading slash */
+       while (reloc_old_root && reloc_old_root[0] == PATH_SEPARATOR) {
+               reloc_old_root++;
+       }
+       while (reloc_root && reloc_root[0] == PATH_SEPARATOR) {
+               reloc_root++;
+       }
+
+       /*
+        * Parse the same directory in the image that we are merging for
+        * multisession stuff.
+        */
+       orig_contents = read_merging_directory(mrootp, &n_orig);
+       if (orig_contents == NULL) {
+               if (reloc_old_root) {
+#ifdef USE_LIBSCHILY
+                       comerrno(EX_BAD,
+                       "Reading old session failed, cannot execute -old-root.\n");
+#else
+                       fprintf(stderr,
+                       "Reading old session failed, cannot execute -old-root.\n");
+                       exit(1);
+#endif
+               }
+               return (0);
+       }
+
+       if (reloc_old_root && reloc_old_root[0]) {
+               struct directory_entry  **new_orig_contents = orig_contents;
+               int                     new_n_orig = n_orig;
+
+               /* decend until we reach the original root */
+               while (reloc_old_root[0]) {
+                       int     i;
+                       char    *next;
+                       int     last;
+
+                       for (next = reloc_old_root; *next && *next != PATH_SEPARATOR; next++);
+                       if (*next) {
+                               last = 0;
+                               *next = 0;
+                               next++;
+                       } else {
+                               last = 1;
+                       }
+                       while (*next == PATH_SEPARATOR) {
+                               next++;
+                       }
+
+                       for (i = 0; i < new_n_orig; i++) {
+                               struct iso_directory_record subroot;
+
+                               if (new_orig_contents[i]->name != NULL &&
+                                   strcmp(new_orig_contents[i]->name, reloc_old_root) != 0) {
+                                       /* Not the same name continue */
+                                       continue;
+                               }
+                               /*
+                                * enter directory, free old one only if not the top level,
+                                * which is still needed
+                                */
+                               subroot = new_orig_contents[i]->isorec;
+                               if (new_orig_contents != orig_contents) {
+                                       free_mdinfo(new_orig_contents, new_n_orig);
+                               }
+                               new_orig_contents = read_merging_directory(&subroot, &new_n_orig);
+
+                               if (!new_orig_contents) {
+#ifdef USE_LIBSCHILY
+                                       comerrno(EX_BAD,
+                                       "Reading directory %s in old session failed, cannot execute -old-root.\n",
+                                                       reloc_old_root);
+#else
+                                       fprintf(stderr,
+                                       "Reading directory %s in old session failed, cannot execute -old-root.\n",
+                                                       reloc_old_root);
+                                       exit(1);
+#endif
+                               }
+                               i = -1;
+                               break;
+                       }
+
+                       if (i == new_n_orig) {
+#ifdef USE_LIBSCHILY
+                               comerrno(EX_BAD,
+                               "-old-root (sub)directory %s not found in old session.\n",
+                                               reloc_old_root);
+#else
+                               fprintf(stderr,
+                               "-old-root (sub)directory %s not found in old session.\n",
+                                               reloc_old_root);
+                               exit(1);
+#endif
+                       }
+
+                       /* restore string, proceed to next sub directory */
+                       if (!last) {
+                               reloc_old_root[strlen(reloc_old_root)] = PATH_SEPARATOR;
+                       }
+                       reloc_old_root = next;
+               }
+
+               /*
+                * preserve the old session, skipping those dirs/files that are found again
+                * in the new root
+                */
+               for (s_entry = this_dir->contents; s_entry; s_entry = s_entry->next) {
+                       status = stat_filter(s_entry->whole_name, &statbuf);
+                       lstatus = lstat_filter(s_entry->whole_name, &lstatbuf);
+
+                       /*
+                        * check_prev_session() will search for s_entry and remove it from
+                        * orig_contents if found
+                        */
+                       retcode = check_prev_session(orig_contents, n_orig, s_entry,
+                           &statbuf, &lstatbuf, NULL);
+                       if (retcode == -1)
+                               return (-1);
+               }
+               merge_remaining_entries(this_dir, orig_contents, n_orig);
+
+               /* use new directory */
+               free_mdinfo(orig_contents, n_orig);
+               orig_contents = new_orig_contents;
+               n_orig = new_n_orig;
+
+               if (reloc_root && reloc_root[0]) {
+                       /* also decend into new root before searching for files */
+                       this_dir = find_or_create_directory(this_dir, reloc_root, NULL, TRUE, NULL);
+                       if (!this_dir) {
+                               return (-1);
+                       }
+               }
+       }
+
+
+       /*
+        * Now we scan the directory itself, and look at what is inside of it.
+        */
+       for (s_entry = this_dir->contents; s_entry; s_entry = s_entry->next) {
+               status = stat_filter(s_entry->whole_name, &statbuf);
+               lstatus = lstat_filter(s_entry->whole_name, &lstatbuf);
+
+               /*
+                * We always should create an entirely new directory tree
+                * whenever we generate a new session, unless there were
+                * *no* changes whatsoever to any of the directories, in which
+                * case it would be kind of pointless to generate a new
+                * session.
+                * I believe it is possible to rigorously prove that any change
+                * anywhere in the filesystem will force the entire tree to be
+                * regenerated because the modified directory will get a new
+                * extent number.  Since each subdirectory of the changed
+                * directory has a '..' entry, all of them will need to be
+                * rewritten too, and since the parent directory of the
+                * modified directory will have an extent pointer to the
+                * directory it too will need to be rewritten.  Thus we will
+                * never be able to reuse any directory information when
+                * writing new sessions.
+                *
+                * We still check the previous session so we can mark off the
+                * equivalent entry in the list we got from the original disc,
+                * however.
+                */
+
+               /*
+                * The check_prev_session function looks for an identical
+                * entry in the previous session.  If we see it, then we copy
+                * the extent number to s_entry, and cross it off the list.
+                * It returns 2 if it's a directory
+                */
+               retcode = check_prev_session(orig_contents, n_orig, s_entry,
+                       &statbuf, &lstatbuf, &odpnt);
+               if (retcode == -1)
+                       return (-1);
+
+               if (retcode == 2 && odpnt != NULL) {
+                       int     dflag;
+
+                       if (strcmp(s_entry->name, ".") != 0 &&
+                                       strcmp(s_entry->name, "..") != 0) {
+                               struct directory *child;
+
+                               /*
+                                * XXX It seems that the tree that has been
+                                * XXX read from the previous session does not
+                                * XXX carry whole_name entries. We provide a
+                                * XXX hack in
+                                * XXX multi.c:find_or_create_directory()
+                                * XXX that should be removed when a
+                                * XXX reasonable method could be found.
+                                */
+                               child = find_or_create_directory(this_dir,
+                                       s_entry->whole_name,
+                                       s_entry, 1, NULL);
+                               dflag = merge_previous_session(child,
+                                       &odpnt->isorec,
+                                       NULL, reloc_old_root);
+                               if (dflag == -1) {
+                                       return (-1);
+                               }
+                               free(odpnt);
+                               odpnt = NULL;
+                       }
+               }
+       }
+
+       if (!reloc_old_root) {
+               /*
+                * Whatever is left over, are things which are no longer in the tree on
+                * disk. We need to also merge these into the tree.
+                */
+               merge_remaining_entries(this_dir, orig_contents, n_orig);
+       }
+       free_mdinfo(orig_contents, n_orig);
+       return (1);
+}
+
+/*
+ * This code deals with relocated directories which may exist
+ * in the previous session.
+ */
+struct dir_extent_link  {
+       unsigned int            extent;
+       struct directory_entry  *de;
+       struct dir_extent_link  *next;
+};
+
+static struct dir_extent_link  *cl_dirs = NULL;
+static struct dir_extent_link  *re_dirs = NULL;
+
+static void
+check_rr_relocation(struct directory_entry *de)
+{
+       unsigned char   sector[SECTOR_SIZE];
+       unsigned char   *pnt = de->rr_attributes;
+               int     len = de->rr_attr_size;
+               int     cont_extent = 0,
+                       cont_offset = 0,
+                       cont_size = 0;
+
+       pnt = parse_xa(pnt, &len, /* dpnt */ 0);
+       while (len >= 4) {
+               if (pnt[3] != 1 && pnt[3] != 2) {
+#ifdef USE_LIBSCHILY
+                       errmsgno(EX_BAD, "**BAD RRVERSION (%d) for %c%c\n", pnt[3], pnt[0], pnt[1]);
+#else
+                       fprintf(stderr, "**BAD RRVERSION (%d) for %c%c\n", pnt[3], pnt[0], pnt[1]);
+#endif
+               }
+               if (strncmp((char *) pnt, "CL", 2) == 0) {
+                       struct dir_extent_link *dlink = e_malloc(sizeof (*dlink));
+
+                       dlink->extent = isonum_733(pnt + 4);
+                       dlink->de = de;
+                       dlink->next = cl_dirs;
+                       cl_dirs = dlink;
+
+               } else if (strncmp((char *) pnt, "RE", 2) == 0) {
+                       struct dir_extent_link *dlink = e_malloc(sizeof (*dlink));
+
+                       dlink->extent = de->starting_block;
+                       dlink->de = de;
+                       dlink->next = re_dirs;
+                       re_dirs = dlink;
+
+               } else if (strncmp((char *) pnt, "CE", 2) == 0) {
+                       cont_extent = isonum_733(pnt + 4);
+                       cont_offset = isonum_733(pnt + 12);
+                       cont_size = isonum_733(pnt + 20);
+
+               } else if (strncmp((char *) pnt, "ST", 2) == 0) {
+                       len = pnt[2];
+               }
+               len -= pnt[2];
+               pnt += pnt[2];
+               if (len <= 3 && cont_extent) {
+                       /* ??? What if cont_offset+cont_size > SECTOR_SIZE */
+                       readsecs(cont_extent, sector, 1);
+                       pnt = sector + cont_offset;
+                       len = cont_size;
+                       cont_extent = cont_offset = cont_size = 0;
+               }
+       }
+
+}
+
+void
+match_cl_re_entries()
+{
+       struct dir_extent_link *re = re_dirs;
+
+       /* for each relocated directory */
+       for (; re; re = re->next) {
+               struct dir_extent_link *cl = cl_dirs;
+
+               for (; cl; cl = cl->next) {
+                       /* find a place where it was relocated from */
+                       if (cl->extent == re->extent) {
+                               /* set link to that place */
+                               re->de->parent_rec = cl->de;
+                               re->de->filedir = cl->de->filedir;
+
+                               /*
+                                * see if it is in rr_moved
+                                */
+                               if (reloc_dir != NULL) {
+                                       struct directory_entry *rr_moved_e = reloc_dir->contents;
+
+                                       for (; rr_moved_e; rr_moved_e = rr_moved_e->next) {
+                                               /* yes it is */
+                                               if (re->de == rr_moved_e) {
+                                                       /* forget it */
+                                                       re->de = NULL;
+                                               }
+                                       }
+                               }
+                               break;
+                       }
+               }
+       }
+}
+
+void
+finish_cl_pl_for_prev_session()
+{
+       struct dir_extent_link *re = re_dirs;
+
+       /* for those that were relocated, but NOT to rr_moved */
+       re = re_dirs;
+       for (; re; re = re->next) {
+               if (re->de != NULL) {
+                       /*
+                        * here we have hypothetical case when previous session
+                        * was not created by genisoimage and contains relocations
+                        */
+                       struct directory_entry *s_entry = re->de;
+                       struct directory_entry *s_entry1;
+                       struct directory *d_entry = reloc_dir->subdir;
+
+                       /* do the same as finish_cl_pl_entries */
+                       if (s_entry->de_flags & INHIBIT_ISO9660_ENTRY) {
+                               continue;
+                       }
+                       while (d_entry) {
+                               if (d_entry->self == s_entry)
+                                       break;
+                               d_entry = d_entry->next;
+                       }
+                       if (!d_entry) {
+#ifdef USE_LIBSCHILY
+                               comerrno(EX_BAD, "Unable to locate directory parent\n");
+#else
+                               fprintf(stderr, "Unable to locate directory parent\n");
+                               exit(1);
+#endif
+                       }
+
+                       if (s_entry->filedir != NULL && s_entry->parent_rec != NULL) {
+                               char    *rr_attr;
+
+                               /*
+                                * First fix the PL pointer in the directory in the
+                                * rr_reloc dir
+                                */
+                               s_entry1 = d_entry->contents->next;
+                               rr_attr = find_rr_attribute(s_entry1->rr_attributes,
+                                       s_entry1->total_rr_attr_size, "PL");
+                               if (rr_attr != NULL)
+                                       set_733(rr_attr + 4, s_entry->filedir->extent);
+
+                               /* Now fix the CL pointer */
+                               s_entry1 = s_entry->parent_rec;
+
+                               rr_attr = find_rr_attribute(s_entry1->rr_attributes,
+                                       s_entry1->total_rr_attr_size, "CL");
+                               if (rr_attr != NULL)
+                                       set_733(rr_attr + 4, d_entry->extent);
+                       }
+               }
+       }
+       /* free memory */
+       re = re_dirs;
+       while (re) {
+               struct dir_extent_link *next = re->next;
+
+               free(re);
+               re = next;
+       }
+       re = cl_dirs;
+       while (re) {
+               struct dir_extent_link *next = re->next;
+
+               free(re);
+               re = next;
+       }
+}
diff --git a/genisoimage/name.c b/genisoimage/name.c
new file mode 100644 (file)
index 0000000..c2faeb6
--- /dev/null
@@ -0,0 +1,531 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)name.c  1.28 04/03/05 joerg */
+/*
+ * File name.c - map full Unix file names to unique 8.3 names that
+ * would be valid on DOS.
+ *
+ *
+ * Written by Eric Youngdale (1993).
+ * Almost totally rewritten by J. Schilling (2000).
+ *
+ * Copyright 1993 Yggdrasil Computing, Incorporated
+ * Copyright (c) 1999,2000 J. Schilling
+ *
+ * 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 <mconfig.h>
+#include "genisoimage.h"
+#include <standard.h>
+#include <schily.h>
+#include <ctype.h>
+
+void   iso9660_check(struct iso_directory_record *idr, 
+                                                 struct directory_entry *ndr);
+int    iso9660_file_length(const char *name,
+                                                                 struct directory_entry *sresult,
+                                                                 int dirflag);
+
+void
+iso9660_check(struct iso_directory_record *idr, 
+                                 struct directory_entry *ndr)
+{
+       int     nlen;
+       char    schar;
+       char    *p;
+       char    *np;
+
+       nlen = idr->name_len[0];
+       schar = idr->name[nlen];
+
+       if (nlen == 1 && (idr->name[0] == '\0' || idr->name[0] == '\001'))
+               return;
+
+       idr->name[nlen] = '\0';         /* Make it null terminated */
+       if ((p = strrchr(idr->name, ';')) != NULL) {
+               *p = '\0';              /* Strip off old version # */
+       }
+       iso9660_file_length(idr->name, ndr,
+                               (idr->flags[0] & ISO_DIRECTORY) != 0);
+
+       if ((np = strrchr(ndr->isorec.name, ';')) != NULL) {
+               *np = '\0';             /* Strip off new version # */
+       }
+       if (strcmp(idr->name, ndr->isorec.name)) {
+               if (p)
+                       *p = ';';       /* Restore old version # */
+               if (np)
+                       *np = ';';      /* Restore new version # */
+               errmsgno(EX_BAD,
+                       "Old session has illegal name '%.*s' length %d\n",
+                       idr->name_len[0],
+                       idr->name,
+                       idr->name_len[0]);
+               errmsgno(EX_BAD,
+                       "New session will use    name '%s'\n",
+                       ndr->isorec.name);
+       }
+       if (p)
+               *p = ';';               /* Restore old version # */
+       if (np)
+               *np = ';';              /* Restore new version # */
+       idr->name[nlen] = schar;        /* Restore old iso record*/
+}
+
+/*
+ * Function:   iso9660_file_length
+ *
+ * Purpose:    Map file name to 8.3 format, return length
+ *             of result.
+ *
+ * Arguments:  name    file name we need to map.
+ *             sresult directory entry structure to contain mapped name.
+ *             dirflag flag indicating whether this is a directory or not.
+ *
+ * Note:       name being const * is a bug introduced by Eric but hard to
+ *             fix without going through the whole source.
+ */
+int
+iso9660_file_length(const char *name /* Not really const !!! */, 
+                                                 struct directory_entry *sresult, int dirflag)
+{
+       char            c;
+       char            *cp;
+       int             before_dot = 8;
+       int             after_dot = 3;
+       int             chars_after_dot = 0;
+       int             chars_before_dot = 0;
+       int             current_length = 0;
+       int             extra = 0;
+       int             ignore = 0;
+       char            *last_dot;
+       const char      *pnt;
+       int             priority = 32767;
+       char            *result;
+       int             ochars_after_dot;
+       int             ochars_before_dot;
+       int             seen_dot = 0;
+       int             seen_semic = 0;
+       int             tildes = 0;
+
+       result = sresult->isorec.name;
+
+       if (sresult->priority)
+               priority = sresult->priority;
+
+       /*
+        * For the '.' entry, generate the correct record, and return 1 for
+        * the length.
+        */
+       if (strcmp(name, ".") == 0) {
+               *result = 0;
+               return (1);
+       }
+       /*
+        * For the '..' entry, generate the correct record, and return 1
+        * for the length.
+        */
+       if (strcmp(name, "..") == 0) {
+               *result++ = 1;
+               *result++ = 0;
+               return (1);
+       }
+       /*
+        * Now scan the directory one character at a time, and figure out
+        * what to do.
+        */
+       pnt = name;
+
+       /*
+        * Find the '.' that we intend to use for the extension.
+        * Usually this is the last dot, but if we have . followed by nothing
+        * or a ~, we would consider this to be unsatisfactory, and we keep
+        * searching.
+        */
+       last_dot = strrchr(pnt, '.');
+       if ((last_dot != NULL) &&
+           ((last_dot[1] == '~') || (last_dot[1] == '\0'))) {
+               cp = last_dot;
+               *cp = '\0';
+               last_dot = strrchr(pnt, '.');
+               *cp = '.';
+               /*
+                * If we found no better '.' back up to the last match.
+                */
+               if (last_dot == NULL)
+                       last_dot = cp;
+       }
+
+       if (last_dot != NULL) {
+               ochars_after_dot = strlen(last_dot);    /* dot counts */
+               ochars_before_dot = last_dot - pnt;
+       } else {
+               ochars_before_dot = 128;
+               ochars_after_dot = 0;
+       }
+       /*
+        * If we have full names, the names we generate will not work
+        * on a DOS machine, since they are not guaranteed to be 8.3.
+        * Nonetheless, in many cases this is a useful option.  We
+        * still only allow one '.' character in the name, however.
+        */
+       if (full_iso9660_filenames || iso9660_level > 1) {
+               before_dot = iso9660_namelen;
+               after_dot = before_dot - 1;
+
+               if (!dirflag) {
+                       if (ochars_after_dot > ((iso9660_namelen/2)+1)) {
+                               /*
+                                * The minimum number of characters before
+                                * the dot is 3 to allow renaming.
+                                * Let us allow to have 15 characters after
+                                * dot to give more rational filenames.
+                                */
+                               before_dot = iso9660_namelen/2;
+                               after_dot = ochars_after_dot;
+                       } else {
+                               before_dot -= ochars_after_dot; /* dot counts */
+                               after_dot = ochars_after_dot;
+                       }
+               }
+       }
+
+       while (*pnt) {
+#ifdef VMS
+               if (strcmp(pnt, ".DIR;1") == 0) {
+                       break;
+               }
+#endif
+
+#ifdef         Eric_code_does_not_work
+               /*
+                * XXX If we make this code active we get corrupted direcrory
+                * XXX trees with infinite loops.
+                */
+               /*
+                * This character indicates a Unix style of backup file
+                * generated by some editors.  Lower the priority of the file.
+                */
+               if (iso_translate && *pnt == '#') {
+                       priority = 1;
+                       pnt++;
+                       continue;
+               }
+               /*
+                * This character indicates a Unix style of backup file
+                * generated by some editors.  Lower the priority of the file.
+                */
+               if (iso_translate && *pnt == '~') {
+                       priority = 1;
+                       tildes++;
+                       pnt++;
+                       continue;
+               }
+#endif
+               /*
+                * This might come up if we had some joker already try and put
+                * iso9660 version numbers into the file names.  This would be
+                * a silly thing to do on a Unix box, but we check for it
+                * anyways.  If we see this, then we don't have to add our own
+                * version number at the end. UNLESS the ';' is part of the
+                * filename and no valid version number is following.
+                */
+               if (use_fileversion && *pnt == ';' && seen_dot) {
+                       /*
+                        * Check if a valid version number follows.
+                        * The maximum valid version number is 32767.
+                        */
+                       for (c = 1, cp = (char *)&pnt[1]; c < 6 && *cp; c++, cp++) {
+                               if (*cp < '0' || *cp > '9')
+                                       break;
+                       }
+                       if (c <= 6 && *cp == '\0' && atoi(&pnt[1]) <= 32767)
+                               seen_semic++;
+               }
+               /*
+                * If we have a name with multiple '.' characters, we ignore
+                * everything after we have gotten the extension.
+                */
+               if (ignore) {
+                       pnt++;
+                       continue;
+               }
+               if (current_length >= iso9660_namelen) {
+#ifdef nono
+                       /*
+                        * Does not work as we may truncate before the dot.
+                        */
+                       fprintf(stderr, "Truncating '%s' to '%.*s'.\n",
+                               name,
+                               current_length, sresult->isorec.name);
+                       ignore++;
+#endif
+                       pnt++;
+                       continue;
+               }
+               /* Spin past any iso9660 version number we might have. */
+               if (seen_semic) {
+                       if (seen_semic == 1) {
+                               seen_semic++;
+                               *result++ = ';';
+                       }
+                       if (*pnt >= '0' && *pnt <= '9') {
+                               *result++ = *pnt;
+                       }
+                       extra++;
+                       pnt++;
+                       continue;
+               }
+
+               if (*pnt == '.') {
+                       if (!allow_multidot) {
+                               if (strcmp(pnt, ".tar.gz") == 0)
+                                       pnt = last_dot = ".tgz";
+                               if (strcmp(pnt, ".ps.gz") == 0)
+                                       pnt = last_dot = ".psz";
+                       }
+
+                       if (!chars_before_dot && !allow_leading_dots) {
+                               /*
+                                * DOS can't read files with dot first
+                                */
+                               chars_before_dot++;
+                               *result++ = '_'; /* Substitute underscore */
+
+                       } else if (pnt == last_dot) {
+                               if (seen_dot) {
+                                       ignore++;
+                                       continue;
+                               }
+                               *result++ = '.';
+                               seen_dot++;
+                       } else if (allow_multidot) {
+                               if (chars_before_dot < before_dot) {
+                                       chars_before_dot++;
+                                       *result++ = '.';
+                               }
+                       } else {
+                               /*
+                                * If this isn't the dot that we use
+                                * for the extension, then change the
+                                * character into a '_' instead.
+                                */
+                               if (chars_before_dot < before_dot) {
+                                       chars_before_dot++;
+                                       *result++ = '_';
+                               }
+                       }
+               } else {
+                       if ((seen_dot && (chars_after_dot < after_dot) &&
+                                               ++chars_after_dot) ||
+                           (!seen_dot && (chars_before_dot < before_dot) &&
+                           ++chars_before_dot)) {
+
+                               c = *pnt;
+                               if (c & 0x80) {
+                                       /*
+                                        * We allow 8 bit chars if -iso-level
+                                        * is at least 4
+                                        *
+                                        * XXX We should check if the output
+                                        * XXX character set is a 7 Bit ASCI
+                                        * extension.
+                                        */
+                                       if (iso9660_level >= 4) {
+                                               c = conv_charset(c, in_nls, out_nls);
+                                       } else {
+                                               c = '_';
+                                       }
+                               } else if (!allow_lowercase) {
+                                       c = islower((unsigned char)c) ?
+                                               toupper((unsigned char)c) : c;
+                               }
+                               if (relaxed_filenames) {
+                                       /*
+                                        * Here we allow a more relaxed syntax.
+                                        */
+                                       if (c == '/')
+                                               c = '_';
+                                       *result++ = c;
+                               } else switch (c) {
+                                       /*
+                                        * Dos style filenames.
+                                        * We really restrict the names here.
+                                        */
+
+                               default:
+                                       *result++ = c;
+                                       break;
+
+                               /*
+                                * Descriptions of DOS's 'Parse Filename'
+                                * (function 29H) describes V1 and V2.0+
+                                * separator and terminator characters. These
+                                * characters in a DOS name make the file
+                                * visible but un-manipulable (all useful
+                                * operations error off.
+                                */
+                               /* separators */
+                               case '+':
+                               case '=':
+                               case '%': /* not legal DOS */
+                                               /* filename */
+                               case ':':
+                               case ';': /* already handled */
+                               case '.': /* already handled */
+                               case ',': /* already handled */
+                               case '\t':
+                               case ' ':
+                               /* V1 only separators */
+                               case '/':
+                               case '"':
+                               case '[':
+                               case ']':
+                               /* terminators */
+                               case '>':
+                               case '<':
+                               case '|':
+                               /*
+                                * Other characters that are not valid ISO-9660
+                                * characters.
+                                */
+                               case '!':
+/*                             case '#':*/
+                               case '$':
+                               case '&':
+                               case '\'':
+                               case '(':
+                               case ')':
+                               case '*':
+/*                             case '-':*/
+                               case '?':
+                               case '@':
+                               case '\\':
+                               case '^':
+                               case '`':
+                               case '{':
+                               case '}':
+/*                             case '~':*/
+                               /*
+                                * All characters below 32 (space) are not
+                                * allowed too.
+                                */
+                               case 1: case 2: case 3: case 4:
+                               case 5: case 6: case 7: case 8:
+                               /* case 9: */
+                               case 10: case 11: case 12:
+                               case 13: case 14: case 15:
+                               case 16: case 17: case 18:
+                               case 19: case 20: case 21:
+                               case 22: case 23: case 24:
+                               case 25: case 26: case 27:
+                               case 28: case 29: case 30:
+                               case 31:
+
+                                       /*
+                                        * Hmm - what to do here? Skip? Win95
+                                        * looks like it substitutes '_'
+                                        */
+                                       *result++ = '_';
+                                       break;
+
+                               case '#':
+                               case '-':
+                               case '~':
+                                       /*
+                                        * Check if we should allow these
+                                        * illegal characters used by
+                                        * Microsoft.
+                                        */
+                                       if (iso_translate)
+                                               *result++ = '_';
+                                       else
+                                               *result++ = c;
+                                       break;
+                               }       /* switch (*pnt) */
+                       } else {        /* if (chars_{after,before}_dot) ... */
+                               pnt++;
+                               continue;
+                       }
+               }       /* else *pnt == '.' */
+               current_length++;
+               pnt++;
+       }       /* while (*pnt) */
+
+       /*
+        * OK, that wraps up the scan of the name.  Now tidy up a few other
+        * things.
+        * Look for emacs style of numbered backups, like foo.c.~3~.  If we
+        * see this, convert the version number into the priority number.
+        * In case of name conflicts, this is what would end up being used as
+        * the 'extension'.
+        */
+       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 this is not a directory, force a '.' in case we haven't seen one,
+        * and add a version number if we haven't seen one of those either.
+        */
+       if (!dirflag) {
+               if (!seen_dot && !omit_period) {
+                       if (chars_before_dot >= (iso9660_namelen-1)) {
+                               chars_before_dot--;
+                               result--;
+                       }
+                       *result++ = '.';
+                       extra++;
+               }
+               if (!omit_version_number && !seen_semic) {
+                       *result++ = ';';
+                       *result++ = '1';
+                       extra += 2;
+               }
+       }
+       *result++ = 0;
+       sresult->priority = priority;
+
+/*#define      DEBBUG*/
+#ifdef DEBBUG
+       fprintf(stderr, "NAME: '%s'\n", sresult->isorec.name);
+       fprintf(stderr, "chars_before_dot %d chars_after_dot %d seen_dot %d extra %d\n",
+               chars_before_dot, chars_after_dot, seen_dot, extra);
+#endif
+       return (chars_before_dot + chars_after_dot + seen_dot + extra);
+}
diff --git a/genisoimage/rock.c b/genisoimage/rock.c
new file mode 100644 (file)
index 0000000..7565bae
--- /dev/null
@@ -0,0 +1,864 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)rock.c  1.43 05/05/01 joerg */
+/*
+ * File rock.c - generate RRIP  records for iso9660 filesystems.
+ *
+ * Written by Eric Youngdale (1993).
+ *
+ * Copyright 1993 Yggdrasil Computing, Incorporated
+ * Copyright (c) 1999,2000-2003 J. Schilling
+ *
+ * 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 <mconfig.h>
+#include "genisoimage.h"
+#include <device.h>
+#include <schily.h>
+
+#define        SU_VERSION 1
+
+#define        SL_ROOT    8
+#define        SL_PARENT  4
+#define        SL_CURRENT 2
+#define        SL_CONTINUE 1
+
+#define        CE_SIZE 28      /* SUSP Continuation aerea                      */
+#define        CL_SIZE 12      /* RR   Child Link for deep dir relocation      */
+#define        ER_SIZE 8       /* RR   Extension record for RR signature       */
+#define        NM_SIZE 5       /* RR   Real name                               */
+#define        PL_SIZE 12      /* RR   Paren Link for deep dir relocation      */
+#define        PN_SIZE 20      /* RR   POSIX device modes (Major/Minor)        */
+#define        PX_SIZE 36      /* RR   POSIX Extensions (mode/nlink(uid/gid)   */
+#define        RE_SIZE 4       /* RR   Relocated directory                     */
+#define        RR_SIZE 5       /* RR   RR Signature in every file              */
+#define        SL_SIZE 20      /* RR   Symlink                                 */
+#define        ZF_SIZE 16      /* RR*  Linux compression extension             */
+#ifdef APPLE_HYB
+#define        AA_SIZE 14      /* size of Apple extension */
+#endif /* APPLE_HYB */
+#if defined(__QNX__) && !defined(__QNXNTO__)   /* Not on Neutrino! never OK? */
+#define        TF_SIZE (5 + 4 * 7)     /* RR   Time field                      */
+#else
+#define        TF_SIZE (5 + 3 * 7)
+#endif
+
+static void    rstrncpy(char *t, char *f, int c,
+                                                       struct unls_table *inls,
+                                                       struct unls_table *onls);
+static void    add_CE_entry(char *field, int line);
+static int     gen_xa_attr(mode_t attr);
+static void    gen_xa(struct stat *lstatbuf);
+int generate_xa_rr_attributes(char *whole_name, char *name,
+                                                                               struct directory_entry *s_entry,
+                                                                               struct stat *statbuf,
+                                                                               struct stat *lstatbuf,
+                                                                               int deep_opt);
+char *generate_rr_extension_record(char *id, char *descriptor, char *source,
+                                                                                         int *size);
+/*
+ * 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        RR_CUR_USE      (CE_SIZE + currlen + (ipnt - recstart))
+
+#define        MAYBE_ADD_CE_ENTRY(BYTES) \
+       (((int)(BYTES)) + CE_SIZE + currlen + (ipnt - recstart) > reclimit ? 1 : 0)
+
+/*
+ * Buffer to build RR attributes
+ */
+static Uchar   Rock[16384];
+static Uchar   symlink_buff[PATH_MAX+1];
+static int     ipnt = 0;       /* Current "write" offset in Rock[]     */
+static int     recstart = 0;   /* Start offset in Rock[] for this area */
+static int     currlen = 0;    /* # of non RR bytes used in this area  */
+static int     mainrec = 0;    /* # of RR bytes use in main dir area   */
+static int     reclimit;       /* Max. # of bytes usable in this area  */
+
+/* if we are using converted filenames, we don't want the '/' character */
+static void
+rstrncpy(char *t, char *f, int c, struct unls_table *inls, 
+                       struct unls_table *onls)
+{
+       while (c-- && *f) {
+               *t = conv_charset(*f, inls, onls);
+               if (*t == '/') {
+                       *t = '_';
+               }
+               t++;
+               f++;
+       }
+}
+
+static void
+add_CE_entry(char *field, int line)
+{
+       if (MAYBE_ADD_CE_ENTRY(0)) {
+               errmsgno(EX_BAD,
+               "Panic: no space, cannot add RR CE entry (%d bytes mising) for %s line %d.\n",
+               (CE_SIZE + currlen + (ipnt - recstart) - reclimit),
+               field, line);
+               errmsgno(EX_BAD, "currlen: %d ipnt: %d, recstart: %d\n",
+                               currlen, ipnt, recstart);
+               errmsgno(EX_BAD, "Send  bug report to the maintainer.\n");
+               comerrno(EX_BAD, "Aborting.\n");
+       }
+
+       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 */
+}
+
+static int
+gen_xa_attr(mode_t attr)
+{
+       int     ret = 0;
+
+       if (attr & S_IRUSR)
+               ret |= XA_O_READ;
+       if (attr & S_IXUSR)
+               ret |= XA_O_EXEC;
+
+       if (attr & S_IRGRP)
+               ret |= XA_G_READ;
+       if (attr & S_IXGRP)
+               ret |= XA_G_EXEC;
+
+       if (attr & S_IROTH)
+               ret |= XA_W_READ;
+       if (attr & S_IXOTH)
+               ret |= XA_W_EXEC;
+
+       ret |= XA_FORM1;
+
+       if (S_ISDIR(attr))
+               ret |= XA_DIR;
+
+       return (ret);
+}
+
+static void
+gen_xa(struct stat *lstatbuf)
+{
+               /*
+                * Group ID
+                */
+               set_722((char *) Rock + ipnt, lstatbuf->st_gid);
+               ipnt += 2;
+               /*
+                * User ID
+                */
+               set_722((char *) Rock + ipnt, lstatbuf->st_uid);
+               ipnt += 2;
+               /*
+                * Attributes
+                */
+               set_722((char *) Rock + ipnt, gen_xa_attr(lstatbuf->st_mode));
+               ipnt += 2;
+
+               Rock[ipnt++] = 'X';     /* XA Signature */
+               Rock[ipnt++] = 'A';
+               Rock[ipnt++] = 0;       /* File number (we always use '0' */
+
+               Rock[ipnt++] = 0;       /* Reserved (5 Byte) */
+               Rock[ipnt++] = 0;
+               Rock[ipnt++] = 0;
+               Rock[ipnt++] = 0;
+               Rock[ipnt++] = 0;
+
+}
+
+int
+generate_xa_rr_attributes(char *whole_name, char *name,
+                                                                 struct directory_entry *s_entry,
+                                                                 struct stat *statbuf,
+                                                                 struct stat *lstatbuf,
+                                                                 int deep_opt)
+{
+       int             flagpos;
+       int             flagval;
+       int             need_ce;
+
+       statbuf = statbuf;      /* this shuts up unreferenced compiler */
+                               /* warnings */
+       mainrec = recstart = ipnt = 0;
+
+       if (use_XA) {
+               gen_xa(lstatbuf);
+       }
+
+/*     reclimit = 0xf8; XXX we now use 254 == 0xfe */
+       reclimit = MAX_ISODIR;
+
+       /* no need to fill in the RR stuff if we won't see the file */
+       if (s_entry->de_flags & INHIBIT_ISO9660_ENTRY)
+               return (0);
+
+       /*
+        * Obtain the amount of space that is currently used for the directory
+        * record.  We may safely use the current name length; because if name
+        * confilcts force us to change the ISO-9660 name later, the name will
+        * never become longer than now.
+        */
+       if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0) {
+               s_entry->isorec.name_len[0] = 1;
+       } else {
+               s_entry->isorec.name_len[0] = strlen(s_entry->isorec.name);
+       }
+       currlen = s_entry->isorec.length[0] = s_entry->isorec.name_len[0] +
+                               offsetof(struct iso_directory_record, name[0]);
+       if (currlen & 1)
+               s_entry->isorec.length[0] = ++currlen;
+
+       if (currlen < 33+37) {
+               /*
+                * If the ISO-9660 name length is less than 37, we may use
+                * ISO-9660:1988 name rules and for this reason, the name len
+                * may later increase from adding e.g. ".;1"; in this case
+                * just use the upper limit.
+                */
+               currlen = 33+37;
+       }
+
+#ifdef APPLE_HYB
+       /* if we have regular file, then add Apple extensions */
+       if (S_ISREG(lstatbuf->st_mode) && apple_ext && s_entry->hfs_ent) {
+               if (MAYBE_ADD_CE_ENTRY(AA_SIZE))
+                       add_CE_entry("AA", __LINE__);
+               Rock[ipnt++] = 'A';     /* AppleSignature */
+               Rock[ipnt++] = 'A';
+               Rock[ipnt++] = AA_SIZE; /* includes AppleSignature bytes */
+               Rock[ipnt++] = 0x02;    /* SystemUseID */
+               Rock[ipnt++] = s_entry->hfs_ent->u.file.type[0];
+               Rock[ipnt++] = s_entry->hfs_ent->u.file.type[1];
+               Rock[ipnt++] = s_entry->hfs_ent->u.file.type[2];
+               Rock[ipnt++] = s_entry->hfs_ent->u.file.type[3];
+               Rock[ipnt++] = s_entry->hfs_ent->u.file.creator[0];
+               Rock[ipnt++] = s_entry->hfs_ent->u.file.creator[1];
+               Rock[ipnt++] = s_entry->hfs_ent->u.file.creator[2];
+               Rock[ipnt++] = s_entry->hfs_ent->u.file.creator[3];
+               Rock[ipnt++] = (s_entry->hfs_ent->fdflags >> 8) & 0xff;
+               Rock[ipnt++] = s_entry->hfs_ent->fdflags & 0xff;
+       }
+#endif /* APPLE_HYB */
+
+       if (!use_RockRidge)
+               goto xa_only;
+
+       /* Identify that we are using the SUSP protocol */
+       if (deep_opt & NEED_SP) {
+               /*
+                * We may not use a CE record here but we never will need to
+                * do so, as this SP record is only used for the "." entry
+                * of the root directory.
+                */
+               Rock[ipnt++] = 'S';
+               Rock[ipnt++] = 'P';
+               Rock[ipnt++] = 7;
+               Rock[ipnt++] = SU_VERSION;
+               Rock[ipnt++] = 0xbe;
+               Rock[ipnt++] = 0xef;
+               if (use_XA)
+                       Rock[ipnt++] = sizeof (struct iso_xa_dir_record);
+               else
+                       Rock[ipnt++] = 0;
+       }
+
+       /* First build the posix name field */
+       if (MAYBE_ADD_CE_ENTRY(RR_SIZE))
+               add_CE_entry("RR", __LINE__);
+       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; /* Remaining name length  */
+               int             use;    /* Current name part used */
+
+#ifdef APPLE_HYB
+               /* use the HFS name if it exists */
+               if (USE_MAC_NAME(s_entry)) {
+                       remain = strlen(s_entry->hfs_ent->name);
+                       npnt = s_entry->hfs_ent->name;
+               } else {
+#endif /* APPLE_HYB */
+
+                       remain = strlen(name);
+                       npnt = name;
+#ifdef APPLE_HYB
+               }
+#endif /* APPLE_HYB */
+
+               if (MAYBE_ADD_CE_ENTRY(NM_SIZE+1))
+                       add_CE_entry("NM", __LINE__);
+               while (remain) {
+                       use = remain;
+                       need_ce = 0;
+                       /* Can we fit this SUSP and a CE entry? */
+                       if (MAYBE_ADD_CE_ENTRY(NM_SIZE+use)) {
+                               use = reclimit - NM_SIZE - RR_CUR_USE;
+                               need_ce++;
+                       }
+                       /* Only room for 256 per SUSP field */
+                       if (use > 0xf8) {
+                               use = 0xf8;
+                               need_ce++;
+                       }
+                       if (use < 0) {
+                               comerrno(EX_BAD,
+                               "Negative RR name length residual: %d\n",
+                                       use);
+                       }
+
+                       /* 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);
+
+                       /* convert charsets as required */
+#ifdef APPLE_HYB
+                       if (USE_MAC_NAME(s_entry))
+                               rstrncpy((char *) &Rock[ipnt], npnt, use,
+                                                       hfs_inls, out_nls);
+                       else
+#endif /* APPLE_HYB */
+                               rstrncpy((char *) &Rock[ipnt], npnt, use,
+                                                       in_nls, out_nls);
+                       npnt += use;
+                       ipnt += use;
+                       remain -= use;
+                       if (remain && need_ce)
+                               add_CE_entry("NM", __LINE__);
+               }
+       }
+
+       /* Add the posix modes */
+       if (MAYBE_ADD_CE_ENTRY(PX_SIZE))
+               add_CE_entry("PX", __LINE__);
+       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 */
+#if    defined(S_IFCHR) || defined(S_IFBLK)
+       /*
+        * The code in this if statement used to be #ifdef'd with NON_UNIXFS.
+        * But as statdefs.h always provides the macros S_ISCHR() & S_ISBLK()
+        * and device.h always provides major()/minor() it is not needed
+        * anymore.
+        */
+       if (S_ISCHR(lstatbuf->st_mode) || S_ISBLK(lstatbuf->st_mode)) {
+               if (MAYBE_ADD_CE_ENTRY(PN_SIZE))
+                       add_CE_entry("PN", __LINE__);
+               Rock[ipnt++] = 'P';
+               Rock[ipnt++] = 'N';
+               Rock[ipnt++] = PN_SIZE;
+               Rock[ipnt++] = SU_VERSION;
+               flagval |= (1 << 1);
+#if 1
+               /* This is the new and only code which uses <device.h> */
+               set_733((char *) Rock + ipnt, major(lstatbuf->st_rdev));
+               ipnt += 8;
+               set_733((char *) Rock + ipnt, minor(lstatbuf->st_rdev));
+               ipnt += 8;
+#else
+               /*
+                * If we don't have sysmacros.h, then we have to guess as to
+                * how best to pick apart the device number for major/minor.
+                * Note: this may very well be wrong for many systems, so it
+                * is always best to use the major/minor macros if the system
+                * supports it.
+                */
+               if (sizeof (dev_t) <= 2) {
+                       set_733((char *)Rock + ipnt, (lstatbuf->st_rdev >> 8));
+                       ipnt += 8;
+                       set_733((char *)Rock + ipnt, lstatbuf->st_rdev & 0xff);
+                       ipnt += 8;
+               } else if (sizeof (dev_t) <= 4) {
+                       set_733((char *)Rock + ipnt,
+                                               (lstatbuf->st_rdev >> 8) >> 8);
+                       ipnt += 8;
+                       set_733((char *)Rock + ipnt,
+                                               lstatbuf->st_rdev & 0xffff);
+                       ipnt += 8;
+               } else {
+                       set_733((char *)Rock + ipnt,
+                                               (lstatbuf->st_rdev >> 16)>>16);
+                       ipnt += 8;
+                       set_733((char *)Rock + ipnt, lstatbuf->st_rdev);
+                       ipnt += 8;
+               }
+#endif
+       }
+#endif /* defined(S_IFCHR) || defined(S_IFBLK) */
+
+       /* Check for and symbolic links.  VMS does not have these. */
+#ifdef S_IFLNK
+       if (S_ISLNK(lstatbuf->st_mode)) {
+               int             lenpos;
+               int             lenval;
+               int             j0;
+               int             j1;
+               int             nchar;
+               Uchar           *cpnt;
+               Uchar           *cpnt1;
+
+#ifdef HAVE_READLINK
+               nchar = readlink(whole_name, (char *)symlink_buff,
+                                               sizeof (symlink_buff)-1);
+#else
+               nchar = -1;
+#endif /* HAVE_READLINK */
+               symlink_buff[nchar < 0 ? 0 : nchar] = 0;
+               nchar = strlen((char *) symlink_buff);
+               set_733(s_entry->isorec.size, 0);
+               cpnt = &symlink_buff[0];
+               flagval |= (1 << 2);
+
+               if (!split_SL_field) {
+                       int             sl_bytes = 0;
+
+                       for (cpnt1 = cpnt; *cpnt1 != '\0'; cpnt1++) {
+                               if (*cpnt1 == '/') {
+                                       sl_bytes += 4;
+                               } else {
+                                       sl_bytes += 1;
+                               }
+                       }
+                       if (sl_bytes > 250) {
+                               /*
+                                * the symbolic link won't fit into one
+                                * SL System Use Field print an error message
+                                * and continue with splited one
+                                */
+                               fprintf(stderr,
+                               "symbolic link ``%s'' to long for one SL System Use Field, splitting",
+                                                               cpnt);
+                       }
+                       if (MAYBE_ADD_CE_ENTRY(SL_SIZE + sl_bytes))
+                               add_CE_entry("SL+", __LINE__);
+               }
+               while (nchar) {
+                       if (MAYBE_ADD_CE_ENTRY(SL_SIZE))
+                               add_CE_entry("SL", __LINE__);
+                       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 = (Uchar *)
+                                               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("SL-parent", __LINE__);
+                                               if (cpnt1) {
+                                                       *cpnt1 = '/';
+                                                       nchar++;
+                                                       /*
+                                                        * A kluge so that we
+                                                        * can restart properly
+                                                        */
+                                                       cpnt1 = NULL;
+                                               }
+                                               break;
+                                       }
+                                       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("SL-current", __LINE__);
+                                               if (cpnt1) {
+                                                       *cpnt1 = '/';
+                                                       nchar++;
+                                                       /*
+                                                        * A kluge so that we
+                                                        * can restart properly
+                                                        */
+                                                       cpnt1 = NULL;
+                                               }
+                                               break;
+                                       }
+                                       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("SL-root", __LINE__);
+                                               if (cpnt1) {
+                                                       *cpnt1 = '/';
+                                                       nchar++;
+                                                       /*
+                                                        * A kluge so that we
+                                                        * can restart properly
+                                                        */
+                                                       cpnt1 = NULL;
+                                               }
+                                               break;
+                                       }
+                                       Rock[ipnt++] = SL_ROOT;
+                                       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 (split_SL_component ?
+                                               MAYBE_ADD_CE_ENTRY(6) :
+                                               MAYBE_ADD_CE_ENTRY(6 + strlen((char *) cpnt))) {
+                                               add_CE_entry("SL++", __LINE__);
+                                               if (cpnt1) {
+                                                       *cpnt1 = '/';
+                                                       nchar++;
+                                                       /*
+                                                        * A kluge so that we
+                                                        * can restart properly
+                                                        */
+                                                       cpnt1 = NULL;
+                                               }
+                                               break;
+                                       }
+                                       j0 = strlen((char *) cpnt);
+                                       while (j0) {
+                                               j1 = j0;
+                                               if (j1 > 0xf8)
+                                                       j1 = 0xf8;
+                                               need_ce = 0;
+                                               if (j1 + currlen + 2 + CE_SIZE +
+                                                   (ipnt - recstart) >
+                                                               reclimit) {
+
+                                                       j1 = reclimit -
+                                                           (currlen + 2) -
+                                                           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;
+                                               /*
+                                                * Number we processed
+                                                * this time
+                                                */
+                                               nchar -= j1;
+                                               j0 -= j1;
+                                               if (need_ce) {
+                                                       add_CE_entry(
+                                                           "SL-path-split",
+                                                           __LINE__);
+                                                       if (cpnt1) {
+                                                               *cpnt1 = '/';
+                                                               nchar++;
+                                                               /*
+                                                                * A kluge so
+                                                                * that we can
+                                                                * restart
+                                                                * properly
+                                                                */
+                                                               cpnt1 = NULL;
+                                                       }
+                                                       break;
+                                               }
+                                       }
+                               }
+                               if (cpnt1) {
+                                       cpnt = cpnt1 + 1;
+                               } else
+                                       break;
+                       }
+                       Rock[lenpos] = lenval;
+                       if (nchar) {
+                               /* We need another SL entry */
+                               Rock[lenpos + 2] = SL_CONTINUE;
+                       }
+               }       /* while nchar */
+       }       /* Is a symbolic link */
+#endif /* S_IFLNK */
+
+       /* Add in the Rock Ridge TF time field */
+       if (MAYBE_ADD_CE_ENTRY(TF_SIZE))
+               add_CE_entry("TF", __LINE__);
+       Rock[ipnt++] = 'T';
+       Rock[ipnt++] = 'F';
+       Rock[ipnt++] = TF_SIZE;
+       Rock[ipnt++] = SU_VERSION;
+#if defined(__QNX__) && !defined(__QNXNTO__)   /* Not on Neutrino! never OK? */
+       Rock[ipnt++] = 0x0f;
+#else
+       Rock[ipnt++] = 0x0e;
+#endif
+       flagval |= (1 << 7);
+
+#if defined(__QNX__) && !defined(__QNXNTO__)   /* Not on Neutrino! never OK? */
+       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 (relocated dir) field */
+       if (deep_opt & NEED_RE) {
+               if (MAYBE_ADD_CE_ENTRY(RE_SIZE))
+                       add_CE_entry("RE", __LINE__);
+               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("PL", __LINE__);
+               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("CL", __LINE__);
+               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 (and only if) it is actually a compressed file!
+        * This relies only on magic number, but it should in general not
+        * be an issue since if you're using -z odds are most of your
+        * files are already compressed.
+        *
+        * In the future it would be nice if genisoimage actually did the
+        * compression.
+        */
+       if (transparent_compression && S_ISREG(lstatbuf->st_mode)) {
+               static const Uchar zisofs_magic[8] =
+                       { 0x37, 0xE4, 0x53, 0x96, 0xC9, 0xDB, 0xD6, 0x07 };
+               FILE            *zffile;
+               unsigned int    file_size;
+               Uchar           header[16];
+               int             OK_flag;
+               int             blocksize;
+               int             headersize;
+
+               /*
+                * First open file and verify that the correct algorithm was
+                * used
+                */
+               file_size = 0;
+               OK_flag = 1;
+
+               memset(header, 0, sizeof (header));
+
+               zffile = fopen(whole_name, "rb");
+               if (zffile != NULL) {
+                       if (fread(header, 1, sizeof (header), zffile) != sizeof (header))
+                               OK_flag = 0;
+
+                       /* Check magic number */
+                       if (memcmp(header, zisofs_magic, sizeof (zisofs_magic)))
+                               OK_flag = 0;
+
+                       /* Get the real size of the file */
+                       file_size = get_731((char *)header+8);
+
+                       /* Get the header size (>> 2) */
+                       headersize = header[12];
+
+                       /* Get the block size (log2) */
+                       blocksize = header[13];
+
+                       fclose(zffile);
+               } else {
+                       OK_flag = 0;
+                       blocksize = headersize = 0; /* Make silly GCC quiet */
+               }
+
+               if (OK_flag) {
+                       if (MAYBE_ADD_CE_ENTRY(ZF_SIZE))
+                               add_CE_entry("ZF", __LINE__);
+                       Rock[ipnt++] = 'Z';
+                       Rock[ipnt++] = 'F';
+                       Rock[ipnt++] = ZF_SIZE;
+                       Rock[ipnt++] = SU_VERSION;
+                       Rock[ipnt++] = 'p'; /* Algorithm: "paged zlib" */
+                       Rock[ipnt++] = 'z';
+                       /* 2 bytes for algorithm-specific information */
+                       Rock[ipnt++] = headersize;
+                       Rock[ipnt++] = blocksize;
+                       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("ER", __LINE__);
+
+       /*
+        * 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);
+
+xa_only:
+       s_entry->rr_attributes = (Uchar *) 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 *
+generate_rr_extension_record(char *id, char *descriptor, char *source, 
+                                                                         int *size)
+{
+       int             lipnt = 0;
+       char            *pnt;
+       int             len_id;
+       int             len_des;
+       int             len_src;
+
+       len_id = strlen(id);
+       len_des = strlen(descriptor);
+       len_src = strlen(source);
+       Rock[lipnt++] = 'E';
+       Rock[lipnt++] = 'R';
+       Rock[lipnt++] = ER_SIZE + len_id + len_des + len_src;
+       Rock[lipnt++] = 1;
+       Rock[lipnt++] = len_id;
+       Rock[lipnt++] = len_des;
+       Rock[lipnt++] = len_src;
+       Rock[lipnt++] = 1;
+
+       memcpy(Rock + lipnt, id, len_id);
+       lipnt += len_id;
+
+       memcpy(Rock + lipnt, descriptor, len_des);
+       lipnt += len_des;
+
+       memcpy(Rock + lipnt, source, len_src);
+       lipnt += len_src;
+
+       if (lipnt > SECTOR_SIZE) {
+#ifdef USE_LIBSCHILY
+               comerrno(EX_BAD, "Extension record too long\n");
+#else
+               fprintf(stderr, "Extension record too long\n");
+               exit(1);
+#endif
+       }
+       pnt = (char *) e_malloc(SECTOR_SIZE);
+       memset(pnt, 0, SECTOR_SIZE);
+       memcpy(pnt, Rock, lipnt);
+       *size = lipnt;
+       return (pnt);
+}
diff --git a/genisoimage/rsync.c b/genisoimage/rsync.c
new file mode 100644 (file)
index 0000000..3f7e416
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+#include "genisoimage.h"
+#include "utypes.h"
+#include <ctype.h>
+#include <mconfig.h>
+
+/* Borrowed from jigdo; original notice:
+
+   These are purely random, no patterns or anything... (I hope)
+
+   I do not claim copyright for the actual numbers below, you may use them
+   for a re-implementation of the algorithm under a license of your choice.
+   -- Richard Atterer. */
+static UInt32_t charTable[256] = {
+  0x51d65c0f, 0x083cd94b, 0x77f73dd8, 0xa0187d36,
+  0x29803d07, 0x7ea8ac0e, 0xea4c16c9, 0xfc576443,
+  0x6213df29, 0x1c012392, 0xb38946ae, 0x2e20ca31,
+  0xe4dc532f, 0xcb281c47, 0x8508b6a5, 0xb93c210d,
+  0xef02b5f3, 0x66548c74, 0x9ae2deab, 0x3b59f472,
+  0x4e546447, 0x45232d1f, 0x0ac0a4b1, 0x6c4c264b,
+  0x5d24ce84, 0x0f2752cc, 0xa35c7ac7, 0x3e31af51,
+  0x79675a59, 0x581f0e81, 0x49053122, 0x7339c9d8,
+  0xf9833565, 0xa3dbe5b3, 0xcc06eeb9, 0x92d0671c,
+  0x3eb220a7, 0x64864eae, 0xca100872, 0xc50977a1,
+  0xd90378e1, 0x7a36cab9, 0x15c15f4b, 0x8b9ef749,
+  0xcc1432dc, 0x1ec578ed, 0x27e6e092, 0xbb06db8f,
+  0x67f661ac, 0x8dd1a3db, 0x2a0ca16b, 0xb229ab84,
+  0x127a3337, 0x347d846f, 0xe1ea4b50, 0x008dbb91,
+  0x414c1426, 0xd2be76f0, 0x08789a39, 0xb4d93e30,
+  0x61667760, 0x8871bee9, 0xab7da12d, 0xe3c58620,
+  0xe9fdfbbe, 0x64fb04f7, 0x8cc5bbf0, 0xf5272d30,
+  0x8f161b50, 0x11122b05, 0x7695e72e, 0xa1c5d169,
+  0x1bfd0e20, 0xef7e6169, 0xf652d08e, 0xa9d0f139,
+  0x2f70aa04, 0xae2c7d6d, 0xa3cb9241, 0x3ae7d364,
+  0x348788f8, 0xf483b8f1, 0x55a011da, 0x189719dc,
+  0xb0c5d723, 0x8b344e33, 0x300d46eb, 0xd44fe34f,
+  0x1a2016c1, 0x66ce4cd7, 0xa45ea5e3, 0x55cb708a,
+  0xbce430df, 0xb01ae6e0, 0x3551163b, 0x2c5b157a,
+  0x574c4209, 0x430fd0e4, 0x3387e4a5, 0xee1d7451,
+  0xa9635623, 0x873ab89b, 0xb96bc6aa, 0x59898937,
+  0xe646c6e7, 0xb79f8792, 0x3f3235d8, 0xef1b5acf,
+  0xd975b22b, 0x427acce6, 0xe47a2411, 0x75f8c1e8,
+  0xa63f799d, 0x53886ad8, 0x9b2d6d32, 0xea822016,
+  0xcdee2254, 0xd98bcd98, 0x2933a544, 0x961f379f,
+  0x49219792, 0xc61c360f, 0x77cc0c64, 0x7b872046,
+  0xb91c7c12, 0x7577154b, 0x196573be, 0xf788813f,
+  0x41e2e56a, 0xec3cd244, 0x8c7401f1, 0xc2e805fe,
+  0xe8872fbe, 0x9e2faf7d, 0x6766456b, 0x888e2197,
+  0x28535c6d, 0x2ce45f3f, 0x24261d2a, 0xd6faab8b,
+  0x7a7b42b8, 0x15f0f6fa, 0xfe1711df, 0x7e5685a6,
+  0x00930268, 0x74755331, 0x1998912c, 0x7b60498b,
+  0x501a5786, 0x92ace0f6, 0x1d9752fe, 0x5a731add,
+  0x5b3b44fc, 0x473673f9, 0xa42c0321, 0xd82f9f18,
+  0xb4b225da, 0xfc89ece2, 0x072e1130, 0x5772aae3,
+  0x29010857, 0x542c970c, 0x94f67fe5, 0x71209e9b,
+  0xdb97ea39, 0x2689b41b, 0xae815804, 0xfc5e2651,
+  0xd4521674, 0x48ed979a, 0x2f617da3, 0xc350353d,
+  0xc3accd94, 0xbd8d313a, 0xc61a8e77, 0xf34940a4,
+  0x8d2c6b0f, 0x0f0e7225, 0x39e183db, 0xd19ebba9,
+  0x6a0f37b9, 0xd18922f3, 0x106420c5, 0xaa5a640b,
+  0x7cf0d273, 0xcf3238a7, 0x3b33204f, 0x476be7bb,
+  0x09d23bca, 0xbe84b2f7, 0xb7a3bace, 0x2528cee1,
+  0x3dcaa1dd, 0x900ad31a, 0xf21dea6d, 0x9ce51463,
+  0xf1540bba, 0x0fab1bdd, 0x89cfb79a, 0x01a2a6e6,
+  0x6f85d67c, 0xd1669ec4, 0x355db722, 0x00ebd5c4,
+  0x926eb385, 0x69ead869, 0x0da2b122, 0x402779fe,
+  0xdaed92d0, 0x57e9aabb, 0x3df64854, 0xfcc774b5,
+  0x2e1740ed, 0xa615e024, 0xf7bac938, 0x377dfd1a,
+  0xd0559d66, 0x25499be8, 0x2d8f2006, 0xfaa9e486,
+  0x95e980e7, 0x82aeba67, 0x5a7f2561, 0xbc60dff6,
+  0x6c8739a2, 0x7ec59a8b, 0x9998f265, 0xdfe37e5e,
+  0xb47cee1e, 0x4dd8bc9e, 0x35c57e09, 0x07850b63,
+  0x06eadbcb, 0x6c1f2956, 0x01685c2c, 0xf5725eef,
+  0xf13b98b5, 0xaab739c2, 0x200b1da2, 0xa716b98b,
+  0xd9ee3058, 0x76acf20b, 0x2f259e04, 0xed11658b,
+  0x1532b331, 0x0ab43204, 0xf0beb023, 0xb1685483,
+  0x58cbdc4f, 0x079384d3, 0x049b141c, 0xc38184b9,
+  0xaf551d9a, 0x66222560, 0x059deeca, 0x535f99e2
+};
+
+unsigned long long rsync64(unsigned char *mem, size_t size)
+{
+    UInt32_t a = 0;
+    UInt32_t b = 0;
+    unsigned char *limit = mem + size;
+    unsigned long long result = 0;
+
+    while (mem < limit)
+    {
+        a += charTable[*mem++];
+        b += a;
+    }
+
+    a = a & 0xffffffff; /* Just in case uint32 can be 64 bits */
+    b = b & 0xffffffff;
+
+    result = ((unsigned long long)b << 32) | a;
+
+    return result;
+}
+
diff --git a/genisoimage/scsi.c b/genisoimage/scsi.c
new file mode 100644 (file)
index 0000000..179cc33
--- /dev/null
@@ -0,0 +1,195 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)scsi.c  1.20 05/05/01 Copyright 1997 J. Schilling */
+/*
+ *     Copyright (c) 1997 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef USE_SCG
+#include <mconfig.h>
+
+#include <stdio.h>
+#include <standard.h>
+#include <stdxlib.h>
+#include <unixstd.h>
+#include <schily.h>
+
+#include "genisoimage.h"
+#include <usal/scsireg.h>
+#include <usal/scsitransp.h>
+
+#include "wodim.h"
+#include "../wodim/defaults.h"
+
+/*
+ * NOTICE:     You should not make BUF_SIZE more than
+ *             the buffer size of the CD-Recorder.
+ *
+ * Do not set BUF_SIZE to be more than 126 KBytes
+ * if you are running cdrecord on a sun4c machine.
+ *
+ * WARNING:    Philips CDD 521 dies if BUF_SIZE is to big.
+ */
+#define        BUF_SIZE        (62*1024)       /* Must be a multiple of 2048      */
+
+static SCSI    *usalp;
+static long    bufsize;                /* The size of the transfer buffer */
+
+int    readsecs(int startsecno, void *buffer, int sectorcount);
+int    scsidev_open(char *path);
+int    scsidev_close(void);
+
+int
+readsecs(int startsecno, void *buffer, int sectorcount)
+{
+       int     f;
+       int     secsize;        /* The drive's SCSI sector size         */
+       long    amount;         /* The number of bytes to be transfered */
+       long    secno;          /* The sector number to read from       */
+       long    secnum;         /* The number of sectors to read        */
+       char    *bp;
+       long    amt;
+
+       if (in_image == NULL) {
+               /*
+                * We are using the standard CD-ROM sectorsize of 2048 bytes
+                * while the drive may be switched to 512 bytes per sector.
+                *
+                * XXX We assume that secsize is no more than SECTOR_SIZE
+                * XXX and that SECTOR_SIZE / secsize is not a fraction.
+                */
+               secsize = usalp->cap->c_bsize;
+               amount = sectorcount * SECTOR_SIZE;
+               secno = startsecno * (SECTOR_SIZE / secsize);
+               bp = buffer;
+
+               while (amount > 0) {
+                       amt = amount;
+                       if (amount > bufsize)
+                               amt = bufsize;
+                       secnum = amt / secsize;
+
+                       if (read_scsi(usalp, bp, secno, secnum) < 0 ||
+                                               usal_getresid(usalp) != 0) {
+#ifdef OLD
+                               return (-1);
+#else
+                               comerr("Read error on old image\n");
+#endif
+                       }
+
+                       amount  -= secnum * secsize;
+                       bp      += secnum * secsize;
+                       secno   += secnum;
+               }
+               return (SECTOR_SIZE * sectorcount);
+       }
+
+       f = fileno(in_image);
+
+       if (lseek(f, (off_t)startsecno * SECTOR_SIZE, SEEK_SET) == (off_t)-1) {
+#ifdef USE_LIBSCHILY
+               comerr("Seek error on old image\n");
+#else
+               fprintf(stderr, "Seek error on old image\n");
+               exit(10);
+#endif
+       }
+       if ((amt = read(f, buffer, (sectorcount * SECTOR_SIZE)))
+                       != (sectorcount * SECTOR_SIZE)) {
+#ifdef USE_LIBSCHILY
+               if (amt < 0)
+                       comerr("Read error on old image\n");
+               comerrno(EX_BAD, "Short read on old image\n"); /* < secnt aber > 0 */
+#else
+               if (amt < 0)
+                       fprintf(stderr, "Read error on old image\n");
+               else
+                       fprintf(stderr, "Short read on old image\n");
+       
+               exit(10);
+#endif
+       }
+       return (sectorcount * SECTOR_SIZE);
+}
+
+int
+scsidev_open(char *path)
+{
+       char    errstr[80];
+       char    *buf;   /* ignored, bit OS/2 ASPI layer needs memory which */
+                       /* has been allocated by scsi_getbuf()             */
+
+       /*
+        * Call usal_remote() to force loading the remote SCSI transport library
+        * code that is located in librusal instead of the dummy remote routines
+        * that are located inside libusal.
+        */
+       usal_remote();
+
+       cdr_defaults(&path, NULL, NULL, NULL);
+                       /* path, debug, verboseopen */
+       usalp = usal_open(path, errstr, sizeof (errstr), 0, 0);
+       if (usalp == 0) {
+               errmsg("%s%sCannot open SCSI driver.\n", errstr, errstr[0]?". ":"");
+               return (-1);
+       }
+
+       bufsize = usal_bufsize(usalp, BUF_SIZE);
+       if ((buf = usal_getbuf(usalp, bufsize)) == NULL) {
+               errmsg("Cannot get SCSI I/O buffer.\n");
+               usal_close(usalp);
+               return (-1);
+       }
+
+       bufsize = (bufsize / SECTOR_SIZE) * SECTOR_SIZE;
+
+       allow_atapi(usalp, TRUE);
+
+       if (!wait_unit_ready(usalp, 60)) { /* Eat Unit att / Wait for drive */
+               usalp->silent--;
+               return (-1);
+       }
+
+       usalp->silent++;
+       read_capacity(usalp);   /* Set Capacity/Sectorsize for I/O */
+       usalp->silent--;
+
+       return (1);
+}
+
+int
+scsidev_close()
+{
+       if (in_image == NULL) {
+               return (usal_close(usalp));
+       } else {
+               return (fclose(in_image));
+       }
+}
+
+#endif /* USE_SCG */
diff --git a/genisoimage/scsi.h b/genisoimage/scsi.h
new file mode 100644 (file)
index 0000000..58fc342
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)scsi.h  1.1 04/05/27 Copyright 1997-2004 J. Schilling */
+/*
+ *     Copyright (c) 1997-2004 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef        _SCSI_H
+#define        _SCSI_H
+
+#ifdef USE_SCG
+extern int     readsecs(int startsecno, void *buffer, int sectorcount);
+extern int     scsidev_open(char *path);
+extern int     scsidev_close(void);
+#endif
+
+#endif /* _SCSI_H */
diff --git a/genisoimage/sha1.c b/genisoimage/sha1.c
new file mode 100644 (file)
index 0000000..ae410ac
--- /dev/null
@@ -0,0 +1,415 @@
+/* sha1.c - Functions to compute SHA1 message digest of files or
+   memory blocks according to the NIST specification FIPS-180-1.
+
+   Copyright (C) 2000, 2001, 2003, 2004, 2005 Free Software Foundation, Inc.
+
+   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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+/* Written by Scott G. Miller
+   Credits:
+      Robert Klep <robert@ilse.nl>  -- Expansion function fix
+*/
+
+#include "sha1.h"
+
+#include <stddef.h>
+#include <string.h>
+
+/* SWAP does an endian swap on architectures that are little-endian,
+   as SHA1 needs some data in a big-endian form.  */
+
+#ifdef WORDS_BIGENDIAN
+# define SWAP(n) (n)
+#else
+# define SWAP(n) \
+    (((n) << 24) | (((n) & 0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24))
+#endif
+
+#define BLOCKSIZE 4096
+#if BLOCKSIZE % 64 != 0
+# error "invalid BLOCKSIZE"
+#endif
+
+/* This array contains the bytes used to pad the buffer to the next
+   64-byte boundary.  (RFC 1321, 3.1: Step 1)  */
+static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ...  */ };
+
+
+/*
+  Takes a pointer to a 160 bit block of data (five 32 bit ints) and
+  intializes it to the start constants of the SHA1 algorithm.  This
+  must be called before using hash in the call to sha1_hash.
+*/
+void
+sha1_init_ctx (struct sha1_ctx *ctx)
+{
+  ctx->A = 0x67452301;
+  ctx->B = 0xefcdab89;
+  ctx->C = 0x98badcfe;
+  ctx->D = 0x10325476;
+  ctx->E = 0xc3d2e1f0;
+
+  ctx->total[0] = ctx->total[1] = 0;
+  ctx->buflen = 0;
+}
+
+/* Put result from CTX in first 20 bytes following RESBUF.  The result
+   must be in little endian byte order.
+
+   IMPORTANT: On some systems it is required that RESBUF is correctly
+   aligned for a 32 bits value.  */
+void *
+sha1_read_ctx (const struct sha1_ctx *ctx, void *resbuf)
+{
+  ((md5_uint32 *) resbuf)[0] = SWAP (ctx->A);
+  ((md5_uint32 *) resbuf)[1] = SWAP (ctx->B);
+  ((md5_uint32 *) resbuf)[2] = SWAP (ctx->C);
+  ((md5_uint32 *) resbuf)[3] = SWAP (ctx->D);
+  ((md5_uint32 *) resbuf)[4] = SWAP (ctx->E);
+
+  return resbuf;
+}
+
+/* Process the remaining bytes in the internal buffer and the usual
+   prolog according to the standard and write the result to RESBUF.
+
+   IMPORTANT: On some systems it is required that RESBUF is correctly
+   aligned for a 32 bits value.  */
+void *
+sha1_finish_ctx (struct sha1_ctx *ctx, void *resbuf)
+{
+  /* Take yet unprocessed bytes into account.  */
+  md5_uint32 bytes = ctx->buflen;
+  size_t pad;
+
+  /* Now count remaining bytes.  */
+  ctx->total[0] += bytes;
+  if (ctx->total[0] < bytes)
+    ++ctx->total[1];
+
+  pad = bytes >= 56 ? 64 + 56 - bytes : 56 - bytes;
+  memcpy (&ctx->buffer[bytes], fillbuf, pad);
+
+  /* Put the 64-bit file length in *bits* at the end of the buffer.  */
+  *(md5_uint32 *) &ctx->buffer[bytes + pad + 4] = SWAP (ctx->total[0] << 3);
+  *(md5_uint32 *) &ctx->buffer[bytes + pad] = SWAP ((ctx->total[1] << 3) |
+                                                   (ctx->total[0] >> 29));
+
+  /* Process last bytes.  */
+  sha1_process_block (ctx->buffer, bytes + pad + 8, ctx);
+
+  return sha1_read_ctx (ctx, resbuf);
+}
+
+/* Compute SHA1 message digest for bytes read from STREAM.  The
+   resulting message digest number will be written into the 16 bytes
+   beginning at RESBLOCK.  */
+int
+sha1_stream (FILE *stream, void *resblock)
+{
+  struct sha1_ctx ctx;
+  char buffer[BLOCKSIZE + 72];
+  size_t sum;
+
+  /* Initialize the computation context.  */
+  sha1_init_ctx (&ctx);
+
+  /* Iterate over full file contents.  */
+  while (1)
+    {
+      /* We read the file in blocks of BLOCKSIZE bytes.  One call of the
+        computation function processes the whole buffer so that with the
+        next round of the loop another block can be read.  */
+      size_t n;
+      sum = 0;
+
+      /* Read block.  Take care for partial reads.  */
+      while (1)
+       {
+         n = fread (buffer + sum, 1, BLOCKSIZE - sum, stream);
+
+         sum += n;
+
+         if (sum == BLOCKSIZE)
+           break;
+
+         if (n == 0)
+           {
+             /* Check for the error flag IFF N == 0, so that we don't
+                exit the loop after a partial read due to e.g., EAGAIN
+                or EWOULDBLOCK.  */
+             if (ferror (stream))
+               return 1;
+             goto process_partial_block;
+           }
+
+         /* We've read at least one byte, so ignore errors.  But always
+            check for EOF, since feof may be true even though N > 0.
+            Otherwise, we could end up calling fread after EOF.  */
+         if (feof (stream))
+           goto process_partial_block;
+       }
+
+      /* Process buffer with BLOCKSIZE bytes.  Note that
+                       BLOCKSIZE % 64 == 0
+       */
+      sha1_process_block (buffer, BLOCKSIZE, &ctx);
+    }
+
+ process_partial_block:;
+
+  /* Process any remaining bytes.  */
+  if (sum > 0)
+    sha1_process_bytes (buffer, sum, &ctx);
+
+  /* Construct result in desired memory.  */
+  sha1_finish_ctx (&ctx, resblock);
+  return 0;
+}
+
+/* Compute MD5 message digest for LEN bytes beginning at BUFFER.  The
+   result is always in little endian byte order, so that a byte-wise
+   output yields to the wanted ASCII representation of the message
+   digest.  */
+void *
+sha1_buffer (const char *buffer, size_t len, void *resblock)
+{
+  struct sha1_ctx ctx;
+
+  /* Initialize the computation context.  */
+  sha1_init_ctx (&ctx);
+
+  /* Process whole buffer but last len % 64 bytes.  */
+  sha1_process_bytes (buffer, len, &ctx);
+
+  /* Put result in desired memory area.  */
+  return sha1_finish_ctx (&ctx, resblock);
+}
+
+void
+sha1_process_bytes (const void *buffer, size_t len, struct sha1_ctx *ctx)
+{
+  /* When we already have some bits in our internal buffer concatenate
+     both inputs first.  */
+  if (ctx->buflen != 0)
+    {
+      size_t left_over = ctx->buflen;
+      size_t add = 128 - left_over > len ? len : 128 - left_over;
+
+      memcpy (&ctx->buffer[left_over], buffer, add);
+      ctx->buflen += add;
+
+      if (ctx->buflen > 64)
+       {
+         sha1_process_block (ctx->buffer, ctx->buflen & ~63, ctx);
+
+         ctx->buflen &= 63;
+         /* The regions in the following copy operation cannot overlap.  */
+         memcpy (ctx->buffer, &ctx->buffer[(left_over + add) & ~63],
+                 ctx->buflen);
+       }
+
+      buffer = (const char *) buffer + add;
+      len -= add;
+    }
+
+  /* Process available complete blocks.  */
+  if (len >= 64)
+    {
+#if !_STRING_ARCH_unaligned
+# define alignof(type) offsetof (struct { char c; type x; }, x)
+# define UNALIGNED_P(p) (((size_t) p) % alignof (md5_uint32) != 0)
+      if (UNALIGNED_P (buffer))
+       while (len > 64)
+         {
+           sha1_process_block (memcpy (ctx->buffer, buffer, 64), 64, ctx);
+           buffer = (const char *) buffer + 64;
+           len -= 64;
+         }
+      else
+#endif
+       {
+         sha1_process_block (buffer, len & ~63, ctx);
+         buffer = (const char *) buffer + (len & ~63);
+         len &= 63;
+       }
+    }
+
+  /* Move remaining bytes in internal buffer.  */
+  if (len > 0)
+    {
+      size_t left_over = ctx->buflen;
+
+      memcpy (&ctx->buffer[left_over], buffer, len);
+      left_over += len;
+      if (left_over >= 64)
+       {
+         sha1_process_block (ctx->buffer, 64, ctx);
+         left_over -= 64;
+         memcpy (ctx->buffer, &ctx->buffer[64], left_over);
+       }
+      ctx->buflen = left_over;
+    }
+}
+
+/* --- Code below is the primary difference between md5.c and sha1.c --- */
+
+/* SHA1 round constants */
+#define K1 0x5a827999L
+#define K2 0x6ed9eba1L
+#define K3 0x8f1bbcdcL
+#define K4 0xca62c1d6L
+
+/* Round functions.  Note that F2 is the same as F4.  */
+#define F1(B,C,D) ( D ^ ( B & ( C ^ D ) ) )
+#define F2(B,C,D) (B ^ C ^ D)
+#define F3(B,C,D) ( ( B & C ) | ( D & ( B | C ) ) )
+#define F4(B,C,D) (B ^ C ^ D)
+
+/* Process LEN bytes of BUFFER, accumulating context into CTX.
+   It is assumed that LEN % 64 == 0.
+   Most of this code comes from GnuPG's cipher/sha1.c.  */
+
+void
+sha1_process_block (const void *buffer, size_t len, struct sha1_ctx *ctx)
+{
+  const md5_uint32 *words = buffer;
+  size_t nwords = len / sizeof (md5_uint32);
+  const md5_uint32 *endp = words + nwords;
+  md5_uint32 x[16];
+  md5_uint32 a = ctx->A;
+  md5_uint32 b = ctx->B;
+  md5_uint32 c = ctx->C;
+  md5_uint32 d = ctx->D;
+  md5_uint32 e = ctx->E;
+
+  /* First increment the byte count.  RFC 1321 specifies the possible
+     length of the file up to 2^64 bits.  Here we only compute the
+     number of bytes.  Do a double word increment.  */
+  ctx->total[0] += len;
+  if (ctx->total[0] < len)
+    ++ctx->total[1];
+
+#define rol(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
+
+#define M(I) ( tm =   x[I&0x0f] ^ x[(I-14)&0x0f] \
+                   ^ x[(I-8)&0x0f] ^ x[(I-3)&0x0f] \
+              , (x[I&0x0f] = rol(tm, 1)) )
+
+#define R(A,B,C,D,E,F,K,M)  do { E += rol( A, 5 )     \
+                                     + F( B, C, D )  \
+                                     + K             \
+                                     + M;            \
+                                B = rol( B, 30 );    \
+                              } while(0)
+
+  while (words < endp)
+    {
+      md5_uint32 tm;
+      int t;
+      for (t = 0; t < 16; t++)
+       {
+         x[t] = SWAP (*words);
+         words++;
+       }
+
+      R( a, b, c, d, e, F1, K1, x[ 0] );
+      R( e, a, b, c, d, F1, K1, x[ 1] );
+      R( d, e, a, b, c, F1, K1, x[ 2] );
+      R( c, d, e, a, b, F1, K1, x[ 3] );
+      R( b, c, d, e, a, F1, K1, x[ 4] );
+      R( a, b, c, d, e, F1, K1, x[ 5] );
+      R( e, a, b, c, d, F1, K1, x[ 6] );
+      R( d, e, a, b, c, F1, K1, x[ 7] );
+      R( c, d, e, a, b, F1, K1, x[ 8] );
+      R( b, c, d, e, a, F1, K1, x[ 9] );
+      R( a, b, c, d, e, F1, K1, x[10] );
+      R( e, a, b, c, d, F1, K1, x[11] );
+      R( d, e, a, b, c, F1, K1, x[12] );
+      R( c, d, e, a, b, F1, K1, x[13] );
+      R( b, c, d, e, a, F1, K1, x[14] );
+      R( a, b, c, d, e, F1, K1, x[15] );
+      R( e, a, b, c, d, F1, K1, M(16) );
+      R( d, e, a, b, c, F1, K1, M(17) );
+      R( c, d, e, a, b, F1, K1, M(18) );
+      R( b, c, d, e, a, F1, K1, M(19) );
+      R( a, b, c, d, e, F2, K2, M(20) );
+      R( e, a, b, c, d, F2, K2, M(21) );
+      R( d, e, a, b, c, F2, K2, M(22) );
+      R( c, d, e, a, b, F2, K2, M(23) );
+      R( b, c, d, e, a, F2, K2, M(24) );
+      R( a, b, c, d, e, F2, K2, M(25) );
+      R( e, a, b, c, d, F2, K2, M(26) );
+      R( d, e, a, b, c, F2, K2, M(27) );
+      R( c, d, e, a, b, F2, K2, M(28) );
+      R( b, c, d, e, a, F2, K2, M(29) );
+      R( a, b, c, d, e, F2, K2, M(30) );
+      R( e, a, b, c, d, F2, K2, M(31) );
+      R( d, e, a, b, c, F2, K2, M(32) );
+      R( c, d, e, a, b, F2, K2, M(33) );
+      R( b, c, d, e, a, F2, K2, M(34) );
+      R( a, b, c, d, e, F2, K2, M(35) );
+      R( e, a, b, c, d, F2, K2, M(36) );
+      R( d, e, a, b, c, F2, K2, M(37) );
+      R( c, d, e, a, b, F2, K2, M(38) );
+      R( b, c, d, e, a, F2, K2, M(39) );
+      R( a, b, c, d, e, F3, K3, M(40) );
+      R( e, a, b, c, d, F3, K3, M(41) );
+      R( d, e, a, b, c, F3, K3, M(42) );
+      R( c, d, e, a, b, F3, K3, M(43) );
+      R( b, c, d, e, a, F3, K3, M(44) );
+      R( a, b, c, d, e, F3, K3, M(45) );
+      R( e, a, b, c, d, F3, K3, M(46) );
+      R( d, e, a, b, c, F3, K3, M(47) );
+      R( c, d, e, a, b, F3, K3, M(48) );
+      R( b, c, d, e, a, F3, K3, M(49) );
+      R( a, b, c, d, e, F3, K3, M(50) );
+      R( e, a, b, c, d, F3, K3, M(51) );
+      R( d, e, a, b, c, F3, K3, M(52) );
+      R( c, d, e, a, b, F3, K3, M(53) );
+      R( b, c, d, e, a, F3, K3, M(54) );
+      R( a, b, c, d, e, F3, K3, M(55) );
+      R( e, a, b, c, d, F3, K3, M(56) );
+      R( d, e, a, b, c, F3, K3, M(57) );
+      R( c, d, e, a, b, F3, K3, M(58) );
+      R( b, c, d, e, a, F3, K3, M(59) );
+      R( a, b, c, d, e, F4, K4, M(60) );
+      R( e, a, b, c, d, F4, K4, M(61) );
+      R( d, e, a, b, c, F4, K4, M(62) );
+      R( c, d, e, a, b, F4, K4, M(63) );
+      R( b, c, d, e, a, F4, K4, M(64) );
+      R( a, b, c, d, e, F4, K4, M(65) );
+      R( e, a, b, c, d, F4, K4, M(66) );
+      R( d, e, a, b, c, F4, K4, M(67) );
+      R( c, d, e, a, b, F4, K4, M(68) );
+      R( b, c, d, e, a, F4, K4, M(69) );
+      R( a, b, c, d, e, F4, K4, M(70) );
+      R( e, a, b, c, d, F4, K4, M(71) );
+      R( d, e, a, b, c, F4, K4, M(72) );
+      R( c, d, e, a, b, F4, K4, M(73) );
+      R( b, c, d, e, a, F4, K4, M(74) );
+      R( a, b, c, d, e, F4, K4, M(75) );
+      R( e, a, b, c, d, F4, K4, M(76) );
+      R( d, e, a, b, c, F4, K4, M(77) );
+      R( c, d, e, a, b, F4, K4, M(78) );
+      R( b, c, d, e, a, F4, K4, M(79) );
+
+      a = ctx->A += a;
+      b = ctx->B += b;
+      c = ctx->C += c;
+      d = ctx->D += d;
+      e = ctx->E += e;
+    }
+}
diff --git a/genisoimage/sha1.h b/genisoimage/sha1.h
new file mode 100644 (file)
index 0000000..51891d0
--- /dev/null
@@ -0,0 +1,88 @@
+/* Declarations of functions and data types used for SHA1 sum
+   library functions.
+   Copyright (C) 2000, 2001, 2003, 2005 Free Software Foundation, Inc.
+
+   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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#ifndef SHA1_H
+# define SHA1_H 1
+
+# include <stdio.h>
+
+typedef unsigned int md5_uint32;
+
+/* Structure to save state of computation between the single steps.  */
+struct sha1_ctx
+{
+  md5_uint32 A;
+  md5_uint32 B;
+  md5_uint32 C;
+  md5_uint32 D;
+  md5_uint32 E;
+
+  md5_uint32 total[2];
+  md5_uint32 buflen;
+  char buffer[128] __attribute__ ((__aligned__ (__alignof__ (md5_uint32))));
+};
+
+
+/* Initialize structure containing state of computation. */
+extern void sha1_init_ctx (struct sha1_ctx *ctx);
+
+/* Starting with the result of former calls of this function (or the
+   initialization function update the context for the next LEN bytes
+   starting at BUFFER.
+   It is necessary that LEN is a multiple of 64!!! */
+extern void sha1_process_block (const void *buffer, size_t len,
+                               struct sha1_ctx *ctx);
+
+/* Starting with the result of former calls of this function (or the
+   initialization function update the context for the next LEN bytes
+   starting at BUFFER.
+   It is NOT required that LEN is a multiple of 64.  */
+extern void sha1_process_bytes (const void *buffer, size_t len,
+                               struct sha1_ctx *ctx);
+
+/* Process the remaining bytes in the buffer and put result from CTX
+   in first 20 bytes following RESBUF.  The result is always in little
+   endian byte order, so that a byte-wise output yields to the wanted
+   ASCII representation of the message digest.
+
+   IMPORTANT: On some systems it is required that RESBUF be correctly
+   aligned for a 32 bits value.  */
+extern void *sha1_finish_ctx (struct sha1_ctx *ctx, void *resbuf);
+
+
+/* Put result from CTX in first 20 bytes following RESBUF.  The result is
+   always in little endian byte order, so that a byte-wise output yields
+   to the wanted ASCII representation of the message digest.
+
+   IMPORTANT: On some systems it is required that RESBUF is correctly
+   aligned for a 32 bits value.  */
+extern void *sha1_read_ctx (const struct sha1_ctx *ctx, void *resbuf);
+
+
+/* Compute SHA1 message digest for bytes read from STREAM.  The
+   resulting message digest number will be written into the 20 bytes
+   beginning at RESBLOCK.  */
+extern int sha1_stream (FILE *stream, void *resblock);
+
+/* Compute SHA1 message digest for LEN bytes beginning at BUFFER.  The
+   result is always in little endian byte order, so that a byte-wise
+   output yields to the wanted ASCII representation of the message
+   digest.  */
+extern void *sha1_buffer (const char *buffer, size_t len, void *resblock);
+
+#endif
diff --git a/genisoimage/sha256.c b/genisoimage/sha256.c
new file mode 100644 (file)
index 0000000..f7558b2
--- /dev/null
@@ -0,0 +1,307 @@
+/* Functions to compute SHA256 message digest of files or memory blocks.
+   according to the definition of SHA256 in FIPS 180-2.
+   Copyright (C) 2007 Free Software Foundation, Inc.
+
+   Copied here from the GNU C Library version 2.7 on the 10 May 2009
+   by Steve McIntyre <93sam@debian.org>. This code was under LGPL v2.1
+   in glibc, and that license gives us the option to use and
+   distribute the code under the terms of the GPL v2 instead. I'm
+   taking that option.
+
+   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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+/* Written by Ulrich Drepper <drepper@redhat.com>, 2007.  */
+
+#include <endian.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include "sha256.h"
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+# ifdef _LIBC
+#  include <byteswap.h>
+#  define SWAP(n) bswap_32 (n)
+# else
+#  define SWAP(n) \
+    (((n) << 24) | (((n) & 0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24))
+# endif
+#else
+# define SWAP(n) (n)
+#endif
+
+
+/* This array contains the bytes used to pad the buffer to the next
+   64-byte boundary.  (FIPS 180-2:5.1.1)  */
+static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ...  */ };
+
+
+/* Constants for SHA256 from FIPS 180-2:4.2.2.  */
+static const uint32_t K[64] =
+  {
+    0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
+    0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
+    0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
+    0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
+    0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
+    0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
+    0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
+    0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
+    0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
+    0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
+    0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
+    0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
+    0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
+    0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
+    0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
+    0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
+  };
+
+
+/* Process LEN bytes of BUFFER, accumulating context into CTX.
+   It is assumed that LEN % 64 == 0.  */
+static void
+sha256_process_block (const void *buffer, size_t len, struct sha256_ctx *ctx)
+{
+  const uint32_t *words = buffer;
+  size_t nwords = len / sizeof (uint32_t);
+  uint32_t a = ctx->H[0];
+  uint32_t b = ctx->H[1];
+  uint32_t c = ctx->H[2];
+  uint32_t d = ctx->H[3];
+  uint32_t e = ctx->H[4];
+  uint32_t f = ctx->H[5];
+  uint32_t g = ctx->H[6];
+  uint32_t h = ctx->H[7];
+
+  /* First increment the byte count.  FIPS 180-2 specifies the possible
+     length of the file up to 2^64 bits.  Here we only compute the
+     number of bytes.  Do a double word increment.  */
+  ctx->total[0] += len;
+  if (ctx->total[0] < len)
+    ++ctx->total[1];
+
+  /* Process all bytes in the buffer with 64 bytes in each round of
+     the loop.  */
+  while (nwords > 0)
+    {
+      uint32_t W[64];
+      uint32_t a_save = a;
+      uint32_t b_save = b;
+      uint32_t c_save = c;
+      uint32_t d_save = d;
+      uint32_t e_save = e;
+      uint32_t f_save = f;
+      uint32_t g_save = g;
+      uint32_t h_save = h;
+
+      unsigned int t;
+
+      /* Operators defined in FIPS 180-2:4.1.2.  */
+#define Ch(x, y, z) ((x & y) ^ (~x & z))
+#define Maj(x, y, z) ((x & y) ^ (x & z) ^ (y & z))
+#define S0(x) (CYCLIC (x, 2) ^ CYCLIC (x, 13) ^ CYCLIC (x, 22))
+#define S1(x) (CYCLIC (x, 6) ^ CYCLIC (x, 11) ^ CYCLIC (x, 25))
+#define R0(x) (CYCLIC (x, 7) ^ CYCLIC (x, 18) ^ (x >> 3))
+#define R1(x) (CYCLIC (x, 17) ^ CYCLIC (x, 19) ^ (x >> 10))
+
+      /* It is unfortunate that C does not provide an operator for
+        cyclic rotation.  Hope the C compiler is smart enough.  */
+#define CYCLIC(w, s) ((w >> s) | (w << (32 - s)))
+
+      /* Compute the message schedule according to FIPS 180-2:6.2.2 step 2.  */
+      for (t = 0; t < 16; ++t)
+       {
+         W[t] = SWAP (*words);
+         ++words;
+       }
+      for (t = 16; t < 64; ++t)
+       W[t] = R1 (W[t - 2]) + W[t - 7] + R0 (W[t - 15]) + W[t - 16];
+
+      /* The actual computation according to FIPS 180-2:6.2.2 step 3.  */
+      for (t = 0; t < 64; ++t)
+       {
+         uint32_t T1 = h + S1 (e) + Ch (e, f, g) + K[t] + W[t];
+         uint32_t T2 = S0 (a) + Maj (a, b, c);
+         h = g;
+         g = f;
+         f = e;
+         e = d + T1;
+         d = c;
+         c = b;
+         b = a;
+         a = T1 + T2;
+       }
+
+      /* Add the starting values of the context according to FIPS 180-2:6.2.2
+        step 4.  */
+      a += a_save;
+      b += b_save;
+      c += c_save;
+      d += d_save;
+      e += e_save;
+      f += f_save;
+      g += g_save;
+      h += h_save;
+
+      /* Prepare for the next round.  */
+      nwords -= 16;
+    }
+
+  /* Put checksum in context given as argument.  */
+  ctx->H[0] = a;
+  ctx->H[1] = b;
+  ctx->H[2] = c;
+  ctx->H[3] = d;
+  ctx->H[4] = e;
+  ctx->H[5] = f;
+  ctx->H[6] = g;
+  ctx->H[7] = h;
+}
+
+
+/* Initialize structure containing state of computation.
+   (FIPS 180-2:5.3.2)  */
+void
+sha256_init_ctx (ctx)
+     struct sha256_ctx *ctx;
+{
+  ctx->H[0] = 0x6a09e667;
+  ctx->H[1] = 0xbb67ae85;
+  ctx->H[2] = 0x3c6ef372;
+  ctx->H[3] = 0xa54ff53a;
+  ctx->H[4] = 0x510e527f;
+  ctx->H[5] = 0x9b05688c;
+  ctx->H[6] = 0x1f83d9ab;
+  ctx->H[7] = 0x5be0cd19;
+
+  ctx->total[0] = ctx->total[1] = 0;
+  ctx->buflen = 0;
+}
+
+
+/* Process the remaining bytes in the internal buffer and the usual
+   prolog according to the standard and write the result to RESBUF.
+
+   IMPORTANT: On some systems it is required that RESBUF is correctly
+   aligned for a 32 bits value.  */
+void *
+sha256_finish_ctx (ctx, resbuf)
+     struct sha256_ctx *ctx;
+     void *resbuf;
+{
+  /* Take yet unprocessed bytes into account.  */
+  uint32_t bytes = ctx->buflen;
+  size_t pad;
+  unsigned int i;
+
+  /* Now count remaining bytes.  */
+  ctx->total[0] += bytes;
+  if (ctx->total[0] < bytes)
+    ++ctx->total[1];
+
+  pad = bytes >= 56 ? 64 + 56 - bytes : 56 - bytes;
+  memcpy (&ctx->buffer[bytes], fillbuf, pad);
+
+  /* Put the 64-bit file length in *bits* at the end of the buffer.  */
+  *(uint32_t *) &ctx->buffer[bytes + pad + 4] = SWAP (ctx->total[0] << 3);
+  *(uint32_t *) &ctx->buffer[bytes + pad] = SWAP ((ctx->total[1] << 3) |
+                                                 (ctx->total[0] >> 29));
+
+  /* Process last bytes.  */
+  sha256_process_block (ctx->buffer, bytes + pad + 8, ctx);
+
+  /* Put result from CTX in first 32 bytes following RESBUF.  */
+  for (i = 0; i < 8; ++i)
+    ((uint32_t *) resbuf)[i] = SWAP (ctx->H[i]);
+
+  return resbuf;
+}
+
+
+void
+sha256_process_bytes (buffer, len, ctx)
+     const void *buffer;
+     size_t len;
+     struct sha256_ctx *ctx;
+{
+  /* When we already have some bits in our internal buffer concatenate
+     both inputs first.  */
+  if (ctx->buflen != 0)
+    {
+      size_t left_over = ctx->buflen;
+      size_t add = 128 - left_over > len ? len : 128 - left_over;
+
+      memcpy (&ctx->buffer[left_over], buffer, add);
+      ctx->buflen += add;
+
+      if (ctx->buflen > 64)
+       {
+         sha256_process_block (ctx->buffer, ctx->buflen & ~63, ctx);
+
+         ctx->buflen &= 63;
+         /* The regions in the following copy operation cannot overlap.  */
+         memcpy (ctx->buffer, &ctx->buffer[(left_over + add) & ~63],
+                 ctx->buflen);
+       }
+
+      buffer = (const char *) buffer + add;
+      len -= add;
+    }
+
+  /* Process available complete blocks.  */
+  if (len >= 64)
+    {
+#if !_STRING_ARCH_unaligned
+/* To check alignment gcc has an appropriate operator.  Other
+   compilers don't.  */
+# if __GNUC__ >= 2
+#  define UNALIGNED_P(p) (((uintptr_t) p) % __alignof__ (uint32_t) != 0)
+# else
+#  define UNALIGNED_P(p) (((uintptr_t) p) % sizeof (uint32_t) != 0)
+# endif
+      if (UNALIGNED_P (buffer))
+       while (len > 64)
+         {
+           sha256_process_block (memcpy (ctx->buffer, buffer, 64), 64, ctx);
+           buffer = (const char *) buffer + 64;
+           len -= 64;
+         }
+      else
+#endif
+       {
+         sha256_process_block (buffer, len & ~63, ctx);
+         buffer = (const char *) buffer + (len & ~63);
+         len &= 63;
+       }
+    }
+
+  /* Move remaining bytes into internal buffer.  */
+  if (len > 0)
+    {
+      size_t left_over = ctx->buflen;
+
+      memcpy (&ctx->buffer[left_over], buffer, len);
+      left_over += len;
+      if (left_over >= 64)
+       {
+         sha256_process_block (ctx->buffer, 64, ctx);
+         left_over -= 64;
+         memcpy (ctx->buffer, &ctx->buffer[64], left_over);
+       }
+      ctx->buflen = left_over;
+    }
+}
diff --git a/genisoimage/sha256.h b/genisoimage/sha256.h
new file mode 100644 (file)
index 0000000..e7f4cb9
--- /dev/null
@@ -0,0 +1,62 @@
+/* Declaration of functions and data types used for SHA256 sum computing
+   library functions.
+   Copyright (C) 2007 Free Software Foundation, Inc.
+
+   Copied here from the GNU C Library version 2.7 on the 10 May 2009
+   by Steve McIntyre <93sam@debian.org>. This code was under GPL v2.1
+   in glibc, and that license gives us the option to use and
+   distribute the code under the terms of the GPL v2 instead. I'm
+   taking that option.
+
+   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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#ifndef _SHA256_H
+#define _SHA256_H 1
+
+#include <limits.h>
+#include <stdint.h>
+#include <stdio.h>
+
+
+/* Structure to save state of computation between the single steps.  */
+struct sha256_ctx
+{
+  uint32_t H[8];
+
+  uint32_t total[2];
+  uint32_t buflen;
+  char buffer[128] __attribute__ ((__aligned__ (__alignof__ (uint32_t))));
+};
+
+/* Initialize structure containing state of computation.
+   (FIPS 180-2: 5.3.2)  */
+extern void sha256_init_ctx (struct sha256_ctx *ctx) __THROW;
+
+/* Starting with the result of former calls of this function (or the
+   initialization function update the context for the next LEN bytes
+   starting at BUFFER.
+   It is NOT required that LEN is a multiple of 64.  */
+extern void sha256_process_bytes (const void *buffer, size_t len,
+                                   struct sha256_ctx *ctx) __THROW;
+
+/* Process the remaining bytes in the buffer and put result from CTX
+   in first 32 bytes following RESBUF.
+
+   IMPORTANT: On some systems it is required that RESBUF is correctly
+   aligned for a 32 bits value.  */
+extern void *sha256_finish_ctx (struct sha256_ctx *ctx, void *resbuf)
+  __THROW;
+
+#endif /* sha256.h */
diff --git a/genisoimage/sha512.c b/genisoimage/sha512.c
new file mode 100644 (file)
index 0000000..c4987ce
--- /dev/null
@@ -0,0 +1,338 @@
+/* Functions to compute SHA512 message digest of files or memory blocks.
+   according to the definition of SHA512 in FIPS 180-2.
+   Copyright (C) 2007 Free Software Foundation, Inc.
+
+   Copied here from the GNU C Library version 2.7 on the 10 May 2009
+   by Steve McIntyre <93sam@debian.org>. This code was under LGPL v2.1
+   in glibc, and that license gives us the option to use and
+   distribute the code under the terms of the GPL v2 instead. I'm
+   taking that option.
+
+   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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+/* Written by Ulrich Drepper <drepper@redhat.com>, 2007.  */
+
+#include <endian.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include "sha512.h"
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+# ifdef _LIBC
+#  include <byteswap.h>
+#  define SWAP(n) bswap_64 (n)
+# else
+#  define SWAP(n) \
+  (((n) << 56)                                 \
+   | (((n) & 0xff00) << 40)                    \
+   | (((n) & 0xff0000) << 24)                  \
+   | (((n) & 0xff000000) << 8)                 \
+   | (((n) >> 8) & 0xff000000)                 \
+   | (((n) >> 24) & 0xff0000)                  \
+   | (((n) >> 40) & 0xff00)                    \
+   | ((n) >> 56))
+# endif
+#else
+# define SWAP(n) (n)
+#endif
+
+
+/* This array contains the bytes used to pad the buffer to the next
+   64-byte boundary.  (FIPS 180-2:5.1.2)  */
+static const unsigned char fillbuf[128] = { 0x80, 0 /* , 0, 0, ...  */ };
+
+
+/* Constants for SHA512 from FIPS 180-2:4.2.3.  */
+static const uint64_t K[80] =
+  {
+    UINT64_C (0x428a2f98d728ae22), UINT64_C (0x7137449123ef65cd),
+    UINT64_C (0xb5c0fbcfec4d3b2f), UINT64_C (0xe9b5dba58189dbbc),
+    UINT64_C (0x3956c25bf348b538), UINT64_C (0x59f111f1b605d019),
+    UINT64_C (0x923f82a4af194f9b), UINT64_C (0xab1c5ed5da6d8118),
+    UINT64_C (0xd807aa98a3030242), UINT64_C (0x12835b0145706fbe),
+    UINT64_C (0x243185be4ee4b28c), UINT64_C (0x550c7dc3d5ffb4e2),
+    UINT64_C (0x72be5d74f27b896f), UINT64_C (0x80deb1fe3b1696b1),
+    UINT64_C (0x9bdc06a725c71235), UINT64_C (0xc19bf174cf692694),
+    UINT64_C (0xe49b69c19ef14ad2), UINT64_C (0xefbe4786384f25e3),
+    UINT64_C (0x0fc19dc68b8cd5b5), UINT64_C (0x240ca1cc77ac9c65),
+    UINT64_C (0x2de92c6f592b0275), UINT64_C (0x4a7484aa6ea6e483),
+    UINT64_C (0x5cb0a9dcbd41fbd4), UINT64_C (0x76f988da831153b5),
+    UINT64_C (0x983e5152ee66dfab), UINT64_C (0xa831c66d2db43210),
+    UINT64_C (0xb00327c898fb213f), UINT64_C (0xbf597fc7beef0ee4),
+    UINT64_C (0xc6e00bf33da88fc2), UINT64_C (0xd5a79147930aa725),
+    UINT64_C (0x06ca6351e003826f), UINT64_C (0x142929670a0e6e70),
+    UINT64_C (0x27b70a8546d22ffc), UINT64_C (0x2e1b21385c26c926),
+    UINT64_C (0x4d2c6dfc5ac42aed), UINT64_C (0x53380d139d95b3df),
+    UINT64_C (0x650a73548baf63de), UINT64_C (0x766a0abb3c77b2a8),
+    UINT64_C (0x81c2c92e47edaee6), UINT64_C (0x92722c851482353b),
+    UINT64_C (0xa2bfe8a14cf10364), UINT64_C (0xa81a664bbc423001),
+    UINT64_C (0xc24b8b70d0f89791), UINT64_C (0xc76c51a30654be30),
+    UINT64_C (0xd192e819d6ef5218), UINT64_C (0xd69906245565a910),
+    UINT64_C (0xf40e35855771202a), UINT64_C (0x106aa07032bbd1b8),
+    UINT64_C (0x19a4c116b8d2d0c8), UINT64_C (0x1e376c085141ab53),
+    UINT64_C (0x2748774cdf8eeb99), UINT64_C (0x34b0bcb5e19b48a8),
+    UINT64_C (0x391c0cb3c5c95a63), UINT64_C (0x4ed8aa4ae3418acb),
+    UINT64_C (0x5b9cca4f7763e373), UINT64_C (0x682e6ff3d6b2b8a3),
+    UINT64_C (0x748f82ee5defb2fc), UINT64_C (0x78a5636f43172f60),
+    UINT64_C (0x84c87814a1f0ab72), UINT64_C (0x8cc702081a6439ec),
+    UINT64_C (0x90befffa23631e28), UINT64_C (0xa4506cebde82bde9),
+    UINT64_C (0xbef9a3f7b2c67915), UINT64_C (0xc67178f2e372532b),
+    UINT64_C (0xca273eceea26619c), UINT64_C (0xd186b8c721c0c207),
+    UINT64_C (0xeada7dd6cde0eb1e), UINT64_C (0xf57d4f7fee6ed178),
+    UINT64_C (0x06f067aa72176fba), UINT64_C (0x0a637dc5a2c898a6),
+    UINT64_C (0x113f9804bef90dae), UINT64_C (0x1b710b35131c471b),
+    UINT64_C (0x28db77f523047d84), UINT64_C (0x32caab7b40c72493),
+    UINT64_C (0x3c9ebe0a15c9bebc), UINT64_C (0x431d67c49c100d4c),
+    UINT64_C (0x4cc5d4becb3e42b6), UINT64_C (0x597f299cfc657e2a),
+    UINT64_C (0x5fcb6fab3ad6faec), UINT64_C (0x6c44198c4a475817)
+  };
+
+
+/* Process LEN bytes of BUFFER, accumulating context into CTX.
+   It is assumed that LEN % 128 == 0.  */
+static void
+sha512_process_block (const void *buffer, size_t len, struct sha512_ctx *ctx)
+{
+  const uint64_t *words = buffer;
+  size_t nwords = len / sizeof (uint64_t);
+  uint64_t a = ctx->H[0];
+  uint64_t b = ctx->H[1];
+  uint64_t c = ctx->H[2];
+  uint64_t d = ctx->H[3];
+  uint64_t e = ctx->H[4];
+  uint64_t f = ctx->H[5];
+  uint64_t g = ctx->H[6];
+  uint64_t h = ctx->H[7];
+
+  /* First increment the byte count.  FIPS 180-2 specifies the possible
+     length of the file up to 2^128 bits.  Here we only compute the
+     number of bytes.  Do a double word increment.  */
+  ctx->total[0] += len;
+  if (ctx->total[0] < len)
+    ++ctx->total[1];
+
+  /* Process all bytes in the buffer with 128 bytes in each round of
+     the loop.  */
+  while (nwords > 0)
+    {
+      uint64_t W[80];
+      uint64_t a_save = a;
+      uint64_t b_save = b;
+      uint64_t c_save = c;
+      uint64_t d_save = d;
+      uint64_t e_save = e;
+      uint64_t f_save = f;
+      uint64_t g_save = g;
+      uint64_t h_save = h;
+      unsigned int t;
+
+      /* Operators defined in FIPS 180-2:4.1.2.  */
+#define Ch(x, y, z) ((x & y) ^ (~x & z))
+#define Maj(x, y, z) ((x & y) ^ (x & z) ^ (y & z))
+#define S0(x) (CYCLIC (x, 28) ^ CYCLIC (x, 34) ^ CYCLIC (x, 39))
+#define S1(x) (CYCLIC (x, 14) ^ CYCLIC (x, 18) ^ CYCLIC (x, 41))
+#define R0(x) (CYCLIC (x, 1) ^ CYCLIC (x, 8) ^ (x >> 7))
+#define R1(x) (CYCLIC (x, 19) ^ CYCLIC (x, 61) ^ (x >> 6))
+
+      /* It is unfortunate that C does not provide an operator for
+        cyclic rotation.  Hope the C compiler is smart enough.  */
+#define CYCLIC(w, s) ((w >> s) | (w << (64 - s)))
+
+      /* Compute the message schedule according to FIPS 180-2:6.3.2 step 2.  */
+      for (t = 0; t < 16; ++t)
+       {
+         W[t] = SWAP (*words);
+         ++words;
+       }
+      for (t = 16; t < 80; ++t)
+       W[t] = R1 (W[t - 2]) + W[t - 7] + R0 (W[t - 15]) + W[t - 16];
+
+      /* The actual computation according to FIPS 180-2:6.3.2 step 3.  */
+      for (t = 0; t < 80; ++t)
+       {
+         uint64_t T1 = h + S1 (e) + Ch (e, f, g) + K[t] + W[t];
+         uint64_t T2 = S0 (a) + Maj (a, b, c);
+         h = g;
+         g = f;
+         f = e;
+         e = d + T1;
+         d = c;
+         c = b;
+         b = a;
+         a = T1 + T2;
+       }
+
+      /* Add the starting values of the context according to FIPS 180-2:6.3.2
+        step 4.  */
+      a += a_save;
+      b += b_save;
+      c += c_save;
+      d += d_save;
+      e += e_save;
+      f += f_save;
+      g += g_save;
+      h += h_save;
+
+      /* Prepare for the next round.  */
+      nwords -= 16;
+    }
+
+  /* Put checksum in context given as argument.  */
+  ctx->H[0] = a;
+  ctx->H[1] = b;
+  ctx->H[2] = c;
+  ctx->H[3] = d;
+  ctx->H[4] = e;
+  ctx->H[5] = f;
+  ctx->H[6] = g;
+  ctx->H[7] = h;
+}
+
+
+/* Initialize structure containing state of computation.
+   (FIPS 180-2:5.3.3)  */
+void
+sha512_init_ctx (ctx)
+     struct sha512_ctx *ctx;
+{
+  ctx->H[0] = UINT64_C (0x6a09e667f3bcc908);
+  ctx->H[1] = UINT64_C (0xbb67ae8584caa73b);
+  ctx->H[2] = UINT64_C (0x3c6ef372fe94f82b);
+  ctx->H[3] = UINT64_C (0xa54ff53a5f1d36f1);
+  ctx->H[4] = UINT64_C (0x510e527fade682d1);
+  ctx->H[5] = UINT64_C (0x9b05688c2b3e6c1f);
+  ctx->H[6] = UINT64_C (0x1f83d9abfb41bd6b);
+  ctx->H[7] = UINT64_C (0x5be0cd19137e2179);
+
+  ctx->total[0] = ctx->total[1] = 0;
+  ctx->buflen = 0;
+}
+
+
+/* Process the remaining bytes in the internal buffer and the usual
+   prolog according to the standard and write the result to RESBUF.
+
+   IMPORTANT: On some systems it is required that RESBUF is correctly
+   aligned for a 32 bits value.  */
+void *
+sha512_finish_ctx (ctx, resbuf)
+     struct sha512_ctx *ctx;
+     void *resbuf;
+{
+  /* Take yet unprocessed bytes into account.  */
+  uint64_t bytes = ctx->buflen;
+  size_t pad;
+  unsigned int i;
+
+  /* Now count remaining bytes.  */
+  ctx->total[0] += bytes;
+  if (ctx->total[0] < bytes)
+    ++ctx->total[1];
+
+  pad = bytes >= 112 ? 128 + 112 - bytes : 112 - bytes;
+  memcpy (&ctx->buffer[bytes], fillbuf, pad);
+
+  /* Put the 128-bit file length in *bits* at the end of the buffer.  */
+  *(uint64_t *) &ctx->buffer[bytes + pad + 8] = SWAP (ctx->total[0] << 3);
+  *(uint64_t *) &ctx->buffer[bytes + pad] = SWAP ((ctx->total[1] << 3) |
+                                                 (ctx->total[0] >> 61));
+
+  /* Process last bytes.  */
+  sha512_process_block (ctx->buffer, bytes + pad + 16, ctx);
+
+  /* Put result from CTX in first 64 bytes following RESBUF.  */
+  for (i = 0; i < 8; ++i)
+    ((uint64_t *) resbuf)[i] = SWAP (ctx->H[i]);
+
+  return resbuf;
+}
+
+
+void
+sha512_process_bytes (buffer, len, ctx)
+     const void *buffer;
+     size_t len;
+     struct sha512_ctx *ctx;
+{
+  /* When we already have some bits in our internal buffer concatenate
+     both inputs first.  */
+  if (ctx->buflen != 0)
+    {
+      size_t left_over = ctx->buflen;
+      size_t add = 256 - left_over > len ? len : 256 - left_over;
+
+      memcpy (&ctx->buffer[left_over], buffer, add);
+      ctx->buflen += add;
+
+      if (ctx->buflen > 128)
+       {
+         sha512_process_block (ctx->buffer, ctx->buflen & ~127, ctx);
+
+         ctx->buflen &= 127;
+         /* The regions in the following copy operation cannot overlap.  */
+         memcpy (ctx->buffer, &ctx->buffer[(left_over + add) & ~127],
+                 ctx->buflen);
+       }
+
+      buffer = (const char *) buffer + add;
+      len -= add;
+    }
+
+  /* Process available complete blocks.  */
+  if (len >= 128)
+    {
+#if !_STRING_ARCH_unaligned
+/* To check alignment gcc has an appropriate operator.  Other
+   compilers don't.  */
+# if __GNUC__ >= 2
+#  define UNALIGNED_P(p) (((uintptr_t) p) % __alignof__ (uint64_t) != 0)
+# else
+#  define UNALIGNED_P(p) (((uintptr_t) p) % sizeof (uint64_t) != 0)
+# endif
+      if (UNALIGNED_P (buffer))
+       while (len > 128)
+         {
+           sha512_process_block (memcpy (ctx->buffer, buffer, 128), 128,
+                                   ctx);
+           buffer = (const char *) buffer + 128;
+           len -= 128;
+         }
+      else
+#endif
+       {
+         sha512_process_block (buffer, len & ~127, ctx);
+         buffer = (const char *) buffer + (len & ~127);
+         len &= 127;
+       }
+    }
+
+  /* Move remaining bytes into internal buffer.  */
+  if (len > 0)
+    {
+      size_t left_over = ctx->buflen;
+
+      memcpy (&ctx->buffer[left_over], buffer, len);
+      left_over += len;
+      if (left_over >= 128)
+       {
+         sha512_process_block (ctx->buffer, 128, ctx);
+         left_over -= 128;
+         memcpy (ctx->buffer, &ctx->buffer[128], left_over);
+       }
+      ctx->buflen = left_over;
+    }
+}
diff --git a/genisoimage/sha512.h b/genisoimage/sha512.h
new file mode 100644 (file)
index 0000000..7298355
--- /dev/null
@@ -0,0 +1,62 @@
+/* Declaration of functions and data types used for SHA512 sum computing
+   library functions.
+   Copyright (C) 2007 Free Software Foundation, Inc.
+
+   Copied here from the GNU C Library version 2.7 on the 10 May 2009
+   by Steve McIntyre <93sam@debian.org>. This code was under GPL v2.1
+   in glibc, and that license gives us the option to use and
+   distribute the code under the terms of the GPL v2 instead. I'm
+   taking that option.
+
+   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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#ifndef _SHA512_H
+#define _SHA512_H 1
+
+#include <limits.h>
+#include <stdint.h>
+#include <stdio.h>
+
+
+/* Structure to save state of computation between the single steps.  */
+struct sha512_ctx
+{
+  uint64_t H[8];
+
+  uint64_t total[2];
+  uint64_t buflen;
+  char buffer[256] __attribute__ ((__aligned__ (__alignof__ (uint64_t))));
+};
+
+/* Initialize structure containing state of computation.
+   (FIPS 180-2: 5.3.3)  */
+extern void sha512_init_ctx (struct sha512_ctx *ctx) __THROW;
+
+/* Starting with the result of former calls of this function (or the
+   initialization function update the context for the next LEN bytes
+   starting at BUFFER.
+   It is NOT required that LEN is a multiple of 128.  */
+extern void sha512_process_bytes (const void *buffer, size_t len,
+                                   struct sha512_ctx *ctx) __THROW;
+
+/* Process the remaining bytes in the buffer and put result from CTX
+   in first 64 bytes following RESBUF.
+
+   IMPORTANT: On some systems it is required that RESBUF is correctly
+   aligned for a 64 bits value.  */
+extern void *sha512_finish_ctx (struct sha512_ctx *ctx, void *resbuf)
+  __THROW;
+
+#endif /* sha512.h */
diff --git a/genisoimage/stream.c b/genisoimage/stream.c
new file mode 100644 (file)
index 0000000..f59c1e3
--- /dev/null
@@ -0,0 +1,272 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)stream.c        1.3 04/03/04 Copyright 2002-2003 J. Schilling */
+/* Parts from @(#)stream.c     1.9 07/02/17 Copyright 2002-2007 J. Schilling */
+/*
+ *     ISO-9660 stream (pipe) file module for genisoimage
+ *
+ *     Copyright (c) 2002-2003 J. Schilling
+ *     Implemented after an idea from M.H. Voase
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <mconfig.h>
+#include "genisoimage.h"
+#include "iso9660.h"
+
+static int     size_str_file(int starting_extent);
+static int     size_str_dir(int starting_extent);
+static int     size_str_path(int starting_extent);
+
+static int     gen_str_path(void);
+
+static int     write_str_file(FILE *outfile);
+static int     write_str_dir(FILE *outfile);
+static int     write_str_path(FILE *outfile);
+
+extern struct directory *root;
+extern unsigned int    session_start;
+extern int             stream_media_size;
+extern char            *stream_filename;
+extern time_t          begun;
+extern int             volume_sequence_number;
+
+static unsigned int    avail_extent;
+static unsigned int    stream_extent;
+static unsigned int    stream_size;
+static unsigned int    stream_pad;
+static char            *l_path;
+static char            *m_path;
+static struct iso_directory_record s_dir;
+static int             stream_finished = 0;
+
+/*
+ * Compute the size of the file
+ */
+static int
+size_str_file(int starting_extent)
+{
+       int     n;
+extern int     dopad;
+
+       stream_extent = last_extent;    /* Start of stream file content */
+
+       avail_extent = stream_media_size;
+       n = last_extent;                /* Room for FS blocks before file */
+       n += 1;                         /* Room for the directory block */
+       stream_pad = 0;
+       if (n < 50) {
+               stream_pad = 50 - n;
+               n = 50;                 /* Make net. size easy to compute */
+       }
+       if (dopad)
+               n += 150;               /* Room for final padding */
+       avail_extent -= n;
+
+       last_extent += avail_extent + stream_pad;
+
+       return (0);
+}
+
+/*
+ * The size of the directory record - one sector
+ */
+static int
+size_str_dir(int starting_extent)
+{
+       root->extent = last_extent;
+       last_extent += 1;
+       return (0);
+}
+
+/*
+ * The size of the path tables - two sectors
+ */
+static int
+size_str_path(int starting_extent)
+{
+       path_table[0] = starting_extent;
+       path_table[1] = 0;
+       path_table[2] = path_table[0] + 1;
+       path_table[3] = 0;
+       last_extent += 2 * 1;
+       return (0);
+}
+
+/*
+ * Generate the path table data
+ */
+static int
+gen_str_path()
+{
+       /*
+        * Basically add the root directory entry
+        */
+       l_path = (char *)e_malloc(SECTOR_SIZE);
+       m_path = (char *)e_malloc(SECTOR_SIZE);
+       memset(l_path, 0, SECTOR_SIZE);
+       memset(m_path, 0, SECTOR_SIZE);
+       l_path[0] = 1;
+       m_path[0] = 1;
+       set_731(l_path + 2, root->extent);
+       set_732(m_path + 2, root->extent);
+       set_721(l_path + 6, 1);
+       set_722(m_path + 6, 1);
+       l_path[8] = '\0'; l_path[9] = '\0';
+       m_path[8] = '\0'; m_path[9] = '\0';
+       return (0);
+}
+
+/*
+ * Write the file content
+ */
+static int
+write_str_file(FILE *outfile)
+{
+       unsigned int    idx = 0;
+       unsigned int    iso_blocks;
+       int             count;
+       char            *buf;
+
+       buf = e_malloc(SECTOR_SIZE);
+       stream_size = 0;
+       while ((idx + SECTOR_SIZE) < (avail_extent * SECTOR_SIZE)) {
+               memset(buf, 0, SECTOR_SIZE);
+               count = fread(buf, 1, SECTOR_SIZE, stdin);
+               if (count <= 0) {
+                       stream_finished = 1;
+                       break;
+               }
+               idx += count;
+               jtwrite(buf, count, 1, 0, FALSE);
+               xfwrite(buf, count, 1, outfile, 0, FALSE);
+       }
+
+       stream_size = idx;
+       iso_blocks = ISO_BLOCKS(idx);
+       memset(buf, 0, SECTOR_SIZE);
+       if (SECTOR_SIZE * iso_blocks - idx)
+    {
+               jtwrite(buf, SECTOR_SIZE * iso_blocks - idx, 1, 0, FALSE);
+               xfwrite(buf, SECTOR_SIZE * iso_blocks - idx, 1, outfile, 0, FALSE);
+    }
+       /*
+        * If we didn't fill the available area, pad to directory block
+        */
+       for (count = 0; count < (avail_extent - iso_blocks); count++)
+    {
+               jtwrite(buf, SECTOR_SIZE, 1, 0, FALSE);
+               xfwrite(buf, SECTOR_SIZE, 1, outfile, 0, FALSE);
+    }
+       for (count = 0; count < stream_pad; count++)
+    {
+               jtwrite(buf, SECTOR_SIZE, 1, 0, FALSE);
+               xfwrite(buf, SECTOR_SIZE, 1, outfile, 0, FALSE);
+    }
+
+       last_extent_written += avail_extent + stream_pad;
+       return (0);
+}
+
+/*
+ * Generate and write the directory record data
+ */
+static int
+write_str_dir(FILE *outfile)
+{
+       int     to_write;
+       char    *buf;
+
+       buf = e_malloc(SECTOR_SIZE); memset(buf, 0, SECTOR_SIZE);
+       memset(&s_dir, 0, sizeof (struct iso_directory_record));
+       s_dir.length[0] = 34;                   /* BAD: Hardcoded - Will fix, MHV */
+       s_dir.ext_attr_length[0] = 0;
+       set_733((char *)s_dir.extent, root->extent);
+       set_733((char *)s_dir.size, SECTOR_SIZE);
+       iso9660_date(s_dir.date, begun);
+       s_dir.flags[0] = ISO_DIRECTORY;
+       s_dir.file_unit_size[0] = 0;
+       s_dir.interleave[0] = 0;
+       set_723((char *)s_dir.volume_sequence_number, volume_sequence_number);
+       s_dir.name_len[0] = 1;
+       s_dir.name[0] = 0;      /* "." */
+       jtwrite(&s_dir, offsetof(struct iso_directory_record, name[0]) + 1, 1, 0, FALSE);
+       xfwrite(&s_dir, offsetof(struct iso_directory_record, name[0]) + 1, 1, outfile, 0, FALSE);
+       s_dir.name[0] = 1;      /* ".." */
+       jtwrite(&s_dir, offsetof(struct iso_directory_record, name[0]) + 1, 1, 0, FALSE);
+       xfwrite(&s_dir, offsetof(struct iso_directory_record, name[0]) + 1, 1, outfile, 0, FALSE);
+       memset(&s_dir, 0, sizeof (struct iso_directory_record));
+       s_dir.length[0] = 34 + strlen(stream_filename);
+       s_dir.ext_attr_length[0] = 0;
+       set_733((char *) s_dir.extent, stream_extent);
+       set_733((char *) s_dir.size, stream_size);
+       iso9660_date(s_dir.date, begun);
+       s_dir.flags[0] = 0;
+       s_dir.file_unit_size[0] = 0;
+       set_723((char *)s_dir.volume_sequence_number, volume_sequence_number);
+       s_dir.name_len[0] = strlen(stream_filename);
+       memcpy(s_dir.name, stream_filename, s_dir.name_len[0]);
+       jtwrite(&s_dir, offsetof(struct iso_directory_record, name[0])
+               + s_dir.name_len[0], 1, 0, FALSE);
+       xfwrite(&s_dir, offsetof(struct iso_directory_record, name[0])
+               + s_dir.name_len[0], 1, outfile, 0, FALSE);
+
+       /*
+        * This calc is: 2 single char directory entries (34) + an additional entry
+        * with filename length stream_filename + round up for even lenght count
+        */
+       to_write = (s_dir.name_len[0] % 2) ? 0 : 1;
+       jtwrite(buf, SECTOR_SIZE - ((3 * 34) + s_dir.name_len[0]) +
+               to_write, 1, 0, FALSE);
+       xfwrite(buf, SECTOR_SIZE - ((3 * 34) + s_dir.name_len[0]) +
+               to_write, 1, outfile, 0, FALSE);
+       free(buf);
+       last_extent_written++;
+       return (0);
+}
+
+/*
+ * Generate the path table data
+ */
+static int
+write_str_path(FILE *outfile)
+{
+       jtwrite(l_path, SECTOR_SIZE, 1, 0, FALSE);
+       xfwrite(l_path, SECTOR_SIZE, 1, outfile, 0, FALSE);
+       last_extent_written++;
+       jtwrite(m_path, SECTOR_SIZE, 1, 0, FALSE);
+       xfwrite(m_path, SECTOR_SIZE, 1, outfile, 0, FALSE);
+       last_extent_written++;
+       free(l_path);
+       free(m_path);
+       path_table_l = NULL;
+       path_table_m = NULL;
+       return (0);
+}
+
+struct output_fragment strfile_desc  = { NULL, size_str_file, NULL,       write_str_file, "Stream File" };
+struct output_fragment strdir_desc  = { NULL, size_str_dir,  NULL,        write_str_dir,  "Stream File Directory"  };
+struct output_fragment strpath_desc = { NULL, size_str_path, gen_str_path, write_str_path, "Stream File Path table" };
diff --git a/genisoimage/sunlabel.h b/genisoimage/sunlabel.h
new file mode 100644 (file)
index 0000000..243e9bb
--- /dev/null
@@ -0,0 +1,206 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)sunlabel.h      1.5 03/12/28 Copyright 1999-2003 J. Schilling */
+/*
+ *     Support for Sun disk label
+ *
+ *     Copyright (c) 1999-2003 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef howmany
+#define        howmany(x, y)   (((x)+((y)-1))/(y))
+#endif
+#ifndef roundup
+#define        roundup(x, y)   ((((x)+((y)-1))/(y))*(y))
+#endif
+
+#define        NDKMAP          8               /* # of sparc partitions */
+#define        NX86MAP         16              /* # if x86   partitions */
+#define        DKL_MAGIC       0xDABE          /* magic number */
+#define        DKL_MAGIC_0     0xDA            /* magic number high byte */
+#define        DKL_MAGIC_1     0xBE            /* magic number low byte  */
+
+#define        CD_DEFLABEL     "CD-ROM Disc with Sun sparc boot created by genisoimage"
+#define        CD_X86LABEL     "CD-ROM Disc with Sun x86 boot created by genisoimage"
+
+/*
+ * Define a virtual geometry for the CD disk label.
+ * The current values are stolen from Sun install disks and do not seem to be
+ * a good idea as they limit the size of the CD to 327680 sectors which is less
+ * than 74 minutes.
+ * There are 84 minute CD's with 378000 sectors and there will be DVD's with
+ * even more.
+ */
+#define        CD_RPM          350
+#define        CD_PCYL         2048
+#define        CD_APC          0
+#define        CD_INTRLV       1
+#define        CD_NCYL         2048
+#define        CD_ACYL         0
+#define        CD_NHEAD        1
+#define        CD_NSECT        640
+
+/*
+ * NOTE: The virtual cylinder size on CD must be a mutiple of 2048.
+ *      This is true if CD_NSECT is a multiple of 4.
+ */
+#define        CD_CYLSIZE      (CD_NSECT*CD_NHEAD*512)
+
+#define        V_VERSION       1               /* The VTOC version      */
+#define        VTOC_SANE       0x600DDEEE      /* Indicates a sane VTOC */
+
+#define        V_ROOT          0x02            /* Root partiton         */
+#define        V_USR           0x04            /* Usr partiton          */
+
+#define        V_RONLY         0x10            /* Read only             */
+
+/*
+ * The Sun sparc disk label (at offset 0 on a disk)
+ */
+struct sun_label {
+       char            dkl_ascilabel[128];
+       struct dk_vtoc {
+               Uchar   v_version[4];   /* layout version        */
+               char    v_volume[8];    /* volume name           */
+               Uchar   v_nparts[2];    /* number of partitions  */
+               struct dk_map2 {
+                       Uchar   p_tag[2]; /* ID tag of partition */
+                       Uchar   p_flag[2]; /* permission flag    */
+
+               }       v_part[NDKMAP];
+               Uchar   v_xxpad[2];     /* To come over Sun's alignement problem */
+               Uchar   v_bootinfo[3*4]; /* info for mboot       */
+               Uchar   v_sanity[4];    /* to verify vtoc sanity */
+               Uchar   v_reserved[10*4];
+               Uchar   v_timestamp[NDKMAP*4];
+
+       }               dkl_vtoc;       /* vtoc inclusions from AT&T SVr4 */
+       char            dkl_pad[512-(128+sizeof (struct dk_vtoc)+NDKMAP*8+14*2)];
+       Uchar           dkl_rpm[2];     /* rotations per minute */
+       Uchar           dkl_pcyl[2];    /* # physical cylinders */
+       Uchar           dkl_apc[2];     /* alternates per cylinder */
+       Uchar           dkl_obs1[2];    /* obsolete */
+       Uchar           dkl_obs2[2];    /* obsolete */
+       Uchar           dkl_intrlv[2];  /* interleave factor */
+       Uchar           dkl_ncyl[2];    /* # of data cylinders */
+       Uchar           dkl_acyl[2];    /* # of alternate cylinders */
+       Uchar           dkl_nhead[2];   /* # of heads in this partition */
+       Uchar           dkl_nsect[2];   /* # of 512 byte sectors per track */
+       Uchar           dkl_obs3[2];    /* obsolete */
+       Uchar           dkl_obs4[2];    /* obsolete */
+
+       struct dk_map {                 /* logical partitions */
+               Uchar   dkl_cylno[4];   /* starting cylinder */
+               Uchar   dkl_nblk[4];    /* number of blocks */
+       }               dkl_map[NDKMAP]; /* logical partition headers */
+
+       Uchar           dkl_magic[2];   /* identifies this label format */
+       Uchar           dkl_cksum[2];   /* xor checksum of sector */
+};
+
+/*
+ * The Sun x86 / AT&T disk label (at offset 512 on a fdisk partition)
+ */
+struct x86_label {
+       struct x86_vtoc {
+               Uchar   v_bootinfo[3*4]; /* unsupported           */
+               Uchar   v_sanity[4];    /* to verify vtoc sanity  */
+               Uchar   v_version[4];   /* layout version         */
+               char    v_volume[8];    /* volume name            */
+               Uchar   v_sectorsz[2];  /* # of bytes in a sector */
+               Uchar   v_nparts[2];    /* # of partitions */
+               Uchar   v_reserved[10*4];
+               struct dkl_partition    {
+                       Uchar   p_tag[2];       /* ID tag of partition */
+                       Uchar   p_flag[2];      /* permission flag    */
+                       Uchar   p_start[4];     /* starting sector    */
+                       Uchar   p_size[4];      /* number of blocks   */
+               }       v_part[NX86MAP];
+               Uchar   timestamp[NX86MAP][4];
+               char    v_asciilabel[128];
+       }               dkl_vtoc;       /* vtoc inclusions from AT&T SVr4 */
+       Uchar           dkl_pcyl[4];    /* # physical cylinders */
+       Uchar           dkl_ncyl[4];    /* # of data cylinders */
+       Uchar           dkl_acyl[2];    /* # of alternate cylinders */
+       Uchar           dkl_bcyl[2];
+       Uchar           dkl_nhead[4];   /* # of heads in this partition */
+       Uchar           dkl_nsect[4];   /* # of 512 byte sectors per track */
+       Uchar           dkl_intrlv[2];  /* interleave factor */
+       Uchar           dkl_skew[2];
+       Uchar           dkl_apc[2];     /* alternates per cylinder */
+       Uchar           dkl_rpm[2];     /* rotations per minute */
+       Uchar           dkl_write_reinstruct[2];
+       Uchar           dkl_read_reinstruct[2];
+       Uchar           dkl_extra[4*2]; /* for later expansions */
+       char            dkl_pad[512-(sizeof (struct x86_vtoc)+4*4+14*2)];
+       Uchar           dkl_magic[2];   /* identifies this label format */
+       Uchar           dkl_cksum[2];   /* xor checksum of sector */
+};
+
+/*
+ * One x86 PC fdisk partition record.
+ */
+struct pc_pr {
+       Uchar   pr_status;              /* Boot status */
+       Uchar   pr_head;                /* Starting head # */
+       char    pr_sec_cyl[2];          /* Starting sec+cyl # */
+       Uchar   pr_type;                /* Partition type */
+       Uchar   pr_e_head;              /* Ending head # */
+       char    pr_e_sec_cyl[2];        /* Ending sec+cyl # */
+       char    pr_partoff[4];          /* Partition start sector # */
+       char    pr_nsect[4];            /* # of sectors in partition */
+};
+
+/*
+ * Flags and macros for above partition record.
+ */
+#define        SEC_MASK        0x3F
+#define        GET_SEC(a)      ((a) & SEC_MASK)
+#define        GET_CYL(a)      ((((a) & 0xFF) >> 8) | (((a) & 0xC0) << 2))
+
+#define        STATUS_INACT    0               /* Marked non bootable  */
+#define        STATUS_ACTIVE   0x80            /* Marked as bootable   */
+
+#define        TYPE_FREE               0       /* Unused partition     */
+#define        TYPE_DOS12              0x01    /* FAT12 fileystem      */
+#define        TYPE_XENIX              0x02    /* XENIX root           */
+#define        TYPE_XENIX2             0x03    /* XENIX usr            */
+#define        TYPE_DOS16              0x04    /* FAT16 filesystem     */
+#define        TYPE_XDOS               0x05    /* Extended DOS part    */
+#define        TYPE_DOS4               0x06    /* FAT16 >= 32 MB       */
+#define        TYPE_SOLARIS            0x82    /* Solaris x86          */
+#define        TYPE_SOLARIS_BOOT       0xBE    /* Solaris boot         */
+#define        TYPE_CDOS4              0xDB    /* CPM                  */
+
+/*
+ * The first sector on a disk from a x86 PC (at offset 0 on a disk)
+ */
+struct pc_part {
+       char            bootcode[0x1BE]; /* Master boot record      */
+       struct pc_pr    part[4];        /* The 4 primary partitions */
+       Uchar           magic[2];       /* Fixed at 0x55 0xAA       */
+};
diff --git a/genisoimage/tree.c b/genisoimage/tree.c
new file mode 100644 (file)
index 0000000..7805888
--- /dev/null
@@ -0,0 +1,2696 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)tree.c  1.82 04/06/12 joerg */
+/*
+ * File tree.c - scan directory  tree and build memory structures for iso9660
+ * filesystem
+ *
+ * Written by Eric Youngdale (1993).
+ *
+ * Copyright 1993 Yggdrasil Computing, Incorporated
+ * Copyright (c) 1999,2000-2004 J. Schilling
+ *
+ * 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 */
+
+/* APPLE_HYB James Pearson j.pearson@ge.ucl.ac.uk 23/2/2000 */
+
+#include <mconfig.h>
+#include "genisoimage.h"
+#include "match.h"
+#include "udf.h"
+#include "exclude.h"
+#include <timedefs.h>
+#include <errno.h>
+#include <fctldefs.h>
+#include <device.h>
+#include <schily.h>
+
+extern int allow_limited_size;
+
+#ifdef VMS
+#include <sys/file.h>
+#include <vms/fabdef.h>
+#include "vms.h"
+#endif
+
+/*
+ * Autoconf should be able to figure this one out for us and let us know
+ * whether the system has memmove or not.
+ */
+#ifndef HAVE_MEMMOVE
+#define        memmove(d, s, n)        bcopy((s), (d), (n))
+#endif
+
+static Uchar   symlink_buff[PATH_MAX+1];
+
+static char    *filetype(int t);
+static char    *rstr(char *s1, char *s2);
+static void    stat_fix(struct stat * st);
+int    stat_filter(char *path, struct stat *st);
+int    lstat_filter(char *path, struct stat *st);
+static int     sort_n_finish(struct directory *this_dir);
+static void    generate_reloc_directory(void);
+static void    attach_dot_entries(struct directory *dirnode, struct stat *dir_stat,
+                                       struct stat *parent_stat);
+static void    update_nlink(struct directory_entry *s_entry, int value);
+static void    increment_nlink(struct directory_entry *s_entry);
+char   *find_rr_attribute(unsigned char *pnt, int len, char *attr_type);
+void   finish_cl_pl_entries(void);
+int    scan_directory_tree(struct directory *this_dir, char *path,
+                                                                 struct directory_entry *de);
+#ifdef APPLE_HYB
+int    insert_file_entry(struct directory *this_dir,
+                                                               char *whole_path,
+                                                               char *short_name,
+                                                               int have_rsrc);
+#else
+int    insert_file_entry(struct directory *this_dir,
+                                                               char *whole_path,
+                                                               char *short_name);
+#endif
+void   generate_iso9660_directories(struct directory *node,
+                                                                                         FILE *outfile);
+struct directory *find_or_create_directory(struct directory *parent,
+                                               const char *path,
+                                               struct directory_entry *de,
+                                               int flag,
+                                               struct stat* stat_template);
+static void    delete_directory(struct directory *parent,
+                                                                                 struct directory *child);
+int    sort_tree(struct directory *node);
+void   dump_tree(struct directory *node);
+void   update_nlink_field(struct directory *node);
+struct directory_entry *search_tree_file(struct directory *node,
+                                                                                                         char *filename);
+void   init_fstatbuf(void);
+
+extern int     verbose;
+struct stat    fstatbuf;               /* We use this for the artificial */
+                                       /* entries we create              */
+struct stat    root_statbuf;           /* Stat buffer for root directory */
+struct directory *reloc_dir;
+
+static char *
+filetype(int t)
+{
+       static  char    unkn[32];
+
+       if (S_ISFIFO(t))                /* 1 */
+               return ("fifo");
+       if (S_ISCHR(t))                 /* 2 */
+               return ("chr");
+       if (S_ISMPC(t))                 /* 3 */
+               return ("multiplexed chr");
+       if (S_ISDIR(t))                 /* 4 */
+               return ("dir");
+       if (S_ISNAM(t))                 /* 5 */
+               return ("named file");
+       if (S_ISBLK(t))                 /* 6 */
+               return ("blk");
+       if (S_ISMPB(t))                 /* 7 */
+               return ("multiplexed blk");
+       if (S_ISREG(t))                 /* 8 */
+               return ("regular file");
+       if (S_ISCNT(t))                 /* 9 */
+               return ("contiguous file");
+       if (S_ISLNK(t))                 /* 10 */
+               return ("symlink");
+       if (S_ISSHAD(t))                /* 11 */
+               return ("Solaris shadow inode");
+       if (S_ISSOCK(t))                /* 12 */
+               return ("socket");
+       if (S_ISDOOR(t))                /* 13 */
+               return ("door");
+       if (S_ISWHT(t))                 /* 14 */
+               return ("whiteout");
+       if (S_ISEVC(t))                 /* 15 */
+               return ("event count");
+
+       /*
+        * Needs to be last in case somebody makes this
+        * a supported file type.
+        */
+       if ((t & S_IFMT) == 0)          /* 0 (unallocated) */
+               return ("unallocated");
+
+       sprintf(unkn, "octal '%o'", t & S_IFMT);
+       return (unkn);
+}
+
+/*
+ * Check if s1 ends in strings s2
+ */
+static char *
+rstr(char *s1, char *s2)
+{
+       int     l1;
+       int     l2;
+
+       l1 = strlen(s1);
+       l2 = strlen(s2);
+       if (l2 > l1)
+               return ((char *) NULL);
+
+       if (strcmp(&s1[l1 - l2], s2) == 0)
+               return (&s1[l1 - l2]);
+       return ((char *) NULL);
+}
+
+static void
+stat_fix(struct stat *st)
+{
+       int adjust_modes = 0;
+
+       if (S_ISREG(st->st_mode))
+               adjust_modes = rationalize_filemode;
+       else if (S_ISDIR(st->st_mode))
+               adjust_modes = rationalize_dirmode;
+       else
+               adjust_modes = (rationalize_filemode || rationalize_dirmode);
+
+       /*
+        * If rationalizing, override the uid and gid, since the
+        * originals will only be useful on the author's system.
+        */
+       if (rationalize_uid)
+               st->st_uid = uid_to_use;
+       if (rationalize_gid)
+               st->st_gid = gid_to_use;
+
+       if (adjust_modes) {
+
+               if (S_ISREG(st->st_mode) && (filemode_to_use != 0)) {
+                       st->st_mode = filemode_to_use | S_IFREG;
+               } else if (S_ISDIR(st->st_mode) && (dirmode_to_use != 0)) {
+                       st->st_mode = dirmode_to_use | S_IFDIR;
+               } else {
+                       /*
+                        * Make sure the file modes make sense.  Turn
+                        * on all read bits.  Turn on all exec/search
+                        * bits if any exec/search bit is set.  Turn
+                        * off all write bits, and all special mode
+                        * bits (on a r/o fs lock bits are useless,
+                        * and with uid+gid 0 don't want set-id bits,
+                        * either).
+                        */
+
+                       st->st_mode |= 0444;
+#if !defined(_WIN32) && !defined(__DJGPP__)    /* make all file "executable" */
+                       if (st->st_mode & 0111)
+#endif
+                               st->st_mode |= 0111;
+                       st->st_mode &= ~07222;
+               }
+       }
+}
+
+int
+stat_filter(char *path, struct stat *st)
+{
+       int     result = stat(path, st);
+
+       if (result >= 0 && rationalize)
+               stat_fix(st);
+       return (result);
+}
+
+int
+lstat_filter(char *path, struct stat *st)
+{
+       int     result = lstat(path, st);
+
+       if (result >= 0 && rationalize)
+               stat_fix(st);
+       return (result);
+}
+
+static int
+sort_n_finish(struct directory *this_dir)
+{
+       struct directory_entry *s_entry;
+       struct directory_entry *s_entry1;
+       struct directory_entry *table;
+       int             count;
+       int             d1;
+       int             d2;
+       int             d3;
+       register int    new_reclen;
+       char            *c;
+       int             status = 0;
+       int             tablesize = 0;
+       char            newname[MAX_ISONAME+1];
+       char            rootname[MAX_ISONAME+1];
+       char            extname[MAX_ISONAME+1];
+
+       /*
+        * Here we can take the opportunity to toss duplicate entries from the
+        * directory.
+        */
+       /* ignore if it's hidden */
+       if (this_dir->dir_flags & INHIBIT_ISO9660_ENTRY) {
+               return (0);
+       }
+       table = NULL;
+
+       init_fstatbuf();
+
+       /*
+        * If we had artificially created this directory, then we might be
+        * missing the required '.' entries.  Create these now if we need
+        * them.
+        */
+       if ((this_dir->dir_flags & (DIR_HAS_DOT | DIR_HAS_DOTDOT)) !=
+               (DIR_HAS_DOT | DIR_HAS_DOTDOT)) {
+               fstatbuf.st_mode = new_dir_mode | S_IFDIR;
+               fstatbuf.st_nlink = 2;
+               attach_dot_entries(this_dir, &fstatbuf, &fstatbuf);
+       }
+       flush_file_hash();
+       s_entry = this_dir->contents;
+       while (s_entry) {
+               /* ignore if it's hidden */
+               if (s_entry->de_flags & INHIBIT_ISO9660_ENTRY) {
+                       s_entry = s_entry->next;
+                       continue;
+               }
+               /* First assume no conflict, and handle this case */
+               if (!(s_entry1 = find_file_hash(s_entry->isorec.name))) {
+                       add_file_hash(s_entry);
+                       s_entry = s_entry->next;
+                       continue;
+               }
+#ifdef APPLE_HYB
+               /*
+                * if the pair are associated, then skip (as they have the
+                * same name!)
+                */
+               if (apple_both && s_entry1->assoc &&
+                                               s_entry1->assoc == s_entry) {
+                       s_entry = s_entry->next;
+                       continue;
+               }
+#endif /* APPLE_HYB */
+
+               if (s_entry1 == s_entry) {
+#ifdef USE_LIBSCHILY
+                       comerrno(EX_BAD,
+                       "Fatal goof, file '%s' already in hash table.\n",
+                       s_entry->isorec.name);
+#else
+                       fprintf(stderr,
+                       "Fatal goof, file '%s' already in hash table.\n",
+                       s_entry->isorec.name);
+                       exit(1);
+#endif
+               }
+               /*
+                * OK, handle the conflicts.  Try substitute names until we
+                * come up with a winner
+                */
+               strcpy(rootname, s_entry->isorec.name);
+               /*
+                * Strip off the non-significant part of the name so that we
+                * are left with a sensible root filename.  If we don't find
+                * a '.', then try a ';'.
+                */
+               c = strchr(rootname, '.');
+               /*
+                * In case we ever allow more than on dot, only modify the
+                * section past the last dot if the file name starts with a
+                * dot.
+                */
+               if (c != NULL && c == rootname && c != strrchr(rootname, '.')) {
+                       c = strrchr(rootname, '.');
+               }
+               extname[0] = '\0';              /* In case we have no ext.  */
+               if (c) {
+                       strcpy(extname, c);
+                       *c = 0;                 /* Cut off complete ext.    */
+               } else {
+                       /*
+                        * Could not find any '.'.
+                        */
+                       c = strchr(rootname, ';');
+                       if (c) {
+                               *c = 0;         /* Cut off version number    */
+                       }
+               }
+               c = strchr(extname, ';');
+               if (c) {
+                       *c = 0;                 /* Cut off version number    */
+               }
+               d1 = strlen(rootname);
+               if (full_iso9660_filenames || iso9660_level > 1) {
+                       d2 = strlen(extname);
+                       /*
+                        * 31/37 chars minus the 3 characters we are
+                        * appending below to create unique filenames.
+                        */
+                       if ((d1 + d2) > (iso9660_namelen - 3))
+                               rootname[iso9660_namelen - 3 - d2] = 0;
+               } else {
+                       if (d1 > 5)
+                               rootname[5] = 0;
+               }
+               new_reclen = strlen(rootname);
+               sprintf(newname, "%s000%s%s",
+                               rootname,
+                               extname,
+                               ((s_entry->isorec.flags[0] & ISO_DIRECTORY) ||
+                               omit_version_number ? "" : ";1"));
+
+               for (d1 = 0; d1 < 36; d1++) {
+                       for (d2 = 0; d2 < 36; d2++) {
+                               for (d3 = 0; d3 < 36; d3++) {
+                                       newname[new_reclen + 0] =
+                                           (d1 <= 9 ? '0' + d1 : 'A' + d1 - 10);
+                                       newname[new_reclen + 1] =
+                                           (d2 <= 9 ? '0' + d2 : 'A' + d2 - 10);
+                                       newname[new_reclen + 2] =
+                                           (d3 <= 9 ? '0' + d3 : 'A' + d3 - 10);
+                                       if (debug)
+                                               fprintf(stderr, "NEW name '%s'\n", newname);
+
+#ifdef VMS
+                                       /* Sigh.  VAXCRTL seems to be broken here */
+                                       {
+                                               int     ijk = 0;
+
+                                               while (newname[ijk]) {
+                                                       if (newname[ijk] == ' ')
+                                                               newname[ijk] = '0';
+                                                       ijk++;
+                                               }
+                                       }
+#endif
+
+                                       if (!find_file_hash(newname))
+                                               goto got_valid_name;
+                               }
+                       }
+               }
+
+               /* If we fell off the bottom here, we were in real trouble. */
+#ifdef USE_LIBSCHILY
+               comerrno(EX_BAD,
+                       "Unable to generate unique name for file %s\n",
+                       s_entry->name);
+#else
+               fprintf(stderr,
+                       "Unable to generate unique name for file %s\n",
+                       s_entry->name);
+               exit(1);
+#endif
+
+got_valid_name:
+               /*
+                * OK, now we have a good replacement name.  Now decide which
+                * one of these two beasts should get the name changed
+                */
+               if (s_entry->priority < s_entry1->priority) {
+                       if (verbose > 0) {
+                               fprintf(stderr, "Using %s for  %s%s%s (%s)\n",
+                                       newname,
+                                       this_dir->whole_name, SPATH_SEPARATOR,
+                                       s_entry->name, s_entry1->name);
+                       }
+                       s_entry->isorec.name_len[0] = strlen(newname);
+                       new_reclen = offsetof(struct iso_directory_record,
+                               name[0]) +
+                               strlen(newname);
+                       if (use_XA || use_RockRidge) {
+                               if (new_reclen & 1)
+                                       new_reclen++; /* Pad to an even byte */
+                               new_reclen += s_entry->rr_attr_size;
+                       }
+                       if (new_reclen & 1)
+                               new_reclen++;   /* Pad to an even byte */
+                       s_entry->isorec.length[0] = new_reclen;
+                       strcpy(s_entry->isorec.name, newname);
+#ifdef APPLE_HYB
+                       /* has resource fork - needs new name */
+                       if (apple_both && s_entry->assoc) {
+                               struct directory_entry *s_entry2 =
+                                                               s_entry->assoc;
+
+                               /*
+                                * resource fork name *should* be the same as
+                                * the data fork
+                                */
+                               s_entry2->isorec.name_len[0] =
+                                               s_entry->isorec.name_len[0];
+                               strcpy(s_entry2->isorec.name,
+                                               s_entry->isorec.name);
+                               s_entry2->isorec.length[0] = new_reclen;
+                       }
+#endif /* APPLE_HYB */
+               } else {
+                       delete_file_hash(s_entry1);
+                       if (verbose > 0) {
+                               fprintf(stderr, "Using %s for  %s%s%s (%s)\n",
+                                       newname,
+                                       this_dir->whole_name, SPATH_SEPARATOR,
+                                       s_entry1->name, s_entry->name);
+                       }
+                       s_entry1->isorec.name_len[0] = strlen(newname);
+                       new_reclen = offsetof(struct iso_directory_record,
+                                       name[0]) +
+                                       strlen(newname);
+                       if (use_XA || use_RockRidge) {
+                               if (new_reclen & 1)
+                                       new_reclen++; /* Pad to an even byte */
+                               new_reclen += s_entry1->rr_attr_size;
+                       }
+                       if (new_reclen & 1)
+                               new_reclen++;   /* Pad to an even byte */
+                       s_entry1->isorec.length[0] = new_reclen;
+                       strcpy(s_entry1->isorec.name, newname);
+                       add_file_hash(s_entry1);
+#ifdef APPLE_HYB
+                       /* has resource fork - needs new name */
+                       if (apple_both && s_entry1->assoc) {
+                               struct directory_entry *s_entry2 =
+                                                       s_entry1->assoc;
+
+                               /*
+                                * resource fork name *should* be the same as
+                                * the data fork
+                                */
+                               s_entry2->isorec.name_len[0] =
+                                               s_entry1->isorec.name_len[0];
+                               strcpy(s_entry2->isorec.name,
+                                                       s_entry1->isorec.name);
+                               s_entry2->isorec.length[0] = new_reclen;
+                       }
+#endif /* APPLE_HYB */
+               }
+               add_file_hash(s_entry);
+               s_entry = s_entry->next;
+       }
+
+       if (generate_tables &&
+           !find_file_hash(trans_tbl) &&
+           (reloc_dir != this_dir) &&
+           (this_dir->extent == 0)) {
+               /* First we need to figure out how big this table is */
+               for (s_entry = this_dir->contents; s_entry;
+                                               s_entry = s_entry->next) {
+                       if (strcmp(s_entry->name, ".") == 0 ||
+                               strcmp(s_entry->name, "..") == 0)
+                               continue;
+#ifdef APPLE_HYB
+                       /* skip table entry for the resource fork */
+                       if (apple_both &&
+                           (s_entry->isorec.flags[0] & ISO_ASSOCIATED))
+                               continue;
+#endif /* APPLE_HYB */
+                       if (s_entry->de_flags & INHIBIT_ISO9660_ENTRY)
+                               continue;
+                       if (s_entry->table) {
+                               /*
+                                * Max namelen, a space before and a space
+                                * after the iso filename.
+                                */
+                               tablesize += MAX_ISONAME + 2 +
+                                               strlen(s_entry->table);
+                       }
+               }
+       }
+       if (tablesize > 0) {
+               table = (struct directory_entry *)
+                       e_malloc(sizeof (struct directory_entry));
+               memset(table, 0, sizeof (struct directory_entry));
+               table->table = NULL;
+               table->next = this_dir->contents;
+               this_dir->contents = table;
+
+               table->filedir = root;
+               table->isorec.flags[0] = ISO_FILE;
+               table->priority = 32768;
+               iso9660_date(table->isorec.date, fstatbuf.st_mtime);
+               table->inode = TABLE_INODE;
+               table->dev = (dev_t) UNCACHED_DEVICE;
+               set_723(table->isorec.volume_sequence_number,
+                                               volume_sequence_number);
+               set_733((char *) table->isorec.size, tablesize);
+               table->realsize = tablesize;
+               table->size = tablesize;
+               table->filedir = this_dir;
+               if (jhide_trans_tbl)
+                       table->de_flags |= INHIBIT_JOLIET_ENTRY;
+/*             table->name = strdup("<translation table>");*/
+               table->name = strdup(trans_tbl);
+               /*
+                * We use sprintf() to create the strings, for this reason
+                * we need to add one byte for the null character at the
+                * end of the string even though we don't use it.
+                */
+               table->table = (char *) e_malloc(ISO_ROUND_UP(tablesize)+1);
+               memset(table->table, 0, ISO_ROUND_UP(tablesize)+1);
+               iso9660_file_length(trans_tbl, table, 0);
+
+               if (use_XA || use_RockRidge) {
+                       fstatbuf.st_mode = 0444 | S_IFREG;
+                       fstatbuf.st_nlink = 1;
+                       generate_xa_rr_attributes("",
+                               trans_tbl, table,
+                               &fstatbuf, &fstatbuf, 0);
+               }
+       }
+       /*
+        * We have now chosen the 8.3 names and we should now know the length
+        * of every entry in the directory.
+        */
+       for (s_entry = this_dir->contents; s_entry; s_entry = s_entry->next) {
+               /* skip if it's hidden */
+               if (s_entry->de_flags & INHIBIT_ISO9660_ENTRY) {
+                       continue;
+               }
+               new_reclen = strlen(s_entry->isorec.name);
+
+               /* First update the path table sizes for directories. */
+               if (s_entry->isorec.flags[0] & ISO_DIRECTORY) {
+                       if (strcmp(s_entry->name, ".") != 0 &&
+                                       strcmp(s_entry->name, "..") != 0) {
+                               path_table_size += new_reclen +
+                                               offsetof(struct iso_path_table,
+                                               name[0]);
+                               if (new_reclen & 1)
+                                       path_table_size++;
+                       } else {
+                               new_reclen = 1;
+                               if (this_dir == root && strlen(s_entry->name)
+                                                                       == 1) {
+                                       path_table_size += new_reclen +
+                                               offsetof(struct iso_path_table,
+                                               name[0]);
+                               }
+                       }
+               }
+               if (path_table_size & 1)
+                       path_table_size++;      /* For odd lengths we pad */
+               s_entry->isorec.name_len[0] = new_reclen;
+
+               new_reclen += offsetof(struct iso_directory_record, name[0]);
+
+               if (new_reclen & 1)
+                       new_reclen++;
+
+               new_reclen += s_entry->rr_attr_size;
+
+               if (new_reclen & 1)
+                       new_reclen++;
+
+               if (new_reclen > 0xff) {
+#ifdef USE_LIBSCHILY
+                       comerrno(EX_BAD,
+                               "Fatal error - RR overflow (reclen %d) for file %s\n",
+                               new_reclen,
+                               s_entry->name);
+#else
+                       fprintf(stderr,
+                               "Fatal error - RR overflow (reclen %d) for file %s\n",
+                               new_reclen,
+                               s_entry->name);
+                       exit(1);
+#endif
+               }
+               s_entry->isorec.length[0] = new_reclen;
+       }
+
+       status = sort_directory(&this_dir->contents, (reloc_dir == this_dir));
+       if (status > 0) {
+     fprintf(stderr, "Unable to sort directory %s\n",
+           this_dir->whole_name);
+     if(merge_warn_msg)
+        fprintf(stderr, merge_warn_msg);
+     exit(1);
+       }
+       /*
+        * If we are filling out a TRANS.TBL, generate the entries that will
+        * go in the thing.
+        */
+       if (table) {
+               count = 0;
+               for (s_entry = this_dir->contents; s_entry;
+                                               s_entry = s_entry->next) {
+                       if (s_entry == table)
+                               continue;
+                       if (!s_entry->table)
+                               continue;
+                       if (strcmp(s_entry->name, ".") == 0 ||
+                               strcmp(s_entry->name, "..") == 0)
+                               continue;
+#ifdef APPLE_HYB
+                       /* skip table entry for the resource fork */
+                       if (apple_both &&
+                           (s_entry->isorec.flags[0] & ISO_ASSOCIATED))
+                               continue;
+#endif /* APPLE_HYB */
+                       if (s_entry->de_flags & INHIBIT_ISO9660_ENTRY)
+                               continue;
+                       /*
+                        * Warning: we cannot use the return value of sprintf
+                        * because old BSD based sprintf() implementations
+                        * will return a pointer to the result instead of a
+                        * count.
+                        * Old mkiofs introduced a space after the iso
+                        * filename to make parsing TRANS.TBL easier.
+                        */
+                       sprintf(table->table + count, "%c %-*s%s",
+                               s_entry->table[0],
+                               MAX_ISONAME + 1,
+                               s_entry->isorec.name, s_entry->table + 1);
+                       count += strlen(table->table + count);
+                       free(s_entry->table);
+                       /*
+                        * for a memory file, set s_entry->table to the
+                        * correct data - which is stored in
+                        * s_entry->whole_name
+                        */
+                       if (s_entry->de_flags & MEMORY_FILE) {
+                               s_entry->table = s_entry->whole_name;
+                               s_entry->whole_name = NULL;
+                       } else {
+                               s_entry->table = NULL;
+                       }
+               }
+
+               if (count != tablesize) {
+#ifdef USE_LIBSCHILY
+                       comerrno(EX_BAD,
+                               "Translation table size mismatch %d %d\n",
+                               count, tablesize);
+#else
+                       fprintf(stderr,
+                               "Translation table size mismatch %d %d\n",
+                               count, tablesize);
+                       exit(1);
+#endif
+               }
+       }
+       /*
+        * Now go through the directory and figure out how large this one will
+        * be. Do not split a directory entry across a sector boundary
+        */
+       s_entry = this_dir->contents;
+       this_dir->ce_bytes = 0;
+       while (s_entry) {
+               /* skip if it's hidden */
+               if (s_entry->de_flags & INHIBIT_ISO9660_ENTRY) {
+                       s_entry = s_entry->next;
+                       continue;
+               }
+               new_reclen = s_entry->isorec.length[0];
+               if ((this_dir->size & (SECTOR_SIZE - 1)) + new_reclen
+                                                               >= SECTOR_SIZE)
+
+                       this_dir->size = (this_dir->size + (SECTOR_SIZE - 1)) &
+                               ~(SECTOR_SIZE - 1);
+               this_dir->size += new_reclen;
+
+               /* See if continuation entries were used on disc */
+               if (use_RockRidge &&
+                       s_entry->rr_attr_size != s_entry->total_rr_attr_size) {
+                       unsigned char   *pnt;
+                       int             len;
+                       int             nbytes;
+
+                       pnt = s_entry->rr_attributes;
+                       len = s_entry->total_rr_attr_size;
+                       pnt = parse_xa(pnt, &len, 0);
+/*                     pnt = parse_xa(pnt, &len, s_entry);*/
+
+                       /*
+                        * We make sure that each continuation entry record is
+                        * not split across sectors, but each file could in
+                        * theory have more than one CE, so we scan through
+                        * and figure out what we need.
+                        */
+                       while (len > 3) {
+                               if (pnt[0] == 'C' && pnt[1] == 'E') {
+                                       nbytes = get_733((char *) pnt + 20);
+
+                                       if ((this_dir->ce_bytes & (SECTOR_SIZE - 1)) + nbytes >=
+                                               SECTOR_SIZE)
+                                               this_dir->ce_bytes =
+                                                       ISO_ROUND_UP(this_dir->ce_bytes);
+                                       /*
+                                        * Now store the block in the
+                                        * ce buffer
+                                        */
+                                       this_dir->ce_bytes += nbytes;
+                                       if (this_dir->ce_bytes & 1)
+                                               this_dir->ce_bytes++;
+                               }
+                               len -= pnt[2];
+                               pnt += pnt[2];
+                       }
+               }
+               s_entry = s_entry->next;
+       }
+       return (status);
+}
+
+static void
+generate_reloc_directory()
+{
+       time_t          current_time;
+       struct directory_entry *s_entry;
+
+       /* Create an  entry for our internal tree */
+       time(&current_time);
+       reloc_dir = (struct directory *)
+               e_malloc(sizeof (struct directory));
+       memset(reloc_dir, 0, sizeof (struct directory));
+       reloc_dir->parent = root;
+       reloc_dir->next = root->subdir;
+       root->subdir = reloc_dir;
+       reloc_dir->depth = 1;
+       if (hide_rr_moved) {
+               reloc_dir->whole_name = strdup("./.rr_moved");
+               reloc_dir->de_name = strdup(".rr_moved");
+       } else {
+               reloc_dir->whole_name = strdup("./rr_moved");
+               reloc_dir->de_name = strdup("rr_moved");
+       }
+       reloc_dir->extent = 0;
+
+
+       /* Now create an actual directory  entry */
+       s_entry = (struct directory_entry *)
+               e_malloc(sizeof (struct directory_entry));
+       memset(s_entry, 0, sizeof (struct directory_entry));
+       s_entry->next = root->contents;
+       reloc_dir->self = s_entry;
+
+       /* The rr_moved entry will not appear in the Joliet tree. */
+       reloc_dir->dir_flags |= INHIBIT_JOLIET_ENTRY;
+       s_entry->de_flags |= INHIBIT_JOLIET_ENTRY;
+
+       /* Hiding RR_MOVED seems not to be possible..... */
+#ifdef HIDE_RR
+       reloc_dir->dir_flags |= INHIBIT_ISO9660_ENTRY;
+       s_entry->de_flags |= INHIBIT_ISO9660_ENTRY;
+#endif
+
+       root->contents = s_entry;
+       root->contents->name = strdup(reloc_dir->de_name);
+       root->contents->filedir = root;
+       root->contents->isorec.flags[0] = ISO_DIRECTORY;
+       root->contents->priority = 32768;
+       iso9660_date(root->contents->isorec.date, current_time);
+       root->contents->inode = UNCACHED_INODE;
+       root->contents->dev = (dev_t) UNCACHED_DEVICE;
+       set_723(root->contents->isorec.volume_sequence_number,
+                                               volume_sequence_number);
+       iso9660_file_length(reloc_dir->de_name, root->contents, 1);
+
+       init_fstatbuf();
+
+       if (use_XA || use_RockRidge) {
+               fstatbuf.st_mode = 0555 | S_IFDIR;
+               fstatbuf.st_nlink = 2;
+               generate_xa_rr_attributes("",
+                       hide_rr_moved ? ".rr_moved" : "rr_moved",
+                       s_entry, &fstatbuf, &fstatbuf, 0);
+       };
+
+       /* Now create the . and .. entries in rr_moved */
+       /* Now create an actual directory  entry */
+       memset(&root_statbuf, 0x0, sizeof(struct stat)); /* be sure */
+       attach_dot_entries(reloc_dir, &fstatbuf, &root_statbuf);
+}
+
+/*
+ * Function:           attach_dot_entries
+ *
+ * Purpose:            Create . and .. entries for a new directory.
+ *
+ * Arguments:          dir_stat contains the ownership/permission information
+ *                     for dirnode, and parent_stat contains 
+ *                     ownership/permission information for its parent
+ *
+ *
+ * Notes:              Only used for artificial directories that
+ *                     we are creating.
+ */
+static void
+attach_dot_entries(struct directory *dirnode, struct stat *dir_stat,
+                       struct stat *parent_stat)
+{
+       struct directory_entry *s_entry;
+       struct directory_entry *orig_contents;
+       int             deep_flag = 0;
+
+       init_fstatbuf();
+
+       orig_contents = dirnode->contents;
+
+       if ((dirnode->dir_flags & DIR_HAS_DOTDOT) == 0) {
+               s_entry = (struct directory_entry *)
+                       e_malloc(sizeof (struct directory_entry));
+               memcpy(s_entry, dirnode->self,
+                       sizeof (struct directory_entry));
+#ifdef APPLE_HYB
+               if (dirnode->self->hfs_ent) {
+                       s_entry->hfs_ent = (hfsdirent *)
+                               e_malloc(sizeof (hfsdirent));
+                       memcpy(s_entry->hfs_ent, dirnode->self->hfs_ent,
+                               sizeof (hfsdirent));
+               }
+#endif
+               s_entry->name = strdup("..");
+               s_entry->whole_name = NULL;
+               s_entry->isorec.name_len[0] = 1;
+               s_entry->isorec.flags[0] = ISO_DIRECTORY;
+               iso9660_file_length("..", s_entry, 1);
+               iso9660_date(s_entry->isorec.date, fstatbuf.st_mtime);
+               set_723(s_entry->isorec.volume_sequence_number,
+                                               volume_sequence_number);
+               set_733(s_entry->isorec.size, SECTOR_SIZE);
+               s_entry->realsize = SECTOR_SIZE;
+               memset(s_entry->isorec.extent, 0, 8);
+               s_entry->filedir = dirnode->parent;
+
+               dirnode->contents = s_entry;
+               dirnode->contents->next = orig_contents;
+               orig_contents = s_entry;
+
+               if (use_XA || use_RockRidge) {
+                       generate_xa_rr_attributes("",
+                               "..", s_entry,
+                               parent_stat,
+                               parent_stat, 0);
+               }
+               dirnode->dir_flags |= DIR_HAS_DOTDOT;
+       }
+       if ((dirnode->dir_flags & DIR_HAS_DOT) == 0) {
+               s_entry = (struct directory_entry *)
+                       e_malloc(sizeof (struct directory_entry));
+               memcpy(s_entry, dirnode->self,
+                       sizeof (struct directory_entry));
+#ifdef APPLE_HYB
+               if (dirnode->self->hfs_ent) {
+                       s_entry->hfs_ent = (hfsdirent *)
+                               e_malloc(sizeof (hfsdirent));
+                       memcpy(s_entry->hfs_ent, dirnode->self->hfs_ent,
+                               sizeof (hfsdirent));
+               }
+#endif
+               s_entry->name = strdup(".");
+               s_entry->whole_name = NULL;
+               s_entry->isorec.name_len[0] = 1;
+               s_entry->isorec.flags[0] = ISO_DIRECTORY;
+               iso9660_file_length(".", s_entry, 1);
+               iso9660_date(s_entry->isorec.date, fstatbuf.st_mtime);
+               set_723(s_entry->isorec.volume_sequence_number,
+                                               volume_sequence_number);
+               set_733(s_entry->isorec.size, SECTOR_SIZE);
+               s_entry->realsize=SECTOR_SIZE;
+               memset(s_entry->isorec.extent, 0, 8);
+               s_entry->filedir = dirnode;
+
+               dirnode->contents = s_entry;
+               dirnode->contents->next = orig_contents;
+
+               if (use_XA || use_RockRidge) {
+
+                       if (dirnode == root) {
+                               deep_flag |= NEED_CE | NEED_SP; /* For extension record */
+                       }
+                       generate_xa_rr_attributes("", ".", s_entry,
+                               dir_stat, dir_stat, deep_flag);
+               }
+               dirnode->dir_flags |= DIR_HAS_DOT;
+       }
+}
+
+static void
+update_nlink(struct directory_entry *s_entry, int value)
+{
+       unsigned char   *pnt;
+       int             len;
+
+       pnt = s_entry->rr_attributes;
+       len = s_entry->total_rr_attr_size;
+       pnt = parse_xa(pnt, &len, 0);
+       while (len >= 4) {
+               if (pnt[3] != 1 && pnt[3] != 2) {
+#ifdef USE_LIBSCHILY
+                       errmsgno(EX_BAD,
+                               "**BAD RRVERSION (%d) for %c%c\n",
+                               pnt[3], pnt[0], pnt[1]);
+#else
+                       fprintf(stderr,
+                               "**BAD RRVERSION (%d) for %c%c\n",
+                               pnt[3], pnt[0], pnt[1]);
+#endif
+               }
+               if (pnt[0] == 'P' && pnt[1] == 'X') {
+                       set_733((char *) pnt + 12, value);
+                       break;
+               }
+               len -= pnt[2];
+               pnt += pnt[2];
+       }
+}
+
+static void
+increment_nlink(struct directory_entry *s_entry)
+{
+       unsigned char   *pnt;
+       int             len,
+                       nlink;
+
+       pnt = s_entry->rr_attributes;
+       len = s_entry->total_rr_attr_size;
+       pnt = parse_xa(pnt, &len, 0);
+       while (len >= 4) {
+               if (pnt[3] != 1 && pnt[3] != 2) {
+#ifdef USE_LIBSCHILY
+                       errmsgno(EX_BAD,
+                               "**BAD RRVERSION (%d) for %c%c\n",
+                               pnt[3], pnt[0], pnt[1]);
+#else
+                       fprintf(stderr,
+                               "**BAD RRVERSION (%d) for %c%c\n",
+                               pnt[3], pnt[0], pnt[1]);
+#endif
+               }
+               if (pnt[0] == 'P' && pnt[1] == 'X') {
+                       nlink = get_733((char *) pnt + 12);
+                       set_733((char *) pnt + 12, nlink + 1);
+                       break;
+               }
+               len -= pnt[2];
+               pnt += pnt[2];
+       }
+}
+
+char *
+find_rr_attribute(unsigned char *pnt, int len, char *attr_type)
+{
+       pnt = parse_xa(pnt, &len, 0);
+       while (len >= 4) {
+               if (pnt[3] != 1 && pnt[3] != 2) {
+#ifdef USE_LIBSCHILY
+                       errmsgno(EX_BAD,
+                               "**BAD RRVERSION (%d) for %c%c\n",
+                               pnt[3], pnt[0], pnt[1]);
+#else
+                       fprintf(stderr,
+                               "**BAD RRVERSION (%d) for %c%c\n",
+                               pnt[3], pnt[0], pnt[1]);
+#endif
+               }
+               if (strncmp((char *) pnt, attr_type, 2) == 0)
+                       return ((char *) pnt);
+               else if (strncmp((char *) pnt, "ST", 2) == 0)
+                       return (NULL);
+               len -= pnt[2];
+               pnt += pnt[2];
+       }
+       return (NULL);
+}
+
+void
+finish_cl_pl_entries()
+{
+       struct directory_entry  *s_entry;
+       struct directory_entry  *s_entry1;
+       struct directory        *d_entry;
+
+       /* if the reloc_dir is hidden (empty), then return */
+       if (reloc_dir->dir_flags & INHIBIT_ISO9660_ENTRY)
+               return;
+
+       s_entry = reloc_dir->contents;
+       s_entry = s_entry->next->next;  /* Skip past . and .. */
+       for (; s_entry; s_entry = s_entry->next) {
+               /* skip if it's hidden */
+               if (s_entry->de_flags & INHIBIT_ISO9660_ENTRY) {
+                       continue;
+               }
+               d_entry = reloc_dir->subdir;
+               while (d_entry) {
+                       if (d_entry->self == s_entry)
+                               break;
+                       d_entry = d_entry->next;
+               };
+               if (!d_entry) {
+#ifdef USE_LIBSCHILY
+                       comerrno(EX_BAD,
+                                       "Unable to locate directory parent\n");
+#else
+                       fprintf(stderr, "Unable to locate directory parent\n");
+                       exit(1);
+#endif
+               };
+
+               if (s_entry->filedir != NULL && s_entry->parent_rec != NULL) {
+                       char    *rr_attr;
+
+                       /*
+                        * First fix the PL pointer in the directory in the
+                        * rr_reloc dir
+                        */
+                       s_entry1 = d_entry->contents->next;
+
+/*                     set_733((char *) s_entry1->rr_attributes +*/
+/*                             s_entry1->total_rr_attr_size - 8,*/
+/*                             s_entry->filedir->extent); */
+                       /*
+                        * The line above won't work when entry was read from
+                        * the previous session, because if total_rr_attr_size
+                        * was odd when recording previous session, now we have
+                        * total_rr_attr_size off by 1 due to padding.
+                        *
+                        * So, just search for the attributes by name
+                        */
+                       rr_attr = find_rr_attribute(s_entry1->rr_attributes,
+                               s_entry1->total_rr_attr_size, "PL");
+                       if (rr_attr != NULL)
+                               set_733(rr_attr + 4, s_entry->filedir->extent);
+
+
+                       /* Now fix the CL pointer */
+                       s_entry1 = s_entry->parent_rec;
+
+/*                     set_733((char *) s_entry1->rr_attributes +*/
+/*                     s_entry1->total_rr_attr_size - 8, d_entry->extent); */
+                       rr_attr = find_rr_attribute(s_entry1->rr_attributes,
+                               s_entry1->total_rr_attr_size, "CL");
+                       if (rr_attr != NULL)
+                               set_733(rr_attr + 4, d_entry->extent);
+               }
+               s_entry->filedir = reloc_dir;   /* Now we can fix this */
+       }
+       /*
+        * Next we need to modify the NLINK terms in the assorted root
+        * directory records to account for the presence of the RR_MOVED
+        * directory
+        */
+       increment_nlink(root->self);
+       increment_nlink(root->self->next);
+       d_entry = root->subdir;
+       while (d_entry) {
+               increment_nlink(d_entry->contents->next);
+               d_entry = d_entry->next;
+       };
+
+       finish_cl_pl_for_prev_session();
+}
+
+/*
+ * Function:           scan_directory_tree
+ *
+ * Purpose:            Walk through a directory on the local machine
+ *                     filter those things we don't want to include
+ *                     and build our representation of a dir.
+ *
+ * Notes:
+ */
+int
+scan_directory_tree(struct directory *this_dir, char *path, 
+                                                 struct directory_entry *de)
+{
+       DIR             *current_dir;
+       char            whole_path[PATH_MAX];
+       struct dirent   *d_entry;
+       struct directory *parent;
+       int             dflag;
+       char            *old_path;
+
+       if (verbose > 1) {
+               fprintf(stderr, "Scanning %s\n", path);
+       }
+/*#define      check_needed*/
+#ifdef check_needed
+       /*
+        * Trying to use this to avoid directory loops from hard links
+        * or followed symlinks does not work. It would prevent us from
+        * implementing merge directories.
+        */
+       if (this_dir->dir_flags & DIR_WAS_SCANNED) {
+               fprintf(stderr, "Already scanned directory %s\n", path);
+               return (1);     /* It's a directory */
+       }
+#endif
+       this_dir->dir_flags |= DIR_WAS_SCANNED;
+
+       errno = 0;      /* Paranoia */
+       current_dir = opendir(path);
+       d_entry = NULL;
+
+       /*
+        * Apparently NFS sometimes allows you to open the directory, but then
+        * refuses to allow you to read the contents.  Allow for this
+        */
+       old_path = path;
+
+       if (current_dir) {
+               errno = 0;
+               d_entry = readdir(current_dir);
+       }
+
+       if (!current_dir || !d_entry) {
+               int     ret = 1;
+
+#ifdef USE_LIBSCHILY
+               errmsg("Unable to open directory %s\n", path);
+#else
+               fprintf(stderr, "Unable to open directory %s\n", path);
+#endif
+               if (errno == ENOTDIR) {
+                       /* Mark as not a directory */
+                       de->isorec.flags[0] &= ~ISO_DIRECTORY;
+                       ret = 0;
+               }
+               if (current_dir)
+                       closedir(current_dir);
+               return (ret);
+       }
+#ifdef ABORT_DEEP_ISO_ONLY
+       if ((this_dir->depth > RR_relocation_depth) && !use_RockRidge) {
+               static  BOOL    did_hint = FALSE;
+
+               errmsgno(EX_BAD,
+                       "Directories too deep for '%s' (%d) max is %d; ignored - continuing.\n",
+                       path, this_dir->depth, RR_relocation_depth);
+               if (!did_hint) {
+                       did_hint = TRUE;
+                       errmsgno(EX_BAD, "To include the complete directory tree,\n");
+                       errmsgno(EX_BAD, "use Rock Ridge extensions via -R or -r,\n");
+                       errmsgno(EX_BAD, "or allow deep ISO9660 directory nesting via -D.\n");
+               }
+               closedir(current_dir);
+               return (1);
+       }
+#endif
+
+       parent = de->filedir;
+       /*
+        * Set up the struct for the current directory, and insert it into
+        * the tree
+        */
+#ifdef VMS
+       vms_path_fixup(path);
+#endif
+
+       /*
+        * if entry for this sub-directory is hidden, then hide this directory
+        */
+       if (de->de_flags & INHIBIT_ISO9660_ENTRY)
+               this_dir->dir_flags |= INHIBIT_ISO9660_ENTRY;
+
+       if (de->de_flags & INHIBIT_JOLIET_ENTRY)
+               this_dir->dir_flags |= INHIBIT_JOLIET_ENTRY;
+
+#ifdef SORTING
+       /*
+        * set any sort weighting from it's own directory entry - if a
+        * directory is given a weighting, then all the contents will use
+        * this as the default weighting
+        */
+       this_dir->sort = de->sort;
+#endif /* SORTING */
+
+       /*
+        * Now we scan the directory itself, and look at what is inside of it.
+        */
+       dflag = 0;
+       while (1 == 1) {
+
+               /*
+                * The first time through, skip this, since we already asked
+                * for the first entry when we opened the directory.
+                */
+               if (dflag)
+                       d_entry = readdir(current_dir);
+               dflag++;
+
+               if (!d_entry)
+                       break;
+
+               /* OK, got a valid entry */
+
+               /* If we do not want all files, then pitch the backups. */
+               if (!all_files) {
+                       if (strchr(d_entry->d_name, '~') ||
+                           strchr(d_entry->d_name, '#') ||
+                           rstr(d_entry->d_name, ".bak")) {
+                               if (verbose > 0) {
+                                       fprintf(stderr,
+                                               "Ignoring file %s\n",
+                                               d_entry->d_name);
+                               }
+                               continue;
+                       }
+               }
+#ifdef APPLE_HYB
+               if (apple_both) {
+                       /*
+                        * exclude certain HFS type files/directories for the
+                        * time being
+                        */
+                       if (hfs_exclude(d_entry->d_name))
+                               continue;
+               }
+#endif /* APPLE_HYB */
+
+               if (strlen(path) + strlen(d_entry->d_name) + 2 >
+                                                       sizeof (whole_path)) {
+#ifdef USE_LIBSCHILY
+                       errmsgno(EX_BAD, "Path name %s/%s too long.\n",
+                                       path, d_entry->d_name);
+                       comerrno(EX_BAD, "Overflow of stat buffer\n");
+#else
+                       fprintf(stderr, "Path name %s/%s too long.\n",
+                                       path, d_entry->d_name);
+                       fprintf(stderr, "Overflow of stat buffer\n");
+                       exit(1);
+#endif
+               };
+
+               /* Generate the complete ASCII path for this file */
+               strcpy(whole_path, path);
+#ifndef VMS
+               if (whole_path[strlen(whole_path) - 1] != '/')
+                       strcat(whole_path, "/");
+#endif
+               strcat(whole_path, d_entry->d_name);
+
+               /** Should we exclude this file ? */
+               if (matches(d_entry->d_name) || matches(whole_path)) {
+                       if (verbose > 1) {
+                               fprintf(stderr,
+                                       "Excluded by match: %s\n", whole_path);
+                       }
+                       continue;
+               }
+               if (generate_tables &&
+                   strcmp(d_entry->d_name, trans_tbl) == 0) {
+                       /*
+                        * Ignore this entry.  We are going to be generating
+                        * new versions of these files, and we need to ignore
+                        * any originals that we might have found.
+                        */
+                       if (verbose > 1) {
+                               fprintf(stderr, "Excluded: %s\n", whole_path);
+                       }
+                       continue;
+               }
+               /*
+                * If we already have a '.' or a '..' entry, then don't insert
+                * new ones.
+                */
+               if (strcmp(d_entry->d_name, ".") == 0 &&
+                   this_dir->dir_flags & DIR_HAS_DOT) {
+                       continue;
+               }
+               if (strcmp(d_entry->d_name, "..") == 0 &&
+                   this_dir->dir_flags & DIR_HAS_DOTDOT) {
+                       continue;
+               }
+#if 0
+               if (verbose > 1)
+                       fprintf(stderr, "%s\n", whole_path);
+#endif
+               /* This actually adds the entry to the directory in question.*/
+#ifdef APPLE_HYB
+               insert_file_entry(this_dir, whole_path, d_entry->d_name, 0);
+#else
+               insert_file_entry(this_dir, whole_path, d_entry->d_name);
+#endif /* APPLE_HYB */
+       }
+       closedir(current_dir);
+
+#ifdef APPLE_HYB
+       /*
+        * if we cached the HFS info stuff for this directory, then delete it
+        */
+       if (this_dir->hfs_info) {
+               del_hfs_info(this_dir->hfs_info);
+               this_dir->hfs_info = 0;
+       }
+#endif /* APPLE_HYB */
+
+       return (1);
+}
+
+
+/*
+ * Function:           insert_file_entry
+ *
+ * Purpose:            Insert one entry into our directory node.
+ *
+ * Note:
+ * This function inserts a single entry into the directory.  It
+ * is assumed that all filtering and decision making regarding what
+ * we want to include has already been made, so the purpose of this
+ * is to insert one entry (file, link, dir, etc), into this directory.
+ * Note that if the entry is a dir (or if we are following links,
+ * and the thing it points to is a dir), then we will scan those
+ * trees before we return.
+ */
+#ifdef APPLE_HYB
+int
+insert_file_entry(struct directory *this_dir, char *whole_path, 
+                                               char *short_name, int have_rsrc)
+#else
+int
+insert_file_entry(struct directory *this_dir, char *whole_path, 
+                                               char *short_name)
+#endif /* APPLE_HYB */
+{
+       struct stat     statbuf,
+                       lstatbuf;
+       struct directory_entry *s_entry,
+                       *s_entry1;
+       int             lstatus;
+       int             status;
+       int             deep_flag;
+       int             no_scandir = 0;
+
+#ifdef APPLE_HYB
+       int             x_hfs = 0;
+       int             htype = TYPE_NONE;
+
+#endif /* APPLE_HYB */
+
+       status = stat_filter(whole_path, &statbuf);
+
+       lstatus = lstat_filter(whole_path, &lstatbuf);
+
+       if ((status == -1) && (lstatus == -1)) {
+               /*
+                * This means that the file doesn't exist, or isn't accessible.
+                * Sometimes this is because of NFS permissions problems.
+                */
+#ifdef USE_LIBSCHILY
+               errmsg("Non-existent or inaccessible: %s\n", whole_path);
+#else
+               fprintf(stderr, "Non-existent or inaccessible: %s\n",
+                                                               whole_path);
+#endif
+               return (0);
+       }
+       if (this_dir == root && strcmp(short_name, ".") == 0)
+               root_statbuf = statbuf; /* Save this for later on */
+
+       /* We do this to make sure that the root entries are consistent */
+       if (this_dir == root && strcmp(short_name, "..") == 0) {
+               statbuf = root_statbuf;
+               lstatbuf = root_statbuf;
+       }
+       if (S_ISLNK(lstatbuf.st_mode)) {
+
+               /*
+                * Here we decide how to handle the symbolic links.  Here we
+                * handle the general case - if we are not following links or
+                * there is an error, then we must change something.  If RR
+                * is in use, it is easy, we let RR describe the file.  If
+                * not, then we punt the file.
+                */
+               if ((status || !follow_links)) {
+                       if (use_RockRidge) {
+                               status = 0;
+                               statbuf.st_size = (off_t)0;
+                               STAT_INODE(statbuf) = UNCACHED_INODE;
+                               statbuf.st_dev = (dev_t) UNCACHED_DEVICE;
+                               statbuf.st_mode =
+                                       (statbuf.st_mode & ~S_IFMT) | S_IFREG;
+                       } else {
+                               if (follow_links) {
+#ifdef USE_LIBSCHILY
+                                       /* XXX errno may be wrong! */
+                                       errmsg("Unable to stat file %s - ignoring and continuing.\n",
+                                               whole_path);
+#else
+                                       fprintf(stderr,
+                                               "Unable to stat file %s - ignoring and continuing.\n",
+                                               whole_path);
+#endif
+                               } else {
+#ifdef USE_LIBSCHILY
+                                       errmsgno(EX_BAD,
+                                               "Symlink %s ignored - continuing.\n",
+                                               whole_path);
+#else
+                                       fprintf(stderr,
+                                               "Symlink %s ignored - continuing.\n",
+                                               whole_path);
+#endif
+                                       return (0); /* Non Rock Ridge discs */
+                                                   /* - ignore all symlinks */
+                               }
+                       }
+               }
+               /*
+                * Here we handle a different kind of case.  Here we have a
+                * symlink, but we want to follow symlinks.  If we run across
+                * a directory loop, then we need to pretend that we are not
+                * following symlinks for this file.  If this is the first
+                * time we have seen this, then make this seem as if there was
+                * no symlink there in the first place
+                */
+               if (follow_links &&
+                   S_ISDIR(statbuf.st_mode)) {
+                       if (strcmp(short_name, ".") &&
+                           strcmp(short_name, "..")) {
+                               if (find_directory_hash(statbuf.st_dev,
+                                                       STAT_INODE(statbuf))) {
+                                       if (!use_RockRidge) {
+                                               fprintf(stderr,
+                                               "Already cached directory seen (%s)\n",
+                                                       whole_path);
+                                               return (0);
+                                       }
+                                       lstatbuf = statbuf;
+                                       /*
+                                        * XXX when this line was active,
+                                        * XXX genisoimage did not include all
+                                        * XXX files if it was called with '-f'
+                                        * XXX (follow symlinks).
+                                        * XXX Now scan_directory_tree()
+                                        * XXX checks if the directory has
+                                        * XXX already been scanned via the
+                                        * XXX DIR_WAS_SCANNED flag.
+                                        */
+/*                                     no_scandir = 1;*/
+                               } else {
+                                       lstatbuf = statbuf;
+                                       add_directory_hash(statbuf.st_dev,
+                                                       STAT_INODE(statbuf));
+                               }
+                       }
+               }
+               /*
+                * For non-directories, we just copy the stat information over
+                * so we correctly include this file.
+                */
+               if (follow_links &&
+                   !S_ISDIR(statbuf.st_mode)) {
+                       lstatbuf = statbuf;
+               }
+       }
+       /*
+        * Add directories to the cache so that we don't waste space even if
+        * we are supposed to be following symlinks.
+        */
+       if (follow_links &&
+           strcmp(short_name, ".") &&
+           strcmp(short_name, "..") &&
+           S_ISDIR(statbuf.st_mode)) {
+               add_directory_hash(statbuf.st_dev, STAT_INODE(statbuf));
+       }
+#ifdef VMS
+       if (!S_ISDIR(lstatbuf.st_mode) && (statbuf.st_fab_rfm != FAB$C_FIX &&
+                       statbuf.st_fab_rfm != FAB$C_STMLF)) {
+               fprintf(stderr,
+                       "Warning - file %s has an unsupported VMS record"
+                       " format (%d)\n",
+                       whole_path, statbuf.st_fab_rfm);
+       }
+#endif
+
+       if (S_ISREG(lstatbuf.st_mode) && (status = access(whole_path, R_OK))) {
+#ifdef USE_LIBSCHILY
+               errmsg("File %s is not readable - ignoring\n",
+                       whole_path);
+#else
+               fprintf(stderr,
+                       "File %s is not readable (errno = %d) - ignoring\n",
+                       whole_path, errno);
+#endif
+               return (0);
+       }
+       /* print a warning but don't spam too much */
+       if (S_ISREG(lstatbuf.st_mode) && (lstatbuf.st_size >= (off_t)0xFFFFFFFF)) {
+               static int udf_warned;
+
+               if( !allow_limited_size || verbose>1)
+                       fprintf(stderr, "File %s is larger than 4GiB-1.\n", whole_path);
+               if( !allow_limited_size)
+               {
+                       fprintf(stderr, "-allow-limited-size was not specified. There is no way do represent this file size. Aborting.\n");
+                       exit(1);
+               }
+               if(verbose>=1 && ! udf_warned ) {
+                       udf_warned++;
+                       fprintf(stderr, "This size can only be represented in the UDF filesystem.\n"
+                                       "Make sure that your clients support and use it.\n"
+                                       "ISO9660, Joliet, RockRidge, HFS will display incorrect size.\n");
+               }
+       }
+       /*
+        * Add this so that we can detect directory loops with hard links.
+        * If we are set up to follow symlinks, then we skip this checking.
+        */
+       if (!follow_links &&
+           S_ISDIR(lstatbuf.st_mode) &&
+           strcmp(short_name, ".") &&
+           strcmp(short_name, "..")) {
+               if (find_directory_hash(statbuf.st_dev, STAT_INODE(statbuf))) {
+#ifdef USE_LIBSCHILY
+/*                     comerrno(EX_BAD,*/
+/*                     "Directory loop - fatal goof (%s %lx %lu).\n",*/
+                       errmsgno(EX_BAD,
+                       "Warning: Directory loop (%s dev: %lx ino: %lu).\n",
+                               whole_path, (unsigned long) statbuf.st_dev,
+                               (unsigned long) STAT_INODE(statbuf));
+#else
+/*                     fprintf(stderr,*/
+/*                     "Directory loop - fatal goof (%s %lx %lu).\n",*/
+                       fprintf(stderr,
+                       "Warning: Directory loop (%s dev: %lx ino: %lu).\n",
+                               whole_path, (unsigned long) statbuf.st_dev,
+                               (unsigned long) STAT_INODE(statbuf));
+#endif
+               }
+               add_directory_hash(statbuf.st_dev, STAT_INODE(statbuf));
+       }
+       if (!S_ISCHR(lstatbuf.st_mode) && !S_ISBLK(lstatbuf.st_mode) &&
+               !S_ISFIFO(lstatbuf.st_mode) && !S_ISSOCK(lstatbuf.st_mode) &&
+               !S_ISLNK(lstatbuf.st_mode) && !S_ISREG(lstatbuf.st_mode) &&
+               !S_ISDIR(lstatbuf.st_mode)) {
+               if ( ! (this_dir == root && strcmp(short_name, "..") == 0)) {
+                       fprintf(stderr,
+                       "Unknown file type (%s) %s - ignoring and continuing.\n",
+                               filetype((int) lstatbuf.st_mode), whole_path);
+               }
+               return (0);
+       }
+       /* Who knows what trash this is - ignore and continue */
+
+       if (status) {
+#ifdef USE_LIBSCHILY
+               errmsg("Unable to stat file %s - ignoring and continuing.\n",
+                       whole_path);
+#else
+               fprintf(stderr,
+                       "Unable to stat file %s - ignoring and continuing.\n",
+                       whole_path);
+#endif
+               return (0);
+       }
+       /*
+        * Check to see if we have already seen this directory node. If so,
+        * then we don't create a new entry for it, but we do want to recurse
+        * beneath it and add any new files we do find.
+        */
+       if (S_ISDIR(statbuf.st_mode)) {
+               int     dflag;
+
+               for (s_entry = this_dir->contents; s_entry;
+                                               s_entry = s_entry->next) {
+                       if (strcmp(s_entry->name, short_name) == 0) {
+                               break;
+                       }
+               }
+               if (s_entry != NULL &&
+                   strcmp(short_name, ".") &&
+                   strcmp(short_name, "..")) {
+                       struct directory *child;
+
+                       if ((s_entry->de_flags & RELOCATED_DIRECTORY) != 0) {
+                               for (s_entry = reloc_dir->contents; s_entry;
+                                               s_entry = s_entry->next) {
+                                       if (strcmp(s_entry->name, short_name)
+                                                                       == 0) {
+                                               break;
+                                       }
+                               }
+                               child = find_or_create_directory(reloc_dir,
+                                       whole_path,
+                                       s_entry, 1, NULL);
+                       } else {
+                               child = find_or_create_directory(this_dir,
+                                       whole_path,
+                                       s_entry, 1, NULL);
+                               /*
+                                * If unable to scan directory, mark this as a
+                                * non-directory
+                                */
+                       }
+/*                     if (no_scandir)*/
+                       if (0)
+                               dflag = 1;
+                       else
+                               dflag = scan_directory_tree(child,
+                                                       whole_path, s_entry);
+                       if (!dflag) {
+                               lstatbuf.st_mode =
+                                       (lstatbuf.st_mode & ~S_IFMT) | S_IFREG;
+                       }
+                       return (0);
+               }
+       }
+#ifdef APPLE_HYB
+       /* Should we exclude this HFS file ? - only works with -hfs */
+       if (!have_rsrc && apple_hyb && strcmp(short_name, ".") &&
+                                               strcmp(short_name, "..")) {
+               if ((x_hfs = (hfs_matches(short_name) ||
+                                       hfs_matches(whole_path))) == 1) {
+                       if (verbose > 1) {
+                               fprintf(stderr, "Hidden from HFS tree: %s\n",
+                                                       whole_path);
+                       }
+               }
+       }
+       /*
+        * check we are a file, using Apple extensions and have a .resource
+        * part and not excluded
+        */
+       if (S_ISREG(lstatbuf.st_mode) && !have_rsrc && apple_both && !x_hfs) {
+               char    rsrc_path[PATH_MAX];    /* rsrc fork filename */
+
+               /* construct the resource full path */
+               htype = get_hfs_rname(whole_path, short_name, rsrc_path);
+               /* check we can read the resouce fork */
+               if (htype) {
+                       struct stat     rstatbuf,
+                                       rlstatbuf;
+
+                       /* some further checks on the file */
+                       status = stat_filter(rsrc_path, &rstatbuf);
+
+                       lstatus = lstat_filter(rsrc_path, &rlstatbuf);
+
+/*                     if (!status && !lstatus && S_ISREG(rlstatbuf.st_mode)*/
+/*                                     && rlstatbuf.st_size > (off_t)0) { */
+                       if (!status && !lstatus && S_ISREG(rstatbuf.st_mode) &&
+                                       rstatbuf.st_size > (off_t)0) {
+
+                               /*
+                                * have a resource file - insert it into the
+                                * current directory but flag that we have a
+                                * resource fork
+                                */
+                               insert_file_entry(this_dir, rsrc_path,
+                                                       short_name, htype);
+                       }
+               }
+       }
+#endif /* APPLE_HYB */
+
+       s_entry = (struct directory_entry *)
+               e_malloc(sizeof (struct directory_entry));
+       /* memset the whole struct, not just the isorec.extent part JCP */
+       memset(s_entry, 0, sizeof (struct directory_entry));
+       s_entry->next = this_dir->contents;
+/*     memset(s_entry->isorec.extent, 0, 8); */
+       this_dir->contents = s_entry;
+       deep_flag = 0;
+       s_entry->table = NULL;
+
+       s_entry->name = strdup(short_name);
+       s_entry->whole_name = strdup(whole_path);
+
+       s_entry->de_flags = 0;
+
+       /*
+        * If the current directory is hidden, then hide all it's members
+        * otherwise check if this entry needs to be hidden as well
+        */
+       if (this_dir->dir_flags & INHIBIT_ISO9660_ENTRY) {
+               s_entry->de_flags |= INHIBIT_ISO9660_ENTRY;
+       } else if (strcmp(short_name, ".") != 0 && strcmp(short_name, "..")
+                                                                       != 0) {
+               if (i_matches(short_name) || i_matches(whole_path)) {
+                       if (verbose > 1) {
+                               fprintf(stderr,
+                                       "Hidden from ISO9660 tree: %s\n",
+                                       whole_path);
+                       }
+                       s_entry->de_flags |= INHIBIT_ISO9660_ENTRY;
+               }
+               if (h_matches(short_name) || h_matches(whole_path)) {
+                       if (verbose > 1) {
+                               fprintf(stderr,
+                                       "Hidden ISO9660 attribute: %s\n",
+                                       whole_path);
+                       }
+                       s_entry->de_flags |= HIDDEN_FILE;
+               }
+       }
+       if (this_dir != reloc_dir &&
+                               this_dir->dir_flags & INHIBIT_JOLIET_ENTRY) {
+               s_entry->de_flags |= INHIBIT_JOLIET_ENTRY;
+       } else if (strcmp(short_name, ".") != 0 && strcmp(short_name, "..")
+                                                                       != 0) {
+               if (j_matches(short_name) || j_matches(whole_path)) {
+                       if (verbose > 1) {
+                               fprintf(stderr,
+                                       "Hidden from Joliet tree: %s\n",
+                                       whole_path);
+                       }
+                       s_entry->de_flags |= INHIBIT_JOLIET_ENTRY;
+               }
+       }
+
+#ifdef SORTING
+       /* inherit any sort weight from parent directory */
+       s_entry->sort = this_dir->sort;
+
+#ifdef  DVD_VIDEO
+       /*
+        * No use at all to do a sort if we don't make a dvd video/audio
+        */
+       /*
+        * Assign special weights to VIDEO_TS and AUDIO_TS files.
+        * This can't be done with sort_matches for two reasons:
+        * first, we need to match against the destination (DVD)
+        * path rather than the source path, and second, there are
+        * about 2400 different file names to check, each needing
+        * a different priority, and adding that many patterns to
+        * sort_matches would slow things to a crawl.
+        */
+
+       if (dvd_video) {
+               s_entry->sort = assign_dvd_weights(s_entry->name, this_dir, s_entry->sort);
+               /* turn on sorting if necessary, regardless of cmd-line options */
+               if ((s_entry->sort != this_dir->sort) && do_sort == 0)
+                       do_sort++;
+       }
+#endif
+
+       /* see if this entry should have a new weighting */
+       if (do_sort && strcmp(short_name, ".") != 0 &&
+                       strcmp(short_name, "..") != 0) {
+               s_entry->sort = sort_matches(whole_path, s_entry->sort);
+       }
+#endif /* SORTING */
+
+       s_entry->filedir = this_dir;
+       s_entry->isorec.flags[0] = ISO_FILE;
+       if (s_entry->de_flags & HIDDEN_FILE)
+               s_entry->isorec.flags[0] |= ISO_EXISTENCE;
+       s_entry->isorec.ext_attr_length[0] = 0;
+       iso9660_date(s_entry->isorec.date, statbuf.st_mtime);
+       s_entry->isorec.file_unit_size[0] = 0;
+       s_entry->isorec.interleave[0] = 0;
+
+#ifdef APPLE_HYB
+       if (apple_both && !x_hfs) {
+               s_entry->hfs_ent = NULL;
+               s_entry->assoc = NULL;
+               s_entry->hfs_off = (off_t)0;
+               s_entry->hfs_type = htype;
+               if (have_rsrc) {
+                       /* associated (rsrc) file */
+                       s_entry->isorec.flags[0] |= ISO_ASSOCIATED;
+                       /* set the type of HFS file */
+                       s_entry->hfs_type = have_rsrc;
+                       /*
+                        * don't want the rsrc file to be included in any
+                        * Joliet tree
+                        */
+                       s_entry->de_flags |= INHIBIT_JOLIET_ENTRY;
+               } else if (s_entry->next) {
+                       /*
+                        * if previous entry is an associated file,
+                        * then "link" it to this file i.e. we have a
+                        * data/resource pair
+                        */
+                       if (s_entry->next->isorec.flags[0] & ISO_ASSOCIATED) {
+                               s_entry->assoc = s_entry->next;
+                               /* share the same HFS parameters */
+                               s_entry->hfs_ent = s_entry->next->hfs_ent;
+                               s_entry->hfs_type = s_entry->next->hfs_type;
+                       }
+               }
+               /* allocate HFS entry if required */
+               if (apple_both && strcmp(short_name, ".") &&
+                                               strcmp(short_name, "..")) {
+                       if (!s_entry->hfs_ent) {
+                               hfsdirent       *hfs_ent;
+
+                               hfs_ent =
+                               (hfsdirent *) e_malloc(sizeof (hfsdirent));
+
+                               /* fill in the defaults */
+                               memset(hfs_ent, 0, sizeof (hfsdirent));
+
+                               s_entry->hfs_ent = hfs_ent;
+                       }
+                       /*
+                        * the resource fork is processed first, but the
+                        * data fork's time info is used in preference
+                        * i.e. time info is set from the resource fork
+                        * initially, then it is set from the data fork
+                        */
+                       if (have_rsrc) {
+                               /* set rsrc size */
+                               s_entry->hfs_ent->u.file.rsize = lstatbuf.st_size;
+                               /*
+                                * this will be overwritten - but might as
+                                * well set it here ...
+                                */
+                               s_entry->hfs_ent->crdate = lstatbuf.st_ctime;
+                               s_entry->hfs_ent->mddate = lstatbuf.st_mtime;
+                       } else {
+                               /* set data size */
+                               s_entry->hfs_ent->u.file.dsize = lstatbuf.st_size;
+                               s_entry->hfs_ent->crdate = lstatbuf.st_ctime;
+                               s_entry->hfs_ent->mddate = lstatbuf.st_mtime;
+                       }
+               }
+       }
+#endif /* APPLE_HYB */
+
+       if (strcmp(short_name, ".") == 0) {
+               this_dir->dir_flags |= DIR_HAS_DOT;
+       }
+       if (strcmp(short_name, "..") == 0) {
+               this_dir->dir_flags |= DIR_HAS_DOTDOT;
+       }
+       if (this_dir->parent &&
+           this_dir->parent == reloc_dir &&
+           strcmp(short_name, "..") == 0) {
+               s_entry->inode = UNCACHED_INODE;
+               s_entry->dev = (dev_t) UNCACHED_DEVICE;
+               deep_flag = NEED_PL;
+       } else
+#ifdef APPLE_HYB
+       if (have_rsrc) {
+               /* don't want rsrc files to be cached */
+               s_entry->inode = UNCACHED_INODE;
+               s_entry->dev = (dev_t) UNCACHED_DEVICE;
+       } else
+#endif /* APPLE_HYB */
+       {
+               s_entry->inode = STAT_INODE(statbuf);
+               s_entry->dev = statbuf.st_dev;
+       }
+       set_723(s_entry->isorec.volume_sequence_number,
+                                               volume_sequence_number);
+       iso9660_file_length(short_name, s_entry, S_ISDIR(statbuf.st_mode));
+       s_entry->rr_attr_size = 0;
+       s_entry->total_rr_attr_size = 0;
+       s_entry->rr_attributes = NULL;
+
+       /* Directories are assigned sizes later on */
+       if (!S_ISDIR(statbuf.st_mode)) {
+               if (S_ISCHR(lstatbuf.st_mode) || S_ISBLK(lstatbuf.st_mode) ||
+                       S_ISFIFO(lstatbuf.st_mode) ||
+                               S_ISSOCK(lstatbuf.st_mode) ||
+                               S_ISLNK(lstatbuf.st_mode)) {
+                       s_entry->size = (off_t)0;
+                       statbuf.st_size = (off_t)0;
+               } else {
+                       s_entry->size = statbuf.st_size;
+               }
+
+               set_733((char *) s_entry->isorec.size, statbuf.st_size);
+               s_entry->realsize = statbuf.st_size;
+       } else {
+               s_entry->isorec.flags[0] |= ISO_DIRECTORY;
+       }
+#ifdef APPLE_HYB
+       /* if the directory is HFS excluded, then we don't have an hfs_ent */
+       if (apple_both && s_entry->hfs_ent &&
+                               (s_entry->isorec.flags[0] & ISO_DIRECTORY)) {
+               /* get the Mac directory name */
+               get_hfs_dir(whole_path, short_name, s_entry);
+
+               /* if required, set ISO directory name from HFS name */
+               if (use_mac_name)
+                       iso9660_file_length(s_entry->hfs_ent->name, s_entry, 1);
+       }
+#endif /* APPLE_HYB */
+
+       if (strcmp(short_name, ".") != 0 && strcmp(short_name, "..") != 0 &&
+               S_ISDIR(statbuf.st_mode) &&
+                               this_dir->depth > RR_relocation_depth) {
+               struct directory *child;
+
+               if (!reloc_dir)
+                       generate_reloc_directory();
+
+               /*
+                * Replicate the entry for this directory.  The old one will
+                * stay where it is, and it will be neutered so that it no
+                * longer looks like a directory. The new one will look like
+                * a directory, and it will be put in the reloc_dir.
+                */
+               s_entry1 = (struct directory_entry *)
+                       e_malloc(sizeof (struct directory_entry));
+               memcpy(s_entry1, s_entry, sizeof (struct directory_entry));
+               s_entry1->table = NULL;
+               s_entry1->name = strdup(this_dir->contents->name);
+               s_entry1->whole_name = strdup(this_dir->contents->whole_name);
+               s_entry1->next = reloc_dir->contents;
+               reloc_dir->contents = s_entry1;
+               s_entry1->priority = 32768;
+               s_entry1->parent_rec = this_dir->contents;
+               set_723(s_entry1->isorec.volume_sequence_number,
+                                               volume_sequence_number);
+
+               deep_flag = NEED_RE;
+
+               if (use_XA || use_RockRidge) {
+                       generate_xa_rr_attributes(whole_path,
+                               short_name, s_entry1,
+                               &statbuf, &lstatbuf, deep_flag);
+               }
+               deep_flag = 0;
+
+               /*
+                * We need to set this temporarily so that the parent to this
+                * is correctly determined.
+                */
+               s_entry1->filedir = reloc_dir;
+               child = find_or_create_directory(reloc_dir, whole_path,
+                       s_entry1, 0, NULL);
+/*             if (!no_scandir)*/
+               if (!0)
+                       scan_directory_tree(child, whole_path, s_entry1);
+               s_entry1->filedir = this_dir;
+
+               statbuf.st_size = (off_t)0;
+               statbuf.st_mode &= 0777;
+               set_733((char *) s_entry->isorec.size, 0);
+               s_entry->realsize=0;
+               s_entry->size = 0;
+               s_entry->isorec.flags[0] = ISO_FILE;
+               s_entry->inode = UNCACHED_INODE;
+               s_entry->de_flags |= RELOCATED_DIRECTORY;
+               deep_flag = NEED_CL;
+       }
+       if (generate_tables &&
+           strcmp(s_entry->name, ".") != 0 &&
+           strcmp(s_entry->name, "..") != 0) {
+
+               char    buffer[SECTOR_SIZE];
+               int     nchar;
+
+               switch (lstatbuf.st_mode & S_IFMT) {
+               case S_IFDIR:
+                       sprintf(buffer, "D\t%s\n",
+                               s_entry->name);
+                       break;
+
+/*
+ * extra for WIN32 - if it doesn't have the major/minor defined, then
+ * S_IFBLK and S_IFCHR type files are unlikely to exist anyway ...
+ * code similar to that in rock.c
+ */
+#if 0
+/*
+ * Use the device handling code from <device.h>
+ */
+#ifndef major
+#define        major(dev) (sizeof (dev_t) <= 2 ? ((dev) >> 8) : \
+       (sizeof (dev_t) <= 4 ? (((dev) >> 8) >> 8) : \
+       (((dev) >> 16) >> 16)))
+#define        minor(dev) (sizeof (dev_t) <= 2 ? (dev) & 0xff : \
+       (sizeof (dev_t) <= 4 ? (dev) & 0xffff : \
+       (dev) & 0xffffffff))
+#endif
+#endif
+
+#ifdef S_IFBLK
+               case S_IFBLK:
+                       sprintf(buffer, "B\t%s\t%lu %lu\n",
+                               s_entry->name,
+                               (unsigned long) major(statbuf.st_rdev),
+                               (unsigned long) minor(statbuf.st_rdev));
+                       break;
+#endif
+#ifdef S_IFIFO
+               case S_IFIFO:
+                       sprintf(buffer, "P\t%s\n",
+                               s_entry->name);
+                       break;
+#endif
+#ifdef S_IFCHR
+               case S_IFCHR:
+                       sprintf(buffer, "C\t%s\t%lu %lu\n",
+                               s_entry->name,
+                               (unsigned long) major(statbuf.st_rdev),
+                               (unsigned long) minor(statbuf.st_rdev));
+                       break;
+#endif
+#ifdef S_IFLNK
+               case S_IFLNK:
+#ifdef HAVE_READLINK
+                       nchar = readlink(whole_path,
+                               (char *) symlink_buff,
+                               sizeof (symlink_buff)-1);
+#else
+                       nchar = -1;
+#endif
+                       symlink_buff[nchar < 0 ? 0 : nchar] = 0;
+                       sprintf(buffer, "L\t%s\t%s\n",
+                               s_entry->name, symlink_buff);
+                       break;
+#endif
+#ifdef S_IFSOCK
+               case S_IFSOCK:
+                       sprintf(buffer, "S\t%s\n",
+                               s_entry->name);
+                       break;
+#endif
+               case S_IFREG:
+               default:
+                       sprintf(buffer, "F\t%s\n",
+                               s_entry->name);
+                       break;
+               };
+               s_entry->table = strdup(buffer);
+       }
+       if (S_ISDIR(statbuf.st_mode)) {
+               int     dflag;
+
+               if (strcmp(short_name, ".") != 0 && strcmp(short_name, "..")
+                                                                       != 0) {
+                       struct directory *child;
+
+                       child = find_or_create_directory(this_dir, whole_path,
+                               s_entry, 1, NULL);
+                       if (no_scandir)
+                               dflag = 1;
+                       else
+                               dflag = scan_directory_tree(child, whole_path,
+                                                               s_entry);
+
+                       if (!dflag) {
+                               lstatbuf.st_mode =
+                                       (lstatbuf.st_mode & ~S_IFMT) | S_IFREG;
+                               if (child->contents == NULL) {
+                                       delete_directory(this_dir, child);
+                               }
+                       }
+               }
+               /* If unable to scan directory, mark this as a non-directory */
+       }
+       if (use_RockRidge && this_dir == root && strcmp(s_entry->name, ".")
+                                                                       == 0) {
+               deep_flag |= NEED_CE | NEED_SP; /* For extension record */
+       }
+       /* Now figure out how much room this file will take in the directory */
+
+#ifdef APPLE_HYB
+       /* if the file is HFS excluded, then we don't have an hfs_ent */
+       if (apple_both && !have_rsrc && s_entry->hfs_ent) {
+               if (S_ISREG(lstatbuf.st_mode)) { /* it's a regular file */
+
+                       /* fill in the rest of the HFS entry */
+                       get_hfs_info(whole_path, short_name, s_entry);
+
+                       /* if required, set ISO directory name from HFS name */
+                       if (use_mac_name)
+                               iso9660_file_length(s_entry->hfs_ent->name,
+                                                               s_entry, 0);
+
+                       /* print details about the HFS file */
+                       if (verbose > 2)
+                               print_hfs_info(s_entry);
+
+                       /*
+                        * copy the new ISO9660 name to the rsrc fork
+                        * - if it exists
+                        */
+                       if (s_entry->assoc)
+                               strcpy(s_entry->assoc->isorec.name,
+                                                       s_entry->isorec.name);
+
+                       /*
+                        * we can't handle hard links in the hybrid case, so we
+                        * "uncache" the file. The downside to this is that
+                        * hard linked files are added to the output image
+                        * more than once (we've already done this for rsrc
+                        * files)
+                        */
+                       if (apple_hyb) {
+                               s_entry->inode = UNCACHED_INODE;
+                               s_entry->dev = (dev_t) UNCACHED_DEVICE;
+                       }
+               } else if (!(s_entry->isorec.flags[0] & ISO_DIRECTORY)) {
+                       /* not a directory .. */
+
+                       /*
+                        * no mac equivalent, so ignore - have to be careful
+                        * here, the hfs_ent may be also be for a relocated
+                        * directory
+                        */
+                       if (s_entry->hfs_ent &&
+                               !(s_entry->de_flags & RELOCATED_DIRECTORY))
+                               free(s_entry->hfs_ent);
+                       s_entry->hfs_ent = NULL;
+               }
+               /*
+                * if the rsrc size is zero, then we don't need the entry, so
+                * we might as well delete it - this will only happen if we
+                * didn't know the rsrc size from the rsrc file size
+                */
+               if (s_entry->assoc && s_entry->assoc->size == 0)
+                       delete_rsrc_ent(s_entry);
+       }
+       if (apple_ext && s_entry->assoc) {
+               /* need Apple extensions for the resource fork as well */
+               generate_xa_rr_attributes(whole_path,
+                       short_name, s_entry->assoc,
+                       &statbuf, &lstatbuf, deep_flag);
+       }
+       /* leave out resource fork for the time being */
+       /*
+        * XXX This is most likely wrong and should just be:
+        * XXX if (use_XA || use_RockRidge) {
+        */
+/*     if ((use_XA || use_RockRidge) && !have_rsrc) {*/
+       if (use_XA || use_RockRidge) {
+#else
+       if (use_XA || use_RockRidge) {
+#endif /* APPLE_HYB */
+               generate_xa_rr_attributes(whole_path,
+                       short_name, s_entry,
+                       &statbuf, &lstatbuf, deep_flag);
+
+       }
+       return (1);
+}
+
+
+void
+generate_iso9660_directories(struct directory *node, FILE *outfile)
+{
+       struct directory *dpnt;
+
+       dpnt = node;
+
+       while (dpnt) {
+               if (dpnt->extent > session_start) {
+                       generate_one_directory(dpnt, outfile);
+               }
+               if (dpnt->subdir)
+                       generate_iso9660_directories(dpnt->subdir, outfile);
+               dpnt = dpnt->next;
+       }
+}
+
+/*
+ * Function:   find_or_create_directory
+ *
+ * Purpose:    Locate a directory entry in the tree, create if needed.
+ *             If a directory is created and stat_template is non-null,
+ *             create the directory with ownership, permissions, etc.,
+ *             from stat_template, otherwise use fallback defaults.
+ *
+ * Arguments:  parent & de are never NULL at the same time.
+ */
+struct directory *
+find_or_create_directory(struct directory *parent,
+                        const char *path, 
+                        struct directory_entry *de,
+                        int flag,
+                        struct stat *stat_template)
+{
+       struct directory *dpnt;
+       struct directory_entry *orig_de;
+       struct directory *next_brother;
+       const char      *cpnt;
+       const char      *pnt;
+       struct stat     my_statbuf;
+
+       orig_de = de;
+
+       /*
+        * XXX It seems that the tree that has been read from the
+        * XXX previous session does not carry whole_name entries.
+        * XXX We provide a hack in multi.c:find_or_create_directory()
+        * XXX that should be removed when a reasonable method could
+        * XXX be found.
+        */
+       if (path == NULL) {
+               fprintf(stderr, "Warning: missing whole name for: '%s'\n", de->name);
+               path = de->name;
+       }
+       pnt = strrchr(path, PATH_SEPARATOR);
+       if (pnt == NULL) {
+               pnt = path;
+       } else {
+               pnt++;
+       }
+
+       if (parent != NULL) {
+               dpnt = parent->subdir;
+
+               while (dpnt) {
+                       /*
+                        * Weird hack time - if there are two directories by
+                        * the same name in the reloc_dir, they are not
+                        * treated as the same thing unless the entire path
+                        * matches completely.
+                        */
+                       if (flag && strcmp(dpnt->de_name, pnt) == 0) {
+                               return (dpnt);
+                       }
+                       dpnt = dpnt->next;
+               }
+       }
+       /*
+        * We don't know if we have a valid directory entry for this one yet.
+        * If not, we need to create one.
+        */
+       if (de == NULL) {
+               de = (struct directory_entry *)
+                       e_malloc(sizeof (struct directory_entry));
+               memset(de, 0, sizeof (struct directory_entry));
+               de->next = parent->contents;
+               parent->contents = de;
+               de->name = strdup(pnt);
+               de->whole_name = strdup(path);
+               de->filedir = parent;
+               de->isorec.flags[0] = ISO_DIRECTORY;
+               de->priority = 32768;
+               de->inode = UNCACHED_INODE;
+               de->dev = (dev_t) UNCACHED_DEVICE;
+               set_723(de->isorec.volume_sequence_number,
+                                               volume_sequence_number);
+               iso9660_file_length(pnt, de, 1);
+
+               /*
+                * If we were given a stat template, use it for
+                * ownership/permissions, otherwise use fallback defaults.
+                */
+               init_fstatbuf();
+               if (stat_template) {
+                       my_statbuf = *stat_template;
+               } else {
+                       my_statbuf = fstatbuf; /* defaults */
+                       my_statbuf.st_mode = new_dir_mode;
+               }
+               my_statbuf.st_mode &= ~S_IFMT; /* zero out file type */
+               my_statbuf.st_mode |= S_IFDIR; /* force to be a directory */
+               my_statbuf.st_nlink = 2;
+               
+               /*
+                * Apply attributes from my_statbuf to the new directory.
+                */
+               if (use_XA || use_RockRidge) {
+                       generate_xa_rr_attributes("", (char *) pnt, de,
+                               &my_statbuf, &my_statbuf, 0);
+               }
+               iso9660_date(de->isorec.date, fstatbuf.st_mtime);
+#ifdef APPLE_HYB
+               if (apple_both) {
+                       /* give the directory an HFS entry */
+                       hfsdirent       *hfs_ent;
+
+                       hfs_ent = (hfsdirent *) e_malloc(sizeof (hfsdirent));
+
+                       /* fill in the defaults */
+                       memset(hfs_ent, 0, sizeof (hfsdirent));
+                       hfs_ent->crdate = my_statbuf.st_ctime;
+                       hfs_ent->mddate = my_statbuf.st_mtime;
+
+                       de->hfs_ent = hfs_ent;
+
+                       /* get the Mac directory name */
+                       get_hfs_dir((char *) path, (char *) pnt, de);
+               }
+#endif /* APPLE_HYB */
+       }
+       /*
+        * If we don't have a directory for this one yet, then allocate it now,
+        * and patch it into the tree in the appropriate place.
+        */
+       dpnt = (struct directory *) e_malloc(sizeof (struct directory));
+       memset(dpnt, 0, sizeof (struct directory));
+       dpnt->next = NULL;
+       dpnt->subdir = NULL;
+       dpnt->self = de;
+       dpnt->contents = NULL;
+       dpnt->whole_name = strdup(path);
+       cpnt = strrchr(path, PATH_SEPARATOR);
+       if (cpnt)
+               cpnt++;
+       else
+               cpnt = path;
+       dpnt->de_name = strdup(cpnt);
+       dpnt->size = 0;
+       dpnt->extent = 0;
+       dpnt->jextent = 0;
+       dpnt->jsize = 0;
+#ifdef APPLE_HYB
+       dpnt->hfs_ent = de->hfs_ent;
+#endif /* APPLE_HYB */
+
+       if (orig_de == NULL) {
+               struct stat     xstatbuf;
+               struct stat     parent_statbuf;
+               int             sts;
+
+               /*
+                * Now add a . and .. entry in the directory itself. This is a
+                * little tricky - if the real directory exists, we need to
+                * stat it first. Otherwise, we use the fictitious fstatbuf
+                * which points to the time at which genisoimage was started.
+                */
+               if (parent == NULL || parent->whole_name[0] == '\0')
+                       sts = -1;
+               else
+                       sts = stat_filter(parent->whole_name, &parent_statbuf);
+               
+               if (sts != 0) {
+                       parent_statbuf = fstatbuf;
+                       parent_statbuf.st_mode = new_dir_mode | S_IFDIR;
+                       parent_statbuf.st_nlink = 2;
+               }
+               
+               if (debug && parent) {
+                       fprintf(stderr, "stat parent->whole_name: '%s' -> %d.\n",
+                               parent->whole_name, sts);
+               }
+               attach_dot_entries(dpnt, &my_statbuf, &parent_statbuf);
+       }
+       if (!parent || parent == root) {
+               if (!root) {
+                       root = dpnt;    /* First time through for root  */
+                                       /* directory only               */
+                       root->depth = 0;
+                       root->parent = root;
+               } else {
+                       dpnt->depth = 1;
+                       if (!root->subdir) {
+                               root->subdir = dpnt;
+                       } else {
+                               next_brother = root->subdir;
+                               while (next_brother->next)
+                                       next_brother = next_brother->next;
+                               next_brother->next = dpnt;
+                       }
+                       dpnt->parent = parent;
+               }
+       } else {
+               /* Come through here for  normal traversal of  tree */
+#ifdef DEBUG
+               fprintf(stderr, "%s(%d) ", path, dpnt->depth);
+#endif
+               if (parent->depth > RR_relocation_depth) {
+                       /*
+                        * XXX to prevent this, we would need to add
+                        * XXX support for RR directory relocation
+                        * XXX to find_or_create_directory()
+                        */
+#ifdef USE_LIBSCHILY
+                       comerrno(EX_BAD,
+                       "Directories too deep for '%s' (%d) max is %d.\n",
+                               path, parent->depth, RR_relocation_depth);
+#else
+                       fprintf(stderr,
+                       "Directories too deep for '%s' (%d) max is %d.\n",
+                               path, parent->depth, RR_relocation_depth);
+                       exit(1);
+#endif
+               }
+               dpnt->parent = parent;
+               dpnt->depth = parent->depth + 1;
+
+               if (!parent->subdir) {
+                       parent->subdir = dpnt;
+               } else {
+                       next_brother = parent->subdir;
+                       while (next_brother->next)
+                               next_brother = next_brother->next;
+                       next_brother->next = dpnt;
+               }
+       }
+
+       return (dpnt);
+}
+
+/*
+ * Function:   delete_directory
+ *
+ * Purpose:    Locate a directory entry in the tree, create if needed.
+ *
+ * Arguments:
+ */
+static void
+delete_directory(parent, child)
+       struct directory        *parent;
+       struct directory        *child;
+{
+       struct directory *tdir;
+
+       if (child->contents != NULL) {
+#ifdef USE_LIBSCHILY
+               comerrno(EX_BAD, "Unable to delete non-empty directory\n");
+#else
+               fprintf(stderr, "Unable to delete non-empty directory\n");
+               exit(1);
+#endif
+       }
+       free(child->whole_name);
+       child->whole_name = NULL;
+
+       free(child->de_name);
+       child->de_name = NULL;
+
+#ifdef APPLE_HYB
+       if (apple_both && child->hfs_ent)
+               free(child->hfs_ent);
+#endif /* APPLE_HYB */
+
+       if (parent->subdir == child) {
+               parent->subdir = child->next;
+       } else {
+               for (tdir = parent->subdir; tdir->next != NULL;
+                                                       tdir = tdir->next) {
+                       if (tdir->next == child) {
+                               tdir->next = child->next;
+                               break;
+                       }
+               }
+               if (tdir == NULL) {
+#ifdef USE_LIBSCHILY
+                       comerrno(EX_BAD,
+                       "Unable to locate child directory in parent list\n");
+#else
+                       fprintf(stderr,
+                       "Unable to locate child directory in parent list\n");
+                       exit(1);
+#endif
+               }
+       }
+       free(child);
+}
+
+int
+sort_tree(struct directory *node)
+{
+       struct directory *dpnt;
+       int             ret = 0;
+
+       dpnt = node;
+
+       while (dpnt) {
+               ret = sort_n_finish(dpnt);
+               if (ret) {
+                       break;
+               }
+               if (dpnt->subdir)
+                       sort_tree(dpnt->subdir);
+               dpnt = dpnt->next;
+       }
+       return (ret);
+}
+
+void
+dump_tree(struct directory *node)
+{
+       struct directory *dpnt;
+
+       dpnt = node;
+
+       while (dpnt) {
+               fprintf(stderr, "%4d %5d %s\n",
+                               dpnt->extent, dpnt->size, dpnt->de_name);
+               if (dpnt->subdir)
+                       dump_tree(dpnt->subdir);
+               dpnt = dpnt->next;
+       }
+}
+
+void
+update_nlink_field(struct directory *node)
+{
+       struct directory *dpnt;
+       struct directory *xpnt;
+       struct directory_entry *s_entry;
+       int             i;
+
+       dpnt = node;
+
+       while (dpnt) {
+               if (dpnt->dir_flags & INHIBIT_ISO9660_ENTRY) {
+                       dpnt = dpnt->next;
+                       continue;
+               }
+               /*
+                * First, count up the number of subdirectories this guy has.
+                */
+               for (i = 0, xpnt = dpnt->subdir; xpnt; xpnt = xpnt->next)
+                       if ((xpnt->dir_flags & INHIBIT_ISO9660_ENTRY) == 0)
+                               i++;
+               /*
+                * Next check to see if we have any relocated directories in
+                * this directory. The nlink field will include these as
+                * real directories when they are properly relocated.
+                * In the non-rockridge disk, the relocated entries appear as
+                * zero length files.
+                */
+               for (s_entry = dpnt->contents; s_entry;
+                                               s_entry = s_entry->next) {
+                       if ((s_entry->de_flags & RELOCATED_DIRECTORY) != 0 &&
+                               (s_entry->de_flags & INHIBIT_ISO9660_ENTRY) ==
+                                                                       0) {
+                               i++;
+                       }
+               }
+               /* Now update the field in the Rock Ridge entry. */
+               update_nlink(dpnt->self, i + 2);
+
+               /* Update the '.' entry for this directory. */
+               update_nlink(dpnt->contents, i + 2);
+
+               /* Update all of the '..' entries that point to this guy. */
+               for (xpnt = dpnt->subdir; xpnt; xpnt = xpnt->next)
+                       update_nlink(xpnt->contents->next, i + 2);
+
+               if (dpnt->subdir)
+                       update_nlink_field(dpnt->subdir);
+               dpnt = dpnt->next;
+       }
+}
+
+/*
+ * something quick and dirty to locate a file given a path
+ * recursively walks down path in filename until it finds the
+ * directory entry for the desired file
+ */
+struct directory_entry *
+search_tree_file(struct directory *node, char *filename)
+{
+       struct directory_entry *depnt;
+       struct directory *dpnt;
+       char            *p1;
+       char            *rest;
+       char            *subdir;
+
+       /* strip off next directory name from filename */
+       subdir = strdup(filename);
+
+       if ((p1 = strchr(subdir, '/')) == subdir) {
+               fprintf(stderr,
+               "call to search_tree_file with an absolute path, stripping\n");
+               fprintf(stderr,
+               "initial path separator. Hope this was intended...\n");
+               memmove(subdir, subdir + 1, strlen(subdir) - 1);
+               p1 = strchr(subdir, '/');
+       }
+       /* do we need to find a subdirectory */
+       if (p1) {
+               *p1 = '\0';
+
+#ifdef DEBUG_TORITO
+               fprintf(stderr, "Looking for subdir called %s\n", p1);
+#endif
+
+               rest = p1 + 1;
+
+#ifdef DEBUG_TORITO
+               fprintf(stderr, "Remainder of path name is now %s\n", rest);
+#endif
+
+               dpnt = node->subdir;
+               while (dpnt) {
+#ifdef DEBUG_TORITO
+                       fprintf(stderr,
+                               "%4d %5d %s\n", dpnt->extent, dpnt->size,
+                               dpnt->de_name);
+#endif
+                       if (strcmp(subdir, dpnt->de_name) == 0) {
+#ifdef DEBUG_TORITO
+                               fprintf(stderr,
+                               "Calling next level with filename = %s", rest);
+#endif
+                               return (search_tree_file(dpnt, rest));
+                       }
+                       dpnt = dpnt->next;
+               }
+
+               /* if we got here means we couldnt find the subdir */
+               return (NULL);
+       } else {
+               /* look for a normal file now */
+               depnt = node->contents;
+               while (depnt) {
+#ifdef DEBUG_TORITO
+                       fprintf(stderr, "%4d %5d %s\n", depnt->isorec.extent,
+                               depnt->size, depnt->name);
+#endif
+                       if (strcmp(filename, depnt->name) == 0) {
+#ifdef DEBUG_TORITO
+                               fprintf(stderr, "Found our file %s", filename);
+#endif
+                               return (depnt);
+                       }
+                       depnt = depnt->next;
+               }
+               /* if we got here means we couldnt find the subdir */
+               return (NULL);
+       }
+#ifdef ERIC_FUN
+       fprintf(stderr, "We cant get here in search_tree_file :-/ \n");
+#endif
+}
+
+void
+init_fstatbuf()
+{
+       time_t  current_time;
+
+       if (fstatbuf.st_ctime == 0) {
+               time(&current_time);
+               if (rationalize_uid)
+                       fstatbuf.st_uid = uid_to_use;
+               else
+                       fstatbuf.st_uid = getuid();
+               if (rationalize_gid)
+                       fstatbuf.st_gid = gid_to_use;
+               else
+                       fstatbuf.st_gid = getgid();
+               fstatbuf.st_ctime = current_time;
+               fstatbuf.st_mtime = current_time;
+               fstatbuf.st_atime = current_time;
+       }
+}
diff --git a/genisoimage/udf.c b/genisoimage/udf.c
new file mode 100644 (file)
index 0000000..c63d372
--- /dev/null
@@ -0,0 +1,1213 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)udf.c   1.14 04/04/15 Copyright 2001 J. Schilling */
+/*
+ * udf.c - UDF support for genisoimage
+ *
+ * Written by Ben Rudiak-Gould (2001).
+ *
+ * Copyright 2001 J. Schilling.
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * Some remaining issues:
+ *
+ * - Do not forget to edit joliet.c and remove the VIDEO_TS lines after
+ *   we did implement a decent own file name handling for UDF.
+ *
+ * - UDF supports UNIX-style file permissions and uid/gid, but currently
+ *   this code just sets them to default values and ignores their Rock
+ *   Ridge counterparts. This would be easy to fix.
+ *
+ * - There's no support for symlinks, Mac type/creator, or Mac resource
+ *   forks. Hard links and followed symlinks may work, but if so, it's
+ *   only by accident.
+ *
+ * - The file system mirrors the Joliet file system, so files excluded
+ *   from Joliet will also be excluded from UDF, the -jcharset option
+ *   also applies to UDF, file names too long for Joliet will also be
+ *   truncated on UDF, and characters not allowed by Joliet will also
+ *   be translated on UDF. (Fortunately, Joliet is pretty lenient.)
+ *
+ * - convert_to_unicode is always called with in_nls, not hfs_nls. This
+ *   may lead to incorrect name conversion sometimes when using a Mac
+ *   filesystem. See joliet.c for an example of what's supposed to be
+ *   done.
+ *
+ * - DVD-Video discs are supposed to have Copyright Management Information
+ *   in both the ISO and UDF filesystems. This is not implemented in ISO,
+ *   and the code to do it in UDF is currently #ifdef'd out. I'm not sure
+ *   whether discs without this information are actually DVD-Video
+ *   compliant. The Copyright Management Information is described in ECMA
+ *   Technical Report TR/71.
+ *
+ * - Most of the space before sector 256 on the disc (~480K) is wasted,
+ *   because UDF Bridge requires a pointer block at sector 256. ISO 9660
+ *   structures could be moved below sector 256 if they're small enough, but
+ *   this would be ugly to implement since it breaks the output_fragment
+ *   abstraction.
+ *
+ * - Each file must have a File Entry, and each File Entry seems to
+ *   require its own 2K sector. As a result, there is an overhead of more
+ *   than 2K *per file* when using UDF. I couldn't see any way to avoid
+ *   this.
+ *
+ * - Read performance would probably be improved by placing the File Entry
+ *   for each file just before the file itself, instead of at the beginning
+ *   of the disc. But this would not work for DVD-Video files, which have
+ *   to be stored contiguously. So there would have to be an override
+ *   mechanism to handle this case. I don't know if it's worth the trouble.
+ */
+
+#ifdef UDF
+
+#include "config.h"
+#include "genisoimage.h"
+#include <timedefs.h>
+#include <schily.h>
+
+#include "udf.h"
+#include "udf_fs.h"
+
+extern int     use_sparcboot;
+
+extern struct directory *root;
+extern time_t          begun;
+
+static unsigned lba_main_seq;
+static unsigned lba_main_seq_copy;
+static unsigned lba_integ_seq;
+static unsigned lba_udf_partition_start;
+static unsigned lba_last_file_entry;
+static unsigned lba_end_anchor_vol_desc;
+
+static unsigned num_udf_files;
+static unsigned num_udf_directories;
+
+static unsigned volume_set_id[2];
+
+#define        UDF_MAIN_SEQ_LENGTH (16)
+#define        UDF_INTEG_SEQ_LENGTH (2)
+
+/* only works for granularity a power of 2! */
+#define        PAD(val, granularity)   (((val)+(granularity)-1)&~((granularity)-1))
+
+#define        read_733(field) ((0[field]&255)+(1[field]&255)*256+(2[field]&255)*65536+(3[field]&255)*16777216)
+
+
+/**************** SIZE ****************/
+
+static int set_file_ident_desc(unsigned char *, unsigned, char *, int, 
+                                                                                unsigned, unsigned);
+
+static unsigned
+directory_size(struct directory *dpnt)
+{
+       unsigned size_in_bytes;
+       struct directory_entry *de;
+       Uchar dummy_buf[SECTOR_SIZE];
+
+       /* parent directory */
+       size_in_bytes = set_file_ident_desc(dummy_buf, 0, 0, 0, 0, 0);
+
+       /* directory contents */
+       for (de = dpnt->jcontents; de; de = de->jnext) {
+               if (!(de->de_flags & INHIBIT_JOLIET_ENTRY)) {
+                       char *name = USE_MAC_NAME(de) ? de->hfs_ent->name : de->name;
+                       /* skip . and .. */
+                       if (name[0] == '.' && (name[1] == 0 || (name[1] == '.' && name[2] == 0)))
+                               continue;
+                       size_in_bytes += set_file_ident_desc(dummy_buf, 0, name, 0, 0, 0);
+               }
+       }
+       return (size_in_bytes);
+}
+
+static void
+assign_udf_directory_addresses(struct directory *dpnt)
+{
+       if (!(dpnt->dir_flags & INHIBIT_JOLIET_ENTRY)) {
+               dpnt->self->udf_file_entry_sector = last_extent;
+               last_extent += 1 + ISO_BLOCKS(directory_size(dpnt));
+               ++num_udf_directories;
+       }
+       if (!(dpnt->dir_flags & INHIBIT_JOLIET_ENTRY) || dpnt == reloc_dir) {
+               for (dpnt = dpnt->subdir; dpnt; dpnt = dpnt->next) {
+                       assign_udf_directory_addresses(dpnt);
+               }
+       }
+}
+
+static void
+assign_udf_file_entry_addresses(struct directory *dpnt)
+{
+       if (!(dpnt->dir_flags & INHIBIT_JOLIET_ENTRY)) {
+               struct directory_entry *de;
+               for (de = dpnt->jcontents; de; de = de->jnext) {
+                       if (!(de->de_flags & RELOCATED_DIRECTORY) &&
+                           !(de->isorec.flags[0] & ISO_DIRECTORY)) {
+                               de->udf_file_entry_sector = last_extent++;
+                               ++num_udf_files;
+                       }
+               }
+       }
+       if (!(dpnt->dir_flags & INHIBIT_JOLIET_ENTRY) || dpnt == reloc_dir) {
+               for (dpnt = dpnt->subdir; dpnt; dpnt = dpnt->next) {
+                       assign_udf_file_entry_addresses(dpnt);
+               }
+       }
+}
+
+/****************************/
+
+static int
+udf_vol_recognition_area_size(int starting_extent)
+{
+       last_extent = starting_extent+3;
+       return (0);
+}
+
+static int
+udf_main_seq_size(int starting_extent)
+{
+       lba_main_seq = starting_extent;
+       last_extent = starting_extent + UDF_MAIN_SEQ_LENGTH;
+       return (0);
+}
+
+static int
+udf_main_seq_copy_size(int starting_extent)
+{
+       lba_main_seq_copy = starting_extent;
+       last_extent = starting_extent + UDF_MAIN_SEQ_LENGTH;
+       return (0);
+}
+
+static int
+udf_integ_seq_size(int starting_extent)
+{
+       lba_integ_seq = starting_extent;
+       last_extent = starting_extent + UDF_INTEG_SEQ_LENGTH;
+       return (0);
+}
+
+static int
+udf_end_anchor_vol_desc_size(int starting_extent)
+{
+       lba_end_anchor_vol_desc = starting_extent;
+       last_extent = starting_extent+1;
+       return (0);
+}
+
+static int
+udf_file_set_desc_size(int starting_extent)
+{
+       lba_udf_partition_start = starting_extent;
+       last_extent = starting_extent+2;
+       return (0);
+}
+
+static int
+udf_dirtree_size(int starting_extent)
+{
+       num_udf_directories = 0;
+       assign_udf_directory_addresses(root);
+       return (0);
+}
+
+static int
+udf_file_entries_size(int starting_extent)
+{
+       num_udf_files = 0;
+       assign_udf_file_entry_addresses(root);
+       lba_last_file_entry = last_extent-1;
+       return (0);
+}
+
+static int
+udf_pad_to_sector_32_size(int starting_extent)
+{
+       if (last_extent < session_start+32)
+               last_extent = session_start+32;
+       return (0);
+}
+
+static int
+udf_pad_to_sector_256_size(int starting_extent)
+{
+       if (last_extent < session_start+256)
+               last_extent = session_start+256;
+       return (0);
+}
+
+static int
+udf_padend_avdp_size(int starting_extent)
+{
+       lba_end_anchor_vol_desc = starting_extent;
+
+       /* add at least 16 and at most 31 sectors, ending at a mult. of 16 */
+       last_extent = (starting_extent+31) & ~15;
+       if (!use_sparcboot)
+               last_extent = starting_extent + 150;
+       return (0);
+}
+
+extern int oneblock_size(int);
+
+/**************** WRITE ****************/
+
+static unsigned
+crc_ccitt(unsigned char *buf, unsigned len)
+{
+       const unsigned poly = 0x11021;
+       static unsigned short lookup[256];
+       unsigned int r;
+       unsigned int i;
+
+       if (lookup[1] == 0) {
+               unsigned int j, k;
+               for (j = 0; j < 256; ++j) {
+                       unsigned int temp = j << 8;
+                       for (k = 0; k < 8; ++k) {
+                               unsigned int hibit = temp & 32768;
+                               temp <<= 1;
+                               if (hibit)
+                                       temp ^= poly;
+                       }
+                       lookup[j] = temp;
+               }
+       }
+
+       r = 0;
+       for (i = 0; i < len; ++i) {
+               r = (r << 8) ^ lookup[((r >> 8) ^ buf[i]) & 255];
+       }
+
+       return (r & 65535);
+}
+
+#define        set8(dst, src)  do { *(dst) = (src); } while (0)
+
+static void
+set16(udf_Uint16 *dst, unsigned int src)
+{
+       dst->l = (char)(src);
+       dst->h = (char)(src>>8);
+}
+
+static void
+set32(udf_Uint32 *dst, unsigned src)
+{
+       dst->l  = (char)(src);
+       dst->ml = (char)(src>>8);
+       dst->mh = (char)(src>>16);
+       dst->h  = (char)(src>>24);
+}
+
+static void
+set64(udf_Uint64 *dst, uint64_t src)
+{
+       set32(&dst->l, src);
+       set32(&dst->h, src>>32);
+}
+
+static int
+set_ostaunicode(unsigned char *dst, int dst_size, char *src)
+{
+       unsigned char buf[1024];
+       int i;
+       int expanded_length;
+
+       expanded_length = joliet_strlen(src, in_nls);
+       if (expanded_length > 1024)
+               expanded_length = 1024;
+       if (expanded_length > (dst_size-1)*2)
+               expanded_length = (dst_size-1)*2;
+
+       convert_to_unicode(buf, expanded_length, src, in_nls);
+       dst[0] = 8;     /* use 8-bit representation by default */
+       for (i = 0; i < (expanded_length>>1); ++i) {
+               dst[i + 1] = buf[i*2+1];
+               if (buf[i*2] != 0) {
+                       /*
+                        * There's a Unicode character with value >=256.
+                        * Use 16-bit representation instead.
+                        */
+                       int length_to_copy = (dst_size-1) & ~1;
+                       if (length_to_copy > expanded_length)
+                               length_to_copy = expanded_length;
+                       dst[0] = 16;
+                       memcpy(dst+1, buf, length_to_copy);
+                       return (length_to_copy + 1);
+               }
+       }
+       return ((expanded_length>>1) + 1);
+}
+
+static void
+set_extent(udf_extent_ad *ext, unsigned lba, unsigned length_bytes)
+{
+       set32(&ext->extent_length, length_bytes);
+       set32(&ext->extent_location, lba);
+}
+
+static void
+set_dstring(udf_dstring *dst, char *src, int n)
+{
+       dst[n-1] = set_ostaunicode((Uchar *)dst, n-1, src);
+}
+
+static void
+set_charspec(udf_charspec *dst)
+{
+       /*set8(&dst->character_set_type, 0);*/
+       memcpy(dst->character_set_info, "OSTA Compressed Unicode", 23);
+}
+
+static void
+set_impl_ident(udf_EntityID *ent)
+{
+       strcpy((char *)ent->ident, "*genisoimage");
+}
+
+static void
+set_tag(udf_tag *t, unsigned tid, unsigned lba, int crc_length)
+{
+       unsigned char checksum;
+       int i;
+
+       set16(&t->tag_ident, tid);
+       set16(&t->desc_version, 2);
+       set16(&t->desc_crc, crc_ccitt((unsigned char *)t+16, crc_length-16));
+       set16(&t->desc_crc_length, crc_length-16);
+       set32(&t->tag_location, lba);
+       set8(&t->tag_checksum, 0);
+       checksum = 0;
+       for (i = 0; i < 16; ++i)
+               checksum += ((unsigned char *)t)[i];
+       set8(&t->tag_checksum, checksum);
+}
+
+static void
+set_timestamp_from_iso_date(udf_timestamp *ts, const char *iso_date_raw)
+{
+       struct {
+               unsigned char years_since_1900;
+               unsigned char month, day;
+               unsigned char hour, minute, second;
+               signed char offset_from_gmt;
+       } *iso_date = (void *)iso_date_raw;
+
+       set16(&ts->type_and_time_zone,
+               4096 + ((iso_date->offset_from_gmt * 15) & 4095));
+       set16(&ts->year, 1900 + iso_date->years_since_1900);
+       set8(&ts->month, iso_date->month);
+       set8(&ts->day, iso_date->day);
+       set8(&ts->hour, iso_date->hour);
+       set8(&ts->minute, iso_date->minute);
+       set8(&ts->second, iso_date->second);
+       /*set8(&ts->centiseconds, 0);*/
+       /*set8(&ts->hundreds_of_microseconds, 0);*/
+       /*set8(&ts->microseconds, 0);*/
+}
+
+static void
+set_timestamp_from_time_t(udf_timestamp *ts, time_t t)
+{
+       char iso_date[7];
+       iso9660_date(iso_date, t);
+       set_timestamp_from_iso_date(ts, iso_date);
+}
+
+
+static void
+set_anchor_volume_desc_pointer(unsigned char *buf, unsigned lba)
+{
+       udf_anchor_volume_desc_ptr *avdp = (udf_anchor_volume_desc_ptr *)buf;
+       set_extent(&avdp->main_volume_desc_seq_extent,
+               lba_main_seq, SECTOR_SIZE*UDF_MAIN_SEQ_LENGTH);
+       set_extent(&avdp->reserve_volume_desc_seq_extent,
+               lba_main_seq_copy, SECTOR_SIZE*UDF_MAIN_SEQ_LENGTH);
+       set_tag(&avdp->desc_tag, UDF_TAGID_ANCHOR_VOLUME_DESC_PTR, lba, 512);
+}
+
+static void
+set_primary_vol_desc(unsigned char *buf, unsigned lba)
+{
+       char temp[17];
+
+       udf_primary_volume_desc *pvd = (udf_primary_volume_desc *)buf;
+       /*set32(&pvd->volume_desc_seq_number, 0);*/
+       /*set32(&pvd->primary_volume_desc_number, 0);*/
+       set_dstring(pvd->volume_ident, volume_id, sizeof (pvd->volume_ident));
+       set16(&pvd->volume_seq_number, 1);
+       set16(&pvd->maximum_volume_seq_number, 1);
+       set16(&pvd->interchange_level, 2);
+       set16(&pvd->maximum_interchange_level, 2);
+       set32(&pvd->character_set_list, 1);
+       set32(&pvd->maximum_character_set_list, 1);
+       sprintf(temp, "%08X%08X", volume_set_id[0], volume_set_id[1]);
+       set_dstring(pvd->volume_set_ident, temp,
+                                       sizeof (pvd->volume_set_ident));
+       set_charspec(&pvd->desc_character_set);
+       set_charspec(&pvd->explanatory_character_set);
+       /*pvd->volume_abstract;*/
+       /*pvd->volume_copyright_notice;*/
+       /*pvd->application_ident;*/
+       set_timestamp_from_time_t(&pvd->recording_date_and_time, begun);
+       set_impl_ident(&pvd->impl_ident);
+       set_tag(&pvd->desc_tag, UDF_TAGID_PRIMARY_VOLUME_DESC, lba, 512);
+}
+
+static void
+set_impl_use_vol_desc(unsigned char *buf, unsigned lba)
+{
+       udf_impl_use_volume_desc *iuvd = (udf_impl_use_volume_desc *)buf;
+       set32(&iuvd->volume_desc_seq_number, 1);
+       strcpy((char *)iuvd->impl_ident.ident, "*UDF LV Info");
+       iuvd->impl_ident.ident_suffix[0] = 2;
+       iuvd->impl_ident.ident_suffix[1] = 1;
+       set_charspec(&iuvd->impl_use.lvi_charset);
+       set_dstring(iuvd->impl_use.logical_volume_ident, volume_id,
+               sizeof (iuvd->impl_use.logical_volume_ident));
+       /*set_dstring(iuvd->impl_use.lv_info1, "", sizeof (iuvd->impl_use.lv_info1));*/
+       /*set_dstring(iuvd->impl_use.lv_info2, "", sizeof (iuvd->impl_use.lv_info2));*/
+       /*set_dstring(iuvd->impl_use.lv_info3, "", sizeof (iuvd->impl_use.lv_info3));*/
+       set_impl_ident(&iuvd->impl_use.impl_id);
+       set_tag(&iuvd->desc_tag, UDF_TAGID_IMPL_USE_VOLUME_DESC, lba, 512);
+}
+
+static void
+set_partition_desc(unsigned char *buf, unsigned lba)
+{
+       udf_partition_desc *pd = (udf_partition_desc *)buf;
+       set32(&pd->volume_desc_seq_number, 2);
+       set16(&pd->partition_flags, UDF_PARTITION_FLAG_ALLOCATED);
+       /*set16(&pd->partition_number, 0);*/
+       set8(&pd->partition_contents.flags, UDF_ENTITYID_FLAG_PROTECTED);       /*???*/
+       strcpy((char *)pd->partition_contents.ident, "+NSR02");
+       set32(&pd->access_type, UDF_ACCESSTYPE_READONLY);
+       set32(&pd->partition_starting_location, lba_udf_partition_start);
+       set32(&pd->partition_length,
+                       lba_end_anchor_vol_desc - lba_udf_partition_start);
+       set_impl_ident(&pd->impl_ident);
+       set_tag(&pd->desc_tag, UDF_TAGID_PARTITION_DESC, lba, 512);
+}
+
+static void
+set_domain_ident(udf_EntityID *ent)
+{
+       strcpy((char *)ent->ident, "*OSTA UDF Compliant");
+       memcpy(ent->ident_suffix, "\002\001\003", 3);
+}
+
+static void
+set_logical_vol_desc(unsigned char *buf, unsigned lba)
+{
+       udf_logical_volume_desc *lvd = (udf_logical_volume_desc *)buf;
+       set32(&lvd->volume_desc_seq_number, 3);
+       set_charspec(&lvd->desc_character_set);
+       set_dstring(lvd->logical_volume_ident, volume_id,
+                                       sizeof (lvd->logical_volume_ident));
+       set32(&lvd->logical_block_size, SECTOR_SIZE);
+       set_domain_ident(&lvd->domain_ident);
+       set32(&lvd->logical_volume_contents_use.extent_length, 2*SECTOR_SIZE);
+       /*set32(&lvd->logical_volume_contents_use.extent_location.logical_block_number, 0);*/
+       /*set16(&lvd->logical_volume_contents_use.extent_location.partition_reference_number, 0);*/
+       set32(&lvd->map_table_length, 6);
+       set32(&lvd->number_of_partition_maps, 1);
+       set_impl_ident(&lvd->impl_ident);
+       set_extent(&lvd->integrity_seq_extent, lba_integ_seq,
+                                       SECTOR_SIZE*UDF_INTEG_SEQ_LENGTH);
+       set8(&lvd->partition_map[0].partition_map_type,
+                                       UDF_PARTITION_MAP_TYPE_1);
+       set8(&lvd->partition_map[0].partition_map_length, 6);
+       set16(&lvd->partition_map[0].volume_seq_number, 1);
+       /*set16(&lvd->partition_map[0].partition_number, 0);*/
+       set_tag(&lvd->desc_tag, UDF_TAGID_LOGICAL_VOLUME_DESC, lba, 446);
+}
+
+static void
+set_unallocated_space_desc(unsigned char *buf, unsigned lba)
+{
+       udf_unallocated_space_desc *usd = (udf_unallocated_space_desc *)buf;
+       set32(&usd->volume_desc_seq_number, 4);
+       /*set32(&usd->number_of_allocation_descs, 0);*/
+       set_tag(&usd->desc_tag, UDF_TAGID_UNALLOCATED_SPACE_DESC, lba, 24);
+}
+
+static void
+set_terminating_desc(unsigned char *buf, unsigned lba)
+{
+       udf_terminating_desc *td = (udf_terminating_desc *)buf;
+       set_tag(&td->desc_tag, UDF_TAGID_TERMINATING_DESC, lba, 512);
+}
+
+static void
+set_logical_vol_integrity_desc(unsigned char *buf, unsigned lba)
+{
+       udf_logical_volume_integrity_desc *lvid =
+                               (udf_logical_volume_integrity_desc *)buf;
+
+       set_timestamp_from_time_t(&lvid->recording_date, begun);
+       set32(&lvid->integrity_type, UDF_INTEGRITY_TYPE_CLOSE);
+       /*lvid->next_integrity_extent;*/
+       set64(&lvid->logical_volume_contents_use.unique_id,
+                                               lba_last_file_entry+1);
+       set32(&lvid->number_of_partitions, 1);
+       set32(&lvid->length_of_impl_use, 46);
+       /*set32(&lvid->free_space_table, 0);*/
+       set32(&lvid->size_table,
+                       lba_end_anchor_vol_desc - lba_udf_partition_start);
+       set_impl_ident(&lvid->impl_use.impl_id);
+       set32(&lvid->impl_use.number_of_files, num_udf_files);
+       set32(&lvid->impl_use.number_of_directories, num_udf_directories);
+       set16(&lvid->impl_use.minimum_udf_read_revision, 0x102);
+       set16(&lvid->impl_use.minimum_udf_write_revision, 0x102);
+       set16(&lvid->impl_use.maximum_udf_write_revision, 0x102);
+       set_tag(&lvid->desc_tag, UDF_TAGID_LOGICAL_VOLUME_INTEGRITY_DESC,
+                                                               lba, 88+46);
+}
+
+static void
+set_file_set_desc(unsigned char *buf, unsigned rba)
+{
+       udf_file_set_desc *fsd = (udf_file_set_desc *)buf;
+
+       set_timestamp_from_time_t(&fsd->recording_date_and_time, begun);
+       set16(&fsd->interchange_level, 3);
+       set16(&fsd->maximum_interchange_level, 3);
+       set32(&fsd->character_set_list, 1);
+       set32(&fsd->maximum_character_set_list, 1);
+       /*set32(&fsd->file_set_number, 0);*/
+       /*set32(&fsd->file_set_desc_number, 0);*/
+       set_charspec(&fsd->logical_volume_ident_character_set);
+       set_dstring(fsd->logical_volume_ident, volume_id,
+                                       sizeof (fsd->logical_volume_ident));
+       set_charspec(&fsd->file_set_character_set);
+       set_dstring(fsd->file_set_ident, volume_id,
+                                       sizeof (fsd->file_set_ident));
+       /*fsd->copyright_file_ident;*/
+       /*fsd->abstract_file_ident;*/
+       set32(&fsd->root_directory_icb.extent_length, SECTOR_SIZE);
+       set32(&fsd->root_directory_icb.extent_location.logical_block_number,
+               root->self->udf_file_entry_sector - lba_udf_partition_start);
+       set_domain_ident(&fsd->domain_ident);
+       /*fsd->next_extent;*/
+       set_tag(&fsd->desc_tag, UDF_TAGID_FILE_SET_DESC, rba, 512);
+}
+
+static int
+set_file_ident_desc(unsigned char *buf, unsigned rba, char *name, 
+                                                 int is_directory, unsigned file_entry_rba, 
+                                                 unsigned unique_id)
+{
+       udf_file_ident_desc *fid = (udf_file_ident_desc *)buf;
+       int length_of_file_ident, length, padded_length;
+       set16(&fid->file_version_number, 1);
+       set8(&fid->file_characteristics,
+               (is_directory ? UDF_FILE_CHARACTERISTIC_DIRECTORY : 0)
+               + (name == 0) * UDF_FILE_CHARACTERISTIC_PARENT);
+       set32(&fid->icb.extent_length, SECTOR_SIZE);
+       set32(&fid->icb.extent_location.logical_block_number, file_entry_rba);
+       set16(&fid->icb.extent_location.partition_reference_number, 0);
+       set32(&fid->icb.impl_use.unique_id, unique_id);
+       set16(&fid->length_of_impl_use, 0);
+       if (name) {
+               length_of_file_ident =
+                       set_ostaunicode((Uchar *)fid->file_ident, 512, name);
+       } else {
+               length_of_file_ident = 0;
+       }
+       set8(&fid->length_of_file_ident, length_of_file_ident);
+       length = 38 + length_of_file_ident;
+       padded_length = PAD(length, 4);
+       while (length < padded_length) {
+               buf[length++] = 0;
+       }
+       set_tag(&fid->desc_tag, UDF_TAGID_FILE_IDENT_DESC, rba, length);
+       return (length);
+}
+
+static void
+set_file_entry(unsigned char *buf, unsigned rba, unsigned file_rba,
+                                       uint64_t length, const char *iso_date, int is_directory,
+                                       unsigned link_count, unsigned unique_id)
+{
+       udf_short_ad    *allocation_desc;
+       unsigned        chunk;
+
+       udf_file_entry *fe = (udf_file_entry *)buf;
+
+       /*set32(&fe->icb_tag.prior_recorded_number_of_direct_entries, 0);*/
+       set16(&fe->icb_tag.strategy_type, 4);
+       /*set16(&fe->icb_tag.strategy_parameter, 0);*/
+       set16(&fe->icb_tag.maximum_number_of_entries, 1);
+       set8(&fe->icb_tag.file_type, is_directory
+               ? UDF_ICBTAG_FILETYPE_DIRECTORY : UDF_ICBTAG_FILETYPE_BYTESEQ);
+       /*fe->icb_tag.parent_icb_location;*/
+       set16(&fe->icb_tag.flags, UDF_ICBTAG_FLAG_NONRELOCATABLE
+               | UDF_ICBTAG_FLAG_ARCHIVE | UDF_ICBTAG_FLAG_CONTIGUOUS);
+       if (rationalize_uid)
+               set32(&fe->uid, uid_to_use);
+       else
+               set32(&fe->uid, -1);
+       if (rationalize_gid)
+               set32(&fe->gid, gid_to_use);
+       else
+               set32(&fe->gid, -1);
+       if (is_directory) {
+               set32(&fe->permissions,
+                   UDF_FILEENTRY_PERMISSION_OR | UDF_FILEENTRY_PERMISSION_OX |
+                   UDF_FILEENTRY_PERMISSION_GR | UDF_FILEENTRY_PERMISSION_GX |
+                   UDF_FILEENTRY_PERMISSION_UR | UDF_FILEENTRY_PERMISSION_UX);
+       } else {
+               set32(&fe->permissions, UDF_FILEENTRY_PERMISSION_OR
+               | UDF_FILEENTRY_PERMISSION_GR | UDF_FILEENTRY_PERMISSION_UR);
+       }
+       set16(&fe->file_link_count, link_count);
+       /*fe->record_format;*/
+       /*fe->record_display_attributes;*/
+       /*fe->record_length;*/
+       set64(&fe->info_length, length);
+       set64(&fe->logical_blocks_recorded, ISO_BLOCKS(length));
+       if (iso_date) {
+               set_timestamp_from_iso_date(&fe->access_time, iso_date);
+               fe->modification_time = fe->access_time;
+               fe->attribute_time = fe->access_time;
+       }
+       set32(&fe->checkpoint, 1);
+       /*fe->ext_attribute_icb;*/
+       set_impl_ident(&fe->impl_ident);
+       set64(&fe->unique_id, unique_id);
+       /*
+        * Extended attributes that may (?) be required for DVD-Video
+        * compliance
+        */
+#if 0
+       set32(&fe->length_of_ext_attributes, 24+52+56);
+       set32(&fe->ext_attribute_header.impl_attributes_location, 24);
+       set32(&fe->ext_attribute_header.application_attributes_location,
+                                                               24+52+56);
+       set_tag(&fe->ext_attribute_header.desc_tag,
+                       UDF_TAGID_EXT_ATTRIBUTE_HEADER_DESC, rba, 24 /*???*/);
+       set32(&fe->ext_attribute_free_ea_space.attribute_type, SECTOR_SIZE);
+       set8(&fe->ext_attribute_free_ea_space.attribute_subtype, 1);
+       set32(&fe->ext_attribute_free_ea_space.attribute_length, 52);
+       set32(&fe->ext_attribute_free_ea_space.impl_use_length, 4);
+       strcpy((char *)fe->ext_attribute_free_ea_space.impl_ident.ident,
+                                                       "*UDF FreeAppEASpace");
+       set32(&fe->ext_attribute_dvd_cgms_info.attribute_type, SECTOR_SIZE);
+       set8(&fe->ext_attribute_dvd_cgms_info.attribute_subtype, 1);
+       set32(&fe->ext_attribute_dvd_cgms_info.attribute_length, 56);
+       set32(&fe->ext_attribute_dvd_cgms_info.impl_use_length, 8);
+       strcpy((char *)fe->ext_attribute_free_ea_space.impl_ident.ident,
+                                                       "*UDF DVD CGMS Info");
+       fe->ext_attribute_free_ea_space.impl_ident.ident_suffix[0] = 2;
+       fe->ext_attribute_free_ea_space.impl_ident.ident_suffix[1] = 1;
+#else
+       /*set32(&fe->length_of_ext_attributes, 0);*/
+#endif
+
+       allocation_desc = &fe->allocation_desc;
+       /*
+        * Only a file size less than 1GB can be expressed by a single
+        * AllocationDescriptor. When the size of a file is larger than 1GB,
+        * 2 or more AllocationDescriptors should be used. We don't know
+        * whether a singl 8-byte AllocationDescriptor should be written or no
+        * one should be written if the size of a file is 0 byte. - FIXME.
+        *
+        * XXX We get called with buf[2048]. This allows a max. file size of
+        * XXX 234 GB. With more we would cause a buffer overflow.
+        * XXX We need to check whether UDF would allow files > 234 GB.
+        */
+       for (; length > 0; length -= chunk) {
+               chunk = (length > 0x3ffff800) ? 0x3ffff800 : length;
+               set32(&allocation_desc->extent_length, chunk);
+               set32(&allocation_desc->extent_position, file_rba);
+               file_rba += chunk >> 11;
+               allocation_desc++;
+       }
+       set32(&fe->length_of_allocation_descs,
+                               (unsigned char *) allocation_desc -
+                               (unsigned char *) &fe->allocation_desc);
+       set_tag(&fe->desc_tag, UDF_TAGID_FILE_ENTRY, rba,
+               (unsigned char *) allocation_desc - buf);
+}
+
+static unsigned
+directory_link_count(struct directory *dpnt)
+{
+       /*
+        * The link count is equal to 1 (for the parent) plus the
+        * number of subdirectories.
+        */
+       unsigned link_count = 1;
+       struct directory_entry *de;
+
+       /* count relocated subdirectories */
+       for (de = dpnt->jcontents; de; de = de->jnext) {
+               if ((de->de_flags &
+                   (INHIBIT_JOLIET_ENTRY | RELOCATED_DIRECTORY)) ==
+                                                       RELOCATED_DIRECTORY) {
+                       link_count++;
+               }
+       }
+       /* count ordinary subdirectories */
+       for (dpnt = dpnt->subdir; dpnt; dpnt = dpnt->next) {
+               if (!(dpnt->dir_flags & INHIBIT_JOLIET_ENTRY)) {
+                       link_count++;
+               }
+       }
+       return (link_count);
+}
+
+static void
+write_one_udf_directory(struct directory *dpnt, FILE *outfile)
+{
+       unsigned size_in_bytes, padded_size_in_bytes;
+       struct directory_entry *de;
+       unsigned ident_size;
+       unsigned base_sector;
+       struct directory *parent;
+       Uchar buf[SECTOR_SIZE];
+
+       memset(buf, 0, SECTOR_SIZE);
+       set_file_entry(
+               buf,
+               last_extent_written - lba_udf_partition_start,
+               last_extent_written+1 - lba_udf_partition_start,
+               directory_size(dpnt),
+               dpnt->self->isorec.date,
+               1,      /* is_directory */
+               directory_link_count(dpnt),
+               (dpnt == root) ? 0 : dpnt->self->udf_file_entry_sector);
+       jtwrite(buf, SECTOR_SIZE, 1, 0, FALSE);
+       xfwrite(buf, SECTOR_SIZE, 1, outfile, 0, FALSE);
+       last_extent_written++;
+
+       base_sector = last_extent_written - lba_udf_partition_start;
+
+       /* parent directory */
+       parent = dpnt->parent;
+       if (parent == reloc_dir) {
+               parent = dpnt->self->parent_rec->filedir;
+       }
+       ident_size = set_file_ident_desc(
+               buf,
+               base_sector,
+               0,
+               1,
+               parent->self->udf_file_entry_sector - lba_udf_partition_start,
+               (parent == root) ? 0 : parent->self->udf_file_entry_sector);
+       jtwrite(buf, ident_size, 1, 0, FALSE);
+       xfwrite(buf, ident_size, 1, outfile, 0, FALSE);
+       size_in_bytes = ident_size;
+
+       /* directory contents */
+       for (de = dpnt->jcontents; de; de = de->jnext) {
+               char *name;
+               struct directory_entry *de1;
+
+               if (de->de_flags & INHIBIT_JOLIET_ENTRY)
+                       continue;
+
+               name = USE_MAC_NAME(de) ? de->hfs_ent->name : de->name;
+
+               /* skip . and .. */
+               if (name[0] == '.' && (name[1] == 0 ||
+                   (name[1] == '.' && name[2] == 0)))
+                       continue;
+
+               /* look in RR_MOVED for relocated directories */
+               de1 = de;
+               if (de->de_flags & RELOCATED_DIRECTORY) {
+                       for (de1 = reloc_dir->contents; de1; de1 = de1->next) {
+                               if (de1->parent_rec == de) {
+                                       break;
+                               }
+                       }
+                       if (!de1) {
+#ifdef USE_LIBSCHILY
+                               comerrno(EX_BAD,
+                               "Unable to locate relocated directory\n");
+#else
+                               fprintf(stderr,
+                               "Unable to locate relocated directory\n");
+                               exit(1);
+#endif
+                       }
+               }
+
+               ident_size = set_file_ident_desc(
+                       buf,
+                       base_sector + (size_in_bytes / SECTOR_SIZE),
+                       name,
+                       !!(de1->isorec.flags[0] & ISO_DIRECTORY),
+                       de1->udf_file_entry_sector - lba_udf_partition_start,
+                       de1->udf_file_entry_sector);
+               jtwrite(buf, ident_size, 1, 0, FALSE);
+               xfwrite(buf, ident_size, 1, outfile, 0, FALSE);
+               size_in_bytes += ident_size;
+       }
+
+       padded_size_in_bytes = PAD(size_in_bytes, SECTOR_SIZE);
+       if (size_in_bytes < padded_size_in_bytes) {
+               memset(buf, 0, padded_size_in_bytes - size_in_bytes);
+               jtwrite(buf, padded_size_in_bytes - size_in_bytes, 1, 0, FALSE);
+               xfwrite(buf, padded_size_in_bytes - size_in_bytes, 1, outfile, 0, FALSE);
+       }
+
+       last_extent_written += padded_size_in_bytes / SECTOR_SIZE;
+}
+
+static void
+write_udf_directories(struct directory *dpnt, FILE *outfile)
+{
+       if (!(dpnt->dir_flags & INHIBIT_JOLIET_ENTRY)) {
+               write_one_udf_directory(dpnt, outfile);
+       }
+       if (!(dpnt->dir_flags & INHIBIT_JOLIET_ENTRY) || dpnt == reloc_dir) {
+               for (dpnt = dpnt->subdir; dpnt; dpnt = dpnt->next) {
+                       write_udf_directories(dpnt, outfile);
+               }
+       }
+}
+
+static void
+write_udf_file_entries(struct directory *dpnt, FILE *outfile)
+{
+       Uchar buf[SECTOR_SIZE];
+
+       memset(buf, 0, SECTOR_SIZE);
+
+       if (!(dpnt->dir_flags & INHIBIT_JOLIET_ENTRY)) {
+               struct directory_entry *de;
+               for (de = dpnt->jcontents; de; de = de->jnext) {
+                       if (!(de->de_flags & RELOCATED_DIRECTORY) &&
+                           !(de->isorec.flags[0] & ISO_DIRECTORY)) {
+
+                               memset(buf, 0, 512);
+                               set_file_entry(
+                                       buf,
+                                       (last_extent_written++) - lba_udf_partition_start,
+                                       read_733(de->isorec.extent) - lba_udf_partition_start,
+                                       de->realsize,
+                                       de->isorec.date,
+                                       0,      /* is_directory */
+                                       1,      /* link_count */
+                                       de->udf_file_entry_sector);
+                               jtwrite(buf, SECTOR_SIZE, 1, 0, FALSE);
+                               xfwrite(buf, SECTOR_SIZE, 1, outfile, 0, FALSE);
+                       }
+               }
+       }
+       if (!(dpnt->dir_flags & INHIBIT_JOLIET_ENTRY) || dpnt == reloc_dir) {
+               for (dpnt = dpnt->subdir; dpnt; dpnt = dpnt->next) {
+                       write_udf_file_entries(dpnt, outfile);
+               }
+       }
+}
+
+/****************************/
+
+static int
+udf_vol_recognition_area_write(FILE *out)
+{
+       static const char *identifiers[3] = { "BEA01", "NSR02", "TEA01" };
+       int i;
+       char buf[SECTOR_SIZE];
+       udf_volume_recognition_desc *vsd = (udf_volume_recognition_desc *)buf;
+
+       memset(buf, 0, sizeof (buf));
+       /*set8(&vsd->structure_type, 0);*/
+       set8(&vsd->structure_version, 1);
+       for (i = 0; i < 3; ++i) {
+               memcpy(vsd->standard_identifier, identifiers[i], 5);
+               jtwrite(buf, SECTOR_SIZE, 1, 0, FALSE);
+               xfwrite(buf, SECTOR_SIZE, 1, out, 0, FALSE);
+       }
+       last_extent_written += 3;
+       return (0);
+}
+
+static int
+udf_main_seq_write(FILE *out)
+{
+       Uchar buf[SECTOR_SIZE];
+       int i;
+
+       /*
+        * volume_set_id needs to be set to a (64-bit) "unique" number.
+        * This will have to do for now.
+        */
+       volume_set_id[0] = begun;
+       volume_set_id[1] = (unsigned)clock();   /* XXX Maybe non-portable */
+
+       memset(buf, 0, sizeof (buf));
+       set_primary_vol_desc(buf, last_extent_written++);
+       jtwrite(buf, SECTOR_SIZE, 1, 0, FALSE);
+       xfwrite(buf, SECTOR_SIZE, 1, out, 0, FALSE);
+
+       memset(buf, 0, sizeof (buf));
+       set_impl_use_vol_desc(buf, last_extent_written++);
+       jtwrite(buf, SECTOR_SIZE, 1, 0, FALSE);
+       xfwrite(buf, SECTOR_SIZE, 1, out, 0, FALSE);
+
+       memset(buf, 0, sizeof (buf));
+       set_partition_desc(buf, last_extent_written++);
+       jtwrite(buf, SECTOR_SIZE, 1, 0, FALSE);
+       xfwrite(buf, SECTOR_SIZE, 1, out, 0, FALSE);
+
+       memset(buf, 0, sizeof (buf));
+       set_logical_vol_desc(buf, last_extent_written++);
+       jtwrite(buf, SECTOR_SIZE, 1, 0, FALSE);
+       xfwrite(buf, SECTOR_SIZE, 1, out, 0, FALSE);
+
+       memset(buf, 0, sizeof (buf));
+       set_unallocated_space_desc(buf, last_extent_written++);
+       jtwrite(buf, SECTOR_SIZE, 1, 0, FALSE);
+       xfwrite(buf, SECTOR_SIZE, 1, out, 0, FALSE);
+
+       memset(buf, 0, sizeof (buf));
+       set_terminating_desc(buf, last_extent_written++);
+       jtwrite(buf, SECTOR_SIZE, 1, 0, FALSE);
+       xfwrite(buf, SECTOR_SIZE, 1, out, 0, FALSE);
+
+       memset(buf, 0, sizeof (buf));
+       for (i = 6; i < UDF_MAIN_SEQ_LENGTH; ++i) {
+        jtwrite(buf, SECTOR_SIZE, 1, 0, FALSE);
+               xfwrite(buf, SECTOR_SIZE, 1, out, 0, FALSE);
+               last_extent_written++;
+       }
+
+       return (0);
+}
+
+static int
+udf_integ_seq_write(FILE *out)
+{
+       Uchar buf[SECTOR_SIZE*UDF_INTEG_SEQ_LENGTH];
+
+       memset(buf, 0, sizeof (buf));
+
+       set_logical_vol_integrity_desc(buf+0*SECTOR_SIZE,
+                                               last_extent_written++);
+       set_terminating_desc(buf+1*SECTOR_SIZE, last_extent_written++);
+
+       jtwrite(buf, SECTOR_SIZE, UDF_INTEG_SEQ_LENGTH, 0, FALSE);
+       xfwrite(buf, SECTOR_SIZE, UDF_INTEG_SEQ_LENGTH, out, 0, FALSE);
+       return (0);
+}
+
+static int
+udf_anchor_vol_desc_write(FILE *out)
+{
+       Uchar buf[SECTOR_SIZE];
+
+       memset(buf, 0, sizeof (buf));
+       set_anchor_volume_desc_pointer(buf, last_extent_written++);
+       jtwrite(buf, SECTOR_SIZE, 1, 0, FALSE);
+       xfwrite(buf, SECTOR_SIZE, 1, out, 0, FALSE);
+       return (0);
+}
+
+static int
+udf_file_set_desc_write(FILE *out)
+{
+       Uchar buf[SECTOR_SIZE*2];
+
+       memset(buf, 0, sizeof (buf));
+
+       set_file_set_desc(buf+0*SECTOR_SIZE,
+                       (last_extent_written++) - lba_udf_partition_start);
+       set_terminating_desc(buf+1*SECTOR_SIZE,
+                       (last_extent_written++) - lba_udf_partition_start);
+
+       jtwrite(buf, SECTOR_SIZE, 2, 0, FALSE);
+       xfwrite(buf, SECTOR_SIZE, 2, out, 0, FALSE);
+
+       return (0);
+}
+
+static int
+udf_dirtree_write(FILE *out)
+{
+       write_udf_directories(root, out);
+       return (0);
+}
+
+static int
+udf_file_entries_write(FILE *out)
+{
+       write_udf_file_entries(root, out);
+       return (0);
+}
+
+static int
+pad_to(unsigned last_extent_to_write, FILE *out)
+{
+       char buf[SECTOR_SIZE];
+       memset(buf, 0, sizeof (buf));
+       while (last_extent_written < last_extent_to_write) {
+               jtwrite(buf, SECTOR_SIZE, 1, 0, FALSE);
+               xfwrite(buf, SECTOR_SIZE, 1, out, 0, FALSE);
+               ++last_extent_written;
+       }
+       return (0);
+}
+
+static int
+udf_pad_to_sector_32_write(FILE *out)
+{
+       return (pad_to(session_start+32, out));
+}
+
+static int
+udf_pad_to_sector_256_write(FILE *out)
+{
+       return (pad_to(session_start+256, out));
+}
+
+static int
+udf_padend_avdp_write(FILE *out)
+{
+       Uchar buf[SECTOR_SIZE];
+       unsigned last_extent_to_write = (last_extent_written+31) & ~15;
+
+       if (!use_sparcboot)
+               last_extent_to_write = last_extent_written + 150;
+
+       memset(buf, 0, sizeof (buf));
+       while (last_extent_written < last_extent_to_write) {
+               set_anchor_volume_desc_pointer(buf, last_extent_written++);
+               jtwrite(buf, SECTOR_SIZE, 1, 0, FALSE);
+               xfwrite(buf, SECTOR_SIZE, 1, out, 0, FALSE);
+       }
+       return (0);
+}
+
+
+struct output_fragment udf_vol_recognition_area_frag = { NULL, udf_vol_recognition_area_size, NULL, udf_vol_recognition_area_write, "UDF volume recognition area" };
+struct output_fragment udf_main_seq_frag = { NULL, udf_main_seq_size, NULL, udf_main_seq_write, "UDF main seq" };
+struct output_fragment udf_main_seq_copy_frag = { NULL, udf_main_seq_copy_size, NULL, udf_main_seq_write, "UDF second seq" };
+struct output_fragment udf_integ_seq_frag = { NULL, udf_integ_seq_size, NULL, udf_integ_seq_write, "UDF integ seq" };
+struct output_fragment udf_anchor_vol_desc_frag = { NULL, oneblock_size, NULL, udf_anchor_vol_desc_write, "UDF Anchor volume" };
+struct output_fragment udf_file_set_desc_frag = { NULL, udf_file_set_desc_size, NULL, udf_file_set_desc_write, "UDF file set" };
+struct output_fragment udf_dirtree_frag = { NULL, udf_dirtree_size, NULL, udf_dirtree_write, "UDF directory tree" };
+struct output_fragment udf_file_entries_frag = { NULL, udf_file_entries_size, NULL, udf_file_entries_write, "UDF file entries" };
+struct output_fragment udf_end_anchor_vol_desc_frag = { NULL, udf_end_anchor_vol_desc_size, NULL, udf_anchor_vol_desc_write, "UDF Anchor end volume" };
+
+struct output_fragment udf_pad_to_sector_32_frag = { NULL, udf_pad_to_sector_32_size, NULL, udf_pad_to_sector_32_write, "UDF pad to sector 32" };
+struct output_fragment udf_pad_to_sector_256_frag = { NULL, udf_pad_to_sector_256_size, NULL, udf_pad_to_sector_256_write, "UDF pad to sector 256" };
+struct output_fragment udf_padend_avdp_frag = { NULL, udf_padend_avdp_size, NULL, udf_padend_avdp_write, "UDF Pad end" };
+
+/*
+ * This function assigns weights as follows:
+ *
+ * /VIDEO_TS/VIDEO_TS.IFO   11199
+ * /VIDEO_TS/VIDEO_TS.VOB   11198
+ * /VIDEO_TS/VIDEO_TS.BUP   11188
+ * /VIDEO_TS/VTS_01_0.IFO   11187
+ * /VIDEO_TS/VTS_01_0.VOB   11186
+ *            :               :
+ * /VIDEO_TS/VTS_01_9.VOB   11177
+ * /VIDEO_TS/VTS_01_0.BUP   11176
+ *            :               :
+ * /VIDEO_TS/VTS_99_0.BUP   10000
+ *
+ * This ensures that DVD-Video files are laid out properly on the disc.
+ * The same thing is done for AUDIO_TS files, except in the 20000 range
+ * instead of the 10000 range.
+ *
+ * Question: what about JACKET_P files?
+ *
+ * Answer: At least as far as I know :)
+ * JACKET_P files are still images (single frame mpeg video .i.e mp2
+ * format). The DVD Jacket pictures will be displayed on the TV screen
+ * when the player is in a stop/resume mode.
+ * The location is not dependent on IFO information and the only must
+ * as far as I know is that they are in upper case (both dir and files).
+ * This sparce information makes me conclude that they don't need any
+ * weight. This obviously needs to be tested.
+ */
+int
+assign_dvd_weights(char *name, struct directory *this_dir, int val)
+{
+       int ts_number;
+       int segment;
+       int audio;
+
+       if (name[0] != 'A' && name[0] != 'V')
+               return (val);
+
+       if (memcmp(name, "VIDEO_TS", 8) == 0) {
+               ts_number = 0;
+               audio = 0;
+       } else if (memcmp(name, "VTS_", 4) == 0) {
+               ts_number = 1;
+               audio = 0;
+       } else if (memcmp(name, "AUDIO_TS", 8) == 0) {
+               ts_number = 0;
+               audio = 1;
+       } else if (memcmp(name, "ATS_", 4) == 0) {
+               ts_number = 1;
+               audio = 1;
+       } else {
+               return (val);
+       }
+
+       if (this_dir->parent != root ||
+           strcmp(this_dir->de_name, "VIDEO_TS") != 0)
+               return (val);
+
+       if (ts_number == 0) {
+               segment = 0;
+       } else {
+               if (name[4] >= '0' && name[4] <= '9' &&
+                   name[5] >= '0' && name[5] <= '9' &&
+                   name[6] == '_' &&
+                   name[7] >= '0' && name[7] <= '9') {
+                       ts_number = name[4] * 10 + name[5] - ('0' * 11);
+                       segment = name[7] - '0';
+               } else {
+                       return (val);
+               }
+       }
+
+       if (strcmp(name+8, audio ? ".AOB" : ".VOB") == 0) {
+               return (audio * 10000 - ts_number * 12 - segment + 11198);
+       } else if (strcmp(name+8, ".IFO") == 0) {
+               return (audio * 10000 - ts_number * 12 + 11199);
+       } else if (strcmp(name+8, ".BUP") == 0) {
+               return (audio * 10000 - ts_number * 12 + 11188);
+       } else {
+               return (val);
+       }
+}
+
+#endif  /* UDF */
diff --git a/genisoimage/udf.h b/genisoimage/udf.h
new file mode 100644 (file)
index 0000000..dc7bb94
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)udf.h   1.2 04/03/01 Copyright 2001-2004 J. Schilling */
+/*
+ *     UDF external definitions for genisoimage
+ *
+ *     Copyright (c) 2001-2004 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef        _UDF_H
+#define        _UDF_H
+
+extern struct output_fragment udf_vol_recognition_area_frag;
+extern struct output_fragment udf_main_seq_frag;
+extern struct output_fragment udf_main_seq_copy_frag;
+extern struct output_fragment udf_integ_seq_frag;
+extern struct output_fragment udf_anchor_vol_desc_frag;
+extern struct output_fragment udf_file_set_desc_frag;
+extern struct output_fragment udf_dirtree_frag;
+extern struct output_fragment udf_file_entries_frag;
+extern struct output_fragment udf_end_anchor_vol_desc_frag;
+
+extern struct output_fragment udf_pad_to_sector_32_frag;
+extern struct output_fragment udf_pad_to_sector_256_frag;
+extern struct output_fragment udf_padend_avdp_frag;
+
+int assign_dvd_weights(char *name, struct directory *this_dir, int val);
+
+extern int use_udf;
+
+#endif /* _UDF_H */
diff --git a/genisoimage/udf_fs.h b/genisoimage/udf_fs.h
new file mode 100644 (file)
index 0000000..850a3cc
--- /dev/null
@@ -0,0 +1,462 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)udf_fs.h        1.2 04/03/01 Copyright 2001-2004 J. Schilling */
+/*
+ * udf_fs.h - UDF structure definitions for genisoimage
+ *
+ * Written by Ben Rudiak-Gould (2001).
+ *
+ * Copyright 2001-2004 J. Schilling.
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef        _UDF_FS_H
+#define        _UDF_FS_H
+
+/*
+ * Abbreviations:
+ *
+ * ad          allocation descriptor
+ * desc                descriptor
+ * ext         extended
+ * ident       identifier
+ * impl                implementation
+ * info                information
+ * ptr         pointer
+ * seq         sequence
+ */
+
+typedef char udf_Uint8;
+typedef char udf_dchar;
+typedef char udf_dstring;
+typedef char udf_byte;
+typedef char udf_zerobyte;
+
+/* Is this safe? Are there compilers so perverse as to pad these structs? */
+typedef struct udf_Uint16_ {
+       char    l;
+       char    h;
+} udf_Uint16;
+
+typedef struct udf_Uint32_ {
+       char    l;
+       char    ml;
+       char    mh;
+       char    h;
+} udf_Uint32;
+typedef struct udf_Uint64_ {
+       udf_Uint32      l;
+       udf_Uint32      h;
+} udf_Uint64;
+
+typedef struct udf_tag_ {                      /* ECMA-167 3/7.2 */
+/* 0*/ udf_Uint16      tag_ident;
+/* 2*/ udf_Uint16      desc_version;
+/* 4*/ udf_Uint8       tag_checksum;
+/* 5*/ udf_zerobyte    reserved;
+/* 6*/ udf_Uint16      tag_serial_number;
+/* 8*/ udf_Uint16      desc_crc;
+/*10*/ udf_Uint16      desc_crc_length;
+/*12*/ udf_Uint32      tag_location;
+/*16*/
+} udf_tag;
+
+#define        UDF_TAGID_PRIMARY_VOLUME_DESC           1
+#define        UDF_TAGID_ANCHOR_VOLUME_DESC_PTR        2
+#define        UDF_TAGID_IMPL_USE_VOLUME_DESC          4
+#define        UDF_TAGID_PARTITION_DESC                5
+#define        UDF_TAGID_LOGICAL_VOLUME_DESC           6
+#define        UDF_TAGID_UNALLOCATED_SPACE_DESC        7
+#define        UDF_TAGID_TERMINATING_DESC              8
+#define        UDF_TAGID_LOGICAL_VOLUME_INTEGRITY_DESC 9
+#define        UDF_TAGID_FILE_SET_DESC                 256
+#define        UDF_TAGID_FILE_IDENT_DESC               257
+#define        UDF_TAGID_FILE_ENTRY                    261
+#define        UDF_TAGID_EXT_ATTRIBUTE_HEADER_DESC     262
+
+typedef struct udf_extent_ad_ {                        /* ECMA-167 3/7.1 */
+/*0*/  udf_Uint32      extent_length;
+/*4*/  udf_Uint32      extent_location;
+/*8*/
+} udf_extent_ad;
+
+typedef struct udf_charspec_ {                 /* ECMA-167 1/7.2.1 */
+/* 0*/ udf_Uint8       character_set_type;
+/* 1*/ udf_byte        character_set_info[63];
+/*64*/
+} udf_charspec;
+
+typedef struct udf_EntityID_ {                 /* ECMA-167 1/7.4 */
+/* 0*/ udf_Uint8       flags;
+/* 1*/ udf_byte        ident[23];
+/*24*/ udf_byte        ident_suffix[8];
+/*32*/
+} udf_EntityID;
+
+#define        UDF_ENTITYID_FLAG_PROTECTED     2       /* ECMA-167 1/7.4.1 */
+
+typedef struct udf_lb_addr_ {                  /* ECMA-167 4/7.1 */
+/*0*/  udf_Uint32      logical_block_number;
+/*4*/  udf_Uint16      partition_reference_number;
+/*6*/
+} udf_lb_addr;
+
+typedef struct udf_short_ad_ {                 /* ECMA-167 4/14.14.1 */
+/*0*/  udf_Uint32      extent_length;
+/*4*/  udf_Uint32      extent_position;
+/*8*/
+} udf_short_ad;
+
+typedef struct udf_long_ad_impl_use_field_ {   /* UDF 2.01 2.3.4.3 */
+/*0*/  udf_Uint16      flags;
+/*2*/  udf_Uint32      unique_id;
+/*6*/
+} udf_long_ad_impl_use_field;
+
+typedef struct udf_long_ad_ {                  /* ECMA-167 4/14.14.2 */
+/* 0*/ udf_Uint32      extent_length;
+/* 4*/ udf_lb_addr     extent_location;
+/*10*/ udf_long_ad_impl_use_field      impl_use;
+/*16*/
+} udf_long_ad;
+
+typedef struct udf_timestamp_ {                        /* TR/71 1.5.4 */
+/* 0*/ udf_Uint16      type_and_time_zone;
+/* 2*/ udf_Uint16      year;
+/* 4*/ udf_Uint8       month;
+/* 5*/ udf_Uint8       day;
+/* 6*/ udf_Uint8       hour;
+/* 7*/ udf_Uint8       minute;
+/* 8*/ udf_Uint8       second;
+/* 9*/ udf_Uint8       centiseconds;
+/*10*/ udf_Uint8       hundreds_of_microseconds;
+/*11*/ udf_Uint8       microseconds;
+/*12*/
+} udf_timestamp;
+
+typedef struct udf_volume_recognition_desc_ {  /* TR/71 2.4.{1,2,3} */
+       udf_Uint8       structure_type;
+       udf_byte        standard_identifier[5];
+       udf_Uint8       structure_version;
+       udf_zerobyte    structure_data[2041];
+} udf_volume_recognition_desc;
+
+typedef struct udf_anchor_volume_desc_ptr_ {   /* TR/71 2.5.1 */
+/*  0*/        udf_tag         desc_tag;
+/* 16*/        udf_extent_ad   main_volume_desc_seq_extent;
+/* 24*/        udf_extent_ad   reserve_volume_desc_seq_extent;
+/* 32*/        udf_zerobyte    reserved[480];
+/*512*/
+} udf_anchor_volume_desc_ptr;
+
+typedef struct udf_primary_volume_desc_ {      /* TR/71 2.6.1 */
+/*  0*/        udf_tag         desc_tag;
+/* 16*/        udf_Uint32      volume_desc_seq_number;
+/* 20*/        udf_Uint32      primary_volume_desc_number;
+/* 24*/        udf_dstring     volume_ident[32];
+/* 56*/        udf_Uint16      volume_seq_number;
+/* 58*/        udf_Uint16      maximum_volume_seq_number;
+/* 60*/        udf_Uint16      interchange_level;
+/* 62*/        udf_Uint16      maximum_interchange_level;
+/* 64*/        udf_Uint32      character_set_list;
+/* 68*/        udf_Uint32      maximum_character_set_list;
+/* 72*/        udf_dstring     volume_set_ident[128];
+/*200*/        udf_charspec    desc_character_set;
+/*264*/        udf_charspec    explanatory_character_set;
+/*328*/        udf_extent_ad   volume_abstract;
+/*336*/        udf_extent_ad   volume_copyright_notice;
+/*344*/        udf_EntityID    application_ident;
+/*376*/        udf_timestamp   recording_date_and_time;
+/*388*/        udf_EntityID    impl_ident;
+/*420*/        udf_byte        impl_use[64];
+/*484*/        udf_Uint32      predecessor_volume_desc_seq_location;
+/*488*/        udf_Uint16      flags;
+/*490*/        udf_zerobyte    reserved[22];
+/*512*/
+} udf_primary_volume_desc;
+
+typedef struct udf_impl_use_volume_desc_impl_use_field_ {      /* TR/71 2.6.3 */
+/*  0*/        udf_charspec    lvi_charset;
+/* 64*/        udf_dstring     logical_volume_ident[128];
+/*192*/        udf_dstring     lv_info1[36];
+/*228*/        udf_dstring     lv_info2[36];
+/*264*/        udf_dstring     lv_info3[36];
+/*300*/        udf_EntityID    impl_id;
+/*332*/        udf_byte        impl_use[128];
+/*460*/
+} udf_impl_use_volume_desc_impl_use_field;
+
+typedef struct udf_impl_use_volume_desc_ {     /* TR/71 2.6.2 */
+/*  0*/        udf_tag         desc_tag;
+/* 16*/        udf_Uint32      volume_desc_seq_number;
+/* 20*/        udf_EntityID    impl_ident;
+/* 52*/        udf_impl_use_volume_desc_impl_use_field impl_use;
+/*512*/
+} udf_impl_use_volume_desc;
+
+typedef struct udf_partition_desc_ {           /* TR/71 2.6.4 */
+/*  0*/        udf_tag         desc_tag;
+/* 16*/        udf_Uint32      volume_desc_seq_number;
+/* 20*/        udf_Uint16      partition_flags;
+/* 22*/        udf_Uint16      partition_number;
+/* 24*/        udf_EntityID    partition_contents;
+/* 56*/        udf_byte        partition_contents_use[128];
+/*184*/        udf_Uint32      access_type;
+/*188*/        udf_Uint32      partition_starting_location;
+/*192*/        udf_Uint32      partition_length;
+/*196*/        udf_EntityID    impl_ident;
+/*228*/        udf_byte        impl_use[128];
+/*356*/        udf_zerobyte    reserved[156];
+/*512*/
+} udf_partition_desc;
+
+#define        UDF_PARTITION_FLAG_ALLOCATED    1       /* ECMA-167 3/10.5.3 */
+#define        UDF_ACCESSTYPE_READONLY         1       /* ECMA-167 3/10.5.7 */
+
+typedef struct udf_type_1_partition_map_ {     /* TR/71 2.6.8 */
+/*0*/  udf_Uint8       partition_map_type;
+/*1*/  udf_Uint8       partition_map_length;
+/*2*/  udf_Uint16      volume_seq_number;
+/*4*/  udf_Uint16      partition_number;
+/*6*/
+} udf_type_1_partition_map;
+
+#define        UDF_PARTITION_MAP_TYPE_1        1
+
+typedef struct udf_logical_volume_desc_ {      /* TR/71 2.6.7 */
+/*  0*/        udf_tag         desc_tag;
+/* 16*/        udf_Uint32      volume_desc_seq_number;
+/* 20*/        udf_charspec    desc_character_set;
+/* 84*/        udf_dstring     logical_volume_ident[128];
+/*212*/        udf_Uint32      logical_block_size;
+/*216*/        udf_EntityID    domain_ident;
+/*248*/        udf_long_ad     logical_volume_contents_use;
+/*264*/        udf_Uint32      map_table_length;
+/*268*/        udf_Uint32      number_of_partition_maps;
+/*272*/        udf_EntityID    impl_ident;
+/*304*/        udf_byte        impl_use[128];
+/*432*/        udf_extent_ad   integrity_seq_extent;
+/*440*/        udf_type_1_partition_map        partition_map[1];
+/*446*/
+} udf_logical_volume_desc;
+
+typedef struct udf_unallocated_space_desc_ {   /* TR/71 2.6.9 */
+/* 0*/ udf_tag         desc_tag;
+/*16*/ udf_Uint32      volume_desc_seq_number;
+/*20*/ udf_Uint32      number_of_allocation_descs;
+/*24*/ /*udf_extent_ad allocation_descs[0];*/
+} udf_unallocated_space_desc;
+
+typedef struct udf_terminating_desc_ {         /* TR/71 2.6.10 */
+/*  0*/        udf_tag         desc_tag;
+/* 16*/        udf_zerobyte    reserved[496];
+/*512*/
+} udf_terminating_desc;
+
+typedef struct udf_logical_volume_integrity_desc_impl_use_field_ {     /* TR/71 2.7.3 */
+/* 0*/ udf_EntityID    impl_id;
+/*32*/ udf_Uint32      number_of_files;
+/*36*/ udf_Uint32      number_of_directories;
+/*40*/ udf_Uint16      minimum_udf_read_revision;
+/*42*/ udf_Uint16      minimum_udf_write_revision;
+/*44*/ udf_Uint16      maximum_udf_write_revision;
+/*46*/ /*udf_byte      impl_use[0];*/
+} udf_logical_volume_integrity_desc_impl_use_field;
+
+typedef struct udf_logical_volume_integrity_desc_contents_use_field_ { /* TR/71 2.7.2 */
+       udf_Uint64      unique_id;
+       udf_zerobyte    reserved[24];
+} udf_logical_volume_integrity_desc_contents_use_field;
+
+typedef struct udf_logical_volume_integrity_desc_ {    /* TR/71 2.7.1 */
+/* 0*/ udf_tag         desc_tag;
+/*16*/ udf_timestamp   recording_date;
+/*28*/ udf_Uint32      integrity_type;
+/*32*/ udf_extent_ad   next_integrity_extent;
+/*40*/ udf_logical_volume_integrity_desc_contents_use_field    logical_volume_contents_use;
+/*72*/ udf_Uint32      number_of_partitions;
+/*76*/ udf_Uint32      length_of_impl_use;
+/*80*/ udf_Uint32      free_space_table;
+/*84*/ udf_Uint32      size_table;
+/*88*/ udf_logical_volume_integrity_desc_impl_use_field        impl_use;
+} udf_logical_volume_integrity_desc;
+
+#define        UDF_INTEGRITY_TYPE_CLOSE        1       /* ECMA-167 3/10.10.3 */
+
+typedef struct udf_file_set_desc_ {            /* TR/71 3.3.1 */
+/* 0*/ udf_tag         desc_tag;
+/*16*/ udf_timestamp   recording_date_and_time;
+/*28*/ udf_Uint16      interchange_level;
+/*30*/ udf_Uint16      maximum_interchange_level;
+/*32*/ udf_Uint32      character_set_list;
+/*36*/ udf_Uint32      maximum_character_set_list;
+/*40*/ udf_Uint32      file_set_number;
+/*44*/ udf_Uint32      file_set_desc_number;
+/*48*/ udf_charspec    logical_volume_ident_character_set;
+/*112*/        udf_dstring     logical_volume_ident[128];
+/*240*/        udf_charspec    file_set_character_set;
+/*304*/        udf_dstring     file_set_ident[32];
+/*336*/        udf_dstring     copyright_file_ident[32];
+/*368*/        udf_dstring     abstract_file_ident[32];
+/*400*/        udf_long_ad     root_directory_icb;
+/*416*/        udf_EntityID    domain_ident;
+/*448*/        udf_long_ad     next_extent;
+/*464*/        udf_zerobyte    reserved[48];
+/*512*/
+} udf_file_set_desc;
+
+typedef struct udf_file_ident_desc_ {          /* TR/71 3.4.1 */
+/* 0*/ udf_tag         desc_tag;
+/*16*/ udf_Uint16      file_version_number;
+/*18*/ udf_Uint8       file_characteristics;
+/*19*/ udf_Uint8       length_of_file_ident;
+/*20*/ udf_long_ad     icb;
+/*36*/ udf_Uint16      length_of_impl_use;
+/*38*/ /*udf_EntityID  impl_use;*/
+/*38*/ udf_dchar       file_ident[1];
+       /*udf_zerobyte  padding[0/1/2/3];*/
+} udf_file_ident_desc;
+
+#define        UDF_FILE_CHARACTERISTIC_HIDDEN          1       /* ECMA-167 4/14.4.3 */
+#define        UDF_FILE_CHARACTERISTIC_DIRECTORY       2
+#define        UDF_FILE_CHARACTERISTIC_DELETED         4
+#define        UDF_FILE_CHARACTERISTIC_PARENT          8
+
+typedef struct udf_icbtag_ {                   /* TR/71 3.5.2 */
+/* 0*/ udf_Uint32      prior_recorded_number_of_direct_entries;
+/* 4*/ udf_Uint16      strategy_type;
+/* 6*/ udf_Uint16      strategy_parameter;
+/* 8*/ udf_Uint16      maximum_number_of_entries;
+/*10*/ udf_zerobyte    reserved;
+/*11*/ udf_Uint8       file_type;
+/*12*/ udf_lb_addr     parent_icb_location;
+/*18*/ udf_Uint16      flags;
+/*20*/
+} udf_icbtag;
+
+#define        UDF_ICBTAG_FILETYPE_DIRECTORY   4       /* ECMA-167 4/14.6.6 */
+#define        UDF_ICBTAG_FILETYPE_BYTESEQ     5
+
+#define        UDF_ICBTAG_FLAG_MASK_AD_TYPE    7       /* TR/71 3.5.3 */
+#define        UDF_ICBTAG_FLAG_SHORT_AD        0
+#define        UDF_ICBTAG_FLAG_DIRECTORY_SORT  8
+#define        UDF_ICBTAG_FLAG_NONRELOCATABLE  16
+#define        UDF_ICBTAG_FLAG_ARCHIVE         32
+#define        UDF_ICBTAG_FLAG_SETUID          64
+#define        UDF_ICBTAG_FLAG_SETGID          128
+#define        UDF_ICBTAG_FLAG_STICKY          256
+#define        UDF_ICBTAG_FLAG_CONTIGUOUS      512
+#define        UDF_ICBTAG_FLAG_SYSTEM          1024
+#define        UDF_ICBTAG_FLAG_TRANSFORMED     2048
+#define        UDF_ICBTAG_FLAG_MULTI_VERSIONS  4096
+
+typedef struct udf_ext_attribute_header_desc_ {        /* TR/71 3.6.1 */
+/* 0*/ udf_tag         desc_tag;
+/*16*/ udf_Uint32      impl_attributes_location;
+/*20*/ udf_Uint32      application_attributes_location;
+/*24*/
+} udf_ext_attribute_header_desc;
+
+typedef struct udf_ext_attribute_free_ea_space_ {      /* TR/71 3.6.{2,3} */
+/* 0*/ udf_Uint32      attribute_type;         /* = 2048 */
+/* 4*/ udf_Uint8       attribute_subtype;      /* = 1 */
+/* 5*/ udf_zerobyte    reserved[3];
+/* 8*/ udf_Uint32      attribute_length;       /* = 52 */
+/*12*/ udf_Uint32      impl_use_length;        /* = 4 */
+/*16*/ udf_EntityID    impl_ident;             /* "*UDF FreeEASpace" */
+/*48*/ udf_Uint16      header_checksum;
+/*50*/ udf_Uint16      free_ea_space;          /* = 0 */
+/*52*/
+} udf_ext_attribute_free_ea_space;
+
+typedef struct udf_ext_attribute_dvd_cgms_info_ {      /* TR/71 3.6.{2,4} */
+/* 0*/ udf_Uint32      attribute_type;         /* = 2048 */
+/* 4*/ udf_Uint8       attribute_subtype;      /* = 1 */
+/* 5*/ udf_zerobyte    reserved[3];
+/* 8*/ udf_Uint32      attribute_length;       /* = 56 */
+/*12*/ udf_Uint32      impl_use_length;        /* = 8 */
+/*16*/ udf_EntityID    impl_ident;             /* "*UDF DVD CGMS Info" */
+/*48*/ udf_Uint16      header_checksum;
+/*50*/ udf_byte        cgms_info;
+/*51*/ udf_Uint8       data_structure_type;
+/*52*/ udf_byte        protection_system_info[4];
+/*56*/
+} udf_ext_attribute_dvd_cgms_info;
+
+#define        UDF_CGMSINFO_NO_COPIES                  48      /* TR/71 3.6.4 */
+#define        UDF_CGMSINFO_ONE_GENERATION             32
+#define        UDF_CGMSINFO_UNLIMITED_COPIES           0
+#define        UDF_CGMSINFO_FLAG_COPYRIGHTED_MATERIAL  128
+
+typedef struct udf_file_entry_ {               /* TR/71 3.5.1 */
+/* 0*/ udf_tag         desc_tag;
+/*16*/ udf_icbtag      icb_tag;
+/*36*/ udf_Uint32      uid;
+/*40*/ udf_Uint32      gid;
+/*44*/ udf_Uint32      permissions;
+/*48*/ udf_Uint16      file_link_count;
+/*50*/ udf_Uint8       record_format;
+/*51*/ udf_Uint8       record_display_attributes;
+/*52*/ udf_Uint32      record_length;
+/*56*/ udf_Uint64      info_length;
+/*64*/ udf_Uint64      logical_blocks_recorded;
+/*72*/ udf_timestamp   access_time;
+/*84*/ udf_timestamp   modification_time;
+/*96*/ udf_timestamp   attribute_time;
+/*108*/        udf_Uint32      checkpoint;
+/*112*/        udf_long_ad     ext_attribute_icb;
+/*128*/        udf_EntityID    impl_ident;
+/*160*/        udf_Uint64      unique_id;
+/*168*/        udf_Uint32      length_of_ext_attributes;
+/*172*/        udf_Uint32      length_of_allocation_descs;
+#if 0
+/*176*/        udf_ext_attribute_header_desc   ext_attribute_header;
+/*200*/        udf_ext_attribute_free_ea_space ext_attribute_free_ea_space;
+/*252*/        udf_ext_attribute_dvd_cgms_info ext_attribute_dvd_cgms_info;
+/*308*/        udf_short_ad    allocation_desc;
+/*316*/
+#else
+/*176*/        udf_short_ad    allocation_desc;
+/*184*/
+#endif
+} udf_file_entry;
+
+/*
+ * (U,G,O) = (owner, group, other)
+ * (X,R) = (execute, read)
+ *
+ * There are Write, Change Attribute and Delete permissions also,
+ * but it is not permitted to set them on DVD Read-Only media.
+ */
+#define        UDF_FILEENTRY_PERMISSION_OX     1       /* TR/71 3.5.4 */
+#define        UDF_FILEENTRY_PERMISSION_OR     4
+#define        UDF_FILEENTRY_PERMISSION_GX     32
+#define        UDF_FILEENTRY_PERMISSION_GR     128
+#define        UDF_FILEENTRY_PERMISSION_UX     1024
+#define        UDF_FILEENTRY_PERMISSION_UR     4096
+
+
+#endif /* _UDF_FS_H */
diff --git a/genisoimage/vms.c b/genisoimage/vms.c
new file mode 100644 (file)
index 0000000..9f1c885
--- /dev/null
@@ -0,0 +1,320 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)vms.c   1.9 04/03/04 joerg */
+/*
+ * File vms.c - assorted bletcherous hacks for VMS.
+ *
+ * Written by Eric Youngdale (1993).
+ *
+ */
+
+#include <mconfig.h>
+#ifdef VMS
+#define        opendir fake_opendir
+#include "genisoimage.h"
+#undef opendir
+#include <rms.h>
+#include <descrip.h>
+#include <ssdef.h>
+
+static struct RAB      *rab;           /* used for external mailfiles */
+static int             rms_status;
+
+static
+error_exit(char *text)
+{
+       fprintf(stderr, "%s\n", text);
+       exit(33);
+}
+
+
+char *strrchr(const char *, char);
+
+int
+VMS_stat(char *path, struct stat * spnt)
+{
+       char            *spath;
+       char            sbuffer[255];
+       char            *pnt,
+                       *ppnt;
+       char            *pnt1;
+
+       ppnt = strrchr(path, ']');
+       if (ppnt)
+               ppnt++;
+       else
+               ppnt = path;
+
+       spath = path;
+
+       if (strcmp(ppnt, ".") == 0 || strcmp(ppnt, "..") == 0) {
+               strcpy(sbuffer, path);
+
+               /* Find end of actual name */
+               pnt = strrchr(sbuffer, ']');
+               if (!pnt)
+                       return (0);
+
+               pnt1 = pnt;
+               while (*pnt1 != '[' && *pnt1 != '.')
+                       pnt1--;
+
+               if (*pnt1 != '[' && strcmp(ppnt, "..") == 0) {
+                       pnt1--;
+                       while (*pnt1 != '[' && *pnt1 != '.')
+                               pnt1--;
+               };
+
+               if (*pnt1 == '.') {
+                       *pnt1 = ']';
+                       pnt = pnt1;
+                       while (*pnt != '.' && *pnt != ']')
+                               pnt++;
+                       *pnt++ = ']';
+                       while (*pnt != '.' && *pnt != ']')
+                               pnt++;
+                       *pnt = 0;
+                       strcat(sbuffer, ".DIR;1");
+               };
+
+               if (*pnt1 == '[') {
+                       pnt1++;
+                       *pnt1 = 0;
+                       strcat(pnt1, "000000]");
+                       pnt1 = strrchr(path, '[') + 1;
+                       pnt = sbuffer + strlen(sbuffer);
+                       while (*pnt1 && *pnt1 != '.' && *pnt1 != ']')
+                               *pnt++ = *pnt1++;
+                       *pnt = 0;
+                       strcat(sbuffer, ".DIR;1");
+               };
+
+               spath = sbuffer;
+       };
+       return (stat_filter(spath, spnt));
+}
+
+static int             dircontext[32] = {0, };
+static char            *searchpath[32];
+static struct direct   d_entry[32];
+
+int                    optind = 0;
+char                   *optarg;
+
+int
+getopt(int argc, char *argv[], char *flags)
+{
+       char            *pnt;
+       char            c;
+
+       optind++;
+       if (*argv[optind] != '-')
+               return (EOF);
+       optarg = 0;
+
+       c = *(argv[optind] + 1);
+       pnt = (char *) strchr(flags, c);
+       if (!pnt)
+               return (c);     /* Not found */
+       if (pnt[1] == ':') {
+               optind++;
+               optarg = argv[optind];
+       };
+       return (c);
+}
+
+void
+vms_path_fixup(char *name)
+{
+       char            *pnt1;
+
+       pnt1 = name + strlen(name) - 6;
+
+       /* First strip the .DIR;1 */
+       if (strcmp(pnt1, ".DIR;1") == 0)
+               *pnt1 = 0;
+
+       pnt1 = (char *) strrchr(name, ']');
+       if (pnt1) {
+               if (pnt1[1] == 0)
+                       return;
+               *pnt1 = '.';
+               strcat(name, "]");
+               return;
+       };
+       pnt1 = (char *) strrchr(name, '>');
+       if (pnt1) {
+               if (pnt1[1] == 0)
+                       return;
+               *pnt1 = '.';
+               strcat(name, ">");
+               return;
+       };
+}
+
+int
+opendir(char *path)
+{
+       int             i;
+
+       for (i = 1; i < 32; i++) {
+               if (dircontext[i] == 0) {
+                       dircontext[i] = -1;
+                       searchpath[i] = (char *) e_malloc(strlen(path) + 6);
+                       strcpy(searchpath[i], path);
+                       vms_path_fixup(searchpath[i]);
+                       strcat(searchpath[i], "*.*.*");
+                       return (i);
+               };
+       };
+       exit(0);
+}
+
+struct direct  *
+readdir(int context)
+{
+       int             i;
+       char            cresult[100];
+       char            *pnt;
+       int             status;
+
+       $DESCRIPTOR(dpath, searchpath[context]);
+       $DESCRIPTOR(result, cresult);
+
+       if (dircontext[context] == -1) {
+               dircontext[context] = -2;
+               strcpy(d_entry[context].d_name, ".");
+               return (&d_entry[context]);
+       };
+
+       if (dircontext[context] == -2) {
+               dircontext[context] = -3;
+               strcpy(d_entry[context].d_name, "..");
+               return (&d_entry[context]);
+       };
+
+       if (dircontext[context] == -3)
+               dircontext[context] = 0;
+
+       dpath.dsc$w_length = strlen(searchpath[context]);
+       lib$find_file(&dpath, &result, &dircontext[context],
+               0, 0, &status, 0);
+
+       if (status == SS$_NOMOREFILES)
+               return (0);
+
+       /* Now trim trailing spaces from the name */
+       i = result.dsc$w_length - 1;
+       while (i && cresult[i] == ' ')
+               i--;
+       cresult[i + 1] = 0;
+
+       /* Now locate the actual portion of the file we want */
+
+       pnt = (char *) strrchr(cresult, ']');
+       if (pnt)
+               pnt++;
+       else
+               pnt = cresult;
+
+       strcpy(d_entry[context].d_name, pnt);
+       return (&d_entry[context]);
+}
+
+void
+closedir(int context)
+{
+       lib$find_file_end(&dircontext[context]);
+       free(searchpath[context]);
+       searchpath[context] = (char *) 0;
+       dircontext[context] = 0;
+}
+
+static
+open_file(char *fn)
+{
+       /*
+        * this routine initializes a rab and  fab required to get the
+        * correct definition of the external data file used by mail
+        */
+       struct FAB      *fab;
+
+       rab = (struct RAB *) e_malloc(sizeof (struct RAB));
+       fab = (struct FAB *) e_malloc(sizeof (struct FAB));
+
+       *rab = cc$rms_rab;      /* initialize RAB */
+       rab->rab$l_fab = fab;
+
+       *fab = cc$rms_fab;      /* initialize FAB */
+       fab->fab$l_fna = fn;
+       fab->fab$b_fns = strlen(fn);
+       fab->fab$w_mrs = 512;
+       fab->fab$b_fac = FAB$M_BIO | FAB$M_GET;
+       fab->fab$b_org = FAB$C_SEQ;
+       fab->fab$b_rfm = FAB$C_FIX;
+       fab->fab$l_xab = (char *) 0;
+
+       rms_status = sys$open(rab->rab$l_fab);
+       if (rms_status != RMS$_NORMAL && rms_status != RMS$_CREATED)
+               error_exit("$OPEN");
+       rms_status = sys$connect(rab);
+       if (rms_status != RMS$_NORMAL)
+               error_exit("$CONNECT");
+       return (1);
+}
+
+static
+close_file(struct RAB * prab)
+{
+       rms_status = sys$close(prab->rab$l_fab);
+       free(prab->rab$l_fab);
+       free(prab);
+       if (rms_status != RMS$_NORMAL)
+               error_exit("$CLOSE");
+}
+
+#define        NSECT 16
+extern unsigned int last_extent_written;
+
+int
+vms_write_one_file(char *filename, off_t size, FILE * outfile)
+{
+       int             status,
+                       i;
+       char            buffer[SECTOR_SIZE * NSECT];
+       int             count;
+       int             use;
+       off_t           remain;
+
+       open_file(filename);
+
+       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);
+               rab->rab$l_ubf = buffer;
+               rab->rab$w_usz = sizeof (buffer);
+               status = sys$read(rab);
+               fwrite(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;
+       };
+
+       close_file(rab);
+}
+
+#endif
diff --git a/genisoimage/vms.h b/genisoimage/vms.h
new file mode 100644 (file)
index 0000000..722fb82
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)vms.h   1.3 04/03/01 eric */
+/*
+ * Header file genisoimage.h - assorted structure definitions and typecasts.
+ *
+ *   Written by Eric Youngdale (1993).
+ */
+
+#ifdef VMS
+#define        stat(X, Y)      VMS_stat(X, Y)
+#define        lstat           VMS_stat
+
+/* gmtime not available under VMS - make it look like we are in Greenwich */
+#define        gmtime  localtime
+
+extern int     vms_write_one_file(char *filename, off_t size, FILE * outfile);
+
+#endif
diff --git a/genisoimage/volume.c b/genisoimage/volume.c
new file mode 100644 (file)
index 0000000..dd45336
--- /dev/null
@@ -0,0 +1,728 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)volume.c        1.14 04/07/09 joerg, Copyright 1997, 1998, 1999, 2000 James Pearson */
+/*
+ *      Copyright (c) 1997, 1998, 1999, 2000 James Pearson
+ *
+ * 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; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ *     volume.c: prepare HFS volume for mkhybrid
+ *
+ *     James Pearson 17/7/97
+ *     modified JCP 29/7/97 to improve allocation sizes to cut
+ *     down on wasted space. Now uses the HFS "allocation" size rounded
+ *     up to the nearest 2048 bytes. Savings can be significant with
+ *     a large volume containing lots of smallish files.
+ *
+ *     Updated for v1.12 - now uses the built in RELOCATED_DIRECTORY
+ *     flag for finding the real directory location JCP 8/1/97
+ */
+
+#ifdef APPLE_HYB
+
+#include <mconfig.h>
+#include "genisoimage.h"
+#include <errno.h>
+
+#define        HFS_MIN_SIZE    1600    /* 800k == 1600 HFS blocks */
+
+static hfsvol  *vol_save = 0;  /* used to "destroy" an HFS volume */
+
+static int     AlcSiz(Ulong);
+static int     XClpSiz(Ulong);
+static int     get_vol_size(int);
+int    write_fork(hfsfile * hfp, long tot);
+int    make_mac_volume(struct directory *, int);
+static int     copy_to_mac_vol(hfsvol *, struct directory *);
+static void    set_dir_info(hfsvol *, struct directory *);
+
+/*
+ *     AlcSiz: find allocation size for given volume size
+ */
+static int
+AlcSiz(Ulong vlen)
+{
+       int     lpa,
+               drAlBlkSiz;
+
+       /* code extracted from hfs_format() */
+       lpa = 1 + vlen / 65536;
+       drAlBlkSiz = lpa * HFS_BLOCKSZ;
+
+       /*
+        * now set our "allocation size" to the allocation block rounded up to
+        * the nearest SECTOR_SIZE (2048 bytes)
+        */
+       drAlBlkSiz = ROUND_UP(drAlBlkSiz, SECTOR_SIZE);
+
+       return (drAlBlkSiz);
+}
+
+/*
+ *     XClpSiz: find the default size of the catalog/extent file
+ */
+static int
+XClpSiz(Ulong vlen)
+{
+       int     olpa,
+               lpa,
+               drNmAlBlks,
+               drAlBlkSiz;
+       int     vbmsz,
+               drXTClpSiz;
+
+       /* code extracted from hfs_format() */
+
+       /* get the lpa from our calculated allocation block size */
+       drAlBlkSiz = AlcSiz(vlen);
+       lpa = drAlBlkSiz / HFS_BLOCKSZ;
+
+       vbmsz = (vlen / lpa + 4095) / 4096;
+       drNmAlBlks = (vlen - 5 - vbmsz) / lpa;
+       drXTClpSiz = drNmAlBlks / 128 * drAlBlkSiz;
+
+       /* override the drXTClpSiz size for large volumes */
+       if (drXTClpSiz > hce->max_XTCsize) {
+               drXTClpSiz = hce->max_XTCsize;
+       } else {
+               /*
+                * make allowances because we have possibly rounded up the
+                * allocation size get the "original" lpa "
+                */
+               olpa = 1 + vlen / 65536;
+
+               /* adjust size upwards */
+               drXTClpSiz = ((Ullong)drXTClpSiz * lpa) / olpa;
+       }
+
+       /* round up to the nearest allocation size */
+       drXTClpSiz = ROUND_UP(drXTClpSiz, drAlBlkSiz);
+
+       return (drXTClpSiz);
+}
+
+/*
+ *     get_vol_size: get the size of the volume including the extent/catalog
+ */
+static int
+get_vol_size(int vblen)
+{
+       int     drXTClpSiz;
+       int     drAlBlkSiz;
+       int     new_vblen;
+
+       /*
+        * try to estimate a "volume size" based on the code in hfs_format
+        * - we need the size of the catalog/extents and Desktop files included
+        * in the volume, as we add this to the end of the ISO volume
+        */
+       drXTClpSiz = XClpSiz(vblen);
+       drAlBlkSiz = AlcSiz(vblen);
+
+       /*
+        * catalog file is set at CTC times (default twice) the extents
+        * file size - hence the (ctc_size + 1) below. The Desktop starts of
+        * the same size as the "clump size" == 4 x drAlBlkSiz,
+        * plus a spare drAlBlkSiz for the alternative MDB
+        */
+       new_vblen = vblen +
+           ((hce->ctc_size + 1) * drXTClpSiz + 5 * drAlBlkSiz) / HFS_BLOCKSZ;
+
+       return (new_vblen);
+}
+
+/*
+ *     write_fork: "write" file data to the volume
+ *
+ *     This is used to update the HFS file internal structures
+ *     but no data is actually written (it's trapped deep down in
+ *     libhfs).
+ */
+int
+write_fork(hfsfile *hfp, long tot)
+{
+       char            blk[HFS_BLOCKSZ];
+       unsigned short  start;
+       long            len;
+
+       len = tot;
+       /* we need to know where this fork starts */
+       start = hfs_get_drAllocPtr(hfp);
+
+       /* loop through the data a block at a time */
+       while (len >= HFS_BLOCKSZ) {
+               if (hfs_write(hfp, blk, HFS_BLOCKSZ) < 0)
+                       return (-1);
+               len -= HFS_BLOCKSZ;
+       }
+       /* write out anything left */
+       if (len)
+               if (hfs_write(hfp, blk, len) < 0)
+                       return (-1);
+
+       /*
+        * set the start of the allocation search to be immediately after
+        * this fork
+        */
+       hfs_set_drAllocPtr(hfp, start, tot);
+
+       return (0);
+}
+
+/*
+ *     make_mac_volume: "create" an HFS volume using the ISO data
+ *
+ *     The HFS volume structures are set up (but no data is written yet).
+ *
+ *     ISO volumes have a allocation size of 2048 bytes - regardless
+ *     of the size of the volume. HFS allocation size is depends on volume
+ *     size, so we may have to update the ISO structures to add in any
+ *     padding.
+ */
+int
+make_mac_volume(struct directory  *dpnt, int start_extent)
+{
+       char    vol_name[HFS_MAX_VLEN + 1];     /* Mac volume name */
+       hfsvol  *vol;                   /* Mac volume */
+       int     vblen;                  /* vol length (HFS blocks) */
+       int     Csize,
+               lastCsize;              /* allocation sizes */
+       int     ret = 0;                /* return value */
+       int     loop = 1;
+
+       /* umount volume if we have had a previous attempt */
+       if (vol_save)
+               if (hfs_umount(vol_save, 0, hfs_lock) < 0)
+                       return (-1);
+
+       /* set the default clump size to the ISO block size */
+       Csize = lastCsize = SECTOR_SIZE;
+
+       if (verbose > 1)
+               fprintf(stderr, "Creating HFS Volume info\n");
+
+       /* name or copy ISO volume name to Mac Volume name */
+       strncpy(vol_name, hfs_volume_id ? hfs_volume_id : volume_id,
+                                                               HFS_MAX_VLEN);
+       vol_name[HFS_MAX_VLEN] = '\0';
+
+       /* get initial size of HFS volume (size of current ISO volume) */
+       vblen = (last_extent - session_start) * HFS_BLK_CONV;
+
+       /* make sure volume is at least 800k */
+       if (vblen < HFS_MIN_SIZE)
+               vblen += insert_padding_file(HFS_MIN_SIZE - vblen);
+
+       /*
+        * add on size of extents/catalog file, but this may mean the
+        * allocation size will change, so loop round until the
+        * allocation size doesn't change
+        */
+       while (loop) {
+               hce->XTCsize = XClpSiz(vblen);
+               vblen = get_vol_size(vblen);
+               Csize = AlcSiz(vblen);
+
+               if (Csize == lastCsize) {
+                       /* allocation size hasn't changed, so carry on */
+                       loop = 0;
+               } else {
+                       /*
+                        * allocation size has changed, so update
+                        * ISO volume size
+                        */
+                       if ((vblen = get_adj_size(Csize)) < 0) {
+                               sprintf(hce->error,
+                                       "too many files for HFS volume");
+                               return (-1);
+                       }
+                       vblen +=
+                               ROUND_UP((start_extent - session_start) *
+                                               HFS_BLK_CONV, Csize);
+                       lastCsize = Csize;
+               }
+       }
+
+       /* take off the label/map size */
+       vblen -= hce->hfs_map_size;
+
+       hce->hfs_vol_size = vblen;
+
+       /* set the default allocation size for libhfs */
+       hce->Csize = Csize;
+
+       /* format and mount the "volume" */
+       if (hfs_format(hce, 0, vol_name) < 0) {
+               sprintf(hce->error, "can't HFS format %s", vol_name);
+               return (-1);
+       }
+       /*
+        * update the ISO structures with new start extents and any
+        * padding required
+        */
+       if (Csize != SECTOR_SIZE) {
+               last_extent = adj_size(Csize, start_extent,
+                                       hce->hfs_hdr_size + hce->hfs_map_size);
+               adj_size_other(dpnt);
+       }
+       if ((vol = hfs_mount(hce, 0, 0)) == 0) {
+               sprintf(hce->error, "can't HFS mount %s", vol_name);
+               return (-1);
+       }
+       /* save the volume for possible later use */
+       vol_save = vol;
+
+       /*
+        * Recursively "copy" the files to the volume
+        * - we need to know the first allocation block in the volume as
+        * starting blocks of files are relative to this.
+        */
+       ret = copy_to_mac_vol(vol, dpnt);
+       if (ret < 0)
+               return (ret);
+
+       /*
+        * make the Desktop files - I *think* this stops the Mac rebuilding the
+        * desktop when the CD is mounted on a Mac These will be ignored if they
+        * already exist
+        */
+       if (create_dt)
+               ret = make_desktop(vol,
+                               (last_extent - session_start) * HFS_BLK_CONV);
+       if (ret < 0)
+               return (ret);
+
+       /* close the volume */
+       if (hfs_flush(vol) < 0)
+               return (-1);
+
+       /* unmount and set the start blocks for the catalog/extents files */
+       if (hfs_umount(vol, (last_extent - session_start) * HFS_BLK_CONV, hfs_lock) < 0)
+               return (-1);
+
+       return (Csize);
+}
+
+#define        TEN 10  /* well, it is! */
+#define        LCHAR "_"
+
+/*
+ *     copy_to_mac_vol: copy all files in a directory to corresponding
+ *                      Mac folder.
+ *
+ *     Files are copied recursively to corresponding folders on the Mac
+ *     volume. The caller routine needs to do a hfs_chdir before calling this
+ *     routine.
+ */
+static int
+copy_to_mac_vol(hfsvol *vol, struct directory *node)
+{
+       struct directory_entry  *s_entry;       /* ISO directory entry */
+       struct directory_entry  *s_entry1;      /* tmp ISO directory entry */
+       struct directory        *dpnt;          /* ISO directory */
+
+       hfsfile                 *hfp;           /* HFS file */
+       hfsdirent               *ent;           /* HFS file entities */
+       long                    id;             /* current HFS folder */
+       long                    dext,
+                               rext;           /* real data/rsrc start blk */
+       int                     ret;            /* result code */
+       int                     new_name;       /* HFS file has modified name */
+
+       int                     tens;
+       int                     digits;
+       int                     i;
+
+       /* store the current HFS directory ID */
+       if ((id = hfs_getcwd(vol)) == 0)
+               return (-1);
+
+       if (verbose > 1)
+               fprintf(stderr, "HFS scanning %s\n", node->whole_name);
+
+       /* loop through the ISO directory entries and process files */
+       for (s_entry = node->contents; s_entry; s_entry = s_entry->next) {
+               /* ignore directory and associated (rsrc) files */
+               if (s_entry->isorec.flags[0] & (ISO_DIRECTORY|ISO_ASSOCIATED))
+                       continue;
+
+               /* ignore any non-Mac type file */
+               if (!s_entry->hfs_ent)
+                       continue;
+
+               /*
+                * ignore if from a previous session
+                * - should be trapped above
+                */
+               if (s_entry->starting_block < session_start)
+                       continue;
+
+#ifdef DEBUG
+               fprintf(stderr, " Name = %s", s_entry->whole_name);
+               fprintf(stderr, "   Startb =  %d\n", s_entry->starting_block);
+#endif /* DEBUG */
+
+               ent = s_entry->hfs_ent;
+
+               /* create file */
+               i = HFS_MAX_FLEN - strlen(ent->name);
+               new_name = 0;
+               tens = TEN;
+               digits = 1;
+
+               while (1) {
+                       /*
+                        * try to open file - if it exists,
+                        * then append '_' to the name and try again
+                        */
+                       errno = 0;
+                       if ((hfs_create(vol, ent->name, ent->u.file.type,
+                                               ent->u.file.creator)) < 0) {
+                               if (errno != EEXIST) {
+                                       /*
+                                        * not an "exist" error, or we can't
+                                        * append as the filename is already
+                                        * HFS_MAX_FLEN chars
+                                        */
+                                       sprintf(hce->error,
+                                               "can't HFS create file %s",
+                                               s_entry->whole_name);
+                                       return (-1);
+                               } else if (i == 0) {
+                                       /*
+                                        * File name at max HFS length
+                                        * - make unique name
+                                        */
+                                       if (!new_name)
+                                               new_name++;
+
+                                       sprintf(ent->name +
+                                               HFS_MAX_FLEN - digits - 1,
+                                               "%s%d", LCHAR, new_name);
+                                       new_name++;
+                                       if (new_name == tens) {
+                                               tens *= TEN;
+                                               digits++;
+                                       }
+                               } else {
+                                       /* append '_' to get new name */
+                                       strcat(ent->name, LCHAR);
+                                       i--;
+                                       new_name = 1;
+                               }
+                       } else
+                               break;
+               }
+
+               /* warn that we have a new name */
+               if (new_name && verbose > 0) {
+                       fprintf(stderr, "Using HFS name: %s for %s\n",
+                               ent->name,
+                               s_entry->whole_name);
+               }
+               /* open file */
+               if ((hfp = hfs_open(vol, ent->name)) == 0) {
+                       sprintf(hce->error, "can't HFS open %s",
+                               s_entry->whole_name);
+                       return (-1);
+               }
+               /* if it has a data fork, then "write" it out */
+               if (ent->u.file.dsize)
+                       write_fork(hfp, ent->u.file.dsize);
+
+               /* if it has a resource fork, set the fork and "write" it out */
+               if (ent->u.file.rsize) {
+                       if ((hfs_setfork(hfp, 1)) < 0)
+                               return (-1);
+                       write_fork(hfp, ent->u.file.rsize);
+               }
+
+               /* make file invisible if ISO9660 hidden */
+               if (s_entry->de_flags & HIDDEN_FILE)
+                       ent->fdflags |= HFS_FNDR_ISINVISIBLE;
+
+               /* update any HFS file attributes */
+               if ((hfs_fsetattr(hfp, ent)) < 0) {
+                       sprintf(hce->error, "can't HFS set attributes %s",
+                               s_entry->whole_name);
+                       return (-1);
+               }
+               /*
+                * get the ISO starting block of data fork (may be zero)
+                * and convert to the equivalent HFS block
+                */
+               if (ent->u.file.dsize) {
+                       dext = (s_entry->starting_block - session_start) *
+                                                               HFS_BLK_CONV;
+               } else {
+                       dext = 0;
+               }
+
+               /*
+                * if the file has a resource fork (associated file),
+                * get it's ISO starting block and convert as above
+                */
+               if (s_entry->assoc && ent->u.file.rsize) {
+                       rext =
+                           (s_entry->assoc->starting_block - session_start) *
+                                                               HFS_BLK_CONV;
+               } else {
+                       rext = 0;
+               }
+
+               /* close the file and update the starting blocks */
+               if (hfs_close(hfp, dext, rext) < 0) {
+                       sprintf(hce->error, "can't HFS close file %s",
+                               s_entry->whole_name);
+                       return (-1);
+               }
+       }
+
+       /* set folder info and custom icon (if it exists) */
+       set_dir_info(vol, node);
+
+       /*
+        * process sub-directories  - have a slight problem here,
+        * if the directory had been relocated, then we need to find the
+        * real directory - we do this by first finding the
+        * real directory_entry, and then finding it's directory info
+        */
+
+       /* following code taken from joliet.c */
+       for (s_entry = node->contents; s_entry; s_entry = s_entry->next) {
+               if ((s_entry->de_flags & RELOCATED_DIRECTORY) != 0) {
+                       /*
+                        * if the directory has been reloacted, then search the
+                        * relocated directory for the real entry
+                        */
+                       for (s_entry1 = reloc_dir->contents; s_entry1;
+                                               s_entry1 = s_entry1->next) {
+                               if (s_entry1->parent_rec == s_entry)
+                                       break;
+                       }
+
+                       /* have a problem - can't find the real directory */
+                       if (s_entry1 == NULL) {
+                               sprintf(hce->error,
+                                       "can't locate relocated directory %s",
+                                       s_entry->whole_name);
+                               return (-1);
+                       }
+               } else
+                       s_entry1 = s_entry;
+
+               /* now have the correct entry - now find the actual directory */
+               if ((s_entry1->isorec.flags[0] & ISO_DIRECTORY) &&
+                               strcmp(s_entry1->name, ".") &&
+                               strcmp(s_entry1->name, "..")) {
+                       if ((s_entry->de_flags & RELOCATED_DIRECTORY) != 0)
+                               dpnt = reloc_dir->subdir;
+                       else
+                               dpnt = node->subdir;
+
+                       while (1) {
+                               if (dpnt->self == s_entry1)
+                                       break;
+                               dpnt = dpnt->next;
+                               if (!dpnt) {
+                                       sprintf(hce->error,
+                                           "can't find directory location %s",
+                                                       s_entry1->whole_name);
+                                       return (-1);
+                               }
+                       }
+                       /*
+                        * now have the correct directory
+                        * - so do the HFS stuff
+                        */
+                       ent = dpnt->hfs_ent;
+
+                       /*
+                        * if we don't have hfs entries, then this is a "deep"
+                        * directory - this will be processed later
+                        */
+                       if (!ent)
+                               continue;
+
+                       /* make sub-folder */
+                       i = HFS_MAX_FLEN - strlen(ent->name);
+                       new_name = 0;
+                       tens = TEN;
+                       digits = 1;
+
+                       while (1) {
+                               /*
+                                * try to create new directory
+                                * - if it exists, then append '_' to the name
+                                * and try again
+                                */
+                               errno = 0;
+                               if (hfs_mkdir(vol, ent->name) < 0) {
+                                       if (errno != EEXIST) {
+                                               /*
+                                                * not an "exist" error,
+                                                * or we can't append as the
+                                                * filename is already
+                                                * HFS_MAX_FLEN chars
+                                                */
+                                               sprintf(hce->error,
+                                                   "can't HFS create folder %s",
+                                                       s_entry->whole_name);
+                                               return (-1);
+                                       } else if (i == 0) {
+                                               /*
+                                                * File name at max HFS length
+                                                * - make unique name
+                                                */
+                                               if (!new_name)
+                                                       new_name++;
+
+                                               sprintf(ent->name +
+                                                   HFS_MAX_FLEN - digits - 1,
+                                                   "%s%d", LCHAR, new_name);
+                                               new_name++;
+                                               if (new_name == tens) {
+                                                       tens *= TEN;
+                                                       digits++;
+                                               }
+                                       } else {
+                                               /* append '_' to get new name */
+                                               strcat(ent->name, LCHAR);
+                                               i--;
+                                               new_name = 1;
+                                       }
+                               } else
+                                       break;
+                       }
+
+                       /* warn that we have a new name */
+                       if (new_name && verbose > 0) {
+                               fprintf(stderr, "Using HFS name: %s for %s\n",
+                                                       ent->name,
+                                                       s_entry->whole_name);
+                       }
+                       /* see if we need to "bless" this folder */
+                       if (hfs_bless && strcmp(s_entry->whole_name, hfs_bless)
+                                       == 0) {
+                               hfs_stat(vol, ent->name, ent);
+                               hfs_vsetbless(vol, ent->cnid);
+                               if (verbose > 0) {
+                                       fprintf(stderr, "Blessing %s (%s)\n",
+                                                       ent->name,
+                                                       s_entry->whole_name);
+                               }
+                               /* stop any further checks */
+                               hfs_bless = NULL;
+                       }
+                       /* change to sub-folder */
+                       if (hfs_chdir(vol, ent->name) < 0)
+                               return (-1);
+
+                       /* recursively copy files ... */
+                       ret = copy_to_mac_vol(vol, dpnt);
+                       if (ret < 0)
+                               return (ret);
+
+                       /* change back to this folder */
+                       if (hfs_setcwd(vol, id) < 0)
+                               return (-1);
+               }
+       }
+
+       return (0);
+}
+
+/*
+ *     set_dir_info:   Set directory info for a file - also use a custom
+ *                     Icon - if it exists.
+ *
+ *     Sets folder' layout (window layout, view, scroll bars etc)
+ *
+ *     Set the 'HFS_FNDR_HASCUSTOMICON' bit of the folder flags
+ *     if a file called 'Icon\r' exists in the folder
+ *
+ *     Also makes sure the Icon file is invisible
+ *     Don't worry if any of this fails ...
+ *
+ *     Thanks to Rob Leslie <rob@mars.org> for how to do this.
+ */
+
+#define        ICON    "Icon"
+
+static void
+set_dir_info(hfsvol *vol, struct directory *de)
+{
+       hfsdirent       *ent = de->hfs_ent;
+       hfsdirent       ent1;
+       char            name[HFS_MAX_FLEN + 1];
+       unsigned short  flags = 0;
+
+       memset(&ent1, 0, sizeof (hfsdirent));
+
+       sprintf(name, "%s\r", ICON);
+
+       /* get the attributes for the Icon file */
+       if (hfs_stat(vol, name, &ent1) == 0) {
+
+               /* make sure it is invisible */
+               ent1.fdflags |= HFS_FNDR_ISINVISIBLE;
+
+               /* set the new attributes for the Icon file */
+               hfs_setattr(vol, name, &ent1);
+
+               /* flag the folder as having a custom icon */
+               flags |= HFS_FNDR_HASCUSTOMICON;
+       }
+
+       /* make the current folder invisible if ISO9660 hidden */
+       if (de->self->de_flags & HIDDEN_FILE) {
+               flags |= HFS_FNDR_ISINVISIBLE;
+       }
+
+       /* may not have an hfs_ent for this directory */
+       if (ent == NULL) {
+               ent = &ent1;
+               memset(ent, 0, sizeof (hfsdirent));
+
+               /* get the attributes for the folder */
+               if (hfs_stat(vol, ":", ent) < 0)
+                       return;
+       }
+
+       /* set HFS_FNDR_HASCUSTOMICON/HFS_FNDR_ISINVISIBLE if needed */
+       ent->fdflags |= flags;
+
+       /* set the new attributes for the folder */
+       if (hfs_setattr(vol, ":", ent) < 0) {
+               /*
+                * Only needed if we add things after this if statement.
+                */
+/*             return;*/
+       }
+}
+
+#endif /* APPLE_HYB */
diff --git a/genisoimage/write.c b/genisoimage/write.c
new file mode 100644 (file)
index 0000000..a423ab1
--- /dev/null
@@ -0,0 +1,2840 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)write.c 1.88 06/02/01 joerg */
+/* Parts from @(#)write.c      1.106 07/02/17 joerg */
+/*
+ * Program write.c - dump memory  structures to  file for iso9660 filesystem.
+ *
+ * Written by Eric Youngdale (1993).
+ *
+ * Copyright 1993 Yggdrasil Computing, Incorporated
+ * Copyright (c) 1999-2003 J. Schilling
+ *
+ * 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.
+ */
+
+/* APPLE_HYB James Pearson j.pearson@ge.ucl.ac.uk 23/2/2000 */
+
+#include <mconfig.h>
+#include "genisoimage.h"
+#include <timedefs.h>
+#include <fctldefs.h>
+#ifdef SORTING
+#include "match.h"
+#endif /* SORTING */
+#include <errno.h>
+#include <schily.h>
+#ifdef DVD_VIDEO
+#include "dvd_reader.h"
+#include "dvd_file.h"
+#include "ifo_read.h"
+#endif
+#ifdef APPLE_HYB
+#include <ctype.h>
+#endif
+
+#ifdef VMS
+#include "vms.h"
+#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 int     next_path_index = 1;
+static int     sort_goof;
+
+static int     is_rr_dir = 0;
+
+struct output_fragment *out_tail;
+struct output_fragment *out_list;
+
+struct iso_primary_descriptor vol_desc;
+
+void   set_721(char *pnt, unsigned int i);
+void   set_722(char *pnt, unsigned int i);
+void   set_723(char *pnt, unsigned int i);
+void   set_731(char *pnt, unsigned int i);
+void   set_732(char *pnt, unsigned int i);
+void   set_733(char *pnt, unsigned int i);
+int    get_731(char *p);
+int    get_732(char *p);
+int    get_733(char *p);
+static int     xawrite(void *buffer, int size, int count, FILE *file, 
+                                                         int submode, BOOL islast);
+void   xfwrite(void *buffer, int size, int count, FILE *file, int submode, 
+                                 BOOL islast);
+static         int     assign_directory_addresses(struct directory *node);
+#ifdef APPLE_HYB
+static         void    write_one_file(char *filename, off_t size, FILE *outfile, 
+                                                                               off_t off);
+#else
+static         void    write_one_file(char *filename, off_t size, FILE *outfile);
+#endif
+static         void    write_files(FILE *outfile);
+#if 0
+static         void    dump_filelist   __PR((void));
+#endif
+static         int     compare_dirs(const void *rr, const void *ll);
+int    sort_directory(struct directory_entry **sort_dir, int rr);
+static         int     root_gen(void);
+static         BOOL    assign_file_addresses(struct directory *dpnt, BOOL isnest);
+static         void    free_one_directory(struct directory *dpnt);
+static         void    free_directories(struct directory *dpnt);
+void   generate_one_directory(struct directory *dpnt, FILE *outfile);
+static         void    build_pathlist(struct directory *node);
+static         int     compare_paths(void const *r, void const *l);
+static         int     generate_path_tables(void);
+void   memcpy_max(char *to, char *from, int max);
+void   outputlist_insert(struct output_fragment *frag);
+static         int     file_write(FILE *outfile);
+static         int     pvd_write(FILE *outfile);
+static         int     xpvd_write(FILE *outfile);
+static         int     evd_write(FILE *outfile);
+static         int     vers_write(FILE *outfile);
+static         int     graftcp(char *to, char *from, char *ep);
+static         int     pathcp(char *to, char *from, char *ep);
+static         int     pathtab_write(FILE *outfile);
+static         int     exten_write(FILE *outfile);
+int    oneblock_size(int starting_extent);
+static         int     pathtab_size(int starting_extent);
+static         int     startpad_size(int starting_extent);
+static         int     interpad_size(int starting_extent);
+static         int     endpad_size(int starting_extent);
+static         int     file_gen(void);
+static         int     dirtree_dump(void);
+static         int     dirtree_fixup(int starting_extent);
+static         int     dirtree_size(int starting_extent);
+static         int     ext_size(int starting_extent);
+static         int     dirtree_write(FILE *outfile);
+static         int     dirtree_cleanup(FILE *outfile);
+static         int     startpad_write(FILE *outfile);
+static         int     interpad_write(FILE *outfile);
+static         int     endpad_write(FILE *outfile);
+#ifdef APPLE_HYB
+static         int     hfs_pad;
+static         int     hfs_get_parms(char *key);
+static         void    hfs_file_gen(int start_extent);
+static         void    gen_prepboot(void);
+Ulong  get_adj_size(int Csize);
+int    adj_size(int Csize, int start_extent, int extra);
+void   adj_size_other(struct directory *dpnt);
+static         int     hfs_hce_write(FILE * outfile);
+int    insert_padding_file(int size);
+#endif /* APPLE_HYB */
+
+#ifdef SORTING
+static         int     compare_sort(const void * rr, const void * ll);
+static         void    reassign_link_addresses(struct directory * dpnt);
+static         int     sort_file_addresses(void);
+#endif /* SORTING */
+
+/*
+ * 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
+set_721(char *pnt, unsigned int i)
+{
+       pnt[0] = i & 0xff;
+       pnt[1] = (i >> 8) & 0xff;
+}
+
+void
+set_722(char *pnt, unsigned int i)
+{
+       pnt[0] = (i >> 8) & 0xff;
+       pnt[1] = i & 0xff;
+}
+
+void
+set_723(char *pnt, unsigned int i)
+{
+       pnt[3] = pnt[0] = i & 0xff;
+       pnt[2] = pnt[1] = (i >> 8) & 0xff;
+}
+
+void
+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
+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;
+}
+
+void
+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;
+}
+
+int
+get_731(char *p)
+{
+       return ((p[0] & 0xff)
+               | ((p[1] & 0xff) << 8)
+               | ((p[2] & 0xff) << 16)
+               | ((p[3] & 0xff) << 24));
+}
+
+int
+get_732(char *p)
+{
+       return ((p[3] & 0xff)
+               | ((p[2] & 0xff) << 8)
+               | ((p[1] & 0xff) << 16)
+               | ((p[0] & 0xff) << 24));
+}
+
+int
+get_733(char *p)
+{
+       return ((p[0] & 0xff)
+               | ((p[1] & 0xff) << 8)
+               | ((p[2] & 0xff) << 16)
+               | ((p[3] & 0xff) << 24));
+}
+
+void
+xfwrite(void *buffer, int size, int count, FILE *file, int submode, BOOL islast)
+{
+       /*
+        * This is a hack that could be made better.
+        * XXXIs this the only place?
+        * It is definitely needed on Operating Systems that do not allow to
+        * write files that are > 2GB. If the system is fast enough to be able
+        * to feed 1400 KB/s writing speed of a DVD-R drive, use stdout.
+        * If the system cannot do this reliable, you need to use this hacky
+        * option.
+        */
+       static int      idx = 0;
+
+#ifdef XFWRITE_DEBUG
+       if (count != 1 || (size % 2048) != 0)
+               fprintf(stderr, "Count: %d, size: %d\n", count, size);
+#endif
+
+       if (split_output != 0 &&
+               (idx == 0 || ftell(file) >= ((off_t)1024 * 1024 * 1024))) {
+               char            nbuf[512];
+               extern char     *outfile;
+
+               if (idx == 0)
+                       unlink(outfile);
+               sprintf(nbuf, "%s_%02d", outfile, idx++);
+               file = freopen(nbuf, "wb", file);
+               if (file == NULL) {
+#ifdef USE_LIBSCHILY
+                       comerr("Cannot open '%s'.\n", nbuf);
+#else
+                       fprintf(stderr, "Cannot open '%s'.\n", nbuf);
+                       exit(1);
+#endif
+               }
+       }
+       while (count) {
+               int     got;
+
+               seterrno(0);
+               if (osecsize != 0)
+                       got = xawrite(buffer, size, count, file, submode, islast);
+               else
+                       got = fwrite(buffer, size, count, file);
+
+               if (got <= 0) {
+#ifdef USE_LIBSCHILY
+                       comerr("cannot fwrite %d*%d\n", size, count);
+#else
+                       fprintf(stderr, "cannot fwrite %d*%d\n", size, count);
+                       exit(1);
+#endif
+               }
+               /*
+                * This comment is in hope to prevent silly people from
+                * e.g. SuSE (who did not yet learn C but believe that
+                * they need to patch other peoples code) from changing the
+                * next cast into an illegal lhs cast expression.
+                * The cast below is the correct way to handle the problem.
+                * The (void *) cast is to avoid a GCC warning like:
+                * "warning: dereferencing type-punned pointer will break \
+                * strict-aliasing rules"
+                * which is wrong this code. (void *) introduces a compatible
+                * intermediate type in the cast list.
+                */
+               count -= got;
+               buffer = (void *)(((char *)buffer) + size * got);
+       }
+}
+
+static int
+xawrite(void *buffer, int size, int count, FILE *file, int submode, BOOL islast)
+{
+       register char   *p = buffer;
+       register int    amt = size * count;
+       register int    n;
+       struct xa_subhdr subhdr[2];
+
+       if (osecsize == 2048)
+               return (fwrite(buffer, size, count, file));
+
+       if (amt % 2048)
+               comerrno(EX_BAD,
+                       "Trying to write %d bytes (not a multiple of 2048).\n",
+                       amt);
+
+       subhdr[0].file_number           = subhdr[1].file_number         = 0;
+       subhdr[0].channel_number        = subhdr[1].channel_number      = 0;
+       subhdr[0].coding                = subhdr[1].coding              = 0;
+
+       while (amt > 0) {
+#ifdef LATER
+               if (submode < 0)
+                       subhdr[0].sub_mode = subhdr[1].sub_mode = XA_SUBH_DATA;
+               else
+                       subhdr[0].sub_mode = subhdr[1].sub_mode = submode;
+#else
+               subhdr[0].sub_mode = subhdr[1].sub_mode = XA_SUBH_DATA;
+#endif
+
+               if ((amt <= 2048) && islast) {
+                       subhdr[0].sub_mode = subhdr[1].sub_mode
+                                               |= (XA_SUBH_EOR|XA_SUBH_EOF);
+               }
+               n = fwrite(&subhdr, sizeof (subhdr), 1, file);
+               if (n <= 0)
+                       return (n);
+
+               n = fwrite(p, 2048, 1, file);
+               if (n <= 0)
+                       return (n);
+
+               p += 2048;
+               amt -= 2048;
+       }
+       return (1);
+}
+
+#ifdef APPLE_HYB
+/*
+ * use the deferred_write struct to store info about the hfs_boot_file
+ */
+static struct deferred_write mac_boot;
+
+#endif /* APPLE_HYB */
+static struct deferred_write   *dw_head = NULL,
+                               *dw_tail = NULL;
+
+unsigned int   last_extent_written = 0;
+static Uint    path_table_index;
+time_t begun;
+
+/*
+ * 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
+ */
+static int
+assign_directory_addresses(struct directory *node)
+{
+       int             dir_size;
+       struct directory *dpnt;
+
+       dpnt = node;
+
+       while (dpnt) {
+               /* skip if it's hidden */
+               if (dpnt->dir_flags & INHIBIT_ISO9660_ENTRY) {
+                       dpnt = dpnt->next;
+                       continue;
+               }
+               /*
+                * If we already have an extent for this (i.e. it came from a
+                * multisession disc), then don't reassign a new extent.
+                */
+               dpnt->path_index = next_path_index++;
+               if (dpnt->extent == 0) {
+                       dpnt->extent = last_extent;
+                       dir_size = ISO_BLOCKS(dpnt->size);
+
+                       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 += ISO_BLOCKS(dpnt->ce_bytes);
+                       }
+               }
+               if (dpnt->subdir) {
+                       assign_directory_addresses(dpnt->subdir);
+               }
+               dpnt = dpnt->next;
+       }
+       return (0);
+}
+
+#ifdef APPLE_HYB
+static void
+write_one_file(char *filename, off_t size, FILE *outfile, off_t off)
+#else
+static void
+write_one_file(char *filename, off_t size, FILE *outfile)
+#endif /* APPLE_HYB */
+{
+       /*
+        * It seems that there are still stone age C-compilers
+        * around.
+        * The Metrowerks C found on BeOS/PPC does not allow
+        * more than 32kB of local vars.
+        * As we do not need to call write_one_file() recursively
+        * we make buffer static.
+        */
+static char            buffer[SECTOR_SIZE * NSECT];
+       FILE            *infile;
+       off_t           remain;
+       int     use;
+
+       char *mirror_name;
+       unsigned char md5[16];
+       int include_in_jigdo = list_file_in_jigdo(filename, size, &mirror_name, md5);
+
+       if ((infile = fopen(filename, "rb")) == NULL) {
+#ifdef USE_LIBSCHILY
+               comerr("cannot open '%s'\n", filename);
+#else
+#ifndef        HAVE_STRERROR
+               fprintf(stderr, "cannot open '%s': (%d)\n",
+                               filename, errno);
+#else
+               fprintf(stderr, "cannot open '%s': %s\n",
+                               filename, strerror(errno));
+#endif
+               exit(1);
+#endif
+       }
+#ifdef APPLE_HYB
+       fseek(infile, off, SEEK_SET);
+#endif /* APPLE_HYB */
+       remain = size;
+
+       if (include_in_jigdo)
+               write_jt_match_record(filename, mirror_name, SECTOR_SIZE, size, md5);
+
+       while (remain > 0) {
+               int     amt;
+
+               use = (remain > SECTOR_SIZE * NSECT - 1 ?
+                               NSECT * SECTOR_SIZE : remain);
+               use = ISO_ROUND_UP(use);        /* Round up to nearest sector */
+                                               /* boundary */
+               memset(buffer, 0, use);
+               seterrno(0);
+               amt = fread(buffer, 1, use, infile);
+               if (amt < use && amt < remain) {
+                       /*
+                        * Note that genisoimage is not star and no 100% archiver.
+                        * We only detect file growth if the new size does not
+                        * match 'use' at the last read.
+                        */
+                       if (geterrno() == 0) {
+#ifdef USE_LIBSCHILY
+         comerrno(EX_BAD,
+               "File '%s' did shrink.\n"
+               "Files must not be changed while genisoimage runs!\n",
+               filename);
+#else
+         fprintf(stderr,
+               "File '%s' did shrink.\n"
+               "Files must not be changed while genisoimage runs!\n",
+               filename);
+                               exit(EX_BAD);
+#endif
+                       }
+#ifdef USE_LIBSCHILY
+                       comerr("Cannot read from '%s'\n", filename);
+#else
+                       fprintf(stderr, "Cannot read from '%s'\n", filename);
+                       exit(1);
+#endif
+               }
+               if (!include_in_jigdo)
+                       jtwrite(buffer, use, 1,
+                               XA_SUBH_DATA, remain <= (SECTOR_SIZE * NSECT));
+               xfwrite(buffer, use, 1, outfile,
+                               XA_SUBH_DATA, remain <= (SECTOR_SIZE * NSECT));
+               last_extent_written += use / SECTOR_SIZE;
+#if 0
+               if ((last_extent_written % 1000) < use / SECTOR_SIZE) {
+                       fprintf(stderr, "%d..", last_extent_written);
+               }
+#else
+               if (verbose > 0 &&
+                   (int)(last_extent_written % (gui ? 500 : 5000)) <
+                                                       use / SECTOR_SIZE) {
+                       time_t  now;
+                       time_t  the_end;
+                       double  frac;
+
+                       time(&now);
+                       frac = last_extent_written / (1.0 * last_extent);
+                       the_end = begun + (now - begun) / frac;
+#ifndef NO_FLOATINGPOINT
+                       fprintf(stderr, "%6.2f%% done, estimate finish %s",
+                               frac * 100., ctime(&the_end));
+#else
+                       fprintf(stderr, "%3d.%-02d%% done, estimate finish %s",
+                               (int)(frac * 100.),
+                               (int)((frac+.00005) * 10000.)%100,
+                               ctime(&the_end));
+#endif
+                       fflush(stderr);
+               }
+#endif
+               remain -= use;
+       }
+       fclose(infile);
+}/* write_one_file(... */
+
+static void
+write_files(FILE *outfile)
+{
+       struct deferred_write   *dwpnt,
+                               *dwnext;
+
+       dwpnt = dw_head;
+       while (dwpnt) {
+/*#define DEBUG*/
+#ifdef DEBUG
+               fprintf(stderr,
+               "The file name is %s and pad is %d, size is %lld and extent is %d\n",
+                               dwpnt->name, dwpnt->pad,
+                               (Llong)dwpnt->size, dwpnt->extent);
+#endif
+               if (dwpnt->table) {
+                       jtwrite(dwpnt->table, ISO_ROUND_UP(dwpnt->size), 1, XA_SUBH_DATA, TRUE);
+                       xfwrite(dwpnt->table, ISO_ROUND_UP(dwpnt->size), 1,
+                                                       outfile,
+                                                       XA_SUBH_DATA, TRUE);
+                       last_extent_written += ISO_BLOCKS(dwpnt->size);
+                       table_size += dwpnt->size;
+/*                     fprintf(stderr, "Size %lld ", (Llong)dwpnt->size); */
+                       free(dwpnt->table);
+                       dwpnt->table = NULL;
+               } else {
+
+#ifdef VMS
+                       vms_write_one_file(dwpnt->name, dwpnt->size, outfile);
+#else
+#ifdef APPLE_HYB
+                       write_one_file(dwpnt->name, dwpnt->size, outfile,
+                                                               dwpnt->off);
+#else
+                       write_one_file(dwpnt->name, dwpnt->size, outfile);
+#endif /* APPLE_HYB */
+#endif
+                       free(dwpnt->name);
+                       dwpnt->name = NULL;
+               }
+
+
+#ifndef DVD_VIDEO
+#define        dvd_video       0
+#endif
+
+#ifndef APPLE_HYB
+#define        apple_hyb       0
+#endif
+
+#if    defined(APPLE_HYB) || defined(DVD_VIDEO)
+
+               if (apple_hyb || dvd_video) {
+                       /*
+                        * we may have to pad out ISO files to work with HFS
+                        * clump sizes
+                        */
+                       char    blk[SECTOR_SIZE];
+                       Uint    i;
+
+                       for (i = 0; i < dwpnt->pad; i++) {
+                               jtwrite(blk, SECTOR_SIZE, 1, 0, FALSE);
+                               xfwrite(blk, SECTOR_SIZE, 1, outfile, 0, FALSE);
+                               last_extent_written++;
+                       }
+               }
+#endif /* APPLE_HYB || DVD_VIDEO */
+
+
+               dwnext = dwpnt;
+               dwpnt = dwpnt->next;
+               free(dwnext);
+               dwnext = NULL;
+       }
+}/* write_files(... */
+
+#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
+
+static int
+compare_dirs(const void *rr, const void *ll)
+{
+       char            *rpnt,
+                       *lpnt;
+       struct directory_entry **r,
+                       **l;
+
+       r = (struct directory_entry **) rr;
+       l = (struct directory_entry **) ll;
+       rpnt = (*r)->isorec.name;
+       lpnt = (*l)->isorec.name;
+
+#ifdef APPLE_HYB
+       /*
+        * resource fork MUST (not sure if this is true for HFS volumes) be
+        * before the data fork - so force it here
+        */
+       if ((*r)->assoc && (*r)->assoc == (*l))
+               return (1);
+       if ((*l)->assoc && (*l)->assoc == (*r))
+               return (-1);
+#endif /* APPLE_HYB */
+
+       /* If the entries are the same, this is an error. */
+       if (strcmp(rpnt, lpnt) == 0) {
+#ifdef USE_LIBSCHILY
+               errmsgno(EX_BAD,
+                       "Error: '%s' and '%s' have the same ISO9660 name '%s'.\n",
+                       (*r)->whole_name, (*l)->whole_name,
+                       rpnt);
+#else
+               fprintf(stderr,
+                       "Error: '%s' and '%s' have the same ISO9660 name '%s'.\n",
+                       (*r)->whole_name, (*l)->whole_name,
+                       rpnt);
+#endif
+               sort_goof++;
+       }
+       /* Check we don't have the same RR name */
+       if (use_RockRidge && !is_rr_dir) {
+               /*
+                * entries *can* have the same RR name in the "rr_moved"
+                * directory so skip checks if we're in reloc_dir
+                */
+               if (!(strcmp((*r)->name, (*l)->name))) {
+#ifdef USE_LIBSCHILY
+                       errmsgno(EX_BAD,
+                       "Error: '%s' and '%s' have the same Rock Ridge name '%s'.\n",
+                               (*r)->whole_name, (*l)->whole_name,
+                               (*r)->name);
+#else
+                       fprintf(stderr,
+                       "Error: '%s' and '%s' have the same Rock Ridge name '%s'.\n",
+                               (*r)->whole_name, (*l)->whole_name,
+                               (*r)->name);
+#endif
+                       sort_goof++;
+               }
+       }
+       /*
+        * Put the '.' and '..' entries on the head of the sorted list. For
+        * normal ASCII, this always happens to be the case, but out of band
+        * characters cause this not to be the case sometimes.
+        * FIXME(eric) - these tests seem redundant, in that the name is never
+        * assigned these values.  It will instead be \000 or \001, and thus
+        * should always be sorted correctly.   I need to figure out why I
+        * thought I needed this in the first place.
+        */
+#if 0
+       if (strcmp(rpnt, ".") == 0)
+               return (-1);
+       if (strcmp(lpnt, ".") == 0)
+               return (1);
+
+       if (strcmp(rpnt, "..") == 0)
+               return (-1);
+       if (strcmp(lpnt, "..") == 0)
+               return (1);
+#else
+       /*
+        * The code above is wrong (as explained in Eric's comment), leading to
+        * incorrect sort order iff the -L option ("allow leading dots") is in
+        * effect and a directory contains entries that start with a dot.
+        *  (TF, Tue Dec 29 13:49:24 CET 1998)
+        */
+       if ((*r)->isorec.name_len[0] == 1 && *rpnt == 0)
+               return (-1);    /* '.' */
+       if ((*l)->isorec.name_len[0] == 1 && *lpnt == 0)
+               return (1);
+
+       if ((*r)->isorec.name_len[0] == 1 && *rpnt == 1)
+               return (-1);    /* '..' */
+       if ((*l)->isorec.name_len[0] == 1 && *lpnt == 1)
+               return (1);
+#endif
+
+       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);
+
+               if ((unsigned char) *rpnt < (unsigned char) *lpnt)
+                       return (-1);
+               if ((unsigned char) *rpnt > (unsigned char) *lpnt)
+                       return (1);
+               rpnt++;
+               lpnt++;
+       }
+       if (*rpnt)
+               return (1);
+       if (*lpnt)
+               return (-1);
+       return (0);
+}
+
+/*
+ * Function:           sort_directory
+ *
+ * Purpose:            Sort the directory in the appropriate ISO9660
+ *                     order.
+ *
+ * Notes:              Returns 0 if OK, returns > 0 if an error occurred.
+ */
+int
+sort_directory(struct directory_entry **sort_dir, int rr)
+{
+       int             dcount = 0;
+       int             xcount = 0;
+       int             j;
+       int             i,
+                       len;
+       struct directory_entry *s_entry;
+       struct directory_entry **sortlist;
+
+       /* need to keep a count of how many entries are hidden */
+       s_entry = *sort_dir;
+       while (s_entry) {
+               if (s_entry->de_flags & INHIBIT_ISO9660_ENTRY)
+                       xcount++;
+               dcount++;
+               s_entry = s_entry->next;
+       }
+
+       if (dcount == 0) {
+               return (0);
+       }
+       /* OK, now we know how many there are.  Build a vector for sorting. */
+       sortlist = (struct directory_entry **)
+               e_malloc(sizeof (struct directory_entry *) * dcount);
+
+       j = dcount - 1;
+       dcount = 0;
+       s_entry = *sort_dir;
+       while (s_entry) {
+               if (s_entry->de_flags & INHIBIT_ISO9660_ENTRY) {
+                       /* put any hidden entries at the end of the vector */
+                       sortlist[j--] = s_entry;
+               } else {
+                       sortlist[dcount] = s_entry;
+                       dcount++;
+               }
+               len = s_entry->isorec.name_len[0];
+               s_entry->isorec.name[len] = 0;
+               s_entry = s_entry->next;
+       }
+
+       /* Each directory is required to contain at least . and .. */
+       if (dcount < 2) {
+#ifdef USE_LIBSCHILY
+               errmsgno(EX_BAD,
+                       "Directory size too small (. or .. missing ??%s)\n",
+                       "?");   /* Try to avoid a GCC trigraph warning */
+#else
+               fprintf(stderr,
+                       "Directory size too small (. or .. missing ??%s)\n",
+                       "?");   /* Try to avoid a GCC trigraph warning */
+#endif
+               sort_goof = 1;
+
+       } else {
+               /* only sort the non-hidden entries */
+               sort_goof = 0;
+               is_rr_dir = rr;
+#ifdef PROTOTYPES
+               qsort(sortlist, dcount, sizeof (struct directory_entry *),
+                       (int (*) (const void *, const void *)) compare_dirs);
+#else
+               qsort(sortlist, dcount, sizeof (struct directory_entry *),
+                       compare_dirs);
+#endif
+
+               /*
+                * Now reassemble the linked list in the proper sorted order
+                * We still need the hidden entries, as they may be used in
+                * the Joliet tree.
+                */
+               for (i = 0; i < dcount + xcount - 1; i++) {
+                       sortlist[i]->next = sortlist[i + 1];
+               }
+
+               sortlist[dcount + xcount - 1]->next = NULL;
+               *sort_dir = sortlist[0];
+       }
+
+       free(sortlist);
+       sortlist = NULL;
+       return (sort_goof);
+}
+
+static int
+root_gen()
+{
+       init_fstatbuf();
+
+       root_record.length[0] = 1 +
+                       offsetof(struct iso_directory_record, name[0]);
+       root_record.ext_attr_length[0] = 0;
+       set_733((char *) root_record.extent, root->extent);
+       set_733((char *) root_record.size, ISO_ROUND_UP(root->size));
+       iso9660_date(root_record.date, root_statbuf.st_mtime);
+       root_record.flags[0] = ISO_DIRECTORY;
+       root_record.file_unit_size[0] = 0;
+       root_record.interleave[0] = 0;
+       set_723(root_record.volume_sequence_number, volume_sequence_number);
+       root_record.name_len[0] = 1;
+       return (0);
+}
+
+#ifdef SORTING
+/*
+ *     sorts deferred_write entries based on the sort weight
+ */
+static int
+compare_sort(const void *rr, const void *ll)
+{
+       struct deferred_write   **r;
+       struct deferred_write   **l;
+       int                     r_sort;
+       int                     l_sort;
+
+       r = (struct deferred_write **) rr;
+       l = (struct deferred_write **) ll;
+       r_sort = (*r)->s_entry->sort;
+       l_sort = (*l)->s_entry->sort;
+
+       if (r_sort != l_sort)
+               return (r_sort < l_sort ? 1 : -1);
+       else
+               return ((*r)->extent - (*l)->extent);
+}
+
+/*
+ *     reassign start extents to files that are "hard links" to
+ *     files that may have been sorted
+ */
+static void
+reassign_link_addresses(struct directory *dpnt)
+{
+       struct directory_entry  *s_entry;
+       struct file_hash        *s_hash;
+
+       while (dpnt) {
+               s_entry = dpnt->contents;
+               for (s_entry = dpnt->contents; s_entry; s_entry = s_entry->next) {
+                       /* link files have already been given the weight NOT_SORTED */
+                       if (s_entry->sort == NOT_SORTED)
+                       {
+                               /* update the start extent */
+                               s_hash = find_hash(s_entry->dev, s_entry->inode);
+                               if (s_hash) {
+                                       set_733((char *) s_entry->isorec.extent,
+                                                       s_hash->starting_block);
+                                       s_entry->starting_block = s_hash->starting_block;
+                               }
+                       }
+
+                       if (verbose > 2 && s_entry->size != 0) {
+                               fprintf(stderr, "%8u %8u ",
+                                       s_entry->starting_block,
+                                       (unsigned int)(s_entry->starting_block + ISO_BLOCKS(s_entry->size) - 1));
+
+                               if (s_entry->inode != TABLE_INODE) {
+                                       fprintf(stderr, "%s\n", s_entry->whole_name);
+                               } else {
+                                       fprintf(stderr, "%s%s%s\n",
+                                               s_entry->filedir->whole_name,
+                                               SPATH_SEPARATOR, trans_tbl);
+                               }
+                       }
+               }
+               if (dpnt->subdir) {
+                       reassign_link_addresses(dpnt->subdir);
+               }
+
+               dpnt = dpnt->next;
+       }
+}
+
+/*
+ *     sort files in order of the given sort weight
+ */
+static int
+sort_file_addresses()
+{
+       struct deferred_write   *dwpnt;
+       struct deferred_write   **sortlist;
+       struct directory_entry  *s_entry;
+       int                     start_extent;
+       int                     num = 0;
+       int                     i;
+
+       /* need to store start extents for linked files */
+       flush_hash();
+
+       /* find out how many files we have */
+       dwpnt = dw_head;
+       while (dwpnt) {
+               num++;
+               dwpnt = dwpnt->next;
+       }
+
+       /* return if we have none */
+       if (num == 0) {
+               return (1);
+       }
+
+       /* save the start extent of the first file */
+       start_extent = dw_head->extent;
+
+       /* set up vector to store entries */
+       sortlist = (struct deferred_write **)
+               e_malloc(sizeof (struct deferred_write *) * num);
+
+       for (i = 0, dwpnt = dw_head; i < num; i++, dwpnt = dwpnt->next)
+               sortlist[i] = dwpnt;
+
+       /* sort the list */
+#ifdef PROTOTYPES
+       qsort(sortlist, num, sizeof (struct deferred_write *),
+               (int (*)(const void *, const void *))compare_sort);
+#else
+       qsort(sortlist, num, sizeof (struct deferred_write *), compare_sort);
+#endif
+
+       /* reconstruct the linked list */
+       for (i = 0; i < num-1; i++) {
+               sortlist[i]->next = sortlist[i+1];
+       }
+
+       sortlist[num-1]->next = NULL;
+       dw_head = sortlist[0];
+
+       free(sortlist);
+
+       /* set the new start extents for the sorted list */
+       for (i = 0, dwpnt = dw_head; i < num; i++, dwpnt = dwpnt->next) {
+               s_entry = dwpnt->s_entry;
+               dwpnt->extent = s_entry->starting_block = start_extent;
+               set_733((char *) s_entry->isorec.extent, start_extent);
+
+               start_extent += ISO_BLOCKS(s_entry->size);
+#ifdef DVD_VIDEO
+               /*
+                * Shouldn't this be done for every type of sort? Otherwise
+                * we will loose every pad info we add if we sort the files
+                */
+               if (dvd_video) {
+                       start_extent += dwpnt->pad;
+               }
+#endif /* DVD_VIDEO */
+
+               /* cache start extents for any linked files */
+               add_hash(s_entry);
+       }
+
+       return (0);
+}
+#endif /* SORTING */
+
+
+
+static BOOL
+assign_file_addresses(struct directory *dpnt, BOOL isnest)
+{
+       struct directory *finddir;
+       struct directory_entry *s_entry;
+       struct file_hash *s_hash;
+       struct deferred_write *dwpnt;
+       char            whole_path[PATH_MAX];
+#ifdef DVD_VIDEO
+       char            dvd_path[PATH_MAX];
+       title_set_info_t * title_set_info = NULL;
+       char    *p;
+#endif
+       BOOL    ret = FALSE;
+
+       while (dpnt) {
+#ifdef DVD_VIDEO
+               if (dvd_video && root == dpnt->parent &&
+                   ((p = strstr(dpnt->whole_name, "VIDEO_TS")) != 0)&&
+                   strcmp(p, "VIDEO_TS") == 0) {
+
+                       int     maxlen = strlen(dpnt->whole_name)-8;
+                       if (maxlen > (sizeof (dvd_path)-1))
+                               maxlen = sizeof (dvd_path)-1;
+                       strncpy(dvd_path, dpnt->whole_name, maxlen);
+                       dvd_path[maxlen] = '\0';
+
+#ifdef DEBUG
+                       fprintf(stderr, "Found 'VIDEO_TS', the path is %s \n", dvd_path);
+#endif
+                       title_set_info = DVDGetFileSet(dvd_path);
+                       if (title_set_info == 0) {
+                               /*
+                                * Do not switch off -dvd-video but let is fail later.
+                                */
+/*                             dvd_video = 0;*/
+                               errmsgno(EX_BAD, "Unable to parse DVD-Video structures.\n");
+                       } else {
+                               ret = TRUE;
+                       }
+               }
+#endif /* DVD_VIDEO */
+
+               s_entry = dpnt->contents;
+               for (s_entry = dpnt->contents; s_entry;
+                                               s_entry = s_entry->next) {
+                       /*
+                        * If we already have an  extent for this entry, then
+                        * don't assign a new one.  It must have come from a
+                        * previous session on the disc.  Note that we don't
+                        * end up scheduling the thing for writing either.
+                        */
+                       if (get_733(s_entry->isorec.extent) != 0) {
+                               continue;
+                       }
+                       /*
+                        * This saves some space if there are symlinks present
+                        */
+                       s_hash = find_hash(s_entry->dev, s_entry->inode);
+                       if (s_hash) {
+                               if (verbose > 2) {
+                                       fprintf(stderr, "Cache hit for '%s%s%s'\n", s_entry->filedir->de_name,
+                                               SPATH_SEPARATOR,
+                                               s_entry->name);
+                               }
+                               set_733((char *) s_entry->isorec.extent,
+                                               s_hash->starting_block);
+                               set_733((char *) s_entry->isorec.size,
+                                               s_hash->size);
+#ifdef SORTING
+                               /* check for non-directory files */
+                               if (do_sort && ((s_entry->isorec.flags[0] & ISO_DIRECTORY) == 0)) {
+                                       /* make sure the real file has the highest weighting */
+                                       s_hash->de->sort = MAX(s_entry->sort, s_hash->de->sort);
+                                       /* flag this as a potential non-sorted file */
+                                       s_entry->sort = NOT_SORTED;
+                               }
+#endif /* SORTING */
+                               continue;
+                       }
+                       /*
+                        * If this is for a directory that is not a . or
+                        * a .. entry, then look up the information for the
+                        * entry.  We have already assigned extents for
+                        * directories, so we just need to fill in the blanks
+                        * here.
+                        */
+                       if (strcmp(s_entry->name, ".") != 0 &&
+                                       strcmp(s_entry->name, "..") != 0 &&
+                                       s_entry->isorec.flags[0] & ISO_DIRECTORY) {
+                               finddir = dpnt->subdir;
+                               while (1 == 1) {
+                                       if (finddir->self == s_entry)
+                                               break;
+                                       finddir = finddir->next;
+                                       if (!finddir) {
+#ifdef DVD_VIDEO
+                                               if (title_set_info != 0) {
+                                                       DVDFreeFileSet(title_set_info);
+                                               }
+#endif
+                                               comerrno(EX_BAD,
+                                                       "Fatal goof - could not find dir entry for '%s'\n",
+                                                       s_entry->name);
+                                       }
+                               }
+                               set_733((char *) s_entry->isorec.extent,
+                                               finddir->extent);
+                               s_entry->starting_block = finddir->extent;
+                               s_entry->size = ISO_ROUND_UP(finddir->size);
+                               total_dir_size += s_entry->size;
+                               add_hash(s_entry);
+                               set_733((char *) s_entry->isorec.size,
+                                               ISO_ROUND_UP(finddir->size));
+                               continue;
+                       }
+                       /*
+                        * If this is . or .., then look up the relevant info
+                        * from the tables.
+                        */
+                       if (strcmp(s_entry->name, ".") == 0) {
+                               set_733((char *) 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 = ISO_ROUND_UP(dpnt->size);
+
+                               add_hash(s_entry);
+                               s_entry->starting_block = dpnt->extent;
+                               set_733((char *) s_entry->isorec.size,
+                                               ISO_ROUND_UP(dpnt->size));
+                               continue;
+                       }
+                       if (strcmp(s_entry->name, "..") == 0) {
+                               if (dpnt == root) {
+                                       total_dir_size += root->size;
+                               }
+                               set_733((char *) 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 =
+                                       ISO_ROUND_UP(dpnt->parent->size);
+
+                               add_hash(s_entry);
+                               s_entry->starting_block = dpnt->parent->extent;
+                               set_733((char *) s_entry->isorec.size,
+                                       ISO_ROUND_UP(dpnt->parent->size));
+                               continue;
+                       }
+                       /*
+                        * Some ordinary non-directory file.  Just 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));
+                               /* save this directory entry for later use */
+                               dwpnt->s_entry = s_entry;
+                               /* set the initial padding to zero */
+                               dwpnt->pad = 0;
+#ifdef DVD_VIDEO
+                               if (dvd_video && (title_set_info != 0)) {
+                                       int pad;
+
+                                       pad = DVDGetFilePad(title_set_info, s_entry->name);
+                                       if (pad < 0) {
+                                               errmsgno(EX_BAD,
+                                               "Implementation botch. Video pad for file %s is %d\n",
+                                               s_entry->name, pad),
+                                               comerrno(EX_BAD,
+                                               "Either the *.IFO file is bad or you found a genisoimage bug.\n");
+                                       }
+                                       dwpnt->pad = pad;
+                                       if (verbose > 0 && pad != 0) {
+                                               fprintf(stderr,
+                                                       "The pad was %d for file %s\n", dwpnt->pad, s_entry->name);
+                                       }
+                               }
+#endif /* DVD_VIDEO */
+#ifdef APPLE_HYB
+                               /*
+                                * maybe an offset to start of the real
+                                * file/fork
+                                */
+                               dwpnt->off = s_entry->hfs_off;
+#else
+                               dwpnt->off = (off_t)0;
+#endif /* APPLE_HYB */
+                               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;
+                                       sprintf(whole_path, "%s%s%s",
+                                               s_entry->filedir->whole_name,
+                                               SPATH_SEPARATOR, trans_tbl);
+                               } 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((char *) s_entry->isorec.extent,
+                                                               last_extent);
+                               s_entry->starting_block = last_extent;
+                               add_hash(s_entry);
+                               last_extent += ISO_BLOCKS(s_entry->size);
+#ifdef DVD_VIDEO
+                               /* Shouldn't we always add the pad info? */
+                               if (dvd_video) {
+                                       last_extent += dwpnt->pad;
+                               }
+#endif /* DVD_VIDEO */
+                               if (verbose > 2 && !do_sort) {
+                                       fprintf(stderr, "%8d %8u %s\n",
+                                               s_entry->starting_block,
+                                               last_extent - 1, whole_path);
+                               }
+#ifdef DBG_ISO
+                               if (ISO_BLOCKS(s_entry->size) > 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 %lld\n",
+                                               (Llong)s_entry->size);
+
+                               }
+#endif
+#ifdef NOT_NEEDED      /* Never use this code if you like to create a DVD */
+
+                               if (last_extent > (800000000 >> 11)) {
+                                       /* More than 800Mb? 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 %lld\n",
+                                                       (Llong)s_entry->size);
+                                       exit(1);
+                               }
+#endif
+                               continue;
+                       }
+                       /*
+                        * 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((char *) s_entry->isorec.extent, last_extent);
+               }
+               if (dpnt->subdir) {
+                       if (assign_file_addresses(dpnt->subdir, TRUE))
+                               ret = TRUE;
+               }
+               dpnt = dpnt->next;
+       }
+#ifdef DVD_VIDEO
+       if (title_set_info != NULL) {
+               DVDFreeFileSet(title_set_info);
+       }
+       if (dvd_video && !ret && !isnest) {
+               errmsgno(EX_BAD,
+                       "Could not find correct 'VIDEO_TS' directory.\n");
+       }
+#endif /* DVD_VIDEO */
+       return (ret);
+} /* assign_file_addresses(... */
+
+static void
+free_one_directory(struct directory *dpnt)
+{
+       struct directory_entry *s_entry;
+       struct directory_entry *s_entry_d;
+
+       s_entry = dpnt->contents;
+       while (s_entry) {
+               s_entry_d = s_entry;
+               s_entry = s_entry->next;
+
+               if (s_entry_d->rr_attributes) {
+                       free(s_entry_d->rr_attributes);
+                       s_entry_d->rr_attributes = NULL;
+               }
+               if (s_entry_d->name != NULL) {
+                       free(s_entry_d->name);
+                       s_entry_d->name = NULL;
+               }
+               if (s_entry_d->whole_name != NULL) {
+                       free(s_entry_d->whole_name);
+                       s_entry_d->whole_name = NULL;
+               }
+#ifdef APPLE_HYB
+               if (apple_both && s_entry_d->hfs_ent && !s_entry_d->assoc)
+                       free(s_entry_d->hfs_ent);
+#endif /* APPLE_HYB */
+
+               free(s_entry_d);
+               s_entry_d = NULL;
+       }
+       dpnt->contents = NULL;
+}/* free_one_directory(... */
+
+static void
+free_directories(struct directory *dpnt)
+{
+       while (dpnt) {
+               free_one_directory(dpnt);
+               if (dpnt->subdir)
+                       free_directories(dpnt->subdir);
+               dpnt = dpnt->next;
+       }
+}
+
+void
+generate_one_directory(struct directory *dpnt, FILE *outfile)
+{
+       unsigned int    ce_address = 0;
+       char            *ce_buffer;
+       unsigned int    ce_index = 0;
+       unsigned int    ce_size;
+       unsigned int    dir_index;
+       char            *directory_buffer;
+       int             new_reclen;
+       struct directory_entry *s_entry;
+       struct directory_entry *s_entry_d;
+       unsigned int    total_size;
+
+       total_size = ISO_ROUND_UP(dpnt->size);
+       directory_buffer = (char *) e_malloc(total_size);
+       memset(directory_buffer, 0, total_size);
+       dir_index = 0;
+
+       ce_size = ISO_ROUND_UP(dpnt->ce_bytes);
+       ce_buffer = NULL;
+
+       if (ce_size > 0) {
+               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) {
+               /* skip if it's hidden */
+               if (s_entry->de_flags & INHIBIT_ISO9660_ENTRY) {
+                       s_entry = s_entry->next;
+                       continue;
+               }
+               /*
+                * 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 = ISO_ROUND_UP(dir_index);
+               }
+               memcpy(directory_buffer + dir_index, &s_entry->isorec,
+                       offsetof(struct iso_directory_record, name[0]) +
+                       s_entry->isorec.name_len[0]);
+               dir_index += offsetof(struct iso_directory_record, name[0]) +
+                       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) {
+                               struct iso_xa_dir_record *xadp;
+                               unsigned char   *pnt;
+                               int             len,
+                                               nbytes;
+
+                               /*
+                                * Go through the entire record, first skip
+                                * the XA record and then 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;
+
+                               if (len >= 14) {
+                                       xadp = (struct iso_xa_dir_record *)pnt;
+
+                                       if (xadp->signature[0] == 'X' && xadp->signature[1] == 'A' &&
+                                                                       xadp->reserved[0] == '\0') {
+                                               len -= 14;
+                                               pnt += 14;
+                                       }
+                               }
+
+                               while (len > 3) {
+#ifdef DEBUG
+                                       if (ce_size <= 0) {
+                                               fprintf(stderr,
+                                               "Warning: ce_index(%d) && ce_address(%d) not initialized\n",
+                                                       ce_index, ce_address);
+                                       }
+#endif
+
+                                       if (pnt[0] == 'C' && pnt[1] == 'E') {
+                                               nbytes = get_733((char *) pnt + 20);
+
+                                               if ((ce_index & (SECTOR_SIZE - 1)) + nbytes >=
+                                                       SECTOR_SIZE) {
+                                                       ce_index = ISO_ROUND_UP(ce_index);
+                                               }
+                                               set_733((char *) pnt + 4,
+                                                       (ce_address + ce_index) >> 11);
+                                               set_733((char *) 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;
+
+               /*
+                * Joliet doesn't use the Rock Ridge attributes, so we free
+                * it here.
+                */
+               if (s_entry_d->rr_attributes) {
+                       free(s_entry_d->rr_attributes);
+                       s_entry_d->rr_attributes = NULL;
+               }
+       }
+
+       if (dpnt->size != dir_index) {
+#ifdef USE_LIBSCHILY
+               errmsgno(EX_BAD,
+                       "Unexpected directory length %lld expected: %d '%s'\n",
+                       (Llong)dpnt->size,
+                       dir_index, dpnt->de_name);
+#else
+               fprintf(stderr,
+                       "Unexpected directory length %lld expected: %d '%s'\n",
+                       (Llong)dpnt->size,
+                       dir_index, dpnt->de_name);
+#endif
+       }
+       jtwrite(directory_buffer, total_size, 1, 0, FALSE);
+       xfwrite(directory_buffer, total_size, 1, outfile, 0, FALSE);
+       last_extent_written += total_size >> 11;
+       free(directory_buffer);
+       directory_buffer = NULL;
+
+       if (ce_size > 0) {
+               if (ce_index != dpnt->ce_bytes) {
+#ifdef USE_LIBSCHILY
+                       errmsgno(EX_BAD,
+                       "Continuation entry record length mismatch %d expected: %d.\n",
+                               ce_index, dpnt->ce_bytes);
+#else
+                       fprintf(stderr,
+                       "Continuation entry record length mismatch %d expected: %d.\n",
+                               ce_index, dpnt->ce_bytes);
+#endif
+               }
+               jtwrite(ce_buffer, ce_size, 1, 0, FALSE);
+               xfwrite(ce_buffer, ce_size, 1, outfile, 0, FALSE);
+               last_extent_written += ce_size >> 11;
+               free(ce_buffer);
+               ce_buffer = NULL;
+       }
+}/* generate_one_directory(... */
+
+static void
+build_pathlist(struct directory *node)
+{
+       struct directory *dpnt;
+
+       dpnt = node;
+
+       while (dpnt) {
+               /* skip if it's hidden */
+               if ((dpnt->dir_flags & INHIBIT_ISO9660_ENTRY) == 0)
+                       pathlist[dpnt->path_index] = dpnt;
+
+               if (dpnt->subdir)
+                       build_pathlist(dpnt->subdir);
+               dpnt = dpnt->next;
+       }
+}/* build_pathlist(... */
+
+static int
+compare_paths(void const *r, void const *l)
+{
+       struct directory const *ll = *(struct directory * const *) l;
+       struct directory const *rr = *(struct directory * const *) r;
+
+       if (rr->parent->path_index < ll->parent->path_index) {
+               return (-1);
+       }
+       if (rr->parent->path_index > ll->parent->path_index) {
+               return (1);
+       }
+       return (strcmp(rr->self->isorec.name, ll->self->isorec.name));
+
+}/* compare_paths(... */
+
+static int
+generate_path_tables()
+{
+       struct directory_entry *de = NULL;
+       struct directory *dpnt;
+       int             fix;
+       int             i;
+       int             j;
+       int             namelen;
+       char            *npnt;
+       char            *npnt1;
+       int             tablesize;
+
+       /* 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;
+#ifdef PROTOTYPES
+               qsort(&pathlist[1], next_path_index - 1,
+                       sizeof (struct directory *),
+                       (int (*) (const void *, const void *)) compare_paths);
+#else
+               qsort(&pathlist[1], next_path_index - 1,
+                       sizeof (struct directory *),
+                       compare_paths);
+#endif
+
+               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) {
+#ifdef USE_LIBSCHILY
+                       comerrno(EX_BAD, "Entry %d not in path tables\n", j);
+#else
+                       fprintf(stderr, "Entry %d not in path tables\n", j);
+                       exit(1);
+#endif
+               }
+               npnt = dpnt->de_name;
+
+               /* So the root comes out OK */
+               if ((*npnt == 0) || (dpnt == root)) {
+                       npnt = ".";
+               }
+               npnt1 = strrchr(npnt, PATH_SEPARATOR);
+               if (npnt1) {
+                       npnt = npnt1 + 1;
+               }
+               de = dpnt->self;
+               if (!de) {
+#ifdef USE_LIBSCHILY
+                       comerrno(EX_BAD,
+                       "Fatal ISO9660 goof - directory has amnesia\n");
+#else
+                       fprintf(stderr,
+                       "Fatal ISO9660 goof - directory has amnesia\n");
+                       exit(1);
+#endif
+               }
+               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;
+
+               if (dpnt->parent->path_index > 0xffff) {
+#ifdef USE_LIBSCHILY
+                       comerrno(EX_BAD,
+                       "Unable to generate sane path tables - too many directories (%d)\n",
+                               dpnt->parent->path_index);
+#else
+                       fprintf(stderr,
+                       "Unable to generate sane path tables - too many directories (%d)\n",
+                               dpnt->parent->path_index);
+                       exit(1);
+#endif
+               }
+
+               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);
+       pathlist = NULL;
+       if (path_table_index != path_table_size) {
+#ifdef USE_LIBSCHILY
+               errmsgno(EX_BAD,
+                       "Path table lengths do not match %d expected: %d\n",
+                       path_table_index,
+                       path_table_size);
+#else
+               fprintf(stderr,
+                       "Path table lengths do not match %d expected: %d\n",
+                       path_table_index,
+                       path_table_size);
+#endif
+       }
+       return (0);
+}/* generate_path_tables(... */
+
+void
+memcpy_max(char *to, char *from, int max)
+{
+       int     n = strlen(from);
+
+       if (n > max) {
+               n = max;
+       }
+       memcpy(to, from, n);
+
+}/* memcpy_max(... */
+
+void
+outputlist_insert(struct output_fragment *frag)
+{
+       struct output_fragment *nfrag;
+
+       nfrag = e_malloc(sizeof (*frag));
+       movebytes(frag, nfrag, sizeof (*frag));
+       nfrag->of_start_extent = 0;
+
+       if (out_tail == NULL) {
+               out_list = out_tail = nfrag;
+       } else {
+               out_tail->of_next = nfrag;
+               out_tail = nfrag;
+       }
+}
+
+static int
+file_write(FILE *outfile)
+{
+       Uint    should_write;
+
+#ifdef APPLE_HYB
+       char    buffer[SECTOR_SIZE];
+
+       memset(buffer, 0, sizeof (buffer));
+
+       if (apple_hyb) {
+
+               int     i;
+
+               /*
+                * write out padding to round up to HFS allocation block
+                */
+               for (i = 0; i < hfs_pad; i++) {
+                       jtwrite(buffer, sizeof (buffer), 1, 0, FALSE);
+                       xfwrite(buffer, sizeof (buffer), 1, outfile, 0, FALSE);
+                       last_extent_written++;
+               }
+       }
+#endif /* APPLE_HYB */
+
+       /*
+        * 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.
+        */
+       should_write = last_extent - session_start;
+
+       if (verbose > 2) {
+#ifdef DBG_ISO
+               fprintf(stderr,
+                       "Total directory extents being written = %d\n",
+                                                       last_extent);
+#endif
+
+#ifdef APPLE_HYB
+               if (apple_hyb)
+                       fprintf(stderr,
+                       "Total extents scheduled to be written (inc HFS) = %d\n",
+                               last_extent - session_start);
+               else
+#endif /* APPLE_HYB */
+
+                       fprintf(stderr,
+                               "Total extents scheduled to be written = %u\n",
+                               last_extent - session_start);
+       }
+       /* Now write all of the files that we need. */
+       write_files(outfile);
+
+#ifdef APPLE_HYB
+       /* write out extents/catalog/dt file */
+       if (apple_hyb) {
+
+               jtwrite(hce->hfs_ce, HFS_BLOCKSZ, hce->hfs_tot_size, 0, FALSE);
+               xfwrite(hce->hfs_ce, HFS_BLOCKSZ, hce->hfs_tot_size, outfile, 0, FALSE);
+
+               /* round up to a whole CD block */
+               if (HFS_ROUND_UP(hce->hfs_tot_size) -
+                                       hce->hfs_tot_size * HFS_BLOCKSZ) {
+                       jtwrite(buffer,
+                               HFS_ROUND_UP(hce->hfs_tot_size) -
+                               hce->hfs_tot_size * HFS_BLOCKSZ, 1, 0, FALSE);
+                       xfwrite(buffer,
+                               HFS_ROUND_UP(hce->hfs_tot_size) -
+                               hce->hfs_tot_size * HFS_BLOCKSZ, 1, outfile, 0, FALSE);
+               }
+               last_extent_written += ISO_ROUND_UP(hce->hfs_tot_size *
+                                               HFS_BLOCKSZ) / SECTOR_SIZE;
+
+               /* write out HFS boot block */
+               if (mac_boot.name)
+                       write_one_file(mac_boot.name, mac_boot.size, outfile,
+                                                               mac_boot.off);
+       }
+#endif /* APPLE_HYB */
+
+       /* The rest is just fluff. */
+       if (verbose == 0) {
+               return (0);
+       }
+#ifdef APPLE_HYB
+       if (apple_hyb) {
+               fprintf(stderr,
+                       "Total extents actually written (inc HFS) = %d\n",
+                       last_extent_written - session_start);
+               fprintf(stderr, "(Size of ISO volume = %d, HFS extra = %d)\n",
+                       last_extent_written - session_start - hfs_extra,
+                       hfs_extra);
+       } else
+#else
+       fprintf(stderr, "Total extents actually written = %d\n",
+               last_extent_written - session_start);
+#endif /* APPLE_HYB */
+
+       /* Hard links throw us off here */
+       if (should_write != (last_extent - session_start)) {
+               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);
+
+}/* iso_write(... */
+
+/*
+ * Function to write the PVD for the disc.
+ */
+static int
+pvd_write(FILE *outfile)
+{
+       char            iso_time[17];
+       int             should_write;
+       struct tm       local;
+       struct tm       gmt;
+
+
+       time(&begun);
+
+       local = *localtime(&begun);
+       gmt = *gmtime(&begun);
+
+       /*
+        * There was a comment here about breaking in the year 2000.
+        * That's not true, in 2000 tm_year == 100, so 1900+tm_year == 2000.
+        */
+       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);
+
+       local.tm_min -= gmt.tm_min;
+       local.tm_hour -= gmt.tm_hour;
+       local.tm_yday -= gmt.tm_yday;
+       if (local.tm_yday < -2)         /* Hit new-year limit   */
+               local.tm_yday = 1;      /* Local is GMT + 1 day */
+       iso_time[16] = (local.tm_min + 60 *
+                               (local.tm_hour + 24 * local.tm_yday)) / 15;
+
+       /* 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_max(vol_desc.system_id, system_id, strlen(system_id));
+
+       memset(vol_desc.volume_id, ' ', sizeof (vol_desc.volume_id));
+       memcpy_max(vol_desc.volume_id, volume_id, strlen(volume_id));
+
+       should_write = last_extent - session_start;
+       set_733((char *) vol_desc.volume_space_size, should_write);
+       set_723(vol_desc.volume_set_size, volume_set_size);
+       set_723(vol_desc.volume_sequence_number, volume_sequence_number);
+       set_723(vol_desc.logical_block_size, SECTOR_SIZE);
+
+       /*
+        * The path tables are used by DOS based machines to cache directory
+        * locations
+        */
+       set_733((char *) 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,
+               offsetof(struct iso_directory_record, name[0]) + 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_max(vol_desc.volume_set_id, volset_id, strlen(volset_id));
+
+       FILL_SPACE(publisher_id);
+       if (publisher)
+               memcpy_max(vol_desc.publisher_id, publisher, strlen(publisher));
+
+       FILL_SPACE(preparer_id);
+       if (preparer)
+               memcpy_max(vol_desc.preparer_id, preparer, strlen(preparer));
+
+       FILL_SPACE(application_id);
+       if (appid)
+               memcpy_max(vol_desc.application_id, appid, strlen(appid));
+
+       FILL_SPACE(copyright_file_id);
+       if (copyright)
+               memcpy_max(vol_desc.copyright_file_id, copyright,
+                       strlen(copyright));
+
+       FILL_SPACE(abstract_file_id);
+       if (abstract)
+               memcpy_max(vol_desc.abstract_file_id, abstract,
+                       strlen(abstract));
+
+       FILL_SPACE(bibliographic_file_id);
+       if (biblio)
+               memcpy_max(vol_desc.bibliographic_file_id, biblio,
+                       strlen(biblio));
+
+       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, 17);
+       memcpy(vol_desc.modification_date, iso_time, 17);
+       memcpy(vol_desc.expiration_date, "0000000000000000", 17);
+       memcpy(vol_desc.effective_date, iso_time, 17);
+
+       if (use_XA) {
+               char    *xap = &((char *)&vol_desc)[1024];
+
+               memcpy(&xap[0], "CD-XA001", 8);                 /* XA Sign.  */
+               memcpy(&xap[8], "\0\0", 2);                     /* XA flags  */
+               memcpy(&xap[10], "\0\0\0\0\0\0\0\0", 8);        /* Start dir */
+               memcpy(&xap[18], "\0\0\0\0\0\0\0\0", 8);        /* Reserved  */
+       }
+
+       /* if not a bootable cd do it the old way */
+       jtwrite(&vol_desc, SECTOR_SIZE, 1, 0, FALSE);
+       xfwrite(&vol_desc, SECTOR_SIZE, 1, outfile, 0, FALSE);
+       last_extent_written++;
+       return (0);
+}
+
+/*
+ * Function to write the Extended PVD for the disc.
+ */
+static int
+xpvd_write(FILE *outfile)
+{
+       vol_desc.type[0] = ISO_VD_SUPPLEMENTARY;
+       vol_desc.version[0] = 2;
+       vol_desc.file_structure_version[0] = 2;
+
+       /* if not a bootable cd do it the old way */
+       jtwrite(&vol_desc, SECTOR_SIZE, 1, 0, FALSE);
+       xfwrite(&vol_desc, SECTOR_SIZE, 1, outfile, 0, FALSE);
+       last_extent_written++;
+       return (0);
+}
+
+/*
+ * Function to write the EVD for the disc.
+ */
+static int
+evd_write(FILE *outfile)
+{
+       struct iso_primary_descriptor evol_desc;
+
+       /*
+        * Now write the end volume descriptor.  Much simpler than the other
+        * one
+        */
+       memset(&evol_desc, 0, sizeof (evol_desc));
+       evol_desc.type[0] = (unsigned char) ISO_VD_END;
+       memcpy(evol_desc.id, ISO_STANDARD_ID, sizeof (ISO_STANDARD_ID));
+       evol_desc.version[0] = 1;
+       jtwrite(&evol_desc, SECTOR_SIZE, 1, 0, TRUE);
+       xfwrite(&evol_desc, SECTOR_SIZE, 1, outfile, 0, TRUE);
+       last_extent_written += 1;
+       return (0);
+}
+
+/*
+ * Function to write the version information for the disc.
+ */
+static int
+vers_write(FILE *outfile)
+{
+       char            vers[SECTOR_SIZE+1];
+       int             X_ac;
+       char            **X_av;
+       char            *cp;
+       int             i;
+       int             idx = 4;
+       int             len;
+       extern char     version_string[];
+       extern int      path_ind;
+
+       /* Now write the version descriptor. */
+       memset(vers, 0, sizeof (vers));
+       strcpy(vers, "MKI ");
+
+       cp = vers;
+       X_ac = saved_ac();
+       X_av = saved_av();
+       strcpy(&cp[idx], ctime(&begun));
+       idx += 25;
+       strcpy(&cp[idx], version_string);
+       idx += strlen(version_string);
+       for (i = 1; i < X_ac; i++) {
+               len = strlen(X_av[i]);
+               if ((idx + len + 2) >= SECTOR_SIZE)
+                       break;
+               cp[idx++] = ' ';
+               /*
+                * Do not give away secret information when not in debug mode.
+                */
+               if (debug)
+                       strcpy(&cp[idx], X_av[i]);
+               else if (i >= path_ind)
+                       len = graftcp(&cp[idx], X_av[i], &vers[SECTOR_SIZE-1]);
+               else if (X_av[i][0] == '/')
+                       len = pathcp(&cp[idx], X_av[i], &vers[SECTOR_SIZE-1]);
+               else
+                       strcpy(&cp[idx], X_av[i]);
+               idx += len;
+       }
+
+       cp[SECTOR_SIZE - 1] = '\0';
+       /* Per default: keep privacy. Blackout the version and arguments. */
+       if(getenv("ISODEBUG")) {
+               jtwrite(vers, SECTOR_SIZE, 1, 0, TRUE);
+               xfwrite(vers, SECTOR_SIZE, 1, outfile, 0, TRUE);
+       } else {
+               jtwrite(calloc(SECTOR_SIZE, 1), SECTOR_SIZE, 1, 0, TRUE);
+               xfwrite(calloc(SECTOR_SIZE, 1), SECTOR_SIZE, 1, outfile, 0, TRUE);
+       }
+    last_extent_written += 1;
+       return (0);
+}
+
+/*
+ * Avoid to write unwanted information into the version info string.
+ */
+static int
+graftcp(char *to, char *from, char *ep)
+{
+       int     len = strlen(from);
+       char    *node = NULL;
+
+       if (use_graft_ptrs)
+               node = findgequal(from);
+
+       if (node == NULL) {
+               len = 0;
+               node = from;
+       } else {
+               len = node - from;
+               *node = '\0';
+               strncpy(to, from, ep - to);
+               *node++ = '=';
+               to += len++;
+               *to++ = '=';
+       }
+       return (len + pathcp(to, node, ep));
+}
+
+static int
+pathcp(char *to, char *from, char *ep)
+{
+       int     len = strlen(from);
+       char    *p;
+
+       p = strrchr(from, '/');
+       if (p == NULL) {
+               strncpy(to, from, ep - to);
+       } else {
+               if (p[1] == '\0') {
+                       --p;
+                       while (p > from && *p != '/')
+                               --p;
+               }
+               len = 0;
+               if (*p == '/') {
+                       strncpy(to, "...", ep - to);
+                       to += 3;
+                       len = 3;
+               }
+               if (to < ep) {
+                       strncpy(to, p, ep - to);
+                       len += strlen(to);
+               }
+       }
+       return (len);
+}
+
+
+/*
+ * Function to write the path table for the disc.
+ */
+static int
+pathtab_write(FILE *outfile)
+{
+       /* Next we write the path tables */
+       jtwrite(path_table_l, path_blocks << 11, 1, 0, FALSE);
+       xfwrite(path_table_l, path_blocks << 11, 1, outfile, 0, FALSE);
+       last_extent_written += path_blocks;
+       jtwrite(path_table_m, path_blocks << 11, 1, 0, FALSE);
+       xfwrite(path_table_m, path_blocks << 11, 1, outfile, 0, FALSE);
+       last_extent_written += path_blocks;
+       free(path_table_l);
+       free(path_table_m);
+       path_table_l = NULL;
+       path_table_m = NULL;
+       return (0);
+}
+
+static int
+exten_write(FILE *outfile)
+{
+       jtwrite(extension_record, SECTOR_SIZE, 1, 0, FALSE);
+       xfwrite(extension_record, SECTOR_SIZE, 1, outfile, 0, FALSE);
+       last_extent_written++;
+       return (0);
+}
+
+/*
+ * Functions to describe padding block at the start of the disc.
+ */
+int
+oneblock_size(int starting_extent)
+{
+       last_extent++;
+       return (0);
+}
+
+/*
+ * Functions to describe path table size.
+ */
+static int
+pathtab_size(int starting_extent)
+{
+       path_table[0] = starting_extent;
+
+       path_table[1] = 0;
+       path_table[2] = path_table[0] + path_blocks;
+       path_table[3] = 0;
+       last_extent += 2 * path_blocks;
+       return (0);
+}
+
+/*
+ * Functions to describe padding blocks before PVD.
+ */
+static int
+startpad_size(int starting_extent)
+{
+       last_extent = session_start + 16;
+       return (0);
+}
+
+/*
+ * Functions to describe padding blocks between sections.
+ */
+static int
+interpad_size(int starting_extent)
+{
+       int     emod = 0;
+
+#ifdef needed
+       starting_extent += 16;  /* First add 16 pad blocks */
+#endif
+       if ((emod = starting_extent % 16) != 0) {
+               starting_extent += 16 - emod;   /* Now pad to mod 16 #     */
+       }
+       last_extent = starting_extent;
+       return (0);
+}
+
+/*
+ * Functions to describe padding blocks at end of disk.
+ */
+static int
+endpad_size(int starting_extent)
+{
+       starting_extent += 150;                 /* 150 pad blocks (post gap) */
+       last_extent = starting_extent;
+       return (0);
+}
+
+static int
+file_gen()
+{
+#ifdef APPLE_HYB
+       int     start_extent = last_extent;     /* orig ISO files start */
+
+#endif /* APPLE_HYB */
+
+       if (!assign_file_addresses(root, FALSE)) {
+#ifdef DVD_VIDEO
+               if (dvd_video) {
+                       comerrno(EX_BAD, "Unable to make a DVD-Video image.\n"
+            "Possible reasons:\n"
+            "  - VIDEO_TS subdirectory was not found on specified location\n"
+            "  - VIDEO_TS has invalid contents\n"
+            );
+               }
+#else
+               ;       /* EMPTY */
+#endif
+       }
+
+
+#ifdef SORTING
+       if (do_sort) {
+               if (sort_file_addresses() == 0)
+                       reassign_link_addresses(root);
+       }
+#endif /* SORTING */
+
+#ifdef APPLE_HYB
+       /*
+        * put this here for the time being - may when I've worked out how to
+        * use Eric's new system for creating/writing parts of the image it
+        * may move to it's own routine
+        */
+       if (apple_hyb)
+               hfs_file_gen(start_extent);
+#ifdef PREP_BOOT
+       else if (use_prep_boot || use_chrp_boot)
+               gen_prepboot();
+#endif /* PREP_BOOT */
+#endif /* APPLE_HYB */
+
+       return (0);
+}
+
+static int
+dirtree_dump()
+{
+       if (verbose > 2) {
+               dump_tree(root);
+       }
+       return (0);
+}
+
+static int
+dirtree_fixup(int starting_extent)
+{
+       if (use_RockRidge && reloc_dir)
+               finish_cl_pl_entries();
+
+       if (use_RockRidge)
+               update_nlink_field(root);
+       return (0);
+}
+
+static int
+dirtree_size(int starting_extent)
+{
+       assign_directory_addresses(root);
+       return (0);
+}
+
+static int
+ext_size(int starting_extent)
+{
+       extern int              extension_record_size;
+       struct directory_entry *s_entry;
+
+       extension_record_extent = starting_extent;
+       s_entry = root->contents;
+       set_733((char *) s_entry->rr_attributes + s_entry->rr_attr_size - 24,
+               extension_record_extent);
+       set_733((char *) s_entry->rr_attributes + s_entry->rr_attr_size - 8,
+               extension_record_size);
+       last_extent++;
+       return (0);
+}
+
+static int
+dirtree_write(FILE *outfile)
+{
+       generate_iso9660_directories(root, outfile);
+       return (0);
+}
+
+static int
+dirtree_cleanup(FILE *outfile)
+{
+       free_directories(root);
+       return (0);
+}
+
+static int
+startpad_write(FILE *outfile)
+{
+       char    buffer[SECTOR_SIZE];
+       int     i;
+       int     npad;
+
+       memset(buffer, 0, sizeof (buffer));
+
+       npad = session_start + 16 - last_extent_written;
+
+       for (i = 0; i < npad; i++) {
+               jtwrite(buffer, sizeof (buffer), 1, 0, FALSE);
+               xfwrite(buffer, sizeof (buffer), 1, outfile, 0, FALSE);
+               last_extent_written++;
+       }
+
+       return (0);
+}
+
+static int
+interpad_write(FILE *outfile)
+{
+       char    buffer[SECTOR_SIZE];
+       int     i;
+       int     npad = 0;
+
+       memset(buffer, 0, sizeof (buffer));
+
+#ifdef needed
+       npad = 16;
+#endif
+       if ((i = last_extent_written % 16) != 0)
+               npad += 16 - i;
+
+       for (i = 0; i < npad; i++) {
+               jtwrite(buffer, sizeof (buffer), 1, 0, FALSE);
+               xfwrite(buffer, sizeof (buffer), 1, outfile, 0, FALSE);
+               last_extent_written++;
+       }
+
+       return (0);
+}
+
+static int
+endpad_write(FILE *outfile)
+{
+       char    buffer[SECTOR_SIZE];
+       int     i;
+
+       memset(buffer, 0, sizeof (buffer));
+
+       for (i = 0; i < 150; i++) {
+               jtwrite(buffer, sizeof (buffer), 1, 0, FALSE);
+               xfwrite(buffer, sizeof (buffer), 1, outfile, 0, FALSE);
+               last_extent_written++;
+       }
+
+       return (0);
+}
+
+#ifdef APPLE_HYB
+
+/*
+ *     hfs_get_parms:  get HFS parameters from the command line
+ */
+
+static int
+hfs_get_parms(char *key)
+{
+       int     ret = 0;
+       char    *p;
+
+       if (hfs_parms == NULL)
+               return (ret);
+
+       if ((p = strstr(hfs_parms, key)) != NULL) {
+               p += strlen(key) + 1;
+               sscanf(p, "%d", &ret);
+       }
+
+       return (ret);
+}
+
+/*
+ *     hfs_file_gen:   set up "fake" HFS volume using the ISO9660 tree
+ */
+static void
+hfs_file_gen(int start_extent)
+{
+       int     Csize;  /* clump size for HFS vol */
+       int     loop;
+       int     last_extent_save = last_extent;
+       char    *p;
+
+       /* allocate memory for the libhfs/genisoimage extra info */
+       hce = (hce_mem *) e_malloc(sizeof (hce_mem));
+
+       hce->error = (char *) e_malloc(1024);
+
+       /* mark as unallocated for use later */
+       hce->hfs_ce = hce->hfs_hdr = hce->hfs_map = 0;
+
+       /* reserve space for the label partition - if it is needed */
+#ifdef PREP_BOOT
+       /* a PReP bootable partition needs the map.. */
+       if (gen_pt || use_prep_boot || use_chrp_boot)
+#else
+       if (gen_pt)
+#endif /* PREP_BOOT */
+               hce->hfs_map_size = HFS_MAP_SIZE;
+       else
+               hce->hfs_map_size = 0;
+
+       /* set the HFS parameter string to upper case */
+       if (hfs_parms) {
+               for (p = hfs_parms; *p; p++)
+                       *p = toupper(*p);
+       }
+
+       /* set the initial factor to increase Catalog file size */
+       if ((hce->ctc_size = hfs_get_parms("CTC")) == 0)
+               hce->ctc_size = CTC;
+
+       /* set the max size of the Catalog file */
+       if ((hce->max_XTCsize = hfs_get_parms("MAX_XTCSIZE")) == 0)
+               hce->max_XTCsize = MAX_XTCSIZE;
+
+       /* set the number of time to try to make an HFS volume */
+       if ((loop = hfs_get_parms("CTC_LOOP")) == 0)
+               loop = CTC_LOOP;
+
+       /*
+        * "create" the HFS volume (just the header, catalog/extents files) if
+        * there's a problem with the Catalog file being too small, we keep on
+        * increasing the size (up to CTC_LOOP) times and try again.
+        * Unfortunately I don't know enough about the inner workings of HFS,
+        * so I can't workout the size of the Catalog file in advance (and I
+        * don't want to "grow" as is is normally allowed to), therefore, this
+        * approach is a bit over the top as it involves throwing away the
+        * "volume" we have created and trying again ...
+        */
+       do {
+               hce->error[0] = '\0';
+
+               /* attempt to create the Mac volume */
+               Csize = make_mac_volume(root, start_extent);
+
+               /* if we have a problem ... */
+               if (Csize < 0) {
+                       /*
+                        * we've made too many attempts, or got some other
+                        * error
+                        */
+                       if (loop == 0 || errno != HCE_ERROR) {
+                               /* HCE_ERROR is not a valid errno value */
+                               if (errno == HCE_ERROR)
+                                       errno = 0;
+
+                               /* exit with the error */
+                               if (*hce->error)
+                                       fprintf(stderr, "%s\n", hce->error);
+                               perr(hfs_error);
+                       } else {
+                               /* increase Catalog file size factor */
+                               hce->ctc_size *= CTC;
+
+                               /*
+                                * reset the initial "last_extent" and try
+                                * again
+                                */
+                               last_extent = last_extent_save;
+                       }
+               } else {
+                       /* everything OK - just carry on ... */
+                       loop = 0;
+               }
+       }
+       while (loop--);
+
+       hfs_extra = HFS_ROUND_UP(hce->hfs_tot_size) / SECTOR_SIZE;
+
+       last_extent += hfs_extra;
+
+       /* generate the Mac label and HFS partition maps */
+       mac_boot.name = hfs_boot_file;
+
+       /*
+        * only generate the partition tables etc. if we are making a bootable
+        * CD - or if the -part option is given
+        */
+       if (gen_pt) {
+               if (gen_mac_label(&mac_boot)) {
+                       if (*hce->error)
+                               fprintf(stderr, "%s\n", hce->error);
+                       perr(hfs_error);
+               }
+       }
+       /* set Autostart filename if required */
+       if (autoname) {
+               if (autostart())
+                       perr("Autostart filename must less than 12 characters");
+       }
+       /* finished with any HFS type errors */
+       free(hce->error);
+       hce->error = 0;
+
+       /*
+        * the ISO files need to start on a multiple of the HFS allocation
+        * blocks, so find out how much padding we need
+        */
+
+       /*
+        * take in accout alignment of files wrt HFS volume start - remove any
+        * previous session as well
+        */
+       start_extent -= session_start;
+       hfs_pad = ROUND_UP(start_extent*SECTOR_SIZE +
+                       (hce->hfs_hdr_size + hce->hfs_map_size) * HFS_BLOCKSZ,
+                                                       Csize) / SECTOR_SIZE;
+
+       hfs_pad -= (start_extent + (hce->hfs_hdr_size + hce->hfs_map_size) /
+                                                       HFS_BLK_CONV);
+
+#ifdef PREP_BOOT
+       gen_prepboot_label(hce->hfs_map);
+#endif /* PREP_BOOT */
+
+}
+
+#ifdef PREP_BOOT
+static void
+gen_prepboot()
+{
+       /*
+        * we need to allocate the hce struct since hce->hfs_map is used to
+        * generate the fdisk partition map required for PReP booting
+        */
+       hce = (hce_mem *) e_malloc(sizeof (hce_mem));
+
+       /* mark as unallocated for use later */
+       hce->hfs_ce = hce->hfs_hdr = hce->hfs_map = 0;
+
+       /* reserve space for the label partition - if it is needed */
+       hce->hfs_map_size = HFS_MAP_SIZE;
+
+       hce->hfs_map = (unsigned char *) e_malloc(hce->hfs_map_size * HFS_BLOCKSZ);
+       gen_prepboot_label(hce->hfs_map);
+}
+
+#endif /* PREP_BOOT */
+
+/*
+ *     get_adj_size:   get the ajusted size of the volume with the HFS
+ *                     allocation block size for each file
+ */
+Ulong
+get_adj_size(int Csize)
+{
+       struct deferred_write *dw;
+       Ulong           size = 0;
+       int             count = 0;
+
+       /* loop through all the files finding the new total size */
+       for (dw = dw_head; dw; dw = dw->next) {
+               size += (ROUND_UP(dw->size, Csize)/HFS_BLOCKSZ);
+               count++;
+       }
+
+       /*
+        * crude attempt to prevent overflows - HFS can only cope with a
+        * maximum of about 65536 forks (actually less) - this will trap cases
+        * when we have far too many files
+        */
+
+       if (count >= 65536)
+               return (-1);
+       else
+               return (size);
+}
+
+/*
+ *     adj_size:       adjust the ISO record entries for all files
+ *                     based on the HFS allocation block size
+ */
+int
+adj_size(int Csize, int start_extent, int extra)
+{
+       struct deferred_write *dw;
+       struct directory_entry *s_entry;
+       int             size;
+
+       /* get the adjusted start_extent (with padding) */
+       /* take in accout alignment of files wrt HFS volume start */
+
+       start_extent -= session_start;
+
+       start_extent = ROUND_UP(start_extent*SECTOR_SIZE + extra*HFS_BLOCKSZ,
+                                               Csize) / SECTOR_SIZE;
+
+       start_extent -= (extra / HFS_BLK_CONV);
+
+       start_extent += session_start;
+
+       /* initialise file hash */
+       flush_hash();
+
+       /*
+        * loop through all files changing their starting blocks and finding
+        * any padding needed to written out latter
+        */
+       for (dw = dw_head; dw; dw = dw->next) {
+               s_entry = dw->s_entry;
+               s_entry->starting_block = dw->extent = start_extent;
+               set_733((char *) s_entry->isorec.extent, start_extent);
+               size = ROUND_UP(dw->size, Csize) / SECTOR_SIZE;
+               dw->pad = size - ISO_ROUND_UP(dw->size) / SECTOR_SIZE;
+
+               /*
+                * cache non-HFS files - as there may be multiple links to
+                * these files (HFS files can't have multiple links). We will
+                * need to change the starting extent of the other links later
+                */
+               if (!s_entry->hfs_ent)
+                       add_hash(s_entry);
+
+               start_extent += size;
+       }
+
+       return (start_extent);
+}
+
+/*
+ *     adj_size_other: adjust any non-HFS files that may be linked
+ *                     to an existing file (i.e. not have a deferred_write
+ *                     entry of it's own
+ */
+void
+adj_size_other(struct directory *dpnt)
+{
+       struct directory_entry *s_entry;
+       struct file_hash *s_hash;
+
+       while (dpnt) {
+               s_entry = dpnt->contents;
+               for (s_entry = dpnt->contents; s_entry;
+                                               s_entry = s_entry->next) {
+                       /*
+                        * if it's an HFS file or a directory - then ignore
+                        * (we're after non-HFS files)
+                        */
+                       if (s_entry->hfs_ent ||
+                           (s_entry->isorec.flags[0] & ISO_DIRECTORY))
+                               continue;
+
+                       /*
+                        * find any cached entry and assign new starting
+                        * extent
+                        */
+                       s_hash = find_hash(s_entry->dev, s_entry->inode);
+                       if (s_hash) {
+                               set_733((char *) s_entry->isorec.extent,
+                                               s_hash->starting_block);
+                               /* not vital - but tidy */
+                               s_entry->starting_block =
+                                                       s_hash->starting_block;
+                       }
+               }
+               if (dpnt->subdir) {
+                       adj_size_other(dpnt->subdir);
+               }
+               dpnt = dpnt->next;
+       }
+
+       /* clear file hash */
+       flush_hash();
+}
+
+/*
+ *     hfs_hce_write:  write out the HFS header stuff
+ */
+static int
+hfs_hce_write(FILE *outfile)
+{
+       char    buffer[SECTOR_SIZE];
+       int     n = 0;
+       int     r;      /* HFS hdr output */
+       int     tot_size = hce->hfs_map_size + hce->hfs_hdr_size;
+
+       memset(buffer, 0, sizeof (buffer));
+
+       /*
+        * hack time ... if the tot_size is greater than 32Kb then
+        * it won't fit in the first 16 blank SECTORS (64 512 byte
+        * blocks, as most of this is padding, we just truncate this
+        * data to 64x4xHFS_BLOCKSZ ... hope this is OK ...
+        */
+
+       if (tot_size > 64) tot_size = 64;
+
+       /* get size in CD blocks == 4xHFS_BLOCKSZ == 2048 */
+       n = tot_size / HFS_BLK_CONV;
+       r = tot_size % HFS_BLK_CONV;
+
+       /* write out HFS volume header info */
+       jtwrite(hce->hfs_map, HFS_BLOCKSZ, tot_size, 0, FALSE);
+       xfwrite(hce->hfs_map, HFS_BLOCKSZ, tot_size, outfile, 0, FALSE);
+
+       /* fill up to a complete CD block */
+       if (r) {
+               jtwrite(buffer, HFS_BLOCKSZ, HFS_BLK_CONV - r, 0, FALSE);
+               xfwrite(buffer, HFS_BLOCKSZ, HFS_BLK_CONV - r, outfile, 0, FALSE);
+               n++;
+       }
+       last_extent_written += n;
+       return (0);
+}
+
+/*
+ *     insert_padding_file : insert a dumy file to make volume at least
+ *                             800k
+ *
+ *     XXX If we ever need to write more then 2 GB, make size off_t
+ */
+int
+insert_padding_file(int size)
+{
+       struct deferred_write *dwpnt;
+
+       /* get the size in bytes */
+       size *= HFS_BLOCKSZ;
+
+       dwpnt = (struct deferred_write *)
+               e_malloc(sizeof (struct deferred_write));
+       dwpnt->s_entry = 0;
+       /* set the padding to zero */
+       dwpnt->pad = 0;
+       /* set offset to zero */
+       dwpnt->off = (off_t)0;
+
+       /*
+        * don't need to wory about the s_entry stuff as it won't be touched#
+        * at this point onwards
+        */
+
+       /* insert the entry in the list */
+       if (dw_tail) {
+               dw_tail->next = dwpnt;
+               dw_tail = dwpnt;
+       } else {
+               dw_head = dwpnt;
+               dw_tail = dwpnt;
+       }
+
+       /* aloocate memory as a "Table" file */
+       dwpnt->table = e_malloc(size);
+       dwpnt->name = NULL;
+
+       dwpnt->next = NULL;
+       dwpnt->size = size;
+       dwpnt->extent = last_extent;
+       last_extent += ISO_BLOCKS(size);
+
+       /* retune the size in HFS blocks */
+       return (ISO_ROUND_UP(size) / HFS_BLOCKSZ);
+}
+
+struct output_fragment hfs_desc                = {NULL, NULL, NULL, hfs_hce_write, "HFS volume header"};
+
+#endif /* APPLE_HYB */
+
+struct output_fragment startpad_desc   = {NULL, startpad_size, NULL,     startpad_write, "Initial Padblock"};
+struct output_fragment voldesc_desc    = {NULL, oneblock_size, root_gen, pvd_write,      "Primary Volume Descriptor"};
+struct output_fragment xvoldesc_desc   = {NULL, oneblock_size, NULL,     xpvd_write,     "Enhanced Volume Descriptor"};
+struct output_fragment end_vol         = {NULL, oneblock_size, NULL,     evd_write,      "End Volume Descriptor" };
+struct output_fragment version_desc    = {NULL, oneblock_size, NULL,     vers_write,     "Version block" };
+struct output_fragment pathtable_desc  = {NULL, pathtab_size,  generate_path_tables, pathtab_write, "Path table"};
+struct output_fragment dirtree_desc    = {NULL, dirtree_size,  NULL,     dirtree_write,  "Directory tree" };
+struct output_fragment dirtree_clean   = {NULL, dirtree_fixup, dirtree_dump, dirtree_cleanup, "Directory tree cleanup" };
+struct output_fragment extension_desc  = {NULL, ext_size,      NULL,     exten_write,    "Extension record" };
+struct output_fragment files_desc      = {NULL, NULL,          file_gen, file_write,     "The File(s)"};
+struct output_fragment interpad_desc   = {NULL, interpad_size, NULL,     interpad_write, "Intermediate Padblock"};
+struct output_fragment endpad_desc     = {NULL, endpad_size,   NULL,     endpad_write,   "Ending Padblock"};
diff --git a/icedax/CMakeLists.txt b/icedax/CMakeLists.txt
new file mode 100644 (file)
index 0000000..54c2e7d
--- /dev/null
@@ -0,0 +1,34 @@
+PROJECT (icedax C)
+INCLUDE_DIRECTORIES(../include ../wodim ../libparanoia ${CMAKE_BINARY_DIR} ${CMAKE_BINARY_DIR}/include)
+include(../include/AddScgBits.cmake)
+include(../include/AddSchilyBits.cmake)
+include(../include/AddNetworkBits.cmake)
+
+FIND_FILE (HAVE_SYS_SOUNDCARD_H sys/soundcard.h)
+IF(HAVE_SYS_SOUNDCARD_H)
+       ADD_DEFINITIONS(-DHAVE_SYS_SOUNDCARD_H)
+ENDIF(HAVE_SYS_SOUNDCARD_H)
+FIND_FILE (HAVE_LINUX_SOUNDCARD_H linux/soundcard.h)
+IF(HAVE_LINUX_SOUNDCARD_H)
+    ADD_DEFINITIONS(-DHAVE_LINUX_SOUNDCARD_H)
+ENDIF(HAVE_LINUX_SOUNDCARD_H)
+
+FIND_LIBRARY(HAVE_LIBOSSAUDIO "ossaudio")
+IF(HAVE_LIBOSSAUDIO)
+   LIST(APPEND EXTRA_LIBS "ossaudio")
+ENDIF(HAVE_LIBOSSAUDIO)
+
+LIST(APPEND EXTRA_LIBS  paranoia)
+IF (WIN32)
+       LIST(APPEND EXTRA_LIBS winmm)
+ENDIF (WIN32)
+
+LINK_DIRECTORIES(../librols ../libusal  ../libparanoia)
+ADD_EXECUTABLE (icedax aifc.c aiff.c base64.c icedax.c interface.c ioctl.c raw.c resample.c ringbuff.c scsi_cmds.c semshm.c setuid.c sha_func.c sndconfig.c sun.c toc.c wav.c)
+TARGET_LINK_LIBRARIES(icedax wodimstuff ${EXTRA_LIBS})
+SET_TARGET_PROPERTIES(icedax PROPERTIES  SKIP_BUILD_RPATH TRUE)
+
+INSTALL(TARGETS icedax DESTINATION bin)
+INSTALL(PROGRAMS pitchplay readmult cdda2mp3 cdda2ogg DESTINATION bin)
+INSTALL(FILES cdda2ogg.1 icedax.1 pitchplay.1 readmult.1 list_audio_tracks.1 DESTINATION ${MANSUBDIR}/man1)
+
diff --git a/icedax/Changelog b/icedax/Changelog
new file mode 100644 (file)
index 0000000..e57a8c1
--- /dev/null
@@ -0,0 +1,570 @@
+210 Einträge
+Fri Apr  6 15:58:32 2001 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * interface.c 1.16
+         bugfix symbolic constant 'linux' -> 'LINUX', code cleanup
+
+Sun Mar 11 17:55:25 2001 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * scsi_cmds.c 1.11
+         schily changes
+
+Sun Mar 11 17:25:14 2001 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * semshm.c 1.6
+         change to new shared memory scheme.
+
+Mon Dec 25 11:13:42 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * config.h 1.3
+         get rid of PRETEND_TO_USE, use ARGSUSED instead
+
+Sun Dec 10 16:49:56 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * scsi_cmds.c 1.10
+         Large file type fix: u_char -> Uchar
+
+Sat Dec  9 23:41:42 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * Makefile 1.2
+         add libraries for remote scsi
+
+Sat Dec  9 23:39:59 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * ioctl.c 1.9
+         read toc in msf AND lba format. Use mins,secs,frms fields.
+
+Sat Dec  9 23:38:25 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * interface.h 1.6
+         portability fix: change signed char to int for mins,secs,frms
+
+Sat Dec  9 23:37:18 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * scsi_cmds.c 1.9
+         change mins, secs, frms to type int; use conversion function lba_2_msf
+
+Sat Dec  9 23:35:43 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * toc.c 1.15
+         add conversion function lba_2_msf
+
+Fri Dec  1 14:37:10 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * interface.c 1.15
+         change ReadToc_sim to define new toc struc members mins, secs, frms.
+
+Fri Dec  1 14:36:22 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * scsi_cmds.c 1.8
+         change ReadToc to read in MSF as well as in LBA format. Store seperately.
+
+Fri Dec  1 14:35:04 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * interface.h 1.5
+         add seperate fields in toc structure: mins, secs, frms for 
+         msf can hold different data than lba (as seen by dvds)
+
+Mon Nov  6 21:14:11 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * cdda2wav.c 1.23
+         fix from Joerg Schilling for better Cygwin old/new compatibility
+
+Wed Oct 25 23:48:02 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * cdda2wav.c 1.22
+         don't try to get cd text info on discs with data tracks only
+
+Wed Oct 25 23:47:20 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * interface.c 1.14
+         disable Read TOC cd text for Sony CRX100E reported by George Fisher (fisher@ssl.berkeley.edu)
+
+Tue Sep 19 21:30:57 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * cdda2wav.c 1.21
+         fix from js for wait() declarations
+
+Fri Sep 15 12:51:43 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * cdda2wav.c 1.20
+         adapt for Cygwin 1.0 header files
+
+Wed Sep 13 23:06:25 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * cdda2wav.c 1.19
+       * interface.c 1.13
+       * scsi_cmds.c 1.7
+         (r)scsi interface changes
+
+Sun Aug 20 17:29:02 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * scsi_cmds.c 1.6
+       * cdda2wav.c 1.18
+       * interface.c 1.12
+         adapt for new libscsi
+
+Sat Jun 24 07:57:38 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * cdda2wav.c 1.17
+         use setpriority if available before nice
+
+Sat Jun 24 07:56:40 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * toc.c 1.14
+         ISRC hardening II
+
+Fri Jun 16 00:12:21 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * mycdrom.h 1.4
+         bugfix: FreeBSD should get the ioctl interface again
+
+Fri Jun 16 00:11:39 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * ioctl.c 1.8
+         bugfix: FreeBSD ioctl should work again
+
+Sat Jun 10 22:27:43 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * toc.c 1.13
+         recorder id detection and extended character range for ISRC
+
+Fri Jun  2 08:56:22 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * interface.c 1.11
+         added schily header files
+         interface change for ReadCdRom* functions
+         now allocate always a SCSI structure for use of silent and verbose
+         thats it.
+
+Fri Jun  2 08:49:08 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * cdda2wav.c 1.16
+         added schily header files
+         major changes for cds with illegal leadout positions
+         moved nSamplesToDo into the shared memory segment
+         added exit wrapper for portability under Max-OS-X
+         cleaned up ring buffer handling
+         bugfix for silent mode (call DisplayToc and Read_MCN_ISRC was needed)
+
+Fri Jun  2 08:37:12 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * toc.c 1.12
+         added schily header files
+         made cd text detection more reliable for plextor/sony non-mmc drives
+         hardened cdda2wav against illegal ISRC codes
+         major changes for cds with illegal leadout positions
+         protected the index scan against illegal leadout positions
+         *** CHANGED *** 00/06/02 07:43:08 heiko
+         added schilys header files
+
+Fri Jun  2 08:33:44 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * aifc.c 1.4
+       * aiff.c 1.4
+         include schilys header files
+
+Fri Jun  2 08:32:28 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * semshm.c 1.5
+         added schily headerfile
+
+Fri Jun  2 08:31:53 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * interface.h 1.4
+         interface change for ReadCdRom*. Return int instead of void
+
+Fri Jun  2 08:30:51 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * scsi_cmds.c 1.5
+         interface change: Read* function do not exit the program, when
+         sectors could not be read. Instead they signal this through the return value.
+
+Fri Jun  2 08:28:37 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * scsi_cmds.h 1.3
+         interface change: Read* functions now return number of sectors read
+         added myscsierr function for scsi result checking
+
+Fri Jun  2 08:26:46 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * ioctl.c 1.7
+         interface change: ReadCdrom and ReadCdromData return number of read sectors
+         schily include file added
+         default buffer size set to 8 sectors for ide on Linux
+         suppress errors when usalp->silent > 0
+
+Fri Jun  2 07:39:55 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * ringbuff.c 1.4
+         added a pointer for the new shared memory reference eorecording
+
+Fri Jun  2 07:38:48 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * ringbuff.h 1.4
+         new variables in shared memory:
+         end_is_reached is set when the previously unknown leadout is encountered.
+         nSamplesToDo has been moved into shared memory to be visible for the writer.
+
+Fri Jun  2 07:36:11 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * local.cnf.in 1.3
+         bugfixes: SunOS sound device, NetBSD inclusion of extralibs
+
+Fri Jun  2 07:34:37 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * configure.in 1.2
+         bugfix. include detected libs in EXTRALIBS
+
+Fri Jun  2 07:29:12 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * global.h 1.4
+         added two globals for detection of cds with illegal lead out positions
+         and one for a drive capability to read beyond the wrong leadout position.
+
+Tue May  2 21:41:40 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * resample.c 1.9
+         fixed an signedness warning for buffer pointer for WriteSound()
+
+Thu Apr 27 23:53:49 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * cdda2wav.c 1.15
+         -t4+4 -B now records only one track +4 is interpreted as a limit
+
+Sat Apr 22 23:37:57 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * setuid.c 1.3
+         fixed a drop root forever bug, when we were currently nonroot
+
+Mon Apr 17 08:27:51 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * resample.c 1.8
+         fixed 'wait for signal'
+
+Mon Apr 17 08:27:23 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * cdda2wav.c 1.14
+         fixed info files generation, added warnings
+
+Mon Apr 17 08:26:37 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * toc.c 1.11
+         fixed empty title display
+
+Thu Apr 13 00:38:04 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * cdda2wav.c 1.13
+         added some consistency checks for info file generation
+
+Wed Apr 12 22:54:37 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * scsi_cmds.c 1.4
+         fixed read cd text wrt reserved track/session field (now 0)
+
+Mon Apr 10 07:49:11 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * sndfile.h 1.3
+         new interface methods for mp3
+
+Thu Mar 30 00:03:38 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * toc.c 1.10
+         add isrc and mcn retrieval for cd-extra
+
+Wed Mar 29 23:12:09 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * toc.c 1.9
+         fixed a bug with gui-mode and quote() function usage
+
+Wed Mar 29 21:24:04 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * ioctl.c 1.6
+         allow for sun type ioctl even on non_suns (HAVE_SYS_CDIO_H)
+
+Wed Mar 29 21:21:51 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * mycdrom.h 1.3
+         disable HAVE_IOCTL_INTERFACE even if HAVE_SYS_CDIO_H (for Mac OS X)
+
+Sun Mar 26 23:17:47 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * resample.c 1.7
+         change write call for sndfile to new sndfile method WriteSound
+
+Sun Mar 26 23:14:47 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * cdda2wav.c 1.12
+         variable name change 'fill_buffer' -> 'he_fill_buffer'
+         prepare for new output format mp3 with lame (disabled with #ifdef USE_LAME)
+
+Sun Mar 26 23:10:19 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * ringbuff.c 1.3
+       * ringbuff.h 1.3
+         variable name change to avoid collision with fill_buffer from lame
+
+Sun Mar 26 23:09:14 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * interface.h 1.3
+         mask SCSI depend declarations with NO_SCSI_STUFF define
+
+Sun Mar 26 23:08:27 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * toc.c 1.8
+         fix an unimportant typo in resolve_id not active
+
+Sun Mar 26 22:14:53 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * aifc.c 1.3
+       * aiff.c 1.3
+       * raw.c 1.3
+       * sun.c 1.3
+       * wav.c 1.3
+         prepared sndfile interface for additional functions needed for mp3
+
+Tue Mar 21 21:42:10 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * interface.c 1.10
+         added the DEC RRD47 drive as not mmc/readCD capable
+
+Tue Mar 21 20:25:44 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * cdda2wav.c 1.11
+         fixed an cd extra detection bug
+         disabled .cddb and .cdindex file generation with --gui
+
+Tue Mar 21 20:22:26 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * Makefile.man 1.1
+         date and time created 00/03/21 20:22:26 by heiko
+
+Tue Mar 21 20:17:28 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * toc.c 1.7
+         added cactus data shield copy protection recognition
+         fixed display for cd extra (track times)
+         fix for sony crx140s (delivers Qsubchannel position data in bcd instead of hex)
+         fixed screen output during index scan cosmetically
+
+Tue Mar 21 20:06:19 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * ioctl.c 1.5
+         added rough debugging messages for -V 
+         fixed index scanning for Linux and FreeBSD
+
+Tue Mar 21 18:45:30 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * interface.c 1.9
+         included inquiry message, added rough ioctl debugging messages
+
+Sun Feb 20 23:07:27 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * resample.c 1.6
+         fixed a compiler warning
+
+Sun Feb 20 23:07:16 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * interface.c 1.8
+         fixed missing global.in_lendian substitutes
+
+Thu Feb 17 22:00:32 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * cdda2wav.c 1.10
+         made deemphasizing automatic
+         adjusted info files accordingly
+         allow non-root users to fail on realtimescheduling (and continue)
+         get shared memory initialization from interface.c now based on nsectors and
+         overlap values.
+         add more checks for buffers and nsectors.
+         increase buffers and nsectors, if necessary
+
+Thu Feb 17 21:56:22 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * interface.c 1.7
+         moved shared memory allocation to cdda2wav.c 
+         open linux ioctl devices with O_NONBLOCK
+
+Thu Feb 17 21:52:15 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * resample.c 1.5
+         fix synchronization with channel swaps or deemphasizing
+
+Thu Feb 17 21:50:59 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * scsi_cmds.c 1.3
+         avoid error message, if speedselectMMC fails (is optional)
+
+Thu Feb 17 21:50:00 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * toc.c 1.6
+         fix compiler warnings, fix index scanning
+
+Thu Feb 17 21:48:43 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * semshm.c 1.4
+         moved free_sem() in order to compile properly
+
+Thu Feb 17 21:47:04 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * global.h 1.3
+         add input endianess variable for SCSI setup
+
+Wed Feb 16 21:26:40 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * semshm.c 1.3
+         fixed comments and variable names for child/parent role swap
+
+Sun Feb 13 22:28:42 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * resample.c 1.4
+         changed deemphasizing (now for marked tracks)
+
+Sun Feb 13 22:27:34 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * cdda2wav.c 1.9
+         automatic handling of -T (with index scanning)
+
+Sun Feb 13 22:26:38 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * cdda2wav.h 1.4
+         new get_current_track() function
+
+Sun Feb 13 22:21:04 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * cdda2wav.1 1.5
+         document new -T, cleanup
+
+Thu Feb 10 18:35:26 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * toc.c 1.5
+         implemented reading of cdplus/info.cdp through ISO file system
+
+Mon Feb  7 22:47:24 2000 root
+       * interface.c 1.6
+         added Hitachi drive to mmc exception list
+
+Mon Feb  7 18:17:40 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * interface.c 1.5
+         explicitly let Toshiba ATAPI drives use the mmc command set.
+
+Sat Feb  5 11:47:00 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * cdda2wav.c 1.8
+         fixed percentage display for the 100% case
+
+Sat Feb  5 11:46:38 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * interface.c 1.4
+         extended simulation interface
+
+Thu Feb  3 20:59:12 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * toc.c 1.4
+         added the missing ascii to html character mapper 
+         added check for valid cd extra
+
+Wed Feb  2 23:54:48 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * cdda2wav.c 1.7
+         fixed mixed mode multinaming
+         allow nonroot users , do not abort for failing prioctl()
+
+Tue Jan 25 18:57:39 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * cdda2wav.h 1.3
+       * toc.h 1.3
+         prototype change with index scanning function
+
+Tue Jan 25 18:55:58 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * ioctl.c 1.4
+         fixed dumb warning
+
+Tue Jan 25 18:43:49 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * interface.c 1.3
+         extend ioctl interface for FreeBSD-4.x atapi driver
+
+Sat Jan 22 21:24:16 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * ioctl.c 1.3
+         fixed data reading for cd-Extra+ATAPI+Linux
+
+Tue Jan 11 23:16:11 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * cdda2wav.c 1.6
+       * toc.c 1.3
+         
+
+Sun Jan  9 12:11:21 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * cdda2wav.c 1.5
+         index scanning limited to single tracks, if requested.
+         changed vfprintf() to Joerg Schillings error() for better portability.
+         modified error handling for wrong parameters. no more long usage listing.
+         
+
+Mon Jan  3 22:53:51 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * cdda2wav.c 1.4
+       * resample.c 1.3
+       * mmsystem.h 1.4
+         *_h -> *_H
+
+Sun Jan  2 23:22:23 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * mmsystem.h 1.3
+         delete ctrl-m lineends
+
+Sun Jan  2 23:18:58 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * cdda2wav.1 1.4
+         new fix for SCCS (@(x))
+
+Sun Jan  2 18:20:36 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * cdda2wav.1 1.3
+         fixed man page for SCCS header
+
+Sun Jan  2 18:07:17 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * mmsystem.h 1.2
+         put under SCCS
+
+Sun Jan  2 18:02:48 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * lconfig.h.in 1.3
+       * sndconfig.c 1.3
+         OSS sound support added for NetBSD
+
+Sun Jan  2 17:56:13 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * mmsystem.h 1.1
+         date and time created 00/01/02 17:56:13 by heiko
+
+Sun Jan  2 17:53:10 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * Makefile 1.1
+         date and time created 00/01/02 17:53:10 by heiko
+
+Sun Jan  2 17:24:41 2000 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * configure.in 1.1
+         date and time created 00/01/02 17:24:41 by heiko
+
+Sun Dec 19 22:34:34 1999 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * cdda2wav.c 1.3
+         multiple file names
+
+Sun Dec 19 21:52:00 1999 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * toc.h 1.2
+       * wav.c 1.2
+       * wav.h 1.2
+       * sha_func.c 1.2
+       * sndconfig.c 1.2
+       * sndconfig.h 1.2
+       * sndfile.h 1.2
+       * sun.c 1.2
+       * sun.h 1.2
+       * toc.c 1.2
+       * ringbuff.h 1.2
+       * saveargs.h 1.2
+       * scsi_cmds.c 1.2
+       * scsi_cmds.h 1.2
+       * semshm.c 1.2
+       * semshm.h 1.2
+       * setuid.c 1.2
+       * setuid.h 1.2
+       * sha.h 1.2
+       * md5c.c 1.2
+       * mycdrom.h 1.2
+       * mytype.h 1.2
+       * raw.c 1.2
+       * raw.h 1.2
+       * resample.c 1.2
+       * resample.h 1.2
+       * ringbuff.c 1.2
+       * global.h 1.2
+       * interface.c 1.2
+       * interface.h 1.2
+       * ioctl.c 1.2
+       * ioctl.h 1.2
+       * lconfig.h.in 1.2
+       * local.cnf.in 1.2
+       * lowlevel.h 1.2
+       * md5.h 1.2
+       * aiff.h 1.2
+       * base64.c 1.2
+       * base64.h 1.2
+       * byteorder.h 1.2
+       * cdda2wav.1 1.2
+       * cdda2wav.c 1.2
+       * cdda2wav.h 1.2
+       * config.h 1.2
+       * aifc.c 1.2
+       * aifc.h 1.2
+       * aiff.c 1.2
+         first
+
+Sat Nov 13 19:30:21 1999 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * cdda2wav.1 1.1
+         date and time created 99/11/13 19:30:21 by heiko
+
+Sat Nov 13 19:25:02 1999 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * lconfig.h.in 1.1
+       * local.cnf.in 1.1
+         date and time created 99/11/13 19:25:02 by heiko
+
+Sat Nov 13 19:24:29 1999 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * aifc.h 1.1
+       * aiff.h 1.1
+       * base64.h 1.1
+       * byteorder.h 1.1
+       * cdda2wav.h 1.1
+       * config.h 1.1
+       * global.h 1.1
+       * interface.h 1.1
+       * ioctl.h 1.1
+       * lowlevel.h 1.1
+       * md5.h 1.1
+       * mycdrom.h 1.1
+       * mytype.h 1.1
+       * raw.h 1.1
+       * resample.h 1.1
+       * ringbuff.h 1.1
+       * saveargs.h 1.1
+       * scsi_cmds.h 1.1
+       * semshm.h 1.1
+       * setuid.h 1.1
+       * sha.h 1.1
+       * sndconfig.h 1.1
+       * sndfile.h 1.1
+       * sun.h 1.1
+       * toc.h 1.1
+       * wav.c 1.1
+       * wav.h 1.1
+         date and time created 99/11/13 19:24:29 by heiko
+
+Sat Nov 13 19:24:28 1999 Heiko Eissfeldt <heiko@colossus.escape.de>
+       * aifc.c 1.1
+       * aiff.c 1.1
+       * base64.c 1.1
+       * cdda2wav.c 1.1
+       * interface.c 1.1
+       * ioctl.c 1.1
+       * md5c.c 1.1
+       * raw.c 1.1
+       * resample.c 1.1
+       * ringbuff.c 1.1
+       * scsi_cmds.c 1.1
+       * semshm.c 1.1
+       * setuid.c 1.1
+       * sha_func.c 1.1
+       * sndconfig.c 1.1
+       * sun.c 1.1
+       * toc.c 1.1
+         date and time created 99/11/13 19:24:28 by heiko
+
diff --git a/icedax/GPL b/icedax/GPL
new file mode 100644 (file)
index 0000000..a43ea21
--- /dev/null
@@ -0,0 +1,339 @@
+                   GNU GENERAL PUBLIC LICENSE
+                      Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                          675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                           Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+\f
+                   GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+\f
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+\f
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+\f
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                           NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                    END OF TERMS AND CONDITIONS
+\f
+       Appendix: How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) 19yy  <name of author>
+
+    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 of the License, 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.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) 19yy name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/icedax/aifc.c b/icedax/aifc.c
new file mode 100644 (file)
index 0000000..a1001c7
--- /dev/null
@@ -0,0 +1,213 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)aifc.c  1.5 01/10/27 Copyright 1998,1999 Heiko Eissfeldt */
+/***
+ * CopyPolicy: GNU Public License 2 applies
+ * Copyright (C) by Heiko Eissfeldt
+ *
+ *
+ * ---------------------------------------------------------------------
+ *  definitions for aifc pcm output
+ * ---------------------------------------------------------------------
+ */
+
+#include "config.h"
+#include "mytype.h"
+#include <stdio.h>
+#include <standard.h>
+#include <unixstd.h>
+#include <strdefs.h>
+#include <schily.h>
+#include "byteorder.h"
+#include "sndfile.h"
+
+typedef UINT4 FOURCC;    /* a four character code */
+typedef struct CHUNKHDR {
+  FOURCC       ckid;          /* chunk ID */
+  UINT4                dwSize; /* chunk size */
+} CHUNKHDR;
+
+#define mmioFOURCC(ch0, ch1, ch2, ch3) \
+  ((UINT4)(unsigned char)(ch3) | ((UINT4)(unsigned char)(ch2) << 8) | \
+  ((UINT4)(unsigned char)(ch1) << 16) | ((UINT4)(unsigned char)(ch0) << 24))
+
+#define FOURCC_FORM     mmioFOURCC ('F', 'O', 'R', 'M')
+#define FOURCC_AIFC     mmioFOURCC ('A', 'I', 'F', 'C')
+#define FOURCC_FVER     mmioFOURCC ('F', 'V', 'E', 'R')
+#define FOURCC_COMM     mmioFOURCC ('C', 'O', 'M', 'M')
+#define FOURCC_NONE     mmioFOURCC ('N', 'O', 'N', 'E')
+#define FOURCC_SSND     mmioFOURCC ('S', 'S', 'N', 'D')
+
+#define NO_COMPRESSION "not compressed"
+
+/* brain dead construction from apple involving bigendian 80-bit doubles.
+   Definitely designed not to be portable. Alignment is a nightmare too. */
+typedef struct AIFCHDR {
+  CHUNKHDR     formChk;
+  FOURCC       formType;
+
+  CHUNKHDR     fverChk;                /* Version chunk */
+  UINT4                timestamp;              /* timestamp identifies version */
+
+  CHUNKHDR     commChk;                /* Common chunk */
+  /* from now on, alignment prevents us from using the original types :-(( */
+  unsigned char        numChannels[2];         /* Audio Channels */
+  unsigned char        numSampleFrames[4];     /* # of samples */
+  unsigned char        samplesize[2];          /* bits per sample */
+  unsigned char        sample_rate[10];        /* sample rate in extended float */
+  unsigned char        compressionType[4];     /* AIFC extension */
+  unsigned char        compressionNameLen;     /* AIFC extension */
+       char    compressionName[sizeof(NO_COMPRESSION)];        /* AIFC extension */
+
+  unsigned char ssndChkid[4];          /* Sound data chunk */
+  unsigned char        dwSize[4];              /* size of chunk */
+  unsigned char        offset[4];              /* start of 1st sample */
+  unsigned char        blocksize[4];           /* aligned sound data block size */
+
+} AIFCHDR;
+
+static AIFCHDR AifcHdr;
+
+/* Prototypes */
+static int Format_samplerate(unsigned long rate, unsigned char the_rate[10]);
+static int InitSound(int audio, long channels, unsigned long rate, 
+                                                       long nBitsPerSample, unsigned long expected_bytes );
+static int ExitSound(int audio, unsigned long nBytesDone);
+static unsigned long GetHdrSize(void);
+static unsigned long InSizeToOutSize(unsigned long BytesToDo);
+
+struct soundfile aifcsound =
+{
+       InitSound,              /* init header method */
+       ExitSound,              /* exit header method */
+       GetHdrSize,             /* report header size method */
+       /* get sound samples out */
+       (int (*)(int audio, unsigned char *buf, unsigned long BytesToDo))write,
+       InSizeToOutSize,        /* compressed? output file size */
+       1                                               /* needs big endian samples */
+};
+
+/* format the sample rate into an
+   bigendian 10-byte IEEE-754 floating point number
+ */
+static int Format_samplerate(unsigned long rate, unsigned char the_rate[10])
+{
+  int i;
+
+  /* normalize rate */
+  for (i = 0; (rate & 0xffff) != 0; rate <<= 1, i++) {
+    if ((rate & 0x8000) != 0) {
+      break;
+    }
+  }
+
+  /* set exponent and sign */
+  the_rate[1] = 14-i;
+  the_rate[0] = 0x40;          /* LSB = sign */
+
+  /* 16-bit part of mantisse for sample rate */
+  the_rate[3] = rate & 0xff;
+  the_rate[2] = (rate >> 8) & 0xff;
+
+  /* initialize lower digits of mantisse */
+  the_rate[4] = the_rate[5] = the_rate[6] =
+  the_rate[7] = the_rate[8] = the_rate[9] = 0;
+
+  return 0;
+}
+
+
+static int InitSound(int audio, long channels, unsigned long rate, 
+                     long nBitsPerSample, unsigned long expected_bytes)
+{
+  UINT4 tmp;
+
+  fillbytes(&AifcHdr, sizeof(AifcHdr), '\0');
+  AifcHdr.formChk.ckid = cpu_to_be32(FOURCC_FORM);
+  AifcHdr.formChk.dwSize= cpu_to_be32(expected_bytes +
+                        offset_of(AIFCHDR,blocksize)+sizeof(AifcHdr.blocksize)
+                                       - offsetof(AIFCHDR,commChk));
+  AifcHdr.formType     = cpu_to_be32(FOURCC_AIFC);
+
+  AifcHdr.fverChk.ckid = cpu_to_be32(FOURCC_FVER);
+  AifcHdr.fverChk.dwSize= cpu_to_be32(offsetof(AIFCHDR,commChk)
+                                       - offsetof(AIFCHDR,timestamp));
+
+  AifcHdr.compressionType[0]='N';
+  AifcHdr.compressionType[1]='O';
+  AifcHdr.compressionType[2]='N';
+  AifcHdr.compressionType[3]='E';
+  AifcHdr.compressionNameLen = sizeof(NO_COMPRESSION)-1;
+  strcpy(AifcHdr.compressionName, NO_COMPRESSION);
+  AifcHdr.timestamp    = cpu_to_be32(UINT4_C(0xA2805140)); /* AIFC Version 1 */
+
+  AifcHdr.commChk.ckid = cpu_to_be32(FOURCC_COMM);
+  AifcHdr.commChk.dwSize= cpu_to_be32(offset_of(AIFCHDR,ssndChkid)
+                                       - offset_of(AIFCHDR,numChannels));
+
+  AifcHdr.numChannels[1]= channels;
+
+  tmp = cpu_to_be32(expected_bytes/(channels * (nBitsPerSample/8)));
+  AifcHdr.numSampleFrames[0] = tmp >> 24;
+  AifcHdr.numSampleFrames[1] = tmp >> 16;
+  AifcHdr.numSampleFrames[2] = tmp >> 8;
+  AifcHdr.numSampleFrames[3] = tmp >> 0;
+  AifcHdr.samplesize[1]        = nBitsPerSample;
+  Format_samplerate(rate, AifcHdr.sample_rate);
+
+  memcpy(AifcHdr.ssndChkid, "SSND", 4);
+  tmp = cpu_to_be32(expected_bytes + offset_of(AIFCHDR,blocksize)+sizeof(AifcHdr.blocksize) - offset_of(AIFCHDR, offset));
+  AifcHdr.dwSize[0] = tmp >> 24;
+  AifcHdr.dwSize[1] = tmp >> 16;
+  AifcHdr.dwSize[2] = tmp >> 8;
+  AifcHdr.dwSize[3] = tmp >> 0;
+
+  return write (audio, &AifcHdr, sizeof (AifcHdr));
+}
+
+static int ExitSound(int audio, unsigned long nBytesDone)
+{
+  UINT4 tmp;
+
+  AifcHdr.formChk.dwSize= cpu_to_be32(nBytesDone + sizeof(AIFCHDR)
+                                       - offsetof(AIFCHDR,commChk));
+  tmp = cpu_to_be32(nBytesDone/(
+       AifcHdr.numChannels[1] * AifcHdr.samplesize[1]/ULONG_C(8)));
+  AifcHdr.numSampleFrames[0] = tmp >> 24;
+  AifcHdr.numSampleFrames[1] = tmp >> 16;
+  AifcHdr.numSampleFrames[2] = tmp >> 8;
+  AifcHdr.numSampleFrames[3] = tmp >> 0;
+
+  /* If an odd number of bytes has been written,
+     extend the chunk with one dummy byte. This is a requirement for AIFC. */
+  if ((nBytesDone & 1) && (lseek(audio, 1L, SEEK_CUR) == -1)) {
+    return 0;
+  }
+
+  /* goto beginning */
+  if (lseek(audio, 0L, SEEK_SET) == -1) {
+    return 0;
+  }
+  return write (audio, &AifcHdr, sizeof (AifcHdr));
+}
+
+static unsigned long GetHdrSize()
+{
+  return sizeof( AifcHdr );
+}
+
+static unsigned long InSizeToOutSize(unsigned long  BytesToDo)
+{
+        return BytesToDo;
+}
+
diff --git a/icedax/aifc.h b/icedax/aifc.h
new file mode 100644 (file)
index 0000000..f9a2c9d
--- /dev/null
@@ -0,0 +1,14 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)aifc.h  1.2 99/12/19 Copyright 1998,1999 Heiko Eissfeldt */
+extern struct soundfile aifcsound;
diff --git a/icedax/aiff.c b/icedax/aiff.c
new file mode 100644 (file)
index 0000000..cd1d98d
--- /dev/null
@@ -0,0 +1,188 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)aiff.c  1.5 01/10/27 Copyright 1998,1999 Heiko Eissfeldt */
+/***
+ * CopyPolicy: GNU Public License 2 applies
+ * Copyright (C) by Heiko Eissfeldt
+ *
+ *
+ * ---------------------------------------------------------------------
+ *  definitions for aiff pcm output
+ * ---------------------------------------------------------------------
+ */
+
+#include "config.h"
+#include <stdio.h>
+#include <unixstd.h>
+#include <strdefs.h>
+#include <standard.h>
+#include <schily.h>
+#include "mytype.h"
+#include "byteorder.h"
+#include "sndfile.h"
+
+typedef UINT4 FOURCC;    /* a four character code */
+typedef struct CHUNKHDR {
+  FOURCC       ckid;          /* chunk ID */
+  UINT4                dwSize; /* chunk size */
+} CHUNKHDR;
+
+#define mmioFOURCC(ch0, ch1, ch2, ch3) \
+  ((UINT4)(unsigned char)(ch3) | ((UINT4)(unsigned char)(ch2) << 8) | \
+  ((UINT4)(unsigned char)(ch1) << 16) | ((UINT4)(unsigned char)(ch0) << 24))
+
+#define FOURCC_FORM     mmioFOURCC ('F', 'O', 'R', 'M')
+#define FOURCC_AIFF     mmioFOURCC ('A', 'I', 'F', 'F')
+#define FOURCC_COMM     mmioFOURCC ('C', 'O', 'M', 'M')
+#define FOURCC_SSND     mmioFOURCC ('S', 'S', 'N', 'D')
+
+typedef struct AIFFHDR {
+  CHUNKHDR     formChk;
+  FOURCC       formType;
+
+  CHUNKHDR     commChk;                /* Common chunk */
+  /* from now on, alignment prevents us from using the original types :-(( */
+  unsigned char numChannels[2];         /* Audio Channels */
+  unsigned char numSampleFrames[4];     /* # of samples */
+  unsigned char samplesize[2];          /* bits per sample */
+  unsigned char sample_rate[10];        /* sample rate in extended float */
+
+  unsigned char ssndChkid[4];           /* Sound data chunk */
+  unsigned char dwSize[4];              /* size of chunk */
+  unsigned char offset[4];              /* start of 1st sample */
+  unsigned char blocksize[4];           /* aligned sound data block size */
+} AIFFHDR;
+
+static AIFFHDR AiffHdr;
+
+/* Prototypes */
+static int Format_samplerate(unsigned long rate, unsigned char the_rate[10]);
+static int InitSound(int audio, long channels, unsigned long rate, 
+                                                       long nBitsPerSample, unsigned long expected_bytes);
+static int ExitSound(int audio, unsigned long nBytesDone);
+static unsigned long GetHdrSize(void);
+static unsigned long InSizeToOutSize(unsigned long BytesToDo);
+
+
+/* format the sample rate into an
+   bigendian 10-byte IEEE-754 floating point number
+ */
+static int Format_samplerate(unsigned long rate, unsigned char the_rate[10])
+{
+  int i;
+
+  /* normalize rate */
+  for (i = 0; (rate & 0xffff) != 0; rate <<= 1, i++) {
+    if ((rate & 0x8000) != 0) {
+      break;
+    }
+  }
+
+  /* set exponent and sign */
+  the_rate[1] = 14-i;
+  the_rate[0] = 0x40;           /* LSB = sign */
+
+  /* 16-bit part of mantisse for sample rate */
+  the_rate[3] = rate & 0xff;
+  the_rate[2] = (rate >> 8) & 0xff;
+
+  /* initialize lower digits of mantisse */
+  the_rate[4] = the_rate[5] = the_rate[6] =
+  the_rate[7] = the_rate[8] = the_rate[9] = 0;
+
+  return 0;
+}
+
+static int InitSound(int audio, long channels, unsigned long rate, 
+                     long nBitsPerSample, unsigned long expected_bytes)
+{
+  UINT4 tmp;
+
+  fillbytes(&AiffHdr, sizeof(AiffHdr), '\0');
+  AiffHdr.formChk.ckid  = cpu_to_be32(FOURCC_FORM);
+  AiffHdr.formChk.dwSize= cpu_to_be32(expected_bytes +
+                       offset_of(AIFFHDR,blocksize)+sizeof(AiffHdr.blocksize)
+                       - offsetof(AIFFHDR,formType));
+  AiffHdr.formType     = cpu_to_be32(FOURCC_AIFF);
+
+  AiffHdr.commChk.ckid = cpu_to_be32(FOURCC_COMM);
+  AiffHdr.commChk.dwSize= cpu_to_be32(offset_of(AIFFHDR,ssndChkid)
+                                       - offset_of(AIFFHDR,numChannels));
+
+  AiffHdr.numChannels[1]= channels;
+  tmp = cpu_to_be32(expected_bytes/(channels * (nBitsPerSample/8)));
+  AiffHdr.numSampleFrames[0] = tmp >> 24;
+  AiffHdr.numSampleFrames[1] = tmp >> 16;
+  AiffHdr.numSampleFrames[2] = tmp >> 8;
+  AiffHdr.numSampleFrames[3] = tmp >> 0;
+  AiffHdr.samplesize[1] = nBitsPerSample;
+  Format_samplerate(rate, AiffHdr.sample_rate);
+
+  memcpy(AiffHdr.ssndChkid, "SSND", 4);
+  tmp = cpu_to_be32(expected_bytes + offset_of(AIFFHDR,blocksize)+sizeof(AiffHdr.blocksize) - offset_of(AIFFHDR, offset));
+  AiffHdr.dwSize[0] = tmp >> 24;
+  AiffHdr.dwSize[1] = tmp >> 16;
+  AiffHdr.dwSize[2] = tmp >> 8;
+  AiffHdr.dwSize[3] = tmp >> 0;
+
+  return write (audio, &AiffHdr, sizeof (AiffHdr));
+}
+
+static int ExitSound(int audio, unsigned long nBytesDone )
+{
+  UINT4 tmp;
+
+  AiffHdr.formChk.dwSize= cpu_to_be32(nBytesDone + sizeof(AIFFHDR)
+                                       - offsetof(AIFFHDR,commChk));
+  tmp = cpu_to_be32(nBytesDone/(
+        AiffHdr.numChannels[1] * AiffHdr.samplesize[1]/ULONG_C(8)));
+  AiffHdr.numSampleFrames[0] = tmp >> 24;
+  AiffHdr.numSampleFrames[1] = tmp >> 16;
+  AiffHdr.numSampleFrames[2] = tmp >> 8;
+  AiffHdr.numSampleFrames[3] = tmp >> 0;
+
+  /* If an odd number of bytes has been written,
+     extend the chunk with one dummy byte. This is a requirement for AIFF. */
+  if ((nBytesDone & 1) && (lseek(audio, 1L, SEEK_CUR) == -1)) {
+    return 0;
+  }
+
+  /* goto beginning */
+  if (lseek(audio, 0L, SEEK_SET) == -1) {
+    return 0;
+  }
+  return write (audio, &AiffHdr, sizeof (AiffHdr));
+}
+
+static unsigned long GetHdrSize()
+{
+  return sizeof( AiffHdr );
+}
+
+static unsigned long InSizeToOutSize(unsigned long BytesToDo)
+{
+        return BytesToDo;
+}
+
+struct soundfile aiffsound =
+{
+       InitSound,              /* init header method */
+       ExitSound,              /* exit header method */
+       GetHdrSize,             /* report header size method */
+       /* get sound samples out */
+       (int (*)(int audio, unsigned char *buf, unsigned long BytesToDo))write,
+       InSizeToOutSize,        /* compressed? output file size */
+       1                                               /* needs big endian samples */
+};
+
+
diff --git a/icedax/aiff.h b/icedax/aiff.h
new file mode 100644 (file)
index 0000000..cc04849
--- /dev/null
@@ -0,0 +1,14 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)aiff.h  1.2 99/12/19 Copyright 1998,1999 Heiko Eissfeldt */
+extern struct soundfile aiffsound;
diff --git a/icedax/base64.c b/icedax/base64.c
new file mode 100644 (file)
index 0000000..69b75cb
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)base64.c        1.4 02/04/06 Copyright 1998,1999 Heiko Eissfeldt */
+/*____________________________________________________________________________
+//
+//   CD Index - The Internet CD Index
+//
+//   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 of the License, 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.
+//
+//   $Id: base64.c,v 1.1.1.3 1999/04/29 00:57:14 marc Exp $
+//____________________________________________________________________________
+*/
+/*
+ * Program:    RFC-822 routines (originally from SMTP)
+ *
+ * Author:     Mark Crispin
+ *             Networks and Distributed Computing
+ *             Computing & Communications
+ *             University of Washington
+ *             Administration Building, AG-44
+ *             Seattle, WA  98195
+ *             Internet: MRC@CAC.Washington.EDU
+ *
+ * Date:       27 July 1988
+ * Last Edited:        10 September 1998
+ *
+ * Sponsorship:        The original version of this work was developed in the
+ *             Symbolic Systems Resources Group of the Knowledge Systems
+ *             Laboratory at Stanford University in 1987-88, and was funded
+ *             by the Biomedical Research Technology Program of the National
+ *             Institutes of Health under grant number RR-00785.
+ *
+ * Original version Copyright 1988 by The Leland Stanford Junior University
+ * Copyright 1998 by the University of Washington
+ *
+ *  Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that both the
+ * above copyright notices and this permission notice appear in supporting
+ * documentation, and that the name of the University of Washington or The
+ * Leland Stanford Junior University not be used in advertising or publicity
+ * pertaining to distribution of the software without specific, written prior
+ * permission.  This software is made available "as is", and
+ * THE UNIVERSITY OF WASHINGTON AND THE LELAND STANFORD JUNIOR UNIVERSITY
+ * DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING WITHOUT LIMITATION ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE, AND IN NO EVENT SHALL THE UNIVERSITY OF
+ * WASHINGTON OR THE LELAND STANFORD JUNIOR UNIVERSITY BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include "config.h"
+#include <stdio.h>
+#include <stdxlib.h>
+
+#include "base64.h"
+
+/* NOTE: This is not true RFC822 anymore. The use of the characters
+// '/', '+', and '=' is no bueno when the ID will be used as part of a URL.
+// '_', '.', and '-' have been used instead
+*/
+
+/* Convert binary contents to BASE64
+ * Accepts: source
+ *         length of source
+ *         pointer to return destination length
+ * Returns: destination as BASE64
+ */
+
+unsigned char *rfc822_binary(char *src, unsigned long srcl, unsigned long *len)
+{
+  unsigned char *ret,*d;
+  unsigned char *s = (unsigned char *) src;
+  char *v = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789._";
+  unsigned long i = ((srcl + 2) / 3) * 4;
+  *len = i += 2 * ((i / 60) + 1);
+  d = ret = malloc ((size_t) ++i);
+  for (i = 0; srcl; s += 3) {  /* process tuplets */
+    *d++ = v[s[0] >> 2];       /* byte 1: high 6 bits (1) */
+                               /* byte 2: low 2 bits (1), high 4 bits (2) */
+    *d++ = v[((s[0] << 4) + (--srcl ? (s[1] >> 4) : 0)) & 0x3f];
+                               /* byte 3: low 4 bits (2), high 2 bits (3) */
+    *d++ = srcl ? v[((s[1] << 2) + (--srcl ? (s[2] >> 6) : 0)) & 0x3f] : '-';
+                               /* byte 4: low 6 bits (3) */
+    *d++ = srcl ? v[s[2] & 0x3f] : '-';
+    if (srcl) srcl--;          /* count third character if processed */
+    if ((++i) == 15) {         /* output 60 characters? */
+      i = 0;                   /* restart line break count, insert CRLF */
+      *d++ = '\015'; *d++ = '\012';
+    }
+  }
+  *d = '\0';                   /* tie off string */
+
+  return ret;                  /* return the resulting string */
+}
diff --git a/icedax/base64.h b/icedax/base64.h
new file mode 100644 (file)
index 0000000..5b8522c
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)base64.h        1.2 99/12/19 Copyright 1998,1999 Heiko Eissfeldt */
+/*____________________________________________________________________________
+//
+//   CD Index - The Internet CD Index
+//
+//   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 of the License, 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.
+//
+//   $Id: base64.h,v 1.1.1.2 1999/04/29 00:53:34 marc Exp $
+//____________________________________________________________________________
+*/
+/*
+ * Program:    RFC-822 routines (originally from SMTP)
+ *
+ * Author:     Mark Crispin
+ *             Networks and Distributed Computing
+ *             Computing & Communications
+ *             University of Washington
+ *             Administration Building, AG-44
+ *             Seattle, WA  98195
+ *             Internet: MRC@CAC.Washington.EDU
+ *
+ * Date:       27 July 1988
+ * Last Edited:        10 September 1998
+ *
+ * Sponsorship:        The original version of this work was developed in the
+ *             Symbolic Systems Resources Group of the Knowledge Systems
+ *             Laboratory at Stanford University in 1987-88, and was funded
+ *             by the Biomedical Research Technology Program of the National
+ *             Institutes of Health under grant number RR-00785.
+ *
+ * Original version Copyright 1988 by The Leland Stanford Junior University
+ * Copyright 1998 by the University of Washington
+ *
+ *  Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose and without fee is hereby granted, provided
+ * that the above copyright notices appear in all copies and that both the
+ * above copyright notices and this permission notice appear in supporting
+ * documentation, and that the name of the University of Washington or The
+ * Leland Stanford Junior University not be used in advertising or publicity
+ * pertaining to distribution of the software without specific, written prior
+ * permission.  This software is made available "as is", and
+ * THE UNIVERSITY OF WASHINGTON AND THE LELAND STANFORD JUNIOR UNIVERSITY
+ * DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING WITHOUT LIMITATION ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE, AND IN NO EVENT SHALL THE UNIVERSITY OF
+ * WASHINGTON OR THE LELAND STANFORD JUNIOR UNIVERSITY BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#ifndef BASE64_H
+#define BASE64_H
+
+unsigned char *rfc822_binary(char *src,unsigned long srcl,unsigned long *len);
+
+#endif
diff --git a/icedax/byteorder.h b/icedax/byteorder.h
new file mode 100644 (file)
index 0000000..0fa8eb6
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)byteorder.h     1.3 03/07/20 Copyright 1998,1999 Heiko Eissfeldt */
+#ifndef MYBYTE_ORDER
+#define MYBYTE_ORDER 1
+/* supply the byte order macros */
+
+#if defined (WORDS_BIGENDIAN)
+# define MY_BIG_ENDIAN 1
+# define MY_LITTLE_ENDIAN 0
+#else
+# define MY_BIG_ENDIAN 0
+# define MY_LITTLE_ENDIAN 1
+#endif
+
+# undef cpu_to_le32
+# undef cpu_to_le16
+# undef cpu_to_be32
+# undef cpu_to_be16
+# undef le32_to_cpu
+# undef le16_to_cpu
+# undef be32_to_cpu
+# undef be16_to_cpu
+
+#  define revert4bytes(x) \
+        ((unsigned long int)((((unsigned long int)(x) & ULONG_C(0x000000ff)) << 24) | \
+                             (((unsigned long int)(x) & ULONG_C(0x0000ff00)) <<  8) | \
+                             (((unsigned long int)(x) & ULONG_C(0x00ff0000)) >>  8) | \
+                             (((unsigned long int)(x) & ULONG_C(0xff000000)) >> 24)))
+#  define revert2bytes(x) \
+        ((unsigned short int)((((unsigned short int)(x) & 0x00ff) <<  8) | \
+                              (((unsigned short int)(x) & 0xff00) >>  8)))
+
+#if    MY_BIG_ENDIAN == 1
+#  define cpu_to_le32(x) revert4bytes(x)
+#  define cpu_to_le16(x) revert2bytes(x)
+#  define le32_to_cpu(x) cpu_to_le32(x)
+#  define le16_to_cpu(x) cpu_to_le16(x)
+#  define cpu_to_be32(x) (x)
+#  define cpu_to_be16(x) (x)
+#  define be32_to_cpu(x) (x)
+#  define be16_to_cpu(x) (x)
+#else
+#  define cpu_to_be32(x) revert4bytes(x)
+#  define cpu_to_be16(x) revert2bytes(x)
+#  define be32_to_cpu(x) cpu_to_be32(x)
+#  define be16_to_cpu(x) cpu_to_be16(x)
+#  define cpu_to_le32(x) (x)
+#  define cpu_to_le16(x) (x)
+#  define le32_to_cpu(x) (x)
+#  define le16_to_cpu(x) (x)
+#endif
+
+#define GET_LE_UINT_FROM_CHARP(p) ((unsigned int)((*(p+3))<<24)|((*(p+2))<<16)|((*(p+1))<<8)|(*(p)))
+#define GET_BE_UINT_FROM_CHARP(p) ((unsigned int)((*(p))<<24)|((*(p+1))<<16)|((*(p+2))<<8)|(*(p+3)))
+
+#endif /* ifndef MYBYTE_ORDER */
diff --git a/icedax/cd_extra.c b/icedax/cd_extra.c
new file mode 100644 (file)
index 0000000..fa17c5b
--- /dev/null
@@ -0,0 +1,417 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)cd_extra.c      1.8 02/11/21 Copyright 2000-2001 Heiko Eissfeldt */
+
+/* This is an include file! */
+/**************** CD-Extra special treatment *********************************/
+
+#include <ctype.h>
+
+static unsigned long Read_CD_Extra_File(unsigned char *Extra_buf, unsigned long sector);
+
+static unsigned long
+Read_CD_Extra_File(unsigned char *Extra_buf, unsigned long sector)
+{
+       unsigned long mysec;
+       
+       /* read PVD */
+       ReadCdRomData(get_scsi_p(), Extra_buf, sector+16, 1);
+
+       /* check ISO signature */
+       if (memcmp(Extra_buf, "\001CD001", 6) != 0) return 0;
+
+       /* get path_table */
+       mysec = Extra_buf[148] << 24;
+       mysec |= Extra_buf[149] << 16;
+       mysec |= Extra_buf[150] << 8;
+       mysec |= Extra_buf[151];
+
+       if (mysec <= sector) return 0;
+
+       /* read path table */
+       ReadCdRomData(get_scsi_p(), Extra_buf, mysec, 1);
+
+       /* find cdplus subdirectory */
+       { unsigned char * p = Extra_buf;
+               while (p+8 < Extra_buf + CD_FRAMESIZE_RAW) {
+                       int namelength;
+                       
+                       namelength = p[0] | (p[1] << 8);
+                       if (namelength == 6 &&
+                           !memcmp(p+8, "CDPLUS", 6)) break;
+                       
+                       p += 8 + namelength + (namelength & 1);
+               }
+               if (p+8 >= Extra_buf + CD_FRAMESIZE_RAW) return 0;
+
+               /* get extent */
+               mysec = p[2] << 24;
+               mysec |= p[3] << 16;
+               mysec |= p[4] << 8;
+               mysec |= p[5];
+       }
+
+       if (mysec <= sector) return 0;
+
+       ReadCdRomData(get_scsi_p(), Extra_buf, mysec, 1);
+
+       /* find file info.cdp */
+       { unsigned char * p = Extra_buf;
+               while (p+33 < Extra_buf + CD_FRAMESIZE_RAW) {
+                       int namelength;
+                       
+                       namelength = p[32];
+                       if (namelength == 10 &&
+                           !memcmp(p+33, "INFO.CDP;1", 10)) break;
+                       
+                       p += p[0];
+               }
+               if (p+33 >= Extra_buf + CD_FRAMESIZE_RAW) return 0;
+
+               /* get extent */
+               mysec = p[6] << 24;
+               mysec |= p[7] << 16;
+               mysec |= p[8] << 8;
+               mysec |= p[9];
+       }
+
+       if (mysec <= sector) return 0;
+
+       /* read file info.cdp */
+       ReadCdRomData(get_scsi_p(), Extra_buf, mysec, 1);
+       
+       return mysec - sector;
+}
+
+static unsigned char Extra_buffer[CD_FRAMESIZE_RAW];
+
+/*
+ * Read the file cdplus/info.cdp from the cd extra disc.
+ * This file has to reside at exactly 75 sectors after start of
+ * the last session (according to Blue Book).
+ * Of course, there are a lot dubious cd extras, which don't care :-(((
+ * As an alternative method, we try reading through the iso9660 file system...
+ */
+static int Read_CD_Extra_Info(unsigned long sector);
+static int Read_CD_Extra_Info(unsigned long sector)
+{
+  unsigned i;
+  static int offsets[] = {
+     75                /* this is what blue book says */
+  };
+
+  for (i = 0; i < sizeof(offsets)/sizeof(int); i++) {
+#ifdef DEBUG_XTRA
+    fprintf(stderr, "debug: Read_CD_Extra_Info at sector %lu\n", sector+offsets[i]);
+#endif
+    ReadCdRomData(get_scsi_p(), Extra_buffer, sector+offsets[i], 1);
+
+    /* If we are unlucky the drive cannot handle XA sectors by default.
+       We try to compensate by ignoring the first eight bytes.
+       Of course then we lack the last 8 bytes of the sector...
+     */
+
+    if (Extra_buffer[0] == 0)
+      memmove(Extra_buffer, Extra_buffer +8, CD_FRAMESIZE - 8);
+
+    /* check for cd extra */
+    if (Extra_buffer[0] == 'C' && Extra_buffer[1] == 'D')
+       return sector+offsets[i];
+
+    /*
+     * CD is not conforming to BlueBook!
+     * Read the file through ISO9660 file system.
+     */
+    {
+    unsigned long offset = Read_CD_Extra_File(Extra_buffer, sector);
+
+    if (offset == 0) return 0;
+
+    if (Extra_buffer[0] == 0)
+      memmove(Extra_buffer, Extra_buffer +8, CD_FRAMESIZE - 8);
+
+    /* check for cd extra */
+    if (Extra_buffer[0] == 'C' && Extra_buffer[1] == 'D')
+       return sector+offset;
+    }
+  }
+
+  return 0;
+}
+
+static void Read_Subinfo(unsigned pos, unsigned length);
+static void Read_Subinfo(unsigned pos, unsigned length)
+{
+  unsigned num_infos, num;
+  unsigned char *Subp, *orgSubp;
+  unsigned this_track = 0xff;
+#ifdef DEBUG_XTRA
+  unsigned char *up;
+  unsigned char *sp;
+  unsigned u;
+  unsigned short s;
+#endif
+
+  length += 8;
+  length = (length + CD_FRAMESIZE_RAW-1) / CD_FRAMESIZE_RAW;
+  length *= CD_FRAMESIZE_RAW;
+  orgSubp = Subp = malloc(length);
+
+  if (Subp == NULL) {
+    fprintf(stderr, "Read_Subinfo no memory(%d)\n",length);
+    goto errorout;
+  }
+
+  ReadCdRomData(get_scsi_p(), Subp, pos, 1);
+
+  num_infos = Subp[45]+(Subp[44] << 8);
+#ifdef DEBUG_XTRA
+  fprintf(stderr, "subinfo version %c%c.%c%c, %d info packets\n",
+         Subp[8],
+         Subp[9],
+         Subp[10],
+         Subp[11],
+         num_infos);
+#endif
+  length -= 46;
+  Subp += 46;
+  for (num = 0; num < num_infos && length > 0; num++) {
+    unsigned id = *Subp;
+    unsigned len = *(Subp +1);
+#define        INFOPACKETTYPES 0x44
+#ifdef INFOPACKETSTRINGS
+    static const char *infopacketID[INFOPACKETTYPES] = { "0", 
+                             "track identifier", 
+                             "album title",
+                             "universal product code", 
+                             "international standard book number",
+                             "copyright",
+                             "track title",
+                             "notes",
+                             "main interpret",
+                             "secondary interpret",
+                             "composer",
+                             "original composer",
+                             "creation date",
+                             "release  date",
+                             "publisher",
+                             "0f",
+                             "isrc audio track",
+                             "isrc lyrics",
+                             "isrc pictures",
+                             "isrc MIDI data",
+                             "14", "15", "16", "17", "18", "19",
+                             "copyright state SUB_INFO",
+                             "copyright state intro lyrics",
+                             "copyright state lyrics",
+                             "copyright state MIDI data",
+                             "1e", "1f",
+                             "intro lyrics",
+                             "pointer to lyrics text file and length", 
+                             "22", "23", "24", "25", "26", "27", "28",
+                             "29", "2a", "2b", "2c", "2d", "2e", "2f",
+                             "still picture descriptor",
+                             "31",
+                             "32", "33", "34", "35", "36", "37", "38",
+                             "39", "3a", "3b", "3c", "3d", "3e", "3f",
+                             "MIDI file descriptor",
+                             "genre code",
+                             "tempo",
+                             "key"
+                            };
+#endif
+
+    if (id >= INFOPACKETTYPES) {
+      fprintf(stderr, "Off=%4d, ind=%2d/%2d, unknown Id=%2u, len=%2u ",
+               /* this pointer difference is assumed to be small enough for an int. */
+               (int)(Subp - orgSubp)
+               , num, num_infos, id, len);
+      Subp += 2 + 1;
+      length -= 2 + 1;
+      break;
+    }
+#ifdef DEBUG_XTRA
+  fprintf(stderr, "info packet %d\n", id);
+#endif
+
+    switch (id) {
+    case 1:    /* track nummer or 0 */
+      this_track = 10 * (*(Subp + 2) - '0') + (*(Subp + 3) - '0');
+      break;
+
+    case 0x02: /* album title */
+       if (global.disctitle == NULL) {
+           global.disctitle = malloc(len + 1);
+           if (global.disctitle != NULL) {
+               memcpy(global.disctitle, Subp + 2, len);
+              global.disctitle[len] = '\0';
+            }
+        }
+      break;
+    case 0x03: /* media catalog number */
+       if (Get_MCN()[0] == '\0' && Subp[2] != '\0' && len >= 13) {
+            Set_MCN( Subp + 2);
+        }
+      break;
+    case 0x06: /* track title */
+       if (this_track > 0 && this_track < 100
+           && global.tracktitle[this_track] == NULL) {
+            global.tracktitle[this_track] = malloc(len + 1);
+            if (global.tracktitle[this_track] != NULL) {
+               memcpy(global.tracktitle[this_track], Subp + 2, len);
+               global.tracktitle[this_track][len] = '\0';
+            }
+        }
+      break;
+    case 0x05: /* copyright message */
+       if (global.copyright_message == NULL) {
+           global.copyright_message = malloc(len + 1);
+           if (global.copyright_message != NULL) {
+               memcpy(global.copyright_message, Subp + 2, len);
+              global.copyright_message[len] = '\0';
+            }
+        }
+      break;
+    case 0x08: /* creator */
+       if (global.creator == NULL) {
+           global.creator = malloc(len + 1);
+           if (global.creator != NULL) {
+               memcpy(global.creator, Subp + 2, len);
+              global.creator[len] = '\0';
+            }
+        }
+      break;
+    case 0x10: /* isrc */
+       if (this_track > 0 && this_track < 100
+           && Get_ISRC(this_track)[0] == '\0' && Subp[2] != '\0'
+           && len >= 15) {
+              Set_ISRC(this_track, Subp + 2);
+       }
+      break;
+#if 0
+    case 0x04:
+    case 0x07:
+    case 0x09:
+    case 0x0a:
+    case 0x0b:
+    case 0x0c:
+    case 0x0d:
+    case 0x0e:
+    case 0x0f:
+#ifdef INFOPACKETSTRINGS
+      fprintf(stderr, "%s: %*.*s\n",infopacketID[id], (int) len, (int) len, (Subp +2));
+#endif
+      break;
+#ifdef DEBUG_XTRA
+    case 0x1a:
+    case 0x1b:
+    case 0x1c:
+    case 0x1d:
+#ifdef INFOPACKETSTRINGS
+       fprintf(stderr, "%s %scopyrighted\n", infopacketID[id], *(Subp + 2) == 0 ? "not " : "");
+#endif
+      break;
+
+    case 0x21:
+      fprintf(stderr, "lyrics file beginning at sector %u",
+             (unsigned) GET_BE_UINT_FROM_CHARP(Subp + 2));
+      if (len == 8)
+       fprintf(stderr, ", having length: %u\n", 
+                (unsigned) GET_BE_UINT_FROM_CHARP(Subp + 6));
+      else
+       fputs("\n", stderr);
+      break;
+
+    case 0x30:
+      sp = Subp + 2;
+      while (sp < Subp + 2 + len) {
+      /*while (len >= 10) {*/
+        s = be16_to_cpu((*(sp)) | (*(sp) << 8));
+        fprintf(stderr, "%04x, ", s);
+       sp += 2;
+        up = sp;
+       switch (s) {
+       case 0:
+       break;
+       case 4:
+       break;
+       case 5:
+       break;
+       case 6:
+       break;
+        }
+        u = GET_BE_UINT_FROM_CHARP(up);
+        fprintf(stderr, "%04lx, ", (long) u);
+        up += 4;
+        u = GET_BE_UINT_FROM_CHARP(up);
+        fprintf(stderr, "%04lx, ", (long) u);
+        up += 4;
+       sp += 8;
+      }
+      fputs("\n", stderr);
+      break;
+
+    case 0x40:
+      fprintf(stderr, "MIDI file beginning at sector %u",
+             (unsigned) GET_BE_UINT_FROM_CHARP(Subp + 2));
+      if (len == 8)
+       fprintf(stderr, ", having length: %u\n", 
+               (unsigned) GET_BE_UINT_FROM_CHARP(Subp + 6));
+      else
+       fputs("\n", stderr);
+      break;
+
+#ifdef INFOPACKETSTRINGS
+    case 0x42:
+      fprintf(stderr, "%s: %d beats per minute\n",infopacketID[id], *(Subp + 2));
+      break;
+    case 0x41:
+      if (len == 8)
+        fprintf(stderr, "%s: %x, %x, %x, %x, %x, %x, %x, %x\n",
+               infopacketID[id],
+               *(Subp + 2),
+               *(Subp + 3),
+               *(Subp + 4),
+               *(Subp + 5),
+               *(Subp + 6),
+               *(Subp + 7),
+               *(Subp + 8),
+               *(Subp + 9)
+       );
+      else
+        fprintf(stderr, "%s:\n",infopacketID[id]);
+      break;
+    case 0x43:
+      fprintf(stderr, "%s: %x\n",infopacketID[id], *(Subp + 2));
+      break;
+    default:
+      fprintf(stderr, "%s: %*.*s\n",infopacketID[id], (int) len, (int) len, (Subp +2));
+#endif
+#endif
+#endif
+    }
+
+    if (len & 1) len++;
+    Subp += 2 + len;
+    length -= 2 + len;
+  }
+
+/* cleanup */
+
+  free(orgSubp);
+
+errorout:
+  return;
+
+}
+
diff --git a/icedax/cd_text.c b/icedax/cd_text.c
new file mode 100644 (file)
index 0000000..6e93b13
--- /dev/null
@@ -0,0 +1,421 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)cd_text.c       1.5 03/12/31 Copyright 2000-2001 Heiko Eissfeldt */
+
+/* This is an include file! */
+/**************** CD-Text special treatment **********************************/
+
+typedef struct {
+       unsigned char headerfield[4];
+       unsigned char textdatafield[12];
+       unsigned char crcfield[2];
+} cdtextpackdata;
+
+static unsigned short crctab[1<<8] = { /* as calculated by initcrctab() */
+    0x0000,  0x1021,  0x2042,  0x3063,  0x4084,  0x50a5,  0x60c6,  0x70e7,
+    0x8108,  0x9129,  0xa14a,  0xb16b,  0xc18c,  0xd1ad,  0xe1ce,  0xf1ef,
+    0x1231,  0x0210,  0x3273,  0x2252,  0x52b5,  0x4294,  0x72f7,  0x62d6,
+    0x9339,  0x8318,  0xb37b,  0xa35a,  0xd3bd,  0xc39c,  0xf3ff,  0xe3de,
+    0x2462,  0x3443,  0x0420,  0x1401,  0x64e6,  0x74c7,  0x44a4,  0x5485,
+    0xa56a,  0xb54b,  0x8528,  0x9509,  0xe5ee,  0xf5cf,  0xc5ac,  0xd58d,
+    0x3653,  0x2672,  0x1611,  0x0630,  0x76d7,  0x66f6,  0x5695,  0x46b4,
+    0xb75b,  0xa77a,  0x9719,  0x8738,  0xf7df,  0xe7fe,  0xd79d,  0xc7bc,
+    0x48c4,  0x58e5,  0x6886,  0x78a7,  0x0840,  0x1861,  0x2802,  0x3823,
+    0xc9cc,  0xd9ed,  0xe98e,  0xf9af,  0x8948,  0x9969,  0xa90a,  0xb92b,
+    0x5af5,  0x4ad4,  0x7ab7,  0x6a96,  0x1a71,  0x0a50,  0x3a33,  0x2a12,
+    0xdbfd,  0xcbdc,  0xfbbf,  0xeb9e,  0x9b79,  0x8b58,  0xbb3b,  0xab1a,
+    0x6ca6,  0x7c87,  0x4ce4,  0x5cc5,  0x2c22,  0x3c03,  0x0c60,  0x1c41,
+    0xedae,  0xfd8f,  0xcdec,  0xddcd,  0xad2a,  0xbd0b,  0x8d68,  0x9d49,
+    0x7e97,  0x6eb6,  0x5ed5,  0x4ef4,  0x3e13,  0x2e32,  0x1e51,  0x0e70,
+    0xff9f,  0xefbe,  0xdfdd,  0xcffc,  0xbf1b,  0xaf3a,  0x9f59,  0x8f78,
+    0x9188,  0x81a9,  0xb1ca,  0xa1eb,  0xd10c,  0xc12d,  0xf14e,  0xe16f,
+    0x1080,  0x00a1,  0x30c2,  0x20e3,  0x5004,  0x4025,  0x7046,  0x6067,
+    0x83b9,  0x9398,  0xa3fb,  0xb3da,  0xc33d,  0xd31c,  0xe37f,  0xf35e,
+    0x02b1,  0x1290,  0x22f3,  0x32d2,  0x4235,  0x5214,  0x6277,  0x7256,
+    0xb5ea,  0xa5cb,  0x95a8,  0x8589,  0xf56e,  0xe54f,  0xd52c,  0xc50d,
+    0x34e2,  0x24c3,  0x14a0,  0x0481,  0x7466,  0x6447,  0x5424,  0x4405,
+    0xa7db,  0xb7fa,  0x8799,  0x97b8,  0xe75f,  0xf77e,  0xc71d,  0xd73c,
+    0x26d3,  0x36f2,  0x0691,  0x16b0,  0x6657,  0x7676,  0x4615,  0x5634,
+    0xd94c,  0xc96d,  0xf90e,  0xe92f,  0x99c8,  0x89e9,  0xb98a,  0xa9ab,
+    0x5844,  0x4865,  0x7806,  0x6827,  0x18c0,  0x08e1,  0x3882,  0x28a3,
+    0xcb7d,  0xdb5c,  0xeb3f,  0xfb1e,  0x8bf9,  0x9bd8,  0xabbb,  0xbb9a,
+    0x4a75,  0x5a54,  0x6a37,  0x7a16,  0x0af1,  0x1ad0,  0x2ab3,  0x3a92,
+    0xfd2e,  0xed0f,  0xdd6c,  0xcd4d,  0xbdaa,  0xad8b,  0x9de8,  0x8dc9,
+    0x7c26,  0x6c07,  0x5c64,  0x4c45,  0x3ca2,  0x2c83,  0x1ce0,  0x0cc1,
+    0xef1f,  0xff3e,  0xcf5d,  0xdf7c,  0xaf9b,  0xbfba,  0x8fd9,  0x9ff8,
+    0x6e17,  0x7e36,  0x4e55,  0x5e74,  0x2e93,  0x3eb2,  0x0ed1,  0x1ef0,
+    };
+
+#define SUBSIZE        18*8
+
+static unsigned short updcrc(unsigned int p_crc, register unsigned char *cp,
+                                                                 register size_t cnt);
+
+static unsigned short updcrc(unsigned int p_crc, register unsigned char *cp, 
+                             register size_t cnt)
+{
+      register unsigned short crc = (unsigned short)p_crc;
+      while( cnt-- ) {
+            crc = (crc<<8) ^ crctab[(crc>>(16-8)) ^ (*cp++)];
+      }
+      return( crc );
+}
+
+static unsigned short calcCRC(unsigned char *buf, unsigned bsize);
+
+static unsigned short calcCRC(unsigned char *buf, unsigned bsize)
+{
+      return updcrc( 0x0, (unsigned char *)buf, bsize );
+}
+
+static unsigned char    fliptab[8] = {
+        0x01,
+        0x02,
+        0x04,
+        0x08,
+        0x10,
+        0x20,
+        0x40,
+        0x80,
+};
+
+static int flip_error_corr(unsigned char *b, int crc);
+
+static int flip_error_corr(unsigned char *b, int crc)
+{
+  if (crc != 0) {
+    int i;
+    for (i = 0; i < SUBSIZE; i++) {
+      char      c;
+
+      c = fliptab[i%8];
+      b[i / 8] ^= c;
+      if ((crc = calcCRC(b, SUBSIZE/8)) == 0) {
+        return crc;
+      }
+      b[i / 8] ^= c;
+    }
+  }
+  return crc & 0xffff;
+}
+
+
+static int cdtext_crc_ok(cdtextpackdata *c);
+
+static int cdtext_crc_ok(cdtextpackdata *c)
+{
+       int crc;
+       int retval;
+
+       c->crcfield[0] ^= 0xff;
+       c->crcfield[1] ^= 0xff;
+       crc = calcCRC(((unsigned char *)c), 18);
+       retval = (0 == flip_error_corr((unsigned char *)c, crc));
+       c->crcfield[0] ^= 0xff;
+       c->crcfield[1] ^= 0xff;
+#if    0
+          fprintf(stderr, "%02x %02x %02x %02x  ",
+                          c->headerfield[0], c->headerfield[1], c->headerfield[2], c->headerfield[3]);
+          fprintf(stderr,
+"%c %c %c %c %c %c %c %c %c %c %c %c  "
+                        , c->textdatafield[0]
+                        , c->textdatafield[1]
+                        , c->textdatafield[2]
+                        , c->textdatafield[3]
+                        , c->textdatafield[4]
+                        , c->textdatafield[5]
+                        , c->textdatafield[6]
+                        , c->textdatafield[7]
+                        , c->textdatafield[8]
+                        , c->textdatafield[9]
+                        , c->textdatafield[10]
+                        , c->textdatafield[11]
+                 );
+          fprintf(stderr, "%02x %02x \n"
+                        , c->crcfield[0]
+                        , c->crcfield[1]
+               );
+#endif
+       return retval;
+}
+
+#define DETAILED 0
+
+#if    DETAILED
+static void dump_binary(cdtextpackdata *c);
+
+static void dump_binary(cdtextpackdata *c)
+{
+          fprintf(stderr, ": header fields %02x %02x %02x  ",
+                          c->headerfield[1], c->headerfield[2], c->headerfield[3]);
+          fprintf(stderr,
+"%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x"
+                        , c->textdatafield[0]
+                        , c->textdatafield[1]
+                        , c->textdatafield[2]
+                        , c->textdatafield[3]
+                        , c->textdatafield[4]
+                        , c->textdatafield[5]
+                        , c->textdatafield[6]
+                        , c->textdatafield[7]
+                        , c->textdatafield[8]
+                        , c->textdatafield[9]
+                        , c->textdatafield[10]
+                        , c->textdatafield[11]
+                 );
+}
+#endif
+
+static int process_header(cdtextpackdata *c, unsigned tracknr, int dbcc, 
+                                                                 unsigned char *line);
+
+static int process_header(cdtextpackdata *c, unsigned tracknr, int dbcc, 
+                          unsigned char *line)
+{
+      switch ((int)c->headerfield[0]) {
+
+        case 0x80: /* Title of album or track */
+#if    DETAILED
+          fprintf (stderr, "Title");
+#endif
+         if (tracknr > 0 && tracknr < 100
+           && global.tracktitle[tracknr] == NULL) {
+           unsigned len;
+
+           len = strlen((char *)line);
+
+            if (len > 0)
+               global.tracktitle[tracknr] = malloc(len + 1);
+            if (global.tracktitle[tracknr] != NULL) {
+               memcpy(global.tracktitle[tracknr], line, len);
+               global.tracktitle[tracknr][len] = '\0';
+            }
+          } else 
+         if (tracknr == 0
+           && global.disctitle == NULL) {
+           unsigned len;
+
+           len = strlen((char *)line);
+
+            if (len > 0)
+               global.disctitle = malloc(len + 1);
+            if (global.disctitle != NULL) {
+               memcpy(global.disctitle, line, len);
+               global.disctitle[len] = '\0';
+            }
+         }
+        break;
+        case 0x81: /* Name(s) of the performer(s) */
+#if    DETAILED
+          fprintf(stderr, "Performer(s)");
+#endif
+         if (tracknr > 0 && tracknr < 100
+           && global.trackcreator[tracknr] == NULL) {
+           unsigned len;
+
+           len = strlen((char *)line);
+
+            if (len > 0)
+               global.trackcreator[tracknr] = malloc(len + 1);
+
+            if (global.trackcreator[tracknr] != NULL) {
+               memcpy(global.trackcreator[tracknr], line, len);
+               global.trackcreator[tracknr][len] = '\0';
+            }
+          } else 
+         if (tracknr == 0
+           && global.creator == NULL) {
+           unsigned len;
+
+           len = strlen((char *)line);
+
+            if (len > 0)
+               global.creator = malloc(len + 1);
+            if (global.creator != NULL) {
+               memcpy(global.creator, line, len);
+               global.creator[len] = '\0';
+            }
+         }
+        break;
+        case 0x82: /* Name(s) of the songwriter(s) */
+#if    DETAILED
+          fprintf(stderr, "Songwriter(s)");
+#endif
+        break;
+        case 0x83: /* Name(s) of the composer(s) */
+#if    DETAILED
+          fprintf(stderr, "Composer(s)");
+#endif
+        break;
+        case 0x84: /* Name(s) of the arranger(s) */
+#if    DETAILED
+          fprintf(stderr, "Arranger(s)");
+#endif
+        break;
+        case 0x85: /* Message from content provider and/or artist */
+#if    DETAILED
+          fprintf(stderr, "Message");
+#endif
+        break;
+        case 0x86: /* Disc Identification and information */
+#if    DETAILED
+          fprintf(stderr, "Disc identification");
+#endif
+         if (tracknr == 0 && line[0] != '\0') {
+           fprintf(stderr, "Disc identification: %s\n", line);
+         }
+        break;
+        case 0x87: /* Genre Identification and information */
+#if    DETAILED
+          fprintf(stderr, "Genre identification");
+#endif
+        break;
+        case 0x8e: /* UPC/EAN code or ISRC code */
+#if    DETAILED
+          fprintf(stderr, "UPC or ISRC");
+#endif
+         if (tracknr > 0 && tracknr < 100) {
+           Set_ISRC(tracknr, line);
+         } else
+         if (tracknr == 0 && line[0] != '\0') {
+           Set_MCN(line);
+         }
+        break;
+        case 0x88: /* Table of Content information */
+#if    DETAILED
+          fprintf(stderr, "Table of Content identification");
+         dump_binary(c); 
+#endif
+        return 0;
+        case 0x89: /* Second Table of Content information */
+#if    DETAILED
+          fprintf(stderr, "Second Table of Content identification");
+         dump_binary(c); 
+#endif
+        return 0;
+        case 0x8f: /* Size information of the block */
+#if    DETAILED == 0
+         break;
+#else
+          switch (tracknr) {
+           case 0:
+         fprintf(stderr, "first track is %d, last track is %d\n", 
+                       c->textdatafield[1],
+                       c->textdatafield[2]);
+         if (c->textdatafield[3] & 0x80) {
+               fprintf(stderr, "Program Area CD Text information available\n");
+               if (c->textdatafield[3] & 0x40) {
+                 fprintf(stderr, "Program Area copy protection available\n");
+               }
+         }
+         if (c->textdatafield[3] & 0x07) {
+               fprintf(stderr, "message information is %scopyrighted\n", 
+                       c->textdatafield[3] & 0x04 ? "": "not ");
+               fprintf(stderr, "Names of performer/songwriter/composer/arranger(s) are %scopyrighted\n", 
+                       c->textdatafield[3] & 0x02 ? "": "not ");
+               fprintf(stderr, "album and track names are %scopyrighted\n", 
+                       c->textdatafield[3] & 0x01 ? "": "not ");
+         }
+         fprintf(stderr, "%d packs with album/track names\n", c->textdatafield[4]);
+         fprintf(stderr, "%d packs with performer names\n", c->textdatafield[5]);
+         fprintf(stderr, "%d packs with songwriter names\n", c->textdatafield[6]);
+         fprintf(stderr, "%d packs with composer names\n", c->textdatafield[7]);
+         fprintf(stderr, "%d packs with arranger names\n", c->textdatafield[8]);
+         fprintf(stderr, "%d packs with artist or content provider messages\n", c->textdatafield[9]);
+         fprintf(stderr, "%d packs with disc identification information\n", c->textdatafield[10]);
+         fprintf(stderr, "%d packs with genre identification/information\n", c->textdatafield[11]);
+         break;
+       case 1:
+         fprintf(stderr, "%d packs with table of contents information\n", c->textdatafield[0]);
+         fprintf(stderr, "%d packs with second table of contents information\n", c->textdatafield[1]);
+         fprintf(stderr, "%d packs with reserved information\n", c->textdatafield[2]);
+         fprintf(stderr, "%d packs with reserved information\n", c->textdatafield[3]);
+         fprintf(stderr, "%d packs with reserved information\n", c->textdatafield[4]);
+         fprintf(stderr, "%d packs with closed information\n", c->textdatafield[5]);
+         fprintf(stderr, "%d packs with UPC/EAN ISRC information\n", c->textdatafield[6]);
+         fprintf(stderr, "%d packs with size information\n", c->textdatafield[7]);
+         fprintf(stderr, "last sequence numbers for blocks 1-8: %d %d %d %d "
+                ,c->textdatafield[8]
+                ,c->textdatafield[9]
+                ,c->textdatafield[10]
+                ,c->textdatafield[11]
+               );
+         break;
+       case 2:
+         fprintf(stderr, "%d %d %d %d\n"
+                ,c->textdatafield[0]
+                ,c->textdatafield[1]
+                ,c->textdatafield[2]
+                ,c->textdatafield[3]
+               );
+         fprintf(stderr, "Language codes for blocks 1-8: %d %d %d %d %d %d %d %d\n"
+                ,c->textdatafield[4]
+                ,c->textdatafield[5]
+                ,c->textdatafield[6]
+                ,c->textdatafield[7]
+                ,c->textdatafield[8]
+                ,c->textdatafield[9]
+                ,c->textdatafield[10]
+                ,c->textdatafield[11]
+               );
+         break;
+        }
+        fprintf(stderr, "Blocksize");
+       dump_binary(c); 
+        return 0;
+#if !defined DEBUG_CDTEXT
+        default:
+#else
+      }
+#endif
+      fprintf(stderr, ": header fields %02x %02x %02x  ",
+              c->headerfield[1], c->headerfield[2], c->headerfield[3]);
+#endif /* DETAILED */
+
+#if !defined DEBUG_CDTEXT
+      }
+#if    DETAILED
+      if (tracknr == 0) {
+            fprintf(stderr, " for album   : ->");
+      } else {
+            fprintf(stderr, " for track %2u: ->", tracknr);
+      }
+      fputs ((char *) line, stderr);
+      fputs ("<-", stderr);
+#endif
+
+      if (dbcc != 0) {
+#else
+      {
+#endif
+      /* EMPTY */
+#if    DETAILED
+          fprintf(stderr,
+"  %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x"
+                        , c->textdatafield[0]
+                        , c->textdatafield[1]
+                        , c->textdatafield[2]
+                        , c->textdatafield[3]
+                        , c->textdatafield[4]
+                        , c->textdatafield[5]
+                        , c->textdatafield[6]
+                        , c->textdatafield[7]
+                        , c->textdatafield[8]
+                        , c->textdatafield[9]
+                        , c->textdatafield[10]
+                        , c->textdatafield[11]
+                 );
+#endif
+      }
+      return 0;
+}
diff --git a/icedax/cdda2mp3 b/icedax/cdda2mp3
new file mode 120000 (symlink)
index 0000000..4a59876
--- /dev/null
@@ -0,0 +1 @@
+cdda2ogg
\ No newline at end of file
diff --git a/icedax/cdda2mp3.new b/icedax/cdda2mp3.new
new file mode 100644 (file)
index 0000000..ee51829
--- /dev/null
@@ -0,0 +1,60 @@
+#!/bin/sh
+# Demo script for processing all audio tracks with a mp3 encoder
+# This variant creates temporary wav files. There is another
+# variant of this script (cdda2mp3), which uses a named pipe
+# instead. This variant needs more disk space than the other one.
+#
+# usage: cdda2mp3.new <name prefix for all mp3 files>
+#
+# list_audio_tracks is a (symbolic) link to cdda2wav
+# and used to generate a list of audio track numbers and start
+# sectors, which in turn are used in a loop to spawn cdda2wav
+# and the post processor on a track by track basis.
+
+#
+# feedback needed!!!!!!!!!!!!!!!!!
+#
+
+# specify the audio track listing program and its options
+LAT=list_audio_tracks
+LAT_OPTIONS=
+
+# specify the sampling program and its options
+# do not specify the track option here!
+CDDA2WAV=cdda2wav
+CDDA2WAV_OPTS='-Owav -H -P0 -q'
+
+# for normal use, comment out the next line with a #
+#DEBUG='-d1'
+
+# specify the post processing program and its options
+MP_CODER=l3enc
+#MP_OPTIONS='2>/dev/null 1>/dev/null'
+MP_OPTIONS='-br 128000'
+#MP_OPTIONS='-hq'
+
+WAVFILE=$$".wav"
+
+FILEPREFIX=${1:-audiotrack}
+
+# clean up wav file on exit, abort, ...
+trap "rm -rf $WAVFILE" 0 2 3 4 6 7 8 10 11 12 13 15
+
+# feed track numbers and start sectors into loop
+$LAT $LAT_OPTIONS | while read TRACK STARTSECTOR;
+do
+  $CDDA2WAV $CDDA2WAV_OPTS -t$TRACK $DEBUG $WAVFILE 
+#  echo n | $MP_CODER $WAVFILE $FILEPREFIX$TRACK.mp3 $MP_OPTIONS 
+  $MP_CODER $WAVFILE $FILEPREFIX$TRACK.mp3 $MP_OPTIONS 
+
+  # check result code
+  RES=$?
+  if [ $RES = 0 ] ; then
+    echo File $FILEPREFIX$TRACK.mp3 finished successfully.
+    rm $WAVFILE
+  else
+    echo File $FILEPREFIX$TRACK.mp3 failed \(result $RES\). Aborted. >&2
+    break
+  fi
+done
+
diff --git a/icedax/cdda2ogg b/icedax/cdda2ogg
new file mode 100755 (executable)
index 0000000..0838384
--- /dev/null
@@ -0,0 +1,82 @@
+#! /bin/sh
+# Script for processing all audio tracks with an ogg or mp3 decoder
+# based on a news article by Tom Kludy
+# This variant uses named pipes in order to save space.
+# usage: cdda2ogg <name prefix for all ogg/mp3 files>
+
+# specify the sampling program and its options
+# do not specify the track option here!
+CDDA2WAV=${CDDA2WAV:-icedax}
+CDDA2WAV_OPTS=${CDDA2WAV_OPTS:-'-H -P0 -q'}
+
+# for normal use, comment out the next line
+#DEBUG='-d1'
+
+# the post processor is fed through a pipe to avoid space waste
+# specify the post processing program and its options
+case $0 in
+   *ogg|*OGG|*Ogg)
+   # ensure the right suffix for suffixes later
+   suffix=ogg
+   missmsg="Encoder not found. Install one first! (eg. vorbis-tools)"
+   MP_CODER=${MP_CODER:-oggenc}
+   outopt="-o"
+   ;;
+   *mp3|*MP3|*mpeg3|*MPEG3|*Mp3)
+   suffix=mp3
+   missmsg="Encoder not found. Install one first! (eg. lame)"
+   MP_CODER=${MP_CODER:-lame}
+   outopt=""
+   ;;
+   *)
+   echo Unknown target file type: $suffix. Valid names for this application are: cdda2mp3, cdda2ogg.
+   exit 1
+   ;;
+esac
+
+MP_OPTIONS=${MP_OPTIONS:-''}
+
+MP_CODER=$(which $MP_CODER 2>/dev/null)
+if [ ! -x "$MP_CODER" ] ; then
+   echo $missmsg
+   exit 1
+fi
+
+CDDA_DEVICE=${CDDA_DEVICE:-/dev/cdrw}
+export CDDA_DEVICE
+
+FILEPREFIX=${1:-audiotrack}
+
+if [ -e /etc/default/cdda2$suffix ]; then
+       . /etc/default/cdda2$suffix
+fi
+
+if [ -z "$LIST" ] ; then
+   echo Looking for available tracks...
+   # could use list_audio_tracks instead but that would need an extra filter as
+   # well, and this way we do not depend on that symlink
+   LIST="$( $CDDA2WAV -J -vtoc -H 2>&1 | sed -e 's/^[^\ ].*//; s/\.([^)]*)/ /g;s/,//g;')"
+   if [ -z "$LIST" ] ; then
+      echo "ERROR: No valid audio tracks detected"
+      exit 1
+   fi
+fi
+
+echo Fetching `echo $LIST | wc -w` tracks from $CDDA_DEVICE, encoding with $MP_CODER.
+echo Cancel with Ctrl-C, watch out for error messages.
+
+for TRACK in $LIST ; do
+   NAME="`printf "%02d" $TRACK`-$FILEPREFIX.$suffix"
+   echo
+   echo "############ Starting with Track Nr. $TRACK -> $NAME ############"
+  $CDDA2WAV $CDDA2WAV_OPTS -t$TRACK $DEBUG - | \
+  $MP_CODER $MP_OPTIONS - $outopt "$NAME"
+
+  # check result code
+  RES=$?
+  if [ $RES != 0 ] ; then
+    echo File $NAME failed \(result $RES\). Aborted. >&2
+    break
+  fi
+done
+
diff --git a/icedax/cdda2ogg.1 b/icedax/cdda2ogg.1
new file mode 100644 (file)
index 0000000..63ac041
--- /dev/null
@@ -0,0 +1,114 @@
+'\"
+.TH "cdda2ogg" "1"
+.SH "NAME"
+cdda2ogg, cdda2mp3 \(em extract audio CD audio tracks and encode them
+.SH "SYNOPSIS"
+.PP
+.B cdda2ogg
+.PP
+.B cdda2mp3
+.SH "DESCRIPTION"
+.PP
+.B cdda2ogg is a simple script that uses the
+.B icedax <fileprefix>
+command to extract all audio tracks with the
+.B icedax <fileprefix>
+command and encode them using the
+.B ogg123
+respective
+.I <censored>
+MP3
+encoder. The scripts are not intended to be full-featured music archiving
+programs, but only for quick storing of few audio data.
+It does not use databases like CDDB or have any extra features. You may look
+at
+.B icedax
+if you need them.
+.PP
+.B ogg123
+is provided by the
+.B vorbis-tools
+which needs to be installed separately.
+See
+.B www.ogg.org
+for more information.
+
+.SH "CONFIGURATION"
+.PP
+.B cdda2ogg
+and
+.B cdda2mp3
+have predefined values for reading and labeling of the target files.
+You can overwrite them with following environment variables:
+
+.IP "CDDA_DEVICE" 10
+Source device specification to get the data from.
+
+.IP "LIST" 10
+List of track numbers to be read, separated by spaces.
+
+.IP "CDDA2WAV" 10
+Defines the command to run the cdda2wav program
+
+.IP "CDDA2WAV_OPTS" 10
+Miscellaneous options passed to 
+.IR $CDDA2WAV .
+
+.IP "MP_CODER" 10
+The encoder program.
+
+.IP "MP_OPTIONS" 10
+Additional options passed to
+.IR $MP_CODER .
+.IP "FILEPREFIX" 10
+The base part of the filename of resulting audio files. This can also be specified as the first argument to the script.
+
+.PP
+See cdda2ogg (cdda2mp3) script file to get the default values
+.PP
+System administrator can also set default values by creating of a shell
+include file, defining the variables for the POSIX shell, and storing them as
+/etc/default/cdda2ogg (resp. cdda2mp3).
+.SH "EXAMPLES"
+.PP
+.B CDDA_DEVICE=/dev/cdrom1 cdda2ogg
+.br
+just stores every track in this device in audiotrackNUMBER.ogg
+.PP
+.PP
+.B LIST="1 5 7" cdda2ogg PartsOfBestOfFoo
+.br
+stores the selected tracks from the default cdrom device as 01-PartsOfBestOfFoo.ogg, 05-PartsOfBestOfFoo.ogg, 07-PartsOfBestOfFoo.ogg.
+
+.SH "SEE ALSO"
+.BR icedax (1)
+.SH "AUTHOR"
+.PP
+This manpage describes the program implementation of
+.B
+cdda2ogg
+as shipped by the cdrkit distribution. See
+.B
+http://alioth.debian.org/projects/debburn/
+for details. It is a spinoff from the original program distributed by the cdrtools project. However, the cdrtools developers are not involved in the development of this spinoff and therefore shall not be made responsible for any problem caused by it. Do not try to get support for this program by contacting the original authors.
+.PP
+If you have support questions, send them to
+.PP
+.B
+debburn-devel@lists.alioth.debian.org
+.br
+.PP
+If you have definitely found a bug, send a mail to this list or to
+.PP
+.B
+submit@bugs.debian.org
+.br
+.PP
+writing at least a short description into the Subject and "Package: cdrkit" into the first line of the mail body.
+.PP
+This manual page was written by Eduard Bloch
+(blade@debian.org) for the
+.B "Debian GNU/Linux system (but may be used by others). Permission is granted
+to copy, distribute and/or modify this document under the terms of the GNU
+General Public License, Version 2 as published by the Free Software Foundation.
diff --git a/icedax/cdda2ogg.mk1 b/icedax/cdda2ogg.mk1
new file mode 100644 (file)
index 0000000..575933b
--- /dev/null
@@ -0,0 +1,18 @@
+#ident @(#)Makefile.man        1.1 00/03/21 
+###########################################################################
+# Sample makefile for installing manual pages
+###########################################################################
+SRCROOT=       ..
+RULESDIR=      RULES
+include                $(SRCROOT)/$(RULESDIR)/rules.top
+###########################################################################
+
+MANDIR=                man
+TARGETMAN=     cdda2ogg
+MANSECT=       $(MANSECT_CMD)
+MANSUFFIX=     $(MANSUFF_CMD)
+MANFILE=       cdda2ogg.1
+
+###########################################################################
+include                $(SRCROOT)/$(RULESDIR)/rules.man
+###########################################################################
diff --git a/icedax/config.h b/icedax/config.h
new file mode 100644 (file)
index 0000000..d08162e
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)config.h        1.7 03/10/06 Copyright 1998-2003 Heiko Eissfeldt */
+/*
+ *     a central configuration file
+ */
+/*
+ * 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; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <mconfig.h>
+
+#if    __STDC__-0 != 0 || (defined PROTOTYPES && defined STDC_HEADERS)
+#define UINT_C(a)      (a##u)
+#define ULONG_C(a)     (a##ul)
+#define USHORT_C(a)    (a##uh)
+#define CONCAT(a,b)    a##b
+#else
+#define UINT_C(a)      ((unsigned) a)
+#define ULONG_C(a)     ((unsigned long) a)
+#define USHORT_C(a)    ((unsigned short) a)
+#define CONCAT(a,b)    a/**/b
+#endif
+
+#include "lconfig.h"
+
+/* temporary until a autoconf check is present */
+#ifdef __BEOS__
+#define        HAVE_AREAS      1
+#endif
+
+#if defined HAVE_FORK && (defined (HAVE_SMMAP) || defined(HAVE_USGSHM) || defined(HAVE_DOSALLOCSHAREDMEM) || defined (HAVE_AREAS))
+#define HAVE_FORK_AND_SHAREDMEM
+#undef FIFO
+#define FIFO
+#else
+#undef FIFO
+#endif
+#if    !defined        HAVE_MEMMOVE
+#define        memmove(dst, src, size) movebytes((src), (dst), (size))
+#endif
diff --git a/icedax/configure b/icedax/configure
new file mode 100755 (executable)
index 0000000..bbbb61f
--- /dev/null
@@ -0,0 +1,1390 @@
+#! /bin/sh
+
+# Guess values for system-dependent variables and create Makefiles.
+# Generated automatically using autoconf version 2.13 
+# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+
+# Defaults:
+ac_help=
+ac_default_prefix=/usr/local
+# Any additions from configure.in:
+
+# Initialize some variables set by options.
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+build=NONE
+cache_file=./config.cache
+exec_prefix=NONE
+host=NONE
+no_create=
+nonopt=NONE
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+target=NONE
+verbose=
+x_includes=NONE
+x_libraries=NONE
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datadir='${prefix}/share'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+libdir='${exec_prefix}/lib'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+infodir='${prefix}/info'
+mandir='${prefix}/man'
+
+# Initialize some other variables.
+subdirs=
+MFLAGS= MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+# Maximum number of lines to put in a shell here document.
+ac_max_here_lines=12
+
+ac_prev=
+for ac_option
+do
+
+  # If the previous option needs an argument, assign it.
+  if test -n "$ac_prev"; then
+    eval "$ac_prev=\$ac_option"
+    ac_prev=
+    continue
+  fi
+
+  case "$ac_option" in
+  -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+  *) ac_optarg= ;;
+  esac
+
+  # Accept the important Cygnus configure options, so we can diagnose typos.
+
+  case "$ac_option" in
+
+  -bindir | --bindir | --bindi | --bind | --bin | --bi)
+    ac_prev=bindir ;;
+  -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+    bindir="$ac_optarg" ;;
+
+  -build | --build | --buil | --bui | --bu)
+    ac_prev=build ;;
+  -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+    build="$ac_optarg" ;;
+
+  -cache-file | --cache-file | --cache-fil | --cache-fi \
+  | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+    ac_prev=cache_file ;;
+  -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+  | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+    cache_file="$ac_optarg" ;;
+
+  -cc=* | --cc=* )
+    CC="$ac_optarg" ; echo using $CC as compiler ;;
+
+  -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
+    ac_prev=datadir ;;
+  -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
+  | --da=*)
+    datadir="$ac_optarg" ;;
+
+  -disable-* | --disable-*)
+    ac_feature=`echo $ac_option|sed -e 's/-*disable-//'`
+    # Reject names that are not valid shell variable names.
+    if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then
+      { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+    fi
+    ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+    eval "enable_${ac_feature}=no" ;;
+
+  -enable-* | --enable-*)
+    ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'`
+    # Reject names that are not valid shell variable names.
+    if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then
+      { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+    fi
+    ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+    case "$ac_option" in
+      *=*) ;;
+      *) ac_optarg=yes ;;
+    esac
+    eval "enable_${ac_feature}='$ac_optarg'" ;;
+
+  -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+  | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+  | --exec | --exe | --ex)
+    ac_prev=exec_prefix ;;
+  -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+  | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+  | --exec=* | --exe=* | --ex=*)
+    exec_prefix="$ac_optarg" ;;
+
+  -gas | --gas | --ga | --g)
+    # Obsolete; use --with-gas.
+    with_gas=yes ;;
+
+  -help | --help | --hel | --he)
+    # Omit some internal or obsolete options to make the list less imposing.
+    # This message is too long to be a string in the A/UX 3.1 sh.
+    cat << EOF
+Usage: configure [options] [host]
+Options: [defaults in brackets after descriptions]
+Configuration:
+  --cache-file=FILE       cache test results in FILE
+  --help                  print this message
+  --no-create             do not create output files
+  --quiet, --silent       do not print \`checking...' messages
+  --version               print the version of autoconf that created configure
+Directory and file names:
+  --prefix=PREFIX         install architecture-independent files in PREFIX
+                          [$ac_default_prefix]
+  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
+                          [same as prefix]
+  --bindir=DIR            user executables in DIR [EPREFIX/bin]
+  --sbindir=DIR           system admin executables in DIR [EPREFIX/sbin]
+  --libexecdir=DIR        program executables in DIR [EPREFIX/libexec]
+  --datadir=DIR           read-only architecture-independent data in DIR
+                          [PREFIX/share]
+  --sysconfdir=DIR        read-only single-machine data in DIR [PREFIX/etc]
+  --sharedstatedir=DIR    modifiable architecture-independent data in DIR
+                          [PREFIX/com]
+  --localstatedir=DIR     modifiable single-machine data in DIR [PREFIX/var]
+  --libdir=DIR            object code libraries in DIR [EPREFIX/lib]
+  --includedir=DIR        C header files in DIR [PREFIX/include]
+  --oldincludedir=DIR     C header files for non-gcc in DIR [/usr/include]
+  --infodir=DIR           info documentation in DIR [PREFIX/info]
+  --mandir=DIR            man documentation in DIR [PREFIX/man]
+  --srcdir=DIR            find the sources in DIR [configure dir or ..]
+  --program-prefix=PREFIX prepend PREFIX to installed program names
+  --program-suffix=SUFFIX append SUFFIX to installed program names
+  --program-transform-name=PROGRAM
+                          run sed PROGRAM on installed program names
+EOF
+    cat << EOF
+Host type:
+  --build=BUILD           configure for building on BUILD [BUILD=HOST]
+  --host=HOST             configure for HOST [guessed]
+  --target=TARGET         configure for TARGET [TARGET=HOST]
+Features and packages:
+  --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
+  --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
+  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
+  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
+  --x-includes=DIR        X include files are in DIR
+  --x-libraries=DIR       X library files are in DIR
+EOF
+    if test -n "$ac_help"; then
+      echo "--enable and --with options recognized:$ac_help"
+    fi
+    exit 0 ;;
+
+  -host | --host | --hos | --ho)
+    ac_prev=host ;;
+  -host=* | --host=* | --hos=* | --ho=*)
+    host="$ac_optarg" ;;
+
+  -includedir | --includedir | --includedi | --included | --include \
+  | --includ | --inclu | --incl | --inc)
+    ac_prev=includedir ;;
+  -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+  | --includ=* | --inclu=* | --incl=* | --inc=*)
+    includedir="$ac_optarg" ;;
+
+  -infodir | --infodir | --infodi | --infod | --info | --inf)
+    ac_prev=infodir ;;
+  -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+    infodir="$ac_optarg" ;;
+
+  -libdir | --libdir | --libdi | --libd)
+    ac_prev=libdir ;;
+  -libdir=* | --libdir=* | --libdi=* | --libd=*)
+    libdir="$ac_optarg" ;;
+
+  -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+  | --libexe | --libex | --libe)
+    ac_prev=libexecdir ;;
+  -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+  | --libexe=* | --libex=* | --libe=*)
+    libexecdir="$ac_optarg" ;;
+
+  -localstatedir | --localstatedir | --localstatedi | --localstated \
+  | --localstate | --localstat | --localsta | --localst \
+  | --locals | --local | --loca | --loc | --lo)
+    ac_prev=localstatedir ;;
+  -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+  | --localstate=* | --localstat=* | --localsta=* | --localst=* \
+  | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
+    localstatedir="$ac_optarg" ;;
+
+  -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+    ac_prev=mandir ;;
+  -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+    mandir="$ac_optarg" ;;
+
+  -nfp | --nfp | --nf)
+    # Obsolete; use --without-fp.
+    with_fp=no ;;
+
+  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+  | --no-cr | --no-c)
+    no_create=yes ;;
+
+  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+    no_recursion=yes ;;
+
+  -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+  | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+  | --oldin | --oldi | --old | --ol | --o)
+    ac_prev=oldincludedir ;;
+  -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+  | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+  | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+    oldincludedir="$ac_optarg" ;;
+
+  -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+    ac_prev=prefix ;;
+  -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+    prefix="$ac_optarg" ;;
+
+  -program-prefix | --program-prefix | --program-prefi | --program-pref \
+  | --program-pre | --program-pr | --program-p)
+    ac_prev=program_prefix ;;
+  -program-prefix=* | --program-prefix=* | --program-prefi=* \
+  | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+    program_prefix="$ac_optarg" ;;
+
+  -program-suffix | --program-suffix | --program-suffi | --program-suff \
+  | --program-suf | --program-su | --program-s)
+    ac_prev=program_suffix ;;
+  -program-suffix=* | --program-suffix=* | --program-suffi=* \
+  | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+    program_suffix="$ac_optarg" ;;
+
+  -program-transform-name | --program-transform-name \
+  | --program-transform-nam | --program-transform-na \
+  | --program-transform-n | --program-transform- \
+  | --program-transform | --program-transfor \
+  | --program-transfo | --program-transf \
+  | --program-trans | --program-tran \
+  | --progr-tra | --program-tr | --program-t)
+    ac_prev=program_transform_name ;;
+  -program-transform-name=* | --program-transform-name=* \
+  | --program-transform-nam=* | --program-transform-na=* \
+  | --program-transform-n=* | --program-transform-=* \
+  | --program-transform=* | --program-transfor=* \
+  | --program-transfo=* | --program-transf=* \
+  | --program-trans=* | --program-tran=* \
+  | --progr-tra=* | --program-tr=* | --program-t=*)
+    program_transform_name="$ac_optarg" ;;
+
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil)
+    silent=yes ;;
+
+  -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+    ac_prev=sbindir ;;
+  -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+  | --sbi=* | --sb=*)
+    sbindir="$ac_optarg" ;;
+
+  -sharedstatedir | --sharedstatedir | --sharedstatedi \
+  | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+  | --sharedst | --shareds | --shared | --share | --shar \
+  | --sha | --sh)
+    ac_prev=sharedstatedir ;;
+  -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+  | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+  | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+  | --sha=* | --sh=*)
+    sharedstatedir="$ac_optarg" ;;
+
+  -site | --site | --sit)
+    ac_prev=site ;;
+  -site=* | --site=* | --sit=*)
+    site="$ac_optarg" ;;
+
+  -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+    ac_prev=srcdir ;;
+  -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+    srcdir="$ac_optarg" ;;
+
+  -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+  | --syscon | --sysco | --sysc | --sys | --sy)
+    ac_prev=sysconfdir ;;
+  -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+  | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+    sysconfdir="$ac_optarg" ;;
+
+  -target | --target | --targe | --targ | --tar | --ta | --t)
+    ac_prev=target ;;
+  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+    target="$ac_optarg" ;;
+
+  -v | -verbose | --verbose | --verbos | --verbo | --verb)
+    verbose=yes ;;
+
+  -version | --version | --versio | --versi | --vers)
+    echo "configure generated by autoconf version 2.13"
+    exit 0 ;;
+
+  -with-* | --with-*)
+    ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'`
+    # Reject names that are not valid shell variable names.
+    if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then
+      { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+    fi
+    ac_package=`echo $ac_package| sed 's/-/_/g'`
+    case "$ac_option" in
+      *=*) ;;
+      *) ac_optarg=yes ;;
+    esac
+    eval "with_${ac_package}='$ac_optarg'" ;;
+
+  -without-* | --without-*)
+    ac_package=`echo $ac_option|sed -e 's/-*without-//'`
+    # Reject names that are not valid shell variable names.
+    if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then
+      { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+    fi
+    ac_package=`echo $ac_package| sed 's/-/_/g'`
+    eval "with_${ac_package}=no" ;;
+
+  --x)
+    # Obsolete; use --with-x.
+    with_x=yes ;;
+
+  -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+  | --x-incl | --x-inc | --x-in | --x-i)
+    ac_prev=x_includes ;;
+  -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+  | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+    x_includes="$ac_optarg" ;;
+
+  -x-libraries | --x-libraries | --x-librarie | --x-librari \
+  | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+    ac_prev=x_libraries ;;
+  -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+  | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+    x_libraries="$ac_optarg" ;;
+
+  -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; }
+    ;;
+
+  *)
+    if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then
+      echo "configure: warning: $ac_option: invalid host type" 1>&2
+    fi
+    if test "x$nonopt" != xNONE; then
+      { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; }
+    fi
+    nonopt="$ac_option"
+    ;;
+
+  esac
+done
+
+if test -n "$ac_prev"; then
+  { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; }
+fi
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+# File descriptor usage:
+# 0 standard input
+# 1 file creation
+# 2 errors and warnings
+# 3 some systems may open it to /dev/tty
+# 4 used on the Kubota Titan
+# 6 checking for... messages and results
+# 5 compiler messages saved in config.log
+if test "$silent" = yes; then
+  exec 6>/dev/null
+else
+  exec 6>&1
+fi
+exec 5>./config.log
+
+echo "\
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+" 1>&5
+
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Also quote any args containing shell metacharacters.
+ac_configure_args=
+for ac_arg
+do
+  case "$ac_arg" in
+  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+  | --no-cr | --no-c) ;;
+  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;;
+  *" "*|*"     "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
+  ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+  *) ac_configure_args="$ac_configure_args $ac_arg" ;;
+  esac
+done
+
+# NLS nuisances.
+# Only set these to C if already set.  These must not be set unconditionally
+# because not all systems understand e.g. LANG=C (notably SCO).
+# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'!
+# Non-C LC_CTYPE values break the ctype check.
+if test "${LANG+set}"   = set; then LANG=C;   export LANG;   fi
+if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
+if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi
+if test "${LC_CTYPE+set}"    = set; then LC_CTYPE=C;    export LC_CTYPE;    fi
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+echo > confdefs.h
+
+# A filename unique to this package, relative to the directory that
+# configure is in, which we can look for to find out if srcdir is correct.
+ac_unique_file=cdda2wav.c
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+  ac_srcdir_defaulted=yes
+  # Try the directory containing this script, then its parent.
+  ac_prog=$0
+  ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'`
+  test "x$ac_confdir" = "x$ac_prog" && ac_confdir=.
+  srcdir=$ac_confdir
+  if test ! -r $srcdir/$ac_unique_file; then
+    srcdir=..
+  fi
+else
+  ac_srcdir_defaulted=no
+fi
+if test ! -r $srcdir/$ac_unique_file; then
+  if test "$ac_srcdir_defaulted" = yes; then
+    { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; }
+  else
+    { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; }
+  fi
+fi
+srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'`
+
+# Prefer explicitly selected file to automatically selected ones.
+if test -z "$CONFIG_SITE"; then
+  if test "x$prefix" != xNONE; then
+    CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
+  else
+    CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+  fi
+fi
+for ac_site_file in $CONFIG_SITE; do
+  if test -r "$ac_site_file"; then
+    echo "loading site script $ac_site_file"
+    . "$ac_site_file"
+  fi
+done
+
+if test -r "$cache_file"; then
+  echo "loading cache $cache_file"
+  . $cache_file
+else
+  echo "creating cache $cache_file"
+  > $cache_file
+fi
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+ac_exeext=
+ac_objext=o
+if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
+  # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
+  if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
+    ac_n= ac_c='
+' ac_t='       '
+  else
+    ac_n=-n ac_c= ac_t=
+  fi
+else
+  ac_n= ac_c='\c' ac_t=
+fi
+
+
+
+
+ac_aux_dir=
+for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
+  if test -f $ac_dir/install-sh; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install-sh -c"
+    break
+  elif test -f $ac_dir/install.sh; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install.sh -c"
+    break
+  fi
+done
+if test -z "$ac_aux_dir"; then
+  { echo "configure: error: can not find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." 1>&2; exit 1; }
+fi
+ac_config_guess=$ac_aux_dir/config.guess
+ac_config_sub=$ac_aux_dir/config.sub
+ac_configure=$ac_aux_dir/configure # This should be Cygnus configure.
+
+
+# Make sure we can run config.sub.
+if ${CONFIG_SHELL-/bin/sh} $ac_config_sub sun4 >/dev/null 2>&1; then :
+else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; }
+fi
+
+echo $ac_n "checking host system type""... $ac_c" 1>&6
+echo "configure:556: checking host system type" >&5
+
+host_alias=$host
+case "$host_alias" in
+NONE)
+  case $nonopt in
+  NONE)
+    if host_alias=`${CONFIG_SHELL-/bin/sh} $ac_config_guess`; then :
+    else { echo "configure: error: can not guess host type; you must specify one" 1>&2; exit 1; }
+    fi ;;
+  *) host_alias=$nonopt ;;
+  esac ;;
+esac
+
+host=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $host_alias`
+host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+echo "$ac_t""$host" 1>&6
+
+
+CDRTOOLS_VERSION=`sed -n -f ../../version.sed <../../../cdrecord/cdrecord.c`
+
+
+
+case "$host_os" in
+   solaris*|sunos*)
+echo $ac_n "checking for sched_get_priority_max in -lposix4""... $ac_c" 1>&6
+echo "configure:584: checking for sched_get_priority_max in -lposix4" >&5
+ac_lib_var=`echo posix4'_'sched_get_priority_max | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  ac_save_LIBS="$LIBS"
+LIBS="-lposix4  $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 592 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char sched_get_priority_max();
+
+int main() {
+sched_get_priority_max()
+; return 0; }
+EOF
+if { (eval echo configure:603: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+    ac_tr_lib=HAVE_LIB`echo posix4 | sed -e 's/[^a-zA-Z0-9_]/_/g' \
+    -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+  cat >> confdefs.h <<EOF
+#define $ac_tr_lib 1
+EOF
+
+  LIBS="-lposix4 $LIBS"
+
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+;;
+esac
+echo $ac_n "checking for _oss_ioctl in -lossaudio""... $ac_c" 1>&6
+echo "configure:633: checking for _oss_ioctl in -lossaudio" >&5
+ac_lib_var=`echo ossaudio'_'_oss_ioctl | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  ac_save_LIBS="$LIBS"
+LIBS="-lossaudio  $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 641 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char _oss_ioctl();
+
+int main() {
+_oss_ioctl()
+; return 0; }
+EOF
+if { (eval echo configure:652: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+    ac_tr_lib=HAVE_LIB`echo ossaudio | sed -e 's/[^a-zA-Z0-9_]/_/g' \
+    -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+  cat >> confdefs.h <<EOF
+#define $ac_tr_lib 1
+EOF
+
+  LIBS="-lossaudio $LIBS"
+
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+
+EXTRALIBS="$LIBS"
+
+
+
+echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
+echo "configure:685: checking how to run the C preprocessor" >&5
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+  CPP=
+fi
+if test -z "$CPP"; then
+if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+    # This must be in double quotes, not single quotes, because CPP may get
+  # substituted into the Makefile and "${CC-cc}" will confuse make.
+  CPP="${CC-cc} -E"
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp.
+  cat > conftest.$ac_ext <<EOF
+#line 700 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:706: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+  :
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  CPP="${CC-cc} -E -traditional-cpp"
+  cat > conftest.$ac_ext <<EOF
+#line 717 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:723: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+  :
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  CPP="${CC-cc} -nologo -E"
+  cat > conftest.$ac_ext <<EOF
+#line 734 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:740: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+  :
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  CPP=/lib/cpp
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+  ac_cv_prog_CPP="$CPP"
+fi
+  CPP="$ac_cv_prog_CPP"
+else
+  ac_cv_prog_CPP="$CPP"
+fi
+echo "$ac_t""$CPP" 1>&6
+
+for ac_hdr in sys/cdio.h sys/cdrio.h sundev/srreg.h sys/audioio.h sun/audioio.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:768: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 773 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:778: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=yes"
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+    ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+  cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+else
+  echo "$ac_t""no" 1>&6
+fi
+done
+
+for ac_hdr in soundcard.h sys/soundcard.h linux/soundcard.h machine/soundcard.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:808: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 813 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:818: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=yes"
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+    ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+  cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+else
+  echo "$ac_t""no" 1>&6
+fi
+done
+
+for ac_hdr in sys/asoundlib.h windows.h mmsystem.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:848: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 853 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:858: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=yes"
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+    ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+  cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+else
+  echo "$ac_t""no" 1>&6
+fi
+done
+
+for ac_hdr in os2.h os2me.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:888: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 893 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:898: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=yes"
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+    ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+  cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+else
+  echo "$ac_t""no" 1>&6
+fi
+done
+
+
+case "${ac_cv_header_sys_cdio_h}""${ac_cv_header_sundev_srreg_h}" in
+   *yes*)
+HAVE_SUN_IOCTL=1
+;;
+   *)
+HAVE_SUN_IOCTL=
+;;
+esac
+
+
+case "${ac_cv_header_sys_audioio_h}""${ac_cv_header_sun_audioio_h}" in
+   *yes*)
+HAVE_SUNSOUND=1
+;;
+   *)
+HAVE_SUNSOUND=
+;;
+esac
+
+
+case "${ac_cv_header_machine_soundcard_h}""${ac_cv_header_sys_soundcard_h}""${ac_cv_header_linux_soundcard_h}" in
+   *yes*)
+HAVE_OSS=1
+;;
+   *)
+HAVE_OSS=
+;;
+esac
+
+
+
+
+case "${ac_cv_header_windows_h}""${ac_cv_header_mmsystem_h}" in
+   *yesyes*)
+HAVE_WINSOUND=1
+;;
+   *)
+HAVE_WINSOUND=
+;;
+esac
+
+
+case "${ac_cv_header_os2_h}""${ac_cv_header_os2me_h}" in
+   *yesyes*)
+HAVE_OS2SOUND=1
+;;
+   *)
+HAVE_OS2SOUND=
+;;
+esac
+
+
+for ac_func in strtoul
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:980: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 985 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func(); below.  */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:1008: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_func_$ac_func=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+    ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+  cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+else
+  echo "$ac_t""no" 1>&6
+fi
+done
+
+trap '' 1 2 15
+cat > confcache <<\EOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs.  It is not useful on other systems.
+# If it contains results you don't want to keep, you may remove or edit it.
+#
+# By default, configure uses ./config.cache as the cache file,
+# creating it if it does not exist already.  You can give configure
+# the --cache-file=FILE option to use a different cache file; that is
+# what configure does when it calls configure scripts in
+# subdirectories, so they share the cache.
+# Giving --cache-file=/dev/null disables caching, for debugging configure.
+# config.status only pays attention to the cache file if you give it the
+# --recheck option to rerun configure.
+#
+EOF
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(set) 2>&1 |
+  case `(ac_space=' '; set | grep ac_space) 2>&1` in
+  *ac_space=\ *)
+    # `set' does not quote correctly, so add quotes (double-quote substitution
+    # turns \\\\ into \\, and sed turns \\ into \).
+    sed -n \
+      -e "s/'/'\\\\''/g" \
+      -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p"
+    ;;
+  *)
+    # `set' quotes correctly as required by POSIX, so do not add quotes.
+    sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p'
+    ;;
+  esac >> confcache
+if cmp -s $cache_file confcache; then
+  :
+else
+  if test -w $cache_file; then
+    echo "updating cache $cache_file"
+    cat confcache > $cache_file
+  else
+    echo "not updating unwritable cache $cache_file"
+  fi
+fi
+rm -f confcache
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# Any assignment to VPATH causes Sun make to only execute
+# the first set of double-colon rules, so remove it if not needed.
+# If there is a colon in the path, we need to keep it.
+if test "x$srcdir" = x.; then
+  ac_vpsub='/^[        ]*VPATH[        ]*=[^:]*$/d'
+fi
+
+trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15
+
+DEFS=-DHAVE_CONFIG_H
+
+# Without the "./", some shells look in PATH for config.status.
+: ${CONFIG_STATUS=./config.status}
+
+echo creating $CONFIG_STATUS
+rm -f $CONFIG_STATUS
+cat > $CONFIG_STATUS <<EOF
+#! /bin/sh
+# Generated automatically by configure.
+# Run this file to recreate the current configuration.
+# This directory was configured as follows,
+# on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+#
+# $0 $ac_configure_args
+#
+# Compiler output produced by configure, useful for debugging
+# configure, is in ./config.log if it exists.
+
+ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]"
+for ac_option
+do
+  case "\$ac_option" in
+  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+    echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
+    exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
+  -version | --version | --versio | --versi | --vers | --ver | --ve | --v)
+    echo "$CONFIG_STATUS generated by autoconf version 2.13"
+    exit 0 ;;
+  -help | --help | --hel | --he | --h)
+    echo "\$ac_cs_usage"; exit 0 ;;
+  *) echo "\$ac_cs_usage"; exit 1 ;;
+  esac
+done
+
+ac_given_srcdir=$srcdir
+
+trap 'rm -fr `echo "local.cnf lconfig.h" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+# Protect against being on the right side of a sed subst in config.status.
+sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g;
+ s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF
+$ac_vpsub
+$extrasub
+s%@SHELL@%$SHELL%g
+s%@CFLAGS@%$CFLAGS%g
+s%@CPPFLAGS@%$CPPFLAGS%g
+s%@CXXFLAGS@%$CXXFLAGS%g
+s%@FFLAGS@%$FFLAGS%g
+s%@DEFS@%$DEFS%g
+s%@LDFLAGS@%$LDFLAGS%g
+s%@LIBS@%$LIBS%g
+s%@exec_prefix@%$exec_prefix%g
+s%@prefix@%$prefix%g
+s%@program_transform_name@%$program_transform_name%g
+s%@bindir@%$bindir%g
+s%@sbindir@%$sbindir%g
+s%@libexecdir@%$libexecdir%g
+s%@datadir@%$datadir%g
+s%@sysconfdir@%$sysconfdir%g
+s%@sharedstatedir@%$sharedstatedir%g
+s%@localstatedir@%$localstatedir%g
+s%@libdir@%$libdir%g
+s%@includedir@%$includedir%g
+s%@oldincludedir@%$oldincludedir%g
+s%@infodir@%$infodir%g
+s%@mandir@%$mandir%g
+s%@host@%$host%g
+s%@host_alias@%$host_alias%g
+s%@host_cpu@%$host_cpu%g
+s%@host_vendor@%$host_vendor%g
+s%@host_os@%$host_os%g
+s%@CDRTOOLS_VERSION@%$CDRTOOLS_VERSION%g
+s%@EXTRALIBS@%$EXTRALIBS%g
+s%@CPP@%$CPP%g
+s%@HAVE_SUN_IOCTL@%$HAVE_SUN_IOCTL%g
+s%@HAVE_SUNSOUND@%$HAVE_SUNSOUND%g
+s%@HAVE_OSS@%$HAVE_OSS%g
+s%@HAVE_SYS_ASOUNDLIB_H@%$HAVE_SYS_ASOUNDLIB_H%g
+s%@HAVE_WINSOUND@%$HAVE_WINSOUND%g
+s%@HAVE_OS2SOUND@%$HAVE_OS2SOUND%g
+
+CEOF
+EOF
+
+cat >> $CONFIG_STATUS <<\EOF
+
+# Split the substitutions into bite-sized pieces for seds with
+# small command number limits, like on Digital OSF/1 and HP-UX.
+ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script.
+ac_file=1 # Number of current file.
+ac_beg=1 # First line for current file.
+ac_end=$ac_max_sed_cmds # Line after last line for current file.
+ac_more_lines=:
+ac_sed_cmds=""
+while $ac_more_lines; do
+  if test $ac_beg -gt 1; then
+    sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file
+  else
+    sed "${ac_end}q" conftest.subs > conftest.s$ac_file
+  fi
+  if test ! -s conftest.s$ac_file; then
+    ac_more_lines=false
+    rm -f conftest.s$ac_file
+  else
+    if test -z "$ac_sed_cmds"; then
+      ac_sed_cmds="sed -f conftest.s$ac_file"
+    else
+      ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file"
+    fi
+    ac_file=`expr $ac_file + 1`
+    ac_beg=$ac_end
+    ac_end=`expr $ac_end + $ac_max_sed_cmds`
+  fi
+done
+if test -z "$ac_sed_cmds"; then
+  ac_sed_cmds=cat
+fi
+EOF
+
+cat >> $CONFIG_STATUS <<EOF
+
+CONFIG_FILES=\${CONFIG_FILES-"local.cnf"}
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
+  # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+  case "$ac_file" in
+  *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
+       ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+  *) ac_file_in="${ac_file}.in" ;;
+  esac
+
+  # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories.
+
+  # Remove last slash and all that follows it.  Not all systems have dirname.
+  ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+  if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+    # The file is in a subdirectory.
+    test ! -d "$ac_dir" && mkdir "$ac_dir"
+    ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`"
+    # A "../" for each directory in $ac_dir_suffix.
+    ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'`
+  else
+    ac_dir_suffix= ac_dots=
+  fi
+
+  case "$ac_given_srcdir" in
+  .)  srcdir=.
+      if test -z "$ac_dots"; then top_srcdir=.
+      else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;;
+  /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;;
+  *) # Relative path.
+    srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix"
+    top_srcdir="$ac_dots$ac_given_srcdir" ;;
+  esac
+
+
+  echo creating "$ac_file"
+  rm -f "$ac_file"
+  configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
+  case "$ac_file" in
+  *Makefile*) ac_comsub="1i\\
+# $configure_input" ;;
+  *) ac_comsub= ;;
+  esac
+
+  ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
+  sed -e "$ac_comsub
+s%@configure_input@%$configure_input%g
+s%@srcdir@%$srcdir%g
+s%@top_srcdir@%$top_srcdir%g
+" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file
+fi; done
+rm -f conftest.s*
+
+# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where
+# NAME is the cpp macro being defined and VALUE is the value it is being given.
+#
+# ac_d sets the value in "#define NAME VALUE" lines.
+ac_dA='s%^\([  ]*\)#\([        ]*define[       ][      ]*\)'
+ac_dB='\([     ][      ]*\)[^  ]*%\1#\2'
+ac_dC='\3'
+ac_dD='%g'
+# ac_u turns "#undef NAME" with trailing blanks into "#define NAME VALUE".
+ac_uA='s%^\([  ]*\)#\([        ]*\)undef\([    ][      ]*\)'
+ac_uB='\([     ]\)%\1#\2define\3'
+ac_uC=' '
+ac_uD='\4%g'
+# ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE".
+ac_eA='s%^\([  ]*\)#\([        ]*\)undef\([    ][      ]*\)'
+ac_eB='$%\1#\2define\3'
+ac_eC=' '
+ac_eD='%g'
+
+if test "${CONFIG_HEADERS+set}" != set; then
+EOF
+cat >> $CONFIG_STATUS <<EOF
+  CONFIG_HEADERS="lconfig.h"
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+fi
+for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then
+  # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+  case "$ac_file" in
+  *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
+       ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+  *) ac_file_in="${ac_file}.in" ;;
+  esac
+
+  echo creating $ac_file
+
+  rm -f conftest.frag conftest.in conftest.out
+  ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
+  cat $ac_file_inputs > conftest.in
+
+EOF
+
+# Transform confdefs.h into a sed script conftest.vals that substitutes
+# the proper values into config.h.in to produce config.h.  And first:
+# Protect against being on the right side of a sed subst in config.status.
+# Protect against being in an unquoted here document in config.status.
+rm -f conftest.vals
+cat > conftest.hdr <<\EOF
+s/[\\&%]/\\&/g
+s%[\\$`]%\\&%g
+s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD}%gp
+s%ac_d%ac_u%gp
+s%ac_u%ac_e%gp
+EOF
+sed -n -f conftest.hdr confdefs.h > conftest.vals
+rm -f conftest.hdr
+
+# This sed command replaces #undef with comments.  This is necessary, for
+# example, in the case of _POSIX_SOURCE, which is predefined and required
+# on some systems where configure will not decide to define it.
+cat >> conftest.vals <<\EOF
+s%^[   ]*#[    ]*undef[        ][      ]*[a-zA-Z_][a-zA-Z_0-9]*%/* & */%
+EOF
+
+# Break up conftest.vals because some shells have a limit on
+# the size of here documents, and old seds have small limits too.
+
+rm -f conftest.tail
+while :
+do
+  ac_lines=`grep -c . conftest.vals`
+  # grep -c gives empty output for an empty file on some AIX systems.
+  if test -z "$ac_lines" || test "$ac_lines" -eq 0; then break; fi
+  # Write a limited-size here document to conftest.frag.
+  echo '  cat > conftest.frag <<CEOF' >> $CONFIG_STATUS
+  sed ${ac_max_here_lines}q conftest.vals >> $CONFIG_STATUS
+  echo 'CEOF
+  sed -f conftest.frag conftest.in > conftest.out
+  rm -f conftest.in
+  mv conftest.out conftest.in
+' >> $CONFIG_STATUS
+  sed 1,${ac_max_here_lines}d conftest.vals > conftest.tail
+  rm -f conftest.vals
+  mv conftest.tail conftest.vals
+done
+rm -f conftest.vals
+
+cat >> $CONFIG_STATUS <<\EOF
+  rm -f conftest.frag conftest.h
+  echo "/* $ac_file.  Generated automatically by configure.  */" > conftest.h
+  cat conftest.in >> conftest.h
+  rm -f conftest.in
+  if cmp -s $ac_file conftest.h 2>/dev/null; then
+    echo "$ac_file is unchanged"
+    rm -f conftest.h
+  else
+    # Remove last slash and all that follows it.  Not all systems have dirname.
+      ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+      if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+      # The file is in a subdirectory.
+      test ! -d "$ac_dir" && mkdir "$ac_dir"
+    fi
+    rm -f $ac_file
+    mv conftest.h $ac_file
+  fi
+fi; done
+
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+
+exit 0
+EOF
+chmod +x $CONFIG_STATUS
+rm -fr confdefs* $ac_clean_files
+test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1
+
diff --git a/icedax/configure.in b/icedax/configure.in
new file mode 100644 (file)
index 0000000..5229ef9
--- /dev/null
@@ -0,0 +1,88 @@
+dnl @(#)configure.in   1.8 06/02/15    Copyright 1998-2003 Heiko Eißfeldt
+dnl Process this file with autoconf to produce a configure script.
+AC_INIT(cdda2wav.c)
+AC_CONFIG_HEADER(lconfig.h)
+
+dnl get canonical host
+AC_CANONICAL_HOST
+
+dnl extract cdrtools version from the cdrecord.c file
+CDRTOOLS_VERSION=`sed -n -f ../../version.sed <../../../cdrecord/cdrecord.c`
+AC_SUBST(CDRTOOLS_VERSION)
+
+dnl set object extension needed for AC_CHECK_HEADERS by autoconf 2.57
+dnl _AC_COMPILER_OBJEXT
+
+dnl check for posix4 library on Solaris or SunOS
+case "$host_os" in
+   solaris*|sunos*)
+AC_CHECK_LIB(posix4, sched_get_priority_max)
+;;
+esac
+AC_CHECK_LIB(ossaudio, _oss_ioctl)
+
+EXTRALIBS="$LIBS"
+
+AC_SUBST(EXTRALIBS)
+
+dnl check header files
+AC_CHECK_HEADERS(sys/cdio.h sys/cdrio.h sundev/srreg.h sys/audioio.h sun/audioio.h)
+AC_CHECK_HEADERS(soundcard.h sys/soundcard.h linux/soundcard.h machine/soundcard.h)
+AC_CHECK_HEADERS(sys/asoundlib.h windows.h mmsystem.h)
+AC_CHECK_HEADERS(os2.h os2me.h)
+
+case "${ac_cv_header_sys_cdio_h}""${ac_cv_header_sundev_srreg_h}" in
+   *yes*)
+HAVE_SUN_IOCTL=1
+;;
+   *)
+HAVE_SUN_IOCTL=
+;;
+esac
+AC_SUBST(HAVE_SUN_IOCTL)
+
+case "${ac_cv_header_sys_audioio_h}""${ac_cv_header_sun_audioio_h}" in
+   *yes*)
+HAVE_SUNSOUND=1
+;;
+   *)
+HAVE_SUNSOUND=
+;;
+esac
+AC_SUBST(HAVE_SUNSOUND)
+
+case "${ac_cv_header_machine_soundcard_h}""${ac_cv_header_sys_soundcard_h}""${ac_cv_header_linux_soundcard_h}" in
+   *yes*)
+HAVE_OSS=1
+;;
+   *)
+HAVE_OSS=
+;;
+esac
+AC_SUBST(HAVE_OSS)
+
+AC_SUBST(HAVE_SYS_ASOUNDLIB_H)
+
+case "${ac_cv_header_windows_h}""${ac_cv_header_mmsystem_h}" in
+   *yesyes*)
+HAVE_WINSOUND=1
+;;
+   *)
+HAVE_WINSOUND=
+;;
+esac
+AC_SUBST(HAVE_WINSOUND)
+
+case "${ac_cv_header_os2_h}""${ac_cv_header_os2me_h}" in
+   *yesyes*)
+HAVE_OS2SOUND=1
+;;
+   *)
+HAVE_OS2SOUND=
+;;
+esac
+AC_SUBST(HAVE_OS2SOUND)
+
+dnl Checks for library functions.
+AC_CHECK_FUNCS(strtoul)
+AC_OUTPUT(local.cnf)
diff --git a/icedax/exitcodes.h b/icedax/exitcodes.h
new file mode 100644 (file)
index 0000000..b75b171
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)exitcodes.h     1.1 02/11/21 Copyright 2002 Heiko Eissfeldt */
+/* header file for system wide exit codes. */
+#ifndef        exitcodes_h
+#define        exitcodes_h
+
+#define NO_ERROR       0
+#define SYNTAX_ERROR   1
+#define PERM_ERROR     2
+#define READ_ERROR     3
+#define WRITE_ERROR    4
+#define SOUND_ERROR    5
+#define STAT_ERROR     6
+#define SIGPIPE_ERROR  7
+#define SETSIG_ERROR   8
+#define SHMMEM_ERROR   9
+#define NOMEM_ERROR    10
+#define MEDIA_ERROR    11
+#define DEVICEOPEN_ERROR       12
+#define RACE_ERROR     13
+#define DEVICE_ERROR   14
+#define INTERNAL_ERROR 15
+#define SEMAPHORE_ERROR        16
+#define SETUPSCSI_ERROR        17
+#define PIPE_ERROR     18
+#endif
diff --git a/icedax/global.h b/icedax/global.h
new file mode 100644 (file)
index 0000000..fc80c78
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)global.h        1.11 04/07/29 Copyright 1998-2004 Heiko Eissfeldt */
+/* Global Variables */
+
+#ifdef  MD5_SIGNATURES
+#include "md5.h"
+#endif
+#ifdef USE_PARANOIA
+#include "cdda_paranoia.h"
+#endif
+
+typedef struct index_list
+{
+       struct index_list       *next;
+       int                     frameoffset;
+}
+index_list;
+
+typedef struct global
+{
+
+       char                    *dev_name;              /* device name */
+       char                    *aux_name;              /* device name */
+       char                    fname_base[200];
+
+       int                     have_forked;
+       int                     parent_died;
+       int                     audio;
+       struct soundfile        *audio_out;
+       int                     cooked_fd;
+       int                     no_file;
+       int                     no_infofile;
+       int                     no_cddbfile;
+       int                     quiet;
+       int                     verbose;
+       int                     scsi_silent;
+       int                     scsi_verbose;
+       int                     scanbus;
+       int                     scandevs;
+       int                     multiname;
+       int                     sh_bits;
+       int                     Remainder;
+       int                     SkippedSamples;
+       int                     OutSampleSize;
+       int                     need_big_endian;
+       int                     need_hostorder;
+       int                     channels;
+       unsigned long           iloop;
+       unsigned long           nSamplesDoneInTrack;
+       unsigned                overlap;
+       int                     useroverlap;
+       unsigned                nsectors;
+       unsigned                buffers;
+       unsigned                shmsize;
+       long                    pagesize;
+       int                     in_lendian;
+       int                     outputendianess;
+       int                     findminmax;
+       int                     maxamp[2];
+       int                     minamp[2];
+       unsigned                speed;
+       int                     userspeed;
+       int                     ismono;
+       int                     findmono;
+       int                     swapchannels;
+       int                     deemphasize;
+       int                     gui;
+       long                    playback_rate;
+       int                     target; /* SCSI Id to be used */
+       int                     lun;    /* SCSI Lun to be used */
+       UINT4                   cddb_id;
+       int                     cddbp;
+       char *                  cddbp_server;
+       char *                  cddbp_port;
+       unsigned                cddb_revision;
+       int                     cddb_year;
+       char                    cddb_genre[60];
+       int                     illleadout_cd;
+       int                     reads_illleadout;
+       unsigned char           *cdindex_id;
+       unsigned char           *creator;
+       unsigned char           *copyright_message;
+       unsigned char           *disctitle;
+       unsigned char           *tracktitle[100];
+       unsigned char           *trackcreator[100];
+       index_list              *trackindexlist[100];
+
+       int                     paranoia_selected;
+#ifdef USE_PARANOIA
+       cdrom_paranoia          *cdp;
+
+       struct paranoia_parms_t
+       {
+               Ucbit   disable_paranoia:1;
+               Ucbit   disable_extra_paranoia:1;
+               Ucbit   disable_scratch_detect:1;
+               Ucbit   disable_scratch_repair:1;
+               int     retries;
+               int     overlap;
+               int     mindynoverlap;
+               int     maxdynoverlap;
+       }
+       paranoia_parms;
+#endif
+
+       unsigned                md5blocksize;
+#ifdef MD5_SIGNATURES
+       int                     md5count;
+       MD5_CTX                 context;
+       unsigned char           MD5_result[16];
+#endif
+
+#ifdef ECHO_TO_SOUNDCARD
+       int                     soundcard_fd;
+#endif
+       int                     echo;
+
+       int                     just_the_toc;
+}
+global_t;
+
+extern global_t global;
diff --git a/icedax/icedax.1 b/icedax/icedax.1
new file mode 100644 (file)
index 0000000..d9daddb
--- /dev/null
@@ -0,0 +1,1025 @@
+'\" t
+.\" @(#)icedax.1       1.14 02/12/09 Copyright 1998,1999,2000 Heiko Eissfeldt
+.if t .ds a \v'-0.55m'\h'0.00n'\z.\h'0.40n'\z.\v'0.55m'\h'-0.40n'a
+.if t .ds o \v'-0.55m'\h'0.00n'\z.\h'0.45n'\z.\v'0.55m'\h'-0.45n'o
+.if t .ds u \v'-0.55m'\h'0.00n'\z.\h'0.40n'\z.\v'0.55m'\h'-0.40n'u
+.if t .ds A \v'-0.77m'\h'0.25n'\z.\h'0.45n'\z.\v'0.77m'\h'-0.70n'A
+.if t .ds O \v'-0.77m'\h'0.25n'\z.\h'0.45n'\z.\v'0.77m'\h'-0.70n'O
+.if t .ds U \v'-0.77m'\h'0.30n'\z.\h'0.45n'\z.\v'0.77m'\h'-0.75n'U
+.if t .ds s \\(*b
+.if t .ds S SS
+.if n .ds a ae
+.if n .ds o oe
+.if n .ds u ue
+.if n .ds s sz
+.if t .ds m \\(*m
+.if n .ds m micro
+.TH ICEDAX 1
+.SH NAME
+icedax \- a sampling utility that dumps CD audio data into wav sound
+files
+.SH SYNOPSIS
+.B icedax
+.RB [ -c
+.IR chans ]
+.RB [ -s ]
+.RB [ -m ]
+.RB [ -b
+.IR bits ]
+.RB [ -r
+.IR rate ]
+.RB [ -a
+.IR divider ]
+.RB [ -t
+.IR track [ +endtrack ]]
+.RB [ -i
+.IR index ]
+.RB [ -o
+.IR offset ]
+.RB [ -d
+.IR duration ]
+.RB [ -x ]
+.RB [ -q ]
+.RB [ -w ]
+.RB [ -v
+.IR optlist ]
+.RB [ -V ]
+.RB [ -Q ]
+.RB [ -J ]
+.RB [ -L
+.IR cddbmode ]
+.RB [ -R ]
+.RB [ -P
+.IR sectors ]
+.RB [ -F ]
+.RB [ -G ]
+.RB [ -T ]
+.RB [ -e ]
+.RB [ -p
+.IR percentage ]
+.RB [ -n
+.IR sectors ]
+.RB [ -l
+.IR buffers ]
+.RB [ -N ]
+.RB [ -J ]
+.RB [ -H ]
+.RB [ -g ]
+.RB [ -B ]
+.RB [ -D
+.IR device ]
+.RB [ -A
+.IR auxdevice ]
+.RB [ -I
+.IR interface ]
+.RB [ -O
+.IR audiotype ]
+.RB [ -C
+.IR input-endianess ]
+.RB [ -E
+.IR output-endianess ]
+.RB [ -M
+.IR count ]
+.RB [ -S
+.IR speed ]
+.RB [ -paranoia ]
+.RB [ cddbp-server=servername ]
+.RB [ cddbp-port=portnumber ]
+.RI [ filename(s)
+or
+.IR directories ]
+.SH DESCRIPTION
+.B icedax
+stands for InCrEdible Digital Audio eXtractor. It can retrieve audio tracks
+.RB ( CDDA )
+from CDROM drives
+that are
+capable of reading audio data digitally to the host
+(see README for a list of drives).
+
+.SH OPTIONS
+.TP
+.BI dev= device
+.TP
+.BI \-D " device
+.TP
+.BI \-device " device
+uses
+.B device
+as the source for CDDA reading. For example
+.B /dev/cdrom
+or
+.B Bus,ID,Lun.
+The device specification can also have influence on the selection of the driver interface (eg. on Linux).
+See the
+.B \-I
+option for details.
+.sp
+The setting of the environment variable
+.B CDDA_DEVICE
+is overridden by this option.
+.TP
+.BI \-A " auxdevice
+.TP
+.BI \-auxdevice " auxdevice
+uses
+.B auxdevice
+as CDROM drive for ioctl usage.
+.TP
+.BI \-I " interface
+.TP
+.BI \-interface " interface
+specifies the interface for CDROM access:
+.B generic_scsi
+or (on Linux, and FreeBSD systems)
+.BR cooked_ioctl .
+.sp
+Using the
+.B cooked_ioctl
+is not recommended as this makes
+.B icedax
+mainly depend on the audio extraction quality of the operating system
+which is usually extremely bad.
+.TP
+.BI \-c " channels  --channels"
+uses
+.B 1
+for mono, or
+.B 2
+for stereo recording,
+or
+.B s
+for stereo recording with both channels swapped.
+.TP
+.B \-s " --stereo"
+sets to stereo recording.
+.TP
+.B \-m " --mono"
+sets to mono recording.
+.TP
+.B \-x " --max"
+sets maximum (CD) quality.
+.TP
+.BI \-b " bits  --bits-per-sample"
+sets bits per sample per channel:
+.BR 8 ,
+.B 12
+or
+.BR 16 .
+.TP
+.BI \-r " rate  --rate"
+sets rate in samples per second.  Possible values are listed with the
+.B \-R
+option.
+.TP
+.BI \-a " divider  --divider"
+sets rate to 44100Hz / divider.  Possible values are listed with the
+.B \-R
+option.
+.TP
+.B \-R " --dump-rates"
+shows a list of all sample rates and their dividers.
+.TP
+.B \-P " sectors  --set-overlap"
+sets the initial number of overlap
+.I sectors
+for jitter correction.
+.TP
+.BI \-n " sectors  --sectors-per-request"
+reads 
+.I sectors
+per request.
+.TP
+.BI \-l " buffers  --buffers-in-ring"
+uses a ring buffer with 
+.I buffers
+total.
+.TP
+.BI \-t " track+endtrack  --track"
+selects the start track and optionally the end track.
+.TP
+.BI \-i " index  --index"
+selects the start index.
+.TP
+.BI \-o " offset  --offset"
+starts
+.I offset
+sectors behind start track (one sector equivalents 1/75 seconds).
+.TP
+.B \-O " audiotype  --output-format"
+can be 
+.I wav
+(for wav files) or
+.I aiff
+(for apple/sgi aiff files) or
+.I aifc
+(for apple/sgi aifc files) or
+.I au
+or
+.I sun
+(for sun .au PCM files) or
+.I cdr
+or
+.I raw
+(for headerless files to be used for cd writers).
+.TP
+.BI \-C " endianess  --cdrom-endianess"
+sets endianess of the input samples to 'little', 'big' or 'guess' to override defaults.
+.TP
+.BI \-E " endianess  --output-endianess"
+sets endianess of the output samples to 'little' or 'big' to override defaults.
+.TP
+.BI \-d " duration  --duration"
+sets recording time in seconds or frames.
+Frames (sectors) are indicated by a 'f' suffix (like 75f for 75 sectors).
+.B 0
+sets the time for whole track.
+.TP
+.B \-B " --bulk --alltracks"
+copies each track into a separate file.
+.TP
+.B \-w " --wait"
+waits for signal, then start recording.
+.TP
+.B \-F " --find-extremes"
+finds extreme amplitudes in samples.
+.TP
+.B \-G " --find-mono"
+finds if input samples are in mono.
+.TP
+.B \-T " --deemphasize"
+undo the effect of pre-emphasis in the input samples.
+.TP
+.B \-e " --echo"
+copies audio data to sound device e.g.
+.BR /dev/dsp .
+.TP
+.B \-p " percentage --set-pitch"
+changes pitch of audio data copied to sound device.
+.TP
+.B \-v " itemlist  --verbose-level"
+prints verbose information about the CD.
+.B Level
+is a list of comma separated suboptions. Each suboption controls the type of information to be reported.
+.TS H
+allbox;
+c cw(1i)
+r l.
+Suboption      Description
+disable        no information is given, warnings appear however
+all    all information is given
+toc    show table of contents
+summary        show a summary of the recording parameters
+indices        determine and display index offsets
+catalog        retrieve and display the media catalog number MCN
+trackid        T{
+.na
+retrieve and display all International Standard Recording Codes ISRC
+T}
+sectors        T{
+.na
+show the table of contents in start sector notation
+T}
+titles T{
+.na
+show the table of contents with track titles (when available)
+T}
+.TE
+.TP
+.B \-N " --no-write"
+does not write to a file, it just reads (for debugging purposes).
+.TP
+.B \-J " --info-only"
+does not write to a file, it just gives information about the disc.
+.TP
+.B \-L " cddb mode --cddb"
+does a cddbp album- and track title lookup based on the cddb id.
+The parameter cddb mode defines how multiple entries shall be handled.
+.TS H
+allbox;
+c cw(4i)
+r l.
+Parameter      Description
+0      T{
+.na
+interactive mode. The user selects the entry to use.
+T}
+1      T{
+.na
+first fit mode. The first entry is taken unconditionally.
+T}
+.TE
+.TP
+.B " cddbp-server=servername"
+sets the server to be contacted for title lookups.
+.TP
+.B " cddbp-port=portnumber"
+sets the port number to be used for title lookups.
+.TP
+.B \-H " --no-infofile"
+does not write an info file and a cddb file.
+.TP
+.B \-g " --gui"
+formats the output to be better parsable by gui frontends.
+.TP
+.B \-M " count --md5"
+enables calculation of MD-5 checksum for 'count' bytes from a beginning of a
+track.
+.TP
+.B \-S " speed --speed"
+sets the cdrom device to one of the selectable speeds for reading.
+.TP
+.B \-q " --quiet"
+quiet operation, no screen output.
+.TP
+.B \-V " --verbose-SCSI"
+enable SCSI command logging to the console. This is mainly used for debugging.
+.TP
+.B \-Q " --silent-SCSI"
+suppress SCSI command error reports to the console. This is mainly used for guis.
+.TP
+.B \-scanbus
+Scan all SCSI devices on all SCSI busses and print the inquiry
+strings. This option may be used to find SCSI address of the 
+CD/DVD-Recorder on a system.
+The numbers printed out as labels are computed by: 
+.B "bus * 100 + target
+.TP
+.B \-\-devices
+Like \-scanbus but works in a more native way, respecting the device name
+specification on the current operating system. See
+.B wodim(1)
+for details.
+.TP
+.B \-paranoia
+use the paranoia library instead of icedax's routines for reading.
+.TP
+.B \-h " --help"
+display version of icedax on standard output.
+.TP
+Defaults depend on the
+.B Makefile
+and
+.B environment variable
+settings (currently
+.B CDDA_DEVICE
+).
+.SH "ENVIRONMENT VARIABLES"
+.B CDDA_DEVICE
+is used to set the device name. The device naming is compatible with the one
+used by the wodim tool.
+.TP
+.B CDDBP_SERVER
+is used for cddbp title lookups when supplied.
+.TP
+.B CDDBP_PORT
+is used for cddbp title lookups when supplied.
+.TP
+.B RSH
+If the 
+.B RSH
+environment variable is present, the remote connection will not be created via
+.BR rcmd (3)
+but by calling the program pointed to by
+.BR RSH .
+Use e.g. 
+.BR RSH= /usr/bin/ssh
+to create a secure shell connection.
+.sp
+Note that this forces 
+.B icedax
+to create a pipe to the 
+.B rsh(1)
+program and disallows
+.B icedax
+to directly access the network socket to the remote server.
+This makes it impossible to set up performance parameters and slows down
+the connection compared to a 
+.B root
+initiated
+.B rcmd(3)
+connection.
+.TP
+.B RSCSI
+If the 
+.B RSCSI
+environment variable is present, the remote SCSI server will not be the program
+.B /opt/schily/sbin/rscsi
+but the program pointed to by
+.BR RSCSI .
+Note that the remote SCSI server program name will be ignored if you log in
+using an account that has been created with a remote SCSI server program as
+login shell.
+.SH "RETURN VALUES"
+.B icedax
+uses the following exit codes to indicate various degrees of success:
+.TS H
+allbox;
+c cw(1i)
+r l.
+Exitcode       Description
+0      no errors encountered, successful operation.
+1      usage or syntax error. icedax got inconsistent arguments.
+2      permission (un)set errors. permission changes failed.
+3      read errors on the cdrom/burner device encountered.
+4      T{
+.na
+write errors while writing one of the output files encountered.
+T}
+5      errors with soundcard handling (initialization/write).
+6      T{
+.na
+errors with stat() system call on the read device (cooked ioctl).
+T}
+7      pipe communication errors encountered (in forked mode).
+8      signal handler installation errors encountered.
+9      allocation of shared memory failed (in forked mode).
+10     dynamic heap memory allocation failed.
+11     errors on the audio cd medium encountered.
+12     device open error in ioctl handling detected.
+13     race condition in ioctl interface handling detected.
+14     error in ioctl() operation encountered.
+15     internal error encountered. Please report back!!!
+16     T{
+.na
+error in semaphore operation encountered (install / request).
+T}
+17     could not get the scsi transfer buffer.
+18     T{
+.na
+could not create pipes for process communication (in forked mode).
+T}
+.TE
+.SH "DISCUSSION"
+.B icedax
+is able to read parts of an
+.B audio
+CD or
+.B multimedia
+CDROM (containing audio parts) directly digitally. These parts can be
+written to a file, a pipe, or to a sound device.
+.PP
+.B icedax
+stands for
+.B CDDA
+to
+.B WAV
+(where
+.B CDDA
+stands for compact disc digital audio and
+.B WAV
+is a sound sample format introduced by MS Windows).  It
+allows copying
+.B CDDA
+audio data from the CDROM drive into a file in 
+.B WAV
+or other formats.
+.PP
+The latest versions try to get higher real-time scheduling priorities to ensure
+smooth (uninterrupted) operation. These priorities are available for super users
+and are higher than those of 'normal' processes. Thus delays are minimized.
+.PP
+If your CDROM is on device
+.B DEV
+and it is loaded with an audio CD, you may simply invoke
+.B icedax dev=DEV
+and it will create the sound file
+.B audio.wav
+recording the whole track beginning with track 1 in stereo at 16 bit at 44100
+Hz sample rate, if your file system has enough space free.  Otherwise
+recording time will be limited. For details see files
+.B README
+and
+.B README.INSTALL
+.
+.SH "HINTS ON OPTIONS"
+.IP "Options"
+Most of the options are used to control the format of the WAV file. In
+the following text all of them are described.
+.IP "Select Device"
+.BI \-D " device"
+selects the CDROM drive device to be used.
+The specifier given should correspond to the selected interface (see below).
+.B CHANGE!
+For the cooked_ioctl interface this is the cdrom device descriptor as before.
+.B The SCSI devices used with the generic SCSI interface however are now
+.B addressed with their SCSI-Bus, SCSI-Id, and SCSI-Lun instead of the generic
+.B SCSI device descriptor!!!
+One example for a SCSI CDROM drive on bus 0 with SCSI ID 3 and lun 0 is -D0,3,0.
+.IP "Select Auxiliary device"
+.BI \-A " auxdevice"
+is necessary for CD-Extra handling. For Non-SCSI-CDROM drives this is the
+same device as given by -D (see above). For SCSI-CDROM drives it is the
+CDROM drive (SCSI) device (i.e.  
+.B /dev/sr0
+) corresponding to the SCSI device (i.e.
+.B 0,3,0
+). It has to match the device used for sampling.
+.IP "Select Interface"
+.BI \-I " interface"
+selects the CDROM drive interface. For SCSI drives use generic_scsi
+(cooked_ioctl may not yet be available for all devices):
+.B generic_scsi
+and
+.BR cooked_ioctl .
+The first uses the generic SCSI interface, the latter uses the ioctl of
+the CDROM driver. The latter variant works only when the kernel driver supports
+.B CDDA
+reading. This entry has to match the selected CDROM device (see above).
+.IP "Enable echo to soundcard"
+.B \-e
+copies audio data to the sound card while recording, so you hear it nearly
+simultaneously. The soundcard gets the same data that is recorded. This
+is time critical, so it works best with the
+.B \-q
+option.  To use
+.B icedax
+as a pseudo CD player without recording in a file you could use
+.B "icedax \-q \-e \-t2 \-d0 \-N"
+to play the whole second track. This feature reduces the recording speed
+to at most onefold speed. You cannot make better recordings than your sound card
+can play (since the same data is used).
+.IP "Change pitch of echoed audio"
+.B "\-p percentage"
+changes the pitch of all audio echoed to a sound card. Only the copy
+to the soundcard is affected, the recorded audio samples in a file
+remain the same.
+Normal pitch, which is the default, is given by 100%.
+Lower percentages correspond to lower pitches, i.e.
+-p 50 transposes the audio output one octave lower.
+See also the script
+.B pitchplay
+as an example. This option was contributed by Raul Sobon.
+.IP "Select mono or stereo recording"
+.B \-m
+or
+.B "\-c 1"
+selects mono recording (both stereo channels are mixed),
+.B \-s
+or
+.B "\-c 2"
+or
+.B "\-c s"
+selects stereo recording. Parameter s
+will swap both sound channels.
+.IP "Select maximum quality"
+.B \-x
+will set stereo, 16 bits per sample at 44.1 KHz (full CD quality).  Note
+that other format options given later can change this setting.
+.IP "Select sample quality"
+.B "\-b 8"
+specifies 8 bit (1 Byte) for each sample in each channel;
+.B "\-b 12"
+specifies 12 bit (2 Byte) for each sample in each channel;
+.B "\-b 16"
+specifies 16 bit (2 Byte) for each sample in each channel (Ensure that
+your sample player or sound card is capable of playing 12-bit or 16-bit
+samples). Selecting 12 or 16 bits doubles file size.  12-bit samples are
+aligned to 16-bit samples, so they waste some disk space.
+.IP "Select sample rate"
+.BI \-r " samplerate"
+selects a sample rate.
+.I samplerate
+can be in a range between 44100 and 900. Option
+.B \-R
+lists all available rates.
+.IP "Select sample rate divider"
+.BI \-a " divider"
+selects a sample rate divider.
+.I divider
+can be minimally 1 and maximally 50.5 and everything between in steps of 0.5.
+Option
+.B \-R
+lists all available rates.
+.IP
+To make the sound smoother at lower sampling rates,
+.B icedax
+sums over
+.I n
+samples (where
+.I n
+is the specific dividend). So for 22050 Hertz output we have to sum over
+2 samples, for 900 Hertz we have to sum over 49 samples.  This cancels
+higher frequencies. Standard sector size of an audio CD (ignoring
+additional information) is 2352 Bytes. In order to finish summing
+for an output sample at sector boundaries the rates above have to be
+chosen.  Arbitrary sampling rates in high quality would require some
+interpolation scheme, which needs much more sophisticated programming.
+.IP "List a table of all sampling rates"
+.BI \-R
+shows a list of all sample rates and their dividers. Dividers can range
+from 1 to 50.5 in steps of 0.5.
+.IP "Select start track and optionally end track"
+.BI \-t " n+m"
+selects
+.B n
+as the start track and optionally
+.B m
+as the last track of a range to be recorded.
+These tracks must be from the table of contents.  This sets
+the track where recording begins. Recording can advance through the
+following tracks as well (limited by the optional end track or otherwise
+depending on recording time). Whether one file or different files are
+then created depends on the
+.B \-B
+option (see below).
+.IP "Select start index"
+.BI \-i " n"
+selects the index to start recording with.  Indices other than 1 will
+invoke the index scanner, which will take some time to find the correct
+start position. An offset may be given additionally (see below).
+.IP "Set recording time"
+.B \-d " n"
+sets recording time to
+.I n
+seconds or set recording time for whole track if
+.I n
+is zero. In order to specify the duration in frames (sectors) also, the
+argument can have an appended 'f'. Then the numerical argument is to be
+taken as frames (sectors) rather than seconds.
+Please note that if track ranges are being used they define the recording
+time as well thus overriding any
+.BR \-d " option"
+specified times.
+.IP
+Recording time is defined as the time the generated sample will play (at
+the defined sample rate). Since it's related to the amount of generated
+samples, it's not the time of the sampling process itself (which can be
+less or more).  It's neither strictly coupled with the time information on
+the audio CD (shown by your hifi CD player).
+Differences can occur by the usage of the
+.B \-o
+option (see below). Notice that recording time will be shortened, unless
+enough disk space exists. Recording can be aborted at anytime by
+pressing the break character (signal SIGQUIT).
+   .IP "Record all tracks of a complete audio CD in separate files"
+.B \-B
+copies each track into a separate file. A base name can be given. File names
+have an appended track number and an extension corresponding to the audio
+format. To record all audio tracks of a CD, use a sufficient high duration
+(i.e. -d99999).
+.IP "Set start sector offset"
+.BI \-o " sectors"
+increments start sector of the track by
+.IR sectors .
+By this option you are able to skip a certain amount at the beginning of
+a track so you can pick exactly the part you want. Each sector runs for 1/75
+seconds, so you have very fine control. If your offset is so high that
+it would not fit into the current track, a warning message is issued
+and the offset is ignored.  Recording time is not reduced.  (To skip
+introductory quiet passages automagically, use the
+.B \-w
+option see below.)
+.IP "Wait for signal option"
+.B \-w
+Turning on this option will suppress all silent output at startup,
+reducing possibly file size.
+.B icedax
+will watch for any signal in the output signal and switches on writing
+to file.
+.IP "Find extreme samples"
+.B \-F
+Turning on this option will display the most negative and the most positive
+sample value found during recording for both channels. This can be useful
+for readjusting the volume. The values shown are not reset at track
+boundaries, they cover the complete sampling process. They are taken from
+the original samples and have the same format (i.e. they are independent
+of the selected output format).
+.IP "Find if input samples are in mono"
+.B \-G
+If this option is given, input samples for both channels will be compared. At
+the end of the program the result is printed. Differences in the channels
+indicate stereo, otherwise when both channels are equal it will indicate mono.
+.IP "Undo the pre-emphasis in the input samples"
+.B \-T
+Some older audio CDs are recorded with a modified frequency response called
+pre-emphasis. This is found mostly in classical recordings. The correction
+can be seen in the flags of the Table Of Contents often. But there are
+recordings, that show this setting only in the subchannels. If this option
+is given, the index scanner will be started, which reads the q-subchannel
+of each track. If pre-emphasis is indicated in the q-subchannel of a track,
+but not in the TOC, pre-emphasis will be assumed to be present, and
+subsequently a reverse filtering is done for this track before the samples
+are written into the audio file.
+.IP "Set audio format"
+.B \-O " audiotype"
+can be 
+.I wav
+(for wav files) or
+.I au
+or
+.I sun
+(for sun PCM files) or
+.I cdr
+or
+.I raw
+(for headerless files to be used for cd writers).
+All file samples are coded in linear pulse code modulation (as done
+in the audio compact disc format). This holds for all audio formats.
+Wav files are compatible to Wind*ws sound files, they have lsb,msb byte order
+as being used on the audio cd. The default filename extension is '.wav'.
+Sun type files are not like the older common logarithmically coded .au files,
+but instead as mentioned above linear PCM is used. The byte order is msb,lsb
+to be compatible. The default filename extension is '.au'.
+The AIFF and the newer variant AIFC from the Apple/SGI world store their samples
+in bigendian format (msb,lsb). In AIFC no compression is used.
+Finally the easiest 'format',
+the cdr aka raw format. It is done per default in msb,lsb byte order to satisfy
+the order wanted by most cd writers. Since there is no header information in this
+format, the sample parameters can only be identified by playing the samples
+on a soundcard or similar. The default filename extension is '.cdr' or '.raw'.
+.IP "Select cdrom drive reading speed"
+.B \-S " speed"
+allows to switch the cdrom drive to a certain level of speed in order to
+reduce read errors. The argument is transfered verbatim to the drive.
+Details depend very much on the cdrom drives.
+An argument of 0 for example is often the default speed of the drive,
+a value of 1 often selects single speed.
+.IP "Enable MD5 checksums"
+.B \-M " count"
+enables calculation of MD-5 checksum for 'count' bytes from the beginning of a
+track. This was introduced for quick comparisons of tracks.
+.IP "Use Monty's libparanoia for reading of sectors"
+.B \-paranoia
+selects an alternate way of extracting audio sectors. Monty's library is used
+with the following default options:
+.sp
+PARANOIA_MODE_FULL, but without PARANOIA_MODE_NEVERSKIP
+.sp
+for details see Monty's libparanoia documentation.
+In this case the option
+.B \-P
+has no effect.
+.IP "Do linear or overlapping reading of sectors"
+(This applies unless option
+.B \-paranoia
+is used.)
+.B \-P " sectors"
+sets the given number of sectors for initial overlap sampling for jitter
+correction. Two cases are to be distinguished. For nonzero values,
+some sectors are read twice to enable icedax's jitter correction.
+If an argument of zero is given, no overlap sampling will be used.
+For nonzero overlap sectors icedax dynamically adjusts the setting during
+sampling (like cdparanoia does).
+If no match can be found, icedax retries the read with an increased overlap.
+If the amount of jitter is lower than the current overlapped samples, icedax
+reduces the overlap setting, resulting in a higher reading speed.
+The argument given has to be lower than the total number of sectors per request
+(see option
+.I -n
+below).
+Icedax will check this setting and issues a error message otherwise.
+The case of zero sectors is nice on low load situations or errorfree (perfect)
+cdrom drives and perfect (not scratched) audio cds.
+.IP "Set the transfer size"
+.B \-n " sectors"
+will set the transfer size to the specified sectors per request.
+.IP "Set number of ring buffer elements"
+.B \-l " buffers"
+will allocate the specified number of ring buffer elements.
+.IP "Set endianess of input samples"
+.B \-C " endianess"
+will override the default settings of the input format.
+Endianess can be set explicitly to "little" or "big" or to the automatic
+endianess detection based on voting with "guess".
+.IP "Set endianess of output samples"
+.B \-E " endianess"
+(endianess can be "little" or "big") will override the default settings 
+of the output format.
+.IP "Verbose option"
+.B \-v " itemlist"
+prints more information. A list allows selection of different
+information items.
+.sp
+.B "disable"
+keeps quiet
+.sp
+.B "toc"
+displays the table of contents
+.sp
+.B "summary"
+displays a summary of recording parameters
+.sp
+.B "indices"
+invokes the index scanner and displays start positions of indices
+.sp
+.B "catalog"
+retrieves and displays a media catalog number
+.sp
+.B "trackid"
+retrieves and displays international standard recording codes
+.sp
+.B "sectors"
+displays track start positions in absolute sector notation
+.sp
+To combine several requests just list the suboptions separated with commas.
+.IP "The table of contents"
+The display will show the table of contents with number of tracks and
+total time (displayed in
+.IR mm : ss . hh
+format,
+.IR mm =minutes,
+.IR ss =seconds,
+.IR hh "=rounded 1/100 seconds)."
+The following list displays track number and track time for each entry.
+The summary gives a line per track describing the type of the track.
+.sp
+.ce 1
+.B "track preemphasis copypermitted tracktype chans"
+.sp
+The
+.B track
+column holds the track number.
+.B preemphasis
+shows if that track has been given a non linear frequency response.
+NOTE: You can undo this effect with the
+.B \-T
+option.
+.B "copy-permitted"
+indicates if this track is allowed to copy.
+.B "tracktype"
+can be data or audio. On multimedia CDs (except hidden track CDs) 
+both of them should be present.
+.B "channels"
+is defined for audio tracks only. There can be two or four channels.
+.IP "No file output"
+.B \-N
+this debugging option switches off writing to a file.
+.IP "No infofile generation"
+.B \-H
+this option switches off creation of an info file and a cddb file.
+.IP "Generation of simple output for gui frontends"
+.B \-g
+this option switches on simple line formatting, which is needed to support
+gui frontends (like xcd-roast).
+.IP "Verbose SCSI logging"
+.B \-V
+this option switches on logging of SCSI commands. This will produce
+a lot of output (when SCSI devices are being used).
+This is needed for debugging purposes. The format
+is the same as being used with the cdrecord program from J\*org Schilling or
+the wodim tool. See there for details.
+.IP "Quiet option"
+.B \-q
+suppresses all screen output except error messages.
+That reduces cpu time resources.
+.IP "Just show information option"
+.B \-J
+does not write a file, it only prints information about the disc (depending
+on the
+.B \-v
+option). This is just for information purposes.
+.SH "CDDBP support"
+.IP "Lookup album and track titles option"
+.B \-L " cddbp mode"
+Icedax tries to retrieve performer, album-, and track titles from a cddbp
+server. The default server right now is 'freedb.freedb.org'.
+It is planned to have more control over the server handling later.
+The parameter defines how multiple entries are handled:
+.PP
+0      interactive mode, the user chooses one of the entries.
+.PP
+1      take the first entry without asking.
+.IP "Set server for title lookups"
+.B cddbp-server " servername"
+When using \-L or --cddb, the server being contacted can be set with
+this option.
+.IP "Set portnumber for title lookups"
+.B cddbp-port " portnumber"
+When using \-L or --cddb, the server port being contacted can be set with
+this option.
+.SH "HINTS ON USAGE"
+Don't create samples you cannot read. First check your sample player
+software and sound card hardware. I experienced problems with very low
+sample rates (stereo <= 1575 Hz, mono <= 3675 Hz) when trying to play
+them with standard WAV players for sound blaster (maybe they are not
+legal in
+.B WAV
+format). Most CD-Writers insist on audio samples in a bigendian format.
+Now icedax supports the 
+.B \-E " endianess"
+option to control the endianess of the written samples.
+.PP
+If your hardware is fast enough to run icedax
+uninterrupted and your CD drive is one of the 'perfect' ones, you will
+gain speed when switching all overlap sampling off with the
+.B \-P " 0"
+option. Further fine tuning can be done with the
+.B \-n " sectors"
+option. You can specify how much sectors should be requested in one go.
+.PP
+Icedax supports
+.B pipes
+now. Use a filename of
+.B \-
+to let icedax output its samples to standard output.
+.PP
+Conversion to other sound formats can be done using the
+.B sox
+program package (although the use of
+.B sox -x
+to change the byte order of samples should be no more necessary; see option
+.B \-E
+to change the output byteorder).
+.PP
+If you want to sample more than one track into
+different files in one run, this is currently possible with the
+.B \-B
+option. When recording time exceeds the track limit a new file will
+be opened for the next track.
+.SH FILES
+Icedax can generate a lot of files for various purposes.
+.sp
+Audio files:
+.sp
+There are audio files containing samples with default extensions
+.wav, .au, .aifc, .aiff, and .cdr according to the selected sound format.
+These files are not generated when option (-N) is given. Multiple files may
+be written when the bulk copy option (-B) is used. Individual file names
+can be given as arguments. If the number of file names given is sufficient
+to cover all included audio tracks, the file names will be used verbatim.
+Otherwise, if there are less file names than files needed to write the
+included tracks, the part of the file name before the extension is extended
+with '_dd' where dd represents the current track number.
+.sp
+Cddb and Cdindex files:
+.sp
+If icedax detects cd-extra or cd-text (album/track) title information,
+then .cddb and .cdindex files are generated unless suppressed by the
+option -H. They contain suitable formatted entries for submission to
+audio cd track title databases in the internet. The CDINDEX and CDDB(tm)
+systems are currently supported. For more information please visit
+www.musicbrainz.org and www.freedb.com.
+.sp
+Inf files:
+.sp
+The inf files are describing the sample files and the part from the audio cd,
+it was taken from. They are a means to transfer information to a cd burning
+program like wodim. For example, if the original audio cd had pre-emphasis
+enabled, and icedax -T did remove the pre-emphasis, then the inf file has
+pre-emphasis not set (since the audio file does not have it anymore), while
+the .cddb and the .cdindex have pre-emphasis set as the original does.
+.SH WARNING
+.B IMPORTANT:
+it is prohibited to sell copies of copyrighted material by noncopyright
+holders. This program may not be used to circumvent copyrights.
+The user acknowledges this constraint when using the software.
+.SH BUGS
+Generation of md5 checksums is currently broken.
+.sp
+Performance may not be optimal on slower systems.
+.sp
+The index scanner may give timeouts.
+.sp
+The resampling (rate conversion code) uses polynomial interpolation, which
+is not optimal.
+.sp
+Icedax should use threads.
+.sp
+Icedax currently cannot sample hidden audio tracks (track 1 index 0).
+.SH ACKNOWLEDGEMENTS
+Thanks goto Project MODE (http://www.mode.net/) and Fraunhofer Institut f\*ur
+integrierte Schaltungen (FhG-IIS) (http://www.iis.fhg.de/) for financial
+support.
+Plextor Europe and Ricoh Japan provided cdrom disk drives and cd burners
+which helped a lot to develop this software.
+Rammi has helped a lot with the debugging and showed a lot of stamina when
+hearing 100 times the first 16 seconds of the first track of the Krupps CD.
+Libparanoia contributed by Monty (Christopher Montgomery) xiphmont@mit.edu.
+.SH AUTHOR
+Heiko Eissfeldt heiko@colossus.escape.de
+.PP
+This manpage describes the program implementation of
+.B
+icedax
+as shipped by the cdrkit distribution. See
+.B
+http://alioth.debian.org/projects/debburn/
+for details. It is a spinoff from the original program cdda2wav as distributed
+in the cdrtools package [1]. However, the cdrtools developers are not involved
+in the development of this spinoff and therefore shall not be made responsible
+for any problem caused by it. Do not try to get support for this program by
+contacting the original authors.
+.PP
+If you have support questions, send them to
+.PP
+.B
+debburn-devel@lists.alioth.debian.org
+.br
+.PP
+If you have definitely found a bug, send a mail to this list or to
+.PP
+.B
+submit@bugs.debian.org
+.br
+.PP
+writing at least a short description into the Subject and "Package: cdrkit" into the first line of the mail body.
+
+.SH DATE
+26 Sep 2006
+
+.SH SOURCES
+.PP
+.br
+[1] Cdrtools 2.01.01a08 from May 2006, http://cdrecord.berlios.de
+
diff --git a/icedax/icedax.c b/icedax/icedax.c
new file mode 100644 (file)
index 0000000..9ac5ee0
--- /dev/null
@@ -0,0 +1,3059 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)cdda2wav.c      1.64 06/02/19 Copyright 1998-2004 Heiko Eissfeldt, Copyright 2004-2006 J. Schilling */
+#undef DEBUG_BUFFER_ADDRESSES
+#undef GPROF
+#undef DEBUG_FORKED
+#undef DEBUG_CLEANUP
+#undef DEBUG_DYN_OVERLAP
+#undef DEBUG_READS
+#define DEBUG_ILLLEADOUT       0       /* 0 disables, 1 enables */
+/*
+ * Copyright: GNU Public License 2 applies
+ *
+ *   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.
+ *
+ */
+/*
+ * parts    (C) Peter Widow
+ * parts    (C) Thomas Niederreiter
+ * parts    (C) RSA Data Security, Inc.
+ *
+ * last changes:
+ *   18.12.93 - first version, OK
+ *   01.01.94 - generalized & clean up HE
+ *   10.06.94 - first linux version HE
+ *   12.06.94 - wav header alignment problem fixed HE
+ *   12.08.94 - open the cdrom device O_RDONLY makes more sense :-)
+ *             no more floating point math
+ *             change to sector size 2352 which is more common
+ *             sub-q-channel information per kernel ioctl requested
+ *             doesn't work as well as before
+ *             some new options (-max -i)
+ *   01.02.95 - async i/o via semaphores and shared memory
+ *   03.02.95 - overlapped reading on sectors
+ *   03.02.95 - generalized sample rates. all integral divisors are legal
+ *   04.02.95 - sun format added
+ *              more divisors: all integral halves >= 1 allowed
+ *             floating point math needed again
+ *   06.02.95 - bugfix for last track and not d0
+ *              tested with photo-cd with audio tracks
+ *             tested with xa disk 
+ *   29.01.96 - new options for bulk transfer
+ *   01.06.96 - tested with enhanced cd
+ *   01.06.96 - tested with cd-plus
+ *   02.06.96 - support pipes
+ *   02.06.96 - support raw format
+ *   04.02.96 - security hole fixed
+ *   22.04.97 - large parts rewritten
+ *   28.04.97 - make file names DOS compatible
+ *   01.09.97 - add speed control
+ *   20.10.97 - add find mono option
+ *   Jan/Feb 98 - conversion to use Joerg Schillings SCSI library
+ *   see ChangeLog
+ */
+
+#include "config.h"
+
+#include <unixstd.h>
+#include <stdio.h>
+#include <standard.h>
+#include <stdxlib.h>
+#include <strdefs.h>
+#include <schily.h>
+#include <signal.h>
+#include <math.h>
+#include <fctldefs.h>
+#include <timedefs.h>
+#if defined (HAVE_LIMITS_H)
+#include <limits.h>
+#endif
+#if defined (HAVE_SYS_IOCTL_H)
+#include <sys/ioctl.h>
+#endif
+#include <errno.h>
+#include <statdefs.h>
+#include <waitdefs.h>
+#if defined (HAVE_SETPRIORITY)
+#include <sys/resource.h>
+#endif
+#include <vadefs.h>
+
+#include <usal/scsitransp.h>
+
+#ifdef HAVE_AREAS
+#include <be/kernel/OS.h>
+#endif
+
+#include "mytype.h"
+#include "sndconfig.h"
+
+#include "semshm.h"    /* semaphore functions */
+#include "sndfile.h"
+#include "wav.h"       /* wav file header structures */
+#include "sun.h"       /* sun audio file header structures */
+#include "raw.h"       /* raw file handling */
+#include "aiff.h"      /* aiff file handling */
+#include "aifc.h"      /* aifc file handling */
+#ifdef USE_LAME
+#include "mp3.h"       /* mp3 file handling */
+#endif
+#include "interface.h"  /* low level cdrom interfacing */
+#include "icedax.h"
+#include "resample.h"
+#include "toc.h"
+#include "setuid.h"
+#include "ringbuff.h"
+#include "global.h"
+#include "exitcodes.h"
+#ifdef USE_PARANOIA
+#include "cdda_paranoia.h"
+#endif
+#include "defaults.h"
+
+static void RestrictPlaybackRate(long newrate);
+static void output_indices(FILE *fp, index_list *p, unsigned trackstart);
+static int     write_info_file(char *fname_baseval, unsigned int track, 
+                                                                        unsigned long SamplesDone, int numbered);
+static void CloseAudio(int channels_val, unsigned long nSamples, 
+                                                         struct soundfile *audio_out);
+static void CloseAll(void);
+static void OpenAudio(char *fname, double rate, long nBitsPerSample, 
+                                                        long channels_val, unsigned long expected_bytes, 
+                                                        struct soundfile*audio_out);
+static void set_offset(myringbuff *p, int offset);
+static int     get_offset(myringbuff *p);
+static void usage(void);
+static void init_globals(void);
+static int     is_fifo(char *filename);
+
+
+/* Rules:
+ * unique parameterless options first,
+ * unique parametrized option names next,
+ * ambigious parameterless option names next,
+ * ambigious string parametrized option names last
+ */
+static const char *opts = "paranoia,paraopts&,version,help,h,\
+no-write,N,dump-rates,R,bulk,B,alltracks,verbose-scsi+,V+,\
+find-extremes,F,find-mono,G,no-infofile,H,\
+deemphasize,T,info-only,J,silent-scsi,Q,\
+cddbp-server*,cddbp-port*,\
+scanbus,devices,device*,dev*,D*,auxdevice*,A*,interface*,I*,output-format*,O*,\
+output-endianess*,E*,cdrom-endianess*,C*,speed#,S#,\
+playback-realtime#L,p#L,md5#,M#,set-overlap#,P#,sound-device*,K*,\
+cddb#,L#,channels*,c*,bits-per-sample#,b#,rate#,r#,gui,g,\
+divider*,a*,track*,t*,index#,i#,duration*,d*,offset#,o#,\
+sectors-per-request#,n#,verbose-level&,v&,buffers-in-ring#,l#,\
+stereo,s,mono,m,wait,w,echo,e,quiet,q,max,x\
+";
+
+
+#ifdef NEED_O_BINARY
+#include <io.h>                /* for setmode() prototype */
+#endif
+
+/* global variables */
+global_t global;
+
+/* static variables */
+static unsigned long nSamplesDone = 0;
+
+static int child_pid = -2;
+
+static unsigned long *nSamplesToDo;
+static unsigned int current_track;
+static int bulk = 0;
+
+unsigned int get_current_track(void);
+
+unsigned int get_current_track()
+{
+       return current_track;
+}
+
+static void RestrictPlaybackRate(long  newrate)
+{
+       global.playback_rate = newrate;
+
+       if ( global.playback_rate < 25 ) global.playback_rate = 25;   /* filter out insane values */
+       if ( global.playback_rate > 250 ) global.playback_rate = 250;
+
+       if ( global.playback_rate < 100 )
+               global.nsectors = (global.nsectors*global.playback_rate)/100;
+}
+
+
+long SamplesNeeded(long amount, long undersampling_val)
+{
+  long retval = ((undersampling_val * 2 + Halved)*amount)/2;
+  if (Halved && (*nSamplesToDo & 1))
+    retval += 2;
+  return retval;
+}
+
+static int argc2;
+static int argc3;
+static char **argv2;
+
+static void reset_name_iterator(void);
+static void reset_name_iterator()
+{
+       argv2 -= argc3 - argc2;
+       argc2 = argc3;
+}
+
+static char *get_next_name(void);
+static char *get_next_name()
+{
+       if (argc2 > 0) {
+               argc2--;
+               return (*argv2++);
+       } else {
+               return NULL;
+       }
+}
+
+static char *cut_extension(char *fname);
+
+static char *cut_extension(char *fname)
+{
+       char *pp;
+
+       pp = strrchr(fname, '.');
+
+       if (pp == NULL) {
+               pp = fname + strlen(fname);
+       }
+       *pp = '\0';
+
+       return pp;
+}
+
+#ifdef INFOFILES
+static void output_indices(FILE *fp, index_list *p, unsigned trackstart)
+{
+  int ci;
+
+  fprintf(fp, "Index=\t\t");
+
+  if (p == NULL) {
+    fprintf(fp, "0\n");
+    return;
+  }
+
+  for (ci = 1; p != NULL; ci++, p = p->next) {
+    int frameoff = p->frameoffset;
+
+    if (p->next == NULL)
+        fputs("\nIndex0=\t\t", fp);
+#if 0
+    else if ( ci > 8 && (ci % 8) == 1)
+        fputs("\nIndex =\t\t", fp);
+#endif
+    if (frameoff != -1)
+         fprintf(fp, "%d ", frameoff - trackstart);
+    else
+         fprintf(fp, "-1 ");
+  }
+  fputs("\n", fp);
+}
+
+/*
+ * write information before the start of the sampling process
+ *
+ *
+ * uglyfied for Joerg Schillings ultra dumb line parser
+ */
+static int write_info_file(char *fname_baseval, unsigned int track, 
+                           unsigned long int SamplesDone, int numbered)
+{
+  FILE *info_fp;
+  char fname[200];
+  char datetime[30];
+  time_t utc_time;
+  struct tm *tmptr;
+
+  /* write info file */
+  if (!strcmp(fname_baseval,"-")) return 0;
+
+  strncpy(fname, fname_baseval, sizeof(fname) -1);
+  fname[sizeof(fname) -1] = 0;
+  if (numbered)
+    sprintf(cut_extension(fname), "_%02u.inf", track);
+  else
+    strcpy(cut_extension(fname), ".inf");
+
+  info_fp = fopen (fname, "w");
+  if (!info_fp)
+    return -1;
+
+#if 0
+#ifdef MD5_SIGNATURES
+  if (global.md5blocksize)
+    MD5Final (global.MD5_result, &global.context);
+#endif
+#endif
+
+  utc_time = time(NULL);
+  tmptr = localtime(&utc_time);
+  if (tmptr) {
+    strftime(datetime, sizeof(datetime), "%x %X", tmptr);
+  } else {
+    strncpy(datetime, "unknown", sizeof(datetime));
+  }
+  fprintf(info_fp, "#created by icedax %s %s\n#\n", VERSION
+         , datetime
+         );
+  fprintf(info_fp,
+"CDINDEX_DISCID=\t'%s'\n" , global.cdindex_id);
+  fprintf(info_fp,
+"CDDB_DISCID=\t0x%08lx\n\
+MCN=\t\t%s\n\
+ISRC=\t\t%15.15s\n\
+#\n\
+Albumperformer=\t'%s'\n\
+Performer=\t'%s'\n\
+Albumtitle=\t'%s'\n"
+         , (unsigned long) global.cddb_id
+         , Get_MCN()
+         , Get_ISRC(track)
+         , global.creator != NULL ? global.creator : (const unsigned char *)""
+         , global.trackcreator[track] != NULL ? global.trackcreator[track] :
+               (global.creator != NULL ? global.creator : (const unsigned char *)"")
+         , global.disctitle != NULL ? global.disctitle : (const unsigned char *)""
+         );
+  fprintf(info_fp,
+         "Tracktitle=\t'%s'\n"
+         , global.tracktitle[track] ? global.tracktitle[track] : (const unsigned char *)""
+         );
+  fprintf(info_fp, "Tracknumber=\t%u\n"
+         , track
+         );
+  fprintf(info_fp, 
+         "Trackstart=\t%ld\n"
+         , Get_AudioStartSector(track)
+         );
+  fprintf(info_fp, 
+         "# track length in sectors (1/75 seconds each), rest samples\nTracklength=\t%ld, %d\n"
+         , SamplesDone/588L,(int)(SamplesDone%588));
+  fprintf(info_fp, 
+         "Pre-emphasis=\t%s\n"
+         , Get_Preemphasis(track) && (global.deemphasize == 0) ? "yes" : "no");
+  fprintf(info_fp, 
+         "Channels=\t%d\n"
+         , Get_Channels(track) ? 4 : global.channels == 2 ? 2 : 1);
+       { int cr = Get_Copyright(track);
+               fputs("Copy_permitted=\t", info_fp);
+               switch (cr) {
+                       case 0:
+                               fputs("once (copyright protected)\n", info_fp);
+                       break;
+                       case 1:
+                               fputs("no (SCMS first copy)\n", info_fp);
+                       break;
+                       case 2:
+                               fputs("yes (not copyright protected)\n", info_fp);
+                       break;
+                       default:
+                               fputs("unknown\n", info_fp);
+               }
+       }
+  fprintf(info_fp, 
+         "Endianess=\t%s\n"
+         , global.need_big_endian ? "big" : "little"
+         );
+  fprintf(info_fp, "# index list\n");
+  output_indices(info_fp, global.trackindexlist[track],
+                Get_AudioStartSector(track));
+#if 0
+/* MD5 checksums in info files are currently broken.
+ *  for on-the-fly-recording the generation of info files has been shifted
+ *  before the recording starts, so there is no checksum at that point.
+ */
+#ifdef MD5_SIGNATURES
+  fprintf(info_fp, 
+         "#(blocksize) checksum\nMD-5=\t\t(%d) %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n"
+         , global.md5blocksize
+         , global.MD5_result[0]
+         , global.MD5_result[1]
+         , global.MD5_result[2]
+         , global.MD5_result[3]
+         , global.MD5_result[4]
+         , global.MD5_result[5]
+         , global.MD5_result[6]
+         , global.MD5_result[7]
+         , global.MD5_result[8]
+         , global.MD5_result[9]
+         , global.MD5_result[10]
+         , global.MD5_result[11]
+         , global.MD5_result[12]
+         , global.MD5_result[13]
+         , global.MD5_result[14]
+         , global.MD5_result[15]);
+#endif
+#endif
+  fclose(info_fp);
+  return 0;
+}
+#endif
+
+static void CloseAudio(int channels_val, unsigned long nSamples, 
+                       struct soundfile *audio_out)
+{
+      /* define length */
+      audio_out->ExitSound( global.audio, (nSamples-global.SkippedSamples)*global.OutSampleSize*channels_val );
+
+      close (global.audio);
+      global.audio = -1;
+}
+
+static unsigned int track = 1;
+
+/* On terminating:
+ * define size-related entries in audio file header, update and close file */
+static void CloseAll()
+{
+       WAIT_T chld_return_status;
+       int amiparent;
+
+       /* terminate child process first */
+       amiparent = child_pid > 0;
+
+       if (global.iloop > 0) {
+               /* set to zero */
+               global.iloop = 0;
+       }
+
+#if    defined HAVE_FORK_AND_SHAREDMEM
+# ifdef DEBUG_CLEANUP
+       fprintf(stderr, "%s terminating, \n", amiparent ? 
+               "Parent (READER)" : "Child (WRITER)");
+#endif
+#else
+# ifdef DEBUG_CLEANUP
+       fprintf(stderr, "icedax single process terminating, \n");
+# endif
+#endif
+
+       if (amiparent || child_pid < 0) {
+               /* switch to original mode and close device */
+               EnableCdda (get_scsi_p(), 0, 0);
+       }
+
+       if (!amiparent) {
+               /* do general clean up */
+
+               if (global.audio>=0) {
+                       if (bulk) {
+                               /* finish sample file for this track */
+                               CloseAudio(global.channels,
+                                global.nSamplesDoneInTrack, global.audio_out);
+                       } else {
+                               /* finish sample file for this track */
+                               CloseAudio(global.channels,
+                                (unsigned int) *nSamplesToDo, global.audio_out);
+                       }
+               }
+
+               /* tell minimum and maximum amplitudes, if required */
+               if (global.findminmax) {
+                       fprintf(stderr,
+                       "Right channel: minimum amplitude :%d/-32768, maximum amplitude :%d/32767\n", 
+                       global.minamp[0], global.maxamp[0]);
+                       fprintf(stderr,
+                       "Left  channel: minimum amplitude :%d/-32768, maximum amplitude :%d/32767\n", 
+                       global.minamp[1], global.maxamp[1]);
+               }
+
+               /* tell mono or stereo recording, if required */
+               if (global.findmono) {
+                       fprintf(stderr, "Audio samples are originally %s.\n", global.ismono ? "mono" : "stereo");
+               }
+
+               return; /* end of child or single process */
+       }
+
+
+       if (global.have_forked == 1) {
+#ifdef DEBUG_CLEANUP
+               fprintf(stderr, "Parent wait for child death, \n");
+#endif
+
+               /* wait for child to terminate */
+               if (0 > wait(&chld_return_status)) {
+                       perror("");
+               } else {
+                       if (WIFEXITED(chld_return_status)) {
+                               if (WEXITSTATUS(chld_return_status)) {
+                                       fprintf(stderr, "\nW Child exited with %d\n", WEXITSTATUS(chld_return_status));
+                               }
+                       }
+                       if (WIFSIGNALED(chld_return_status)) {
+                               fprintf(stderr, "\nW Child exited due to signal %d\n", WTERMSIG(chld_return_status));
+                       }
+                       if (WIFSTOPPED(chld_return_status)) {
+                               fprintf(stderr, "\nW Child is stopped due to signal %d\n", WSTOPSIG(chld_return_status));
+                       }
+               }
+
+#ifdef DEBUG_CLEANUP
+               fprintf(stderr, "\nW Parent child death, state:%d\n", chld_return_status);
+#endif
+       }
+
+#ifdef GPROF
+       rename("gmon.out", "gmon.child");
+#endif
+}
+
+
+/* report a usage error and exit */
+#ifdef  PROTOTYPES
+static void usage2 (const char *szMessage, ...)
+#else
+static void usage2(const char *szMessage, va_dcl va_alist)
+#endif
+{
+       va_list marker;
+
+#ifdef  PROTOTYPES
+       va_start(marker, szMessage);
+#else
+       va_start(marker);
+#endif
+
+       vfprintf(stderr, szMessage, marker);
+
+       va_end(marker);
+       fprintf(stderr, "\nPlease use -help or consult the man page for help.\n");
+
+       exit (1);
+}
+
+
+/* report a fatal error, clean up and exit */
+#ifdef  PROTOTYPES
+void FatalError (const char *szMessage, ...)
+#else
+void FatalError(const char *szMessage, va_dcl va_alist)
+#endif
+{
+       va_list marker;
+
+#ifdef  PROTOTYPES
+       va_start(marker, szMessage);
+#else
+       va_start(marker);
+#endif
+
+       vfprintf(stderr, szMessage, marker);
+
+       va_end(marker);
+
+       if (child_pid >= 0) {
+               if (child_pid == 0) {
+                       pid_t   ppid;
+                       /*
+                        * Kill the parent too if we are not orphaned.
+                        */
+                       ppid = getppid();
+                       if (ppid > 1)
+                               kill(ppid, SIGINT);
+               } else {
+                       kill(child_pid, SIGINT);
+               }
+       }
+       exit (1);
+}
+
+
+/* open the audio output file and prepare the header. 
+ * the header will be defined on terminating (when the size
+ * is known). So hitting the interrupt key leaves an intact
+ * file.
+ */
+static void OpenAudio(char *fname, double rate, long nBitsPerSample, 
+                      long channels_val, unsigned long expected_bytes, 
+                      struct soundfile *audio_out)
+{
+  if (global.audio == -1) {
+
+    global.audio = open (fname, O_CREAT | O_WRONLY | O_TRUNC | O_BINARY
+#ifdef SYNCHRONOUS_WRITE
+                        | O_SYNC
+#endif
+                 , 0666);
+    if (global.audio == -1) {
+      if (errno == EAGAIN && is_fifo(fname)) {
+        FatalError ("Could not open fifo %s. Probably no fifo reader present.\n", fname);
+      }
+      perror("open audio sample file");
+      FatalError ("Could not open file %s\n", fname);
+    }
+  }
+  global.SkippedSamples = 0;
+  any_signal = 0;
+  audio_out->InitSound( global.audio, channels_val, (unsigned long)rate, nBitsPerSample, expected_bytes );
+
+#ifdef MD5_SIGNATURES
+  if (global.md5blocksize)
+    MD5Init (&global.context);
+  global.md5count = global.md5blocksize;
+#endif
+}
+
+#include "scsi_cmds.h"
+
+static int RealEnd(SCSI *usalp, UINT4 *buff);
+
+static int RealEnd(SCSI *usalp, UINT4 *buff)
+{
+       if (usal_cmd_err(usalp) != 0) {
+               int c,k,q;
+
+               k = usal_sense_key(usalp);
+               c = usal_sense_code(usalp);
+               q = usal_sense_qual(usalp);
+               if ((k == 0x05 /* ILLEGAL_REQUEST */ &&
+                    c == 0x21 /* lba out of range */ &&
+                    q == 0x00) ||
+                   (k == 0x05 /* ILLEGAL_REQUEST */ &&
+                    c == 0x63 /*end of user area encountered on this track*/ &&
+                    q == 0x00) ||
+                   (k == 0x08 /* BLANK_CHECK */ &&
+                    c == 0x64 /* illegal mode for this track */ &&
+                    q == 0x00)) {
+                       return 1;
+               }
+       }
+
+       if (usal_getresid(usalp) > 16) return 1;
+
+       {
+               unsigned char *p;
+               /* Look into the subchannel data */
+               buff += CD_FRAMESAMPLES;
+               p = (unsigned char *)buff;
+               if (p[0] == 0x21 && p[1] == 0xaa) {
+                       return 1;
+               }
+       }
+       return 0;
+}
+
+static void set_offset(myringbuff *p, int offset)
+{
+#ifdef DEBUG_SHM
+  fprintf(stderr, "Write offset %d at %p\n", offset, &p->offset);
+#endif
+  p->offset = offset;
+}
+
+
+static int get_offset(myringbuff *p)
+{
+#ifdef DEBUG_SHM
+  fprintf(stderr, "Read offset %d from %p\n", p->offset, &p->offset);
+#endif
+  return p->offset;
+}
+
+
+static void usage()
+{
+  fputs(
+"usage: icedax [OPTIONS ...] [trackfilenames ...]\n\
+OPTIONS:\n\
+        [-c chans] [-s] [-m] [-b bits] [-r rate] [-a divider] [-S speed] [-x]\n\
+        [-t track[+endtrack]] [-i index] [-o offset] [-d duration] [-F] [-G]\n\
+        [-q] [-w] [-v vopts] [-R] [-P overlap] [-B] [-T] [-C input-endianess]\n\
+        [-e] [-n sectors] [-N] [-J] [-L cddbp-mode] [-H] [-g] [-l buffers] [-D cd-device]\n\
+        [-I interface] [-K sound-device] [-O audiotype] [-E output-endianess]\n\
+        [-A auxdevice] [-paranoia] [-cddbp-server=name] [-cddbp-port=port] [-version]\n", stderr);
+  fputs("\
+  (-D) dev=device              set the cdrom or scsi device (as Bus,Id,Lun).\n\
+  (-A) auxdevice=device                set the aux device (typically /dev/cdrom).\n\
+  (-K) sound-device=device     set the sound device to use for -e (typically /dev/dsp).\n\
+  (-I) interface=interface     specify the interface for cdrom access.\n\
+        (generic_scsi or cooked_ioctl).\n\
+  (-c) channels=channels       set 1 for mono, 2 or s for stereo (s: channels swapped).\n\
+  (-s) -stereo                 select stereo recording.\n\
+  (-m) -mono                   select mono recording.\n\
+  (-x) -max                    select maximum quality (stereo/16-bit/44.1 KHz).\n\
+  (-b) bits=bits               set bits per sample per channel (8, 12 or 16 bits).\n\
+  (-r) rate=rate               set rate in samples per second. -R gives all rates\n\
+  (-a) divider=divider         set rate to 44100Hz / divider. -R gives all rates\n\
+  (-R) -dump-rates             dump a table with all available sample rates\n\
+  (-S) speed=speedfactor       set the cdrom drive to a given speed during reading\n\
+  (-P) set-overlap=sectors     set amount of overlap sampling (default is 0)\n\
+  (-n) sectors-per-request=secs        read 'sectors' sectors per request.\n\
+  (-l) buffers-in-ring=buffers use a ring buffer with 'buffers' elements.\n\
+  (-t) track=track[+end track] select start track (option. end track).\n\
+  (-i) index=index             select start index.\n\
+  (-o) offset=offset           start at 'offset' sectors behind start track/index.\n\
+        one sector equivalents 1/75 second.\n\
+  (-O) output-format=audiotype set to wav, au (sun), cdr (raw), aiff or aifc format.\n\
+  (-C) cdrom-endianess=endian  set little, big or guess input sample endianess.\n\
+  (-E) output-endianess=endian set little or big output sample endianess.\n\
+  (-d) duration=seconds                set recording time in seconds or 0 for whole track.\n\
+  (-w) -wait                   wait for audio signal, then start recording.\n\
+  (-F) -find-extremes          find extrem amplitudes in samples.\n\
+  (-G) -find-mono              find if input samples are mono.\n\
+  (-T) -deemphasize            undo pre-emphasis in input samples.\n\
+  (-e) -echo                   echo audio data to sound device (see -K) SOUND_DEV.\n\
+  (-v) verbose-level=optlist   controls verbosity (for a list use -vhelp).\n\
+  (-N) -no-write               do not create audio sample files.\n\
+  (-J) -info-only              give disc information only.\n\
+  (-L) cddb=cddbpmode          do cddbp title lookups.\n\
+        resolve multiple entries according to cddbpmode: 0=interactive, 1=first entry\n\
+  (-H) -no-infofile            no info file generation.\n\
+  (-g) -gui                    generate special output suitable for gui frontends.\n\
+  (-Q) -silent-scsi            do not print status of erreneous scsi-commands.\n\
+       -scanbus                        scan the SCSI bus and exit\n\
+       --devices               scan for system devices and print with native names\n\
+  (-M) md5=count               calculate MD-5 checksum for blocks of 'count' bytes.\n\
+  (-q) -quiet                  quiet operation, no screen output.\n\
+  (-p) playback-realtime=perc  play (echo) audio pitched at perc percent (50%-200%).\n\
+  (-V) -verbose-scsi           each option increases verbosity for SCSI commands.\n\
+  (-h) -help                   show this help screen.\n\
+  (-B) -alltracks, -bulk       record each track into a seperate file.\n\
+       -paranoia               use the lib paranoia for reading.\n\
+       -paraopts=opts          set options for lib paranoia (see -paraopts=help).\n\
+       -cddbp-server=servername        set the cddbp server to use for title lookups.\n\
+       -cddbp-port=portnumber  set the cddbp port to use for title lookups.\n\
+       -version                        print version information.\n\
+\n\
+Please note: some short options will be phased out soon (disappear)!\n\
+\n\
+parameters: (optional) one or more file names or - for standard output.\n\
+", stderr);
+  fputs("Version ", stderr);
+  fputs(VERSION, stderr);
+  fprintf(stderr, "\n\
+defaults       %s, %d bit, %d.%02d Hz, track 1, no offset, one track,\n",
+         CHANNELS-1?"stereo":"mono", BITS_P_S,
+        44100 / UNDERSAMPLING,
+        (4410000 / UNDERSAMPLING) % 100);
+  fprintf(stderr, "\
+          type %s '%s', don't wait for signal, not quiet,\n",
+          AUDIOTYPE, FILENAME);
+  fprintf(stderr, "\
+          use %s, device %s, aux %s\n",
+         DEF_INTERFACE, CD_DEVICE, AUX_DEVICE);
+  exit( SYNTAX_ERROR );
+}
+
+static void init_globals()
+{
+#ifdef HISTORICAL_JUNK
+  global.dev_name = CD_DEVICE; /* device name */
+#endif
+  global.aux_name = AUX_DEVICE;/* auxiliary cdrom device */
+  strncpy(global.fname_base, FILENAME, sizeof(global.fname_base));/* auxiliary cdrom device */
+  global.have_forked = 0;      /* state variable for clean up */
+  global.parent_died = 0;      /* state variable for clean up */
+  global.audio    = -1;                /* audio file desc */
+  global.cooked_fd  = -1;      /* cdrom file desc */
+  global.no_file  =  0;                /* flag no_file */
+  global.no_infofile  =  0;    /* flag no_infofile */
+  global.no_cddbfile  =  0;    /* flag no_cddbfile */
+  global.quiet   =  0;         /* flag quiet */
+  global.verbose  =  SHOW_TOC + SHOW_SUMMARY + SHOW_STARTPOSITIONS + SHOW_TITLES;      /* verbose level */
+  global.scsi_silent = 0;
+  global.scsi_verbose = 0;             /* SCSI verbose level */
+  global.scanbus = 0;
+  global.scandevs = 0;
+  global.multiname = 0;                /* multiple file names given */
+  global.sh_bits  =  0;                /* sh_bits: sample bit shift */
+  global.Remainder=  0;                /* remainder */
+  global.iloop    =  0;                /* todo counter */
+  global.SkippedSamples =  0;  /* skipped samples */
+  global.OutSampleSize  =  0;  /* output sample size */
+  global.channels = CHANNELS;  /* output sound channels */
+  global.nSamplesDoneInTrack = 0; /* written samples in current track */
+  global.buffers = 4;           /* buffers to use */
+  global.nsectors = NSECTORS;   /* sectors to read in one request */
+  global.overlap = 1;           /* amount of overlapping sectors */
+  global.useroverlap = -1;      /* amount of overlapping sectors user override */
+  global.need_hostorder = 0;   /* processing needs samples in host endianess */
+  global.in_lendian = -1;      /* input endianess from SetupSCSI() */
+  global.outputendianess = NONE; /* user specified output endianess */
+  global.findminmax  =  0;     /* flag find extrem amplitudes */
+#ifdef HAVE_LIMITS_H
+  global.maxamp[0] = INT_MIN;  /* maximum amplitude */
+  global.maxamp[1] = INT_MIN;  /* maximum amplitude */
+  global.minamp[0] = INT_MAX;  /* minimum amplitude */
+  global.minamp[1] = INT_MAX;  /* minimum amplitude */
+#else
+  global.maxamp[0] = -32768;   /* maximum amplitude */
+  global.maxamp[1] = -32768;   /* maximum amplitude */
+  global.minamp[0] = 32767;    /* minimum amplitude */
+  global.minamp[1] = 32767;    /* minimum amplitude */
+#endif
+  global.speed = DEFAULT_SPEED; /* use default */ 
+  global.userspeed = -1;        /* speed user override */
+  global.findmono  =  0;       /* flag find if samples are mono */
+  global.ismono  =  1;         /* flag if samples are mono */
+  global.swapchannels  =  0;   /* flag if channels shall be swapped */
+  global.deemphasize  =  0;    /* flag undo pre-emphasis in samples */
+  global.playback_rate = 100;   /* new fancy selectable sound output rate */
+  global.gui  =  0;            /* flag plain formatting for guis */
+  global.cddb_id = 0;           /* disc identifying id for CDDB database */
+  global.cddb_revision = 0;     /* entry revision for CDDB database */
+  global.cddb_year = 0;         /* disc identifying year for CDDB database */
+  global.cddb_genre[0] = '\0';  /* disc identifying genre for CDDB database */
+  global.cddbp = 0;             /* flag if titles shall be looked up from CDDBP */
+  global.cddbp_server = 0;      /* user supplied CDDBP server */
+  global.cddbp_port = 0;        /* user supplied CDDBP port */
+  global.illleadout_cd = 0;     /* flag if illegal leadout is present */
+  global.reads_illleadout = 0;  /* flag if cdrom drive reads cds with illegal leadouts */
+  global.disctitle = NULL;
+  global.creator = NULL;
+  global.copyright_message = NULL;
+  memset(global.tracktitle, 0, sizeof(global.tracktitle));
+  memset(global.trackindexlist, 0, sizeof(global.trackindexlist));
+
+  global.just_the_toc = 0;
+#ifdef USE_PARANOIA
+       global.paranoia_parms.disable_paranoia = 
+       global.paranoia_parms.disable_extra_paranoia = 
+       global.paranoia_parms.disable_scratch_detect =
+       global.paranoia_parms.disable_scratch_repair = 0;
+       global.paranoia_parms.retries = 20;
+       global.paranoia_parms.overlap = -1;
+       global.paranoia_parms.mindynoverlap = -1;
+       global.paranoia_parms.maxdynoverlap = -1;
+#endif
+}
+
+#if !defined (HAVE_STRCASECMP) || (HAVE_STRCASECMP != 1)
+#include <ctype.h>
+static int strcasecmp(const char *s1, const char *s2);
+static int strcasecmp(const char *s1, const char *s2)
+{
+  if (s1 && s2) {
+    while (*s1 && *s2 && (tolower(*s1) - tolower(*s2) == 0)) {
+      s1++;
+      s2++;
+    }
+    if (*s1 == '\0' && *s2 == '\0') return 0;
+    if (*s1 == '\0') return -1;
+    if (*s2 == '\0') return +1;
+    return tolower(*s1) - tolower(*s2);
+  }
+  return -1;
+}
+#endif
+
+static int is_fifo(char *filename)
+{
+#if    defined S_ISFIFO
+  struct stat statstruct;
+
+  if (stat(filename, &statstruct)) {
+    /* maybe the output file does not exist. */
+    if (errno == ENOENT)
+       return 0;
+    else comerr("Error during stat for output file\n");
+  } else {
+    if (S_ISFIFO(statstruct.st_mode)) {
+       return 1;
+    }
+  }
+  return 0;
+#else
+  return 0;
+#endif
+}
+
+
+#if !defined (HAVE_STRTOUL) || (HAVE_STRTOUL != 1)
+static unsigned int strtoul(const char *s1, char **s2, int base);
+static unsigned int strtoul(const char *s1, char **s2, int base)
+{
+       long retval;
+
+       if (base == 10) {
+               /* strip zeros in front */
+               while (*s1 == '0')
+                       s1++;
+       }
+       if (s2 != NULL) {
+               *s2 = astol(s1, &retval);
+       } else {
+               (void) astol(s1, &retval);
+       }
+
+       return (unsigned long) retval;  
+}
+#endif
+
+static unsigned long SectorBurst;
+#if (SENTINEL > CD_FRAMESIZE_RAW)
+error block size for overlap check has to be < sector size
+#endif
+
+
+static void
+switch_to_realtime_priority(void);
+
+#ifdef  HAVE_SYS_PRIOCNTL_H
+
+#include <sys/priocntl.h>
+#include <sys/rtpriocntl.h>
+static void switch_to_realtime_priority()
+{
+        pcinfo_t        info;
+        pcparms_t       param;
+        rtinfo_t        rtinfo;
+        rtparms_t       rtparam;
+       int             pid;
+
+       pid = getpid();
+
+        /* get info */
+        strcpy(info.pc_clname, "RT");
+        if (-1 == priocntl(P_PID, pid, PC_GETCID, (void *)&info)) {
+                errmsg("Cannot get priority class id priocntl(PC_GETCID)\n");
+               goto prio_done;
+       }
+
+        memmove(&rtinfo, info.pc_clinfo, sizeof(rtinfo_t));
+
+        /* set priority not to the max */
+        rtparam.rt_pri = rtinfo.rt_maxpri - 2;
+        rtparam.rt_tqsecs = 0;
+        rtparam.rt_tqnsecs = RT_TQDEF;
+        param.pc_cid = info.pc_cid;
+        memmove(param.pc_clparms, &rtparam, sizeof(rtparms_t));
+       priv_on();
+       needroot(0);
+        if (-1 == priocntl(P_PID, pid, PC_SETPARMS, (void *)&param))
+                errmsg("Cannot set priority class parameters priocntl(PC_SETPARMS)\n");
+prio_done:
+       priv_off();
+       dontneedroot();
+}
+#else
+#if defined(_POSIX_PRIORITY_SCHEDULING) && _POSIX_PRIORITY_SCHEDULING -0 >= 0
+#define        USE_POSIX_PRIORITY_SCHEDULING
+#endif
+#ifdef USE_POSIX_PRIORITY_SCHEDULING
+#include <sched.h>
+
+static void switch_to_realtime_priority()
+{
+#ifdef  _SC_PRIORITY_SCHEDULING
+       if (sysconf(_SC_PRIORITY_SCHEDULING) == -1) {
+               errmsg("WARNING: RR-scheduler not available, disabling.\n");
+       } else
+#endif
+       {
+       int sched_fifo_min, sched_fifo_max;
+       struct sched_param sched_parms;
+
+       sched_fifo_min = sched_get_priority_min(SCHED_FIFO);
+       sched_fifo_max = sched_get_priority_max(SCHED_FIFO);
+       sched_parms.sched_priority = sched_fifo_max - 1;
+       priv_on();
+       needroot(0);
+       if (-1 == sched_setscheduler(getpid(), SCHED_FIFO, &sched_parms)
+               && global.quiet != 1)
+               errmsg("cannot set posix realtime scheduling policy\n");
+       priv_off();
+       dontneedroot();
+       }
+}
+#else
+#if defined(__CYGWIN32__)
+
+/*
+ * NOTE: Base.h from Cygwin-B20 has a second typedef for BOOL.
+ *      We define BOOL to make all local code use BOOL
+ *      from Windows.h and use the hidden __SBOOL for
+ *      our global interfaces.
+ *
+ * NOTE: windows.h from Cygwin-1.x includes a structure field named sample,
+ *      so me may not define our own 'sample' or need to #undef it now.
+ *      With a few nasty exceptions, Microsoft assumes that any global
+ *      defines or identifiers will begin with an Uppercase letter, so
+ *      there may be more of these problems in the future.
+ *
+ * NOTE: windows.h defines interface as an alias for struct, this 
+ *      is used by COM/OLE2, I guess it is class on C++
+ *      We man need to #undef 'interface'
+ */
+#define        BOOL    WBOOL           /* This is the Win BOOL         */
+#define        format  __format        /* Avoid format parameter hides global ... */
+#include <windows.h>
+#undef format
+#undef interface
+
+static void switch_to_realtime_priority()
+{
+   /* set priority class */
+   if (FALSE == SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS)) {
+     fprintf(stderr, "No realtime priority possible.\n");
+     return;
+   }
+
+   /* set thread priority */
+   if (FALSE == SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST)) {
+     fprintf(stderr, "Could not set realtime priority.\n");
+   }
+}
+#else
+static void switch_to_realtime_priority()
+{
+}
+#endif
+#endif
+#endif
+
+/* SCSI cleanup */
+int on_exitscsi(void *status);
+
+int on_exitscsi(void *status)
+{
+       exit((intptr_t)status);
+       return 0;
+}
+
+/* wrapper for signal handler exit needed for Mac-OS-X */
+static void exit_wrapper(int status);
+
+static void exit_wrapper(int status)
+{
+#if defined DEBUG_CLEANUP
+       fprintf( stderr, "Exit(%d) for %s\n", status, child_pid == 0 ? "Child" : "Parent");
+       fflush(stderr);
+#endif
+
+       if (child_pid != 0) {
+               SCSI *usalp = get_scsi_p();
+               if (usalp->running) {
+                       usalp->cb_fun = on_exitscsi;
+                       usalp->cb_arg = (void *) (uintptr_t) status;
+               } else {
+                       on_exitscsi((void *) (intptr_t) status);
+               } 
+       } else {
+               exit(status);
+       }
+}
+
+/* signal handler for process communication */
+static void set_nonforked(int status);
+
+/* ARGSUSED */
+static void set_nonforked(int status)
+{
+       global.parent_died = 1;
+#if defined DEBUG_CLEANUP
+fprintf( stderr, "SIGPIPE received from %s\n.", child_pid == 0 ? "Child" : "Parent");
+#endif
+       if (child_pid == 0) {
+               pid_t   ppid;
+               /*
+                * Kill the parent too if we are not orphaned.
+                */
+               ppid = getppid();
+               if (ppid > 1)
+                       kill(ppid, SIGINT);
+       } else {
+               kill(child_pid, SIGINT);
+       }
+       exit(SIGPIPE_ERROR);
+}
+
+
+
+#ifdef USE_PARANOIA
+static struct paranoia_statistics
+{
+       long    c_sector;
+       long    v_sector;
+       int     last_heartbeatstate;
+       long    lasttime;
+       char    heartbeat;
+       int     minoverlap;
+       int     curoverlap;
+       int     maxoverlap;
+       int     slevel;
+       int     slastlevel;
+       int     stimeout;
+       int     rip_smile_level;
+       unsigned verifies;
+       unsigned reads;
+       unsigned fixup_edges;
+       unsigned fixup_atoms;
+       unsigned readerrs;
+       unsigned skips;
+       unsigned overlaps;
+       unsigned scratchs;
+       unsigned drifts;
+       unsigned fixup_droppeds;
+       unsigned fixup_dupeds;
+}      *para_stat;
+
+
+static void paranoia_reset(void);
+static void paranoia_reset()
+{
+       para_stat->c_sector = 0;
+       para_stat->v_sector = 0;
+       para_stat->last_heartbeatstate = 0;
+       para_stat->lasttime = 0;
+       para_stat->heartbeat = ' ';
+       para_stat->minoverlap = 0x7FFFFFFF;
+       para_stat->curoverlap = 0;
+       para_stat->maxoverlap = 0;
+       para_stat->slevel = 0;
+       para_stat->slastlevel = 0;
+       para_stat->stimeout = 0;
+       para_stat->rip_smile_level = 0;
+       para_stat->verifies = 0;
+       para_stat->reads = 0;
+       para_stat->readerrs = 0;
+       para_stat->fixup_edges = 0;
+       para_stat->fixup_atoms = 0;
+       para_stat->fixup_droppeds = 0;
+       para_stat->fixup_dupeds = 0;
+       para_stat->drifts = 0;
+       para_stat->scratchs = 0;
+       para_stat->overlaps = 0;
+       para_stat->skips = 0;
+}
+
+static void paranoia_callback(long inpos, int function);
+
+static void paranoia_callback(long inpos, int function)
+{
+       struct timeval thistime;
+       long    test;
+
+       switch (function) {
+               case    -2:
+                       para_stat->v_sector = inpos / CD_FRAMEWORDS;
+                       return;
+               case    -1:
+                       para_stat->last_heartbeatstate = 8;
+                       para_stat->heartbeat = '*';
+                       para_stat->slevel = 0;
+                       para_stat->v_sector = inpos / CD_FRAMEWORDS;
+               break;
+               case    PARANOIA_CB_VERIFY:
+                       if (para_stat->stimeout >= 30) {
+                               if (para_stat->curoverlap > CD_FRAMEWORDS) {
+                                       para_stat->slevel = 2;
+                               } else {
+                                       para_stat->slevel = 1;
+                               }
+                       }
+                       para_stat->verifies++;
+               break;
+               case    PARANOIA_CB_READ:
+                       if (inpos / CD_FRAMEWORDS > para_stat->c_sector) {
+                               para_stat->c_sector = inpos / CD_FRAMEWORDS;
+                       }
+                       para_stat->reads++;
+               break;
+               case    PARANOIA_CB_FIXUP_EDGE:
+                       if (para_stat->stimeout >= 5) {
+                               if (para_stat->curoverlap > CD_FRAMEWORDS) {
+                                       para_stat->slevel = 2;
+                               } else {
+                                       para_stat->slevel = 1;
+                               }
+                       }
+                       para_stat->fixup_edges++;
+               break;
+               case    PARANOIA_CB_FIXUP_ATOM:
+                       if (para_stat->slevel < 3 || para_stat->stimeout > 5) {
+                               para_stat->slevel = 3;
+                       }
+                       para_stat->fixup_atoms++;
+               break;
+               case    PARANOIA_CB_READERR:
+                       para_stat->slevel = 6;
+                       para_stat->readerrs++;
+               break;
+               case    PARANOIA_CB_SKIP:
+                       para_stat->slevel = 8;
+                       para_stat->skips++;
+               break;
+               case    PARANOIA_CB_OVERLAP:
+                       para_stat->curoverlap = inpos;
+                       if (inpos > para_stat->maxoverlap)
+                               para_stat->maxoverlap = inpos;
+                       if (inpos < para_stat->minoverlap)
+                               para_stat->minoverlap = inpos;
+                       para_stat->overlaps++;
+               break;
+               case    PARANOIA_CB_SCRATCH:
+                       para_stat->slevel = 7;
+                       para_stat->scratchs++;
+               break;
+               case    PARANOIA_CB_DRIFT:
+                       if (para_stat->slevel < 4 || para_stat->stimeout > 5) {
+                               para_stat->slevel = 4;
+                       }
+                       para_stat->drifts++;
+               break;
+               case    PARANOIA_CB_FIXUP_DROPPED:
+                       para_stat->slevel = 5;
+                       para_stat->fixup_droppeds++;
+               break;
+               case    PARANOIA_CB_FIXUP_DUPED:
+                       para_stat->slevel = 5;
+                       para_stat->fixup_dupeds++;
+               break;
+       }
+
+       gettimeofday(&thistime, NULL);
+       /* now in tenth of seconds. */
+       test = thistime.tv_sec * 10 + thistime.tv_usec / 100000;
+
+       if (para_stat->lasttime != test
+               || function == -1
+               || para_stat->slastlevel != para_stat->slevel) {
+
+               if (function == -1
+                       || para_stat->slastlevel != para_stat->slevel) {
+
+                       static const char hstates[] = " .o0O0o.";
+
+                       para_stat->lasttime = test;
+                       para_stat->stimeout++;
+
+                       para_stat->last_heartbeatstate++;
+                       if (para_stat->last_heartbeatstate > 7) {
+                               para_stat->last_heartbeatstate = 0;
+                       }
+                       para_stat->heartbeat = hstates[para_stat->last_heartbeatstate];
+
+                       if (function == -1) {
+                               para_stat->heartbeat = '*';
+                       }
+               }
+
+               if (para_stat->slastlevel != para_stat->slevel) {
+                       para_stat->stimeout = 0;
+               }
+               para_stat->slastlevel = para_stat->slevel;
+       }
+
+       if (para_stat->slevel < 8) {
+               para_stat->rip_smile_level = para_stat->slevel;
+       } else {
+               para_stat->rip_smile_level = 0;
+       }
+}
+#endif
+
+static long lSector;
+static long lSector_p2;
+static double rate = 44100.0 / UNDERSAMPLING;
+static int bits = BITS_P_S;
+static char fname[200];
+static const char *audio_type;
+static long BeginAtSample;
+static unsigned long SamplesToWrite; 
+static unsigned minover;
+static unsigned maxover;
+
+static unsigned long calc_SectorBurst(void);
+static unsigned long calc_SectorBurst()
+{
+       unsigned long SectorBurstVal;
+
+       SectorBurstVal = min(global.nsectors,
+                 (global.iloop + CD_FRAMESAMPLES-1) / CD_FRAMESAMPLES);
+       if ( lSector+(int)SectorBurst-1 >= lSector_p2 )
+               SectorBurstVal = lSector_p2 - lSector;
+       return SectorBurstVal;
+}
+
+/* if PERCENTAGE_PER_TRACK is defined, the percentage message will reach
+ * 100% every time a track end is reached or the time limit is reached.
+ *
+ * Otherwise if PERCENTAGE_PER_TRACK is not defined, the percentage message
+ * will reach 100% once at the very end of the last track.
+ */
+#define        PERCENTAGE_PER_TRACK
+
+static int do_read(myringbuff *p, unsigned *total_unsuccessful_retries);
+static int do_read(myringbuff *p, unsigned *total_unsuccessful_retries)
+{
+       unsigned char *newbuf;
+       int offset;
+       unsigned int added_size;
+
+       /* how many sectors should be read */
+       SectorBurst =  calc_SectorBurst();
+
+#ifdef USE_PARANOIA
+       if (global.paranoia_selected) {
+               int i;
+
+               for (i = 0; i < SectorBurst; i++) {
+                       void *dp;
+
+                       dp = paranoia_read_limited(global.cdp, paranoia_callback,
+                               global.paranoia_parms.retries);
+/*
+                       {
+                               char *err;
+                               char *msg;
+                               err = cdda_errors(global.cdp);
+                               msg = cdda_messages(global.cdp);
+                               if (err) {
+                                       fputs(err, stderr);
+                                       free(err);
+                               }
+                               if (msg) {
+                                       fputs(msg, stderr);
+                                       free(msg);
+                               }
+                       }
+*/
+                       if (dp != NULL) {
+                               memcpy(p->data + i*CD_FRAMESAMPLES, dp,
+                                       CD_FRAMESIZE_RAW);
+                       } else {
+                               fputs("E unrecoverable error!", stderr);
+                               exit(READ_ERROR);
+                       }
+               }
+               newbuf = (unsigned char *)p->data;
+               offset = 0;
+               set_offset(p,offset);
+               added_size = SectorBurst * CD_FRAMESAMPLES;
+               global.overlap = 0;
+               handle_inputendianess(p->data, added_size);
+       } else 
+#endif
+       {
+               unsigned int retry_count;
+#define MAX_READRETRY 12
+
+               retry_count = 0;
+               do {
+                       SCSI *usalp = get_scsi_p();
+                       int retval;
+#ifdef DEBUG_READS
+fprintf(stderr, "reading from %lu to %lu, overlap %u\n", lSector, lSector + SectorBurst -1, global.overlap);
+#endif
+
+#ifdef DEBUG_BUFFER_ADDRESSES
+fprintf(stderr, "%p %l\n", p->data, global.pagesize);
+if (((unsigned)p->data) & (global.pagesize -1) != 0) {
+  fprintf(stderr, "Address %p is NOT page aligned!!\n", p->data);
+}
+#endif
+
+                       if (global.reads_illleadout != 0 && lSector > Get_StartSector(LastTrack())) {
+                               int singles = 0;
+                               UINT4 bufferSub[CD_FRAMESAMPLES + 24];
+
+                               /* we switch to single sector reads,
+                                * in order to handle the remaining sectors. */
+                               usalp->silent++;
+                               do {
+                                       ReadCdRomSub( usalp, bufferSub, lSector+singles, 1 );
+                                       *eorecording = RealEnd( usalp, bufferSub );
+                                       if (*eorecording) {
+                                               break;
+                                       }
+                                       memcpy(p->data+singles*CD_FRAMESAMPLES, bufferSub, CD_FRAMESIZE_RAW);
+                                       singles++;
+                               } while (singles < SectorBurst);
+                               usalp->silent--;
+
+                               if ( *eorecording ) {
+                                       patch_real_end(lSector+singles);
+                                       SectorBurst = singles;
+#if    DEBUG_ILLLEADOUT
+fprintf(stderr, "iloop=%11lu, nSamplesToDo=%11lu, end=%lu -->\n",
+global.iloop, *nSamplesToDo, lSector+singles);
+#endif
+
+                                       *nSamplesToDo -= global.iloop - SectorBurst*CD_FRAMESAMPLES;
+                                       global.iloop = SectorBurst*CD_FRAMESAMPLES;
+#if    DEBUG_ILLLEADOUT
+fprintf(stderr, "iloop=%11lu, nSamplesToDo=%11lu\n\n",
+global.iloop, *nSamplesToDo);
+#endif
+
+                               }
+                       } else {
+                               retval = ReadCdRom( usalp, p->data, lSector, SectorBurst );
+                       }
+                       handle_inputendianess(p->data, SectorBurst * CD_FRAMESAMPLES);
+                       if (NULL ==
+                               (newbuf = synchronize( p->data, SectorBurst*CD_FRAMESAMPLES,
+                                       *nSamplesToDo-global.iloop ))) {
+                               /* could not synchronize!
+                                * Try to invalidate the cdrom cache.
+                                * Increase overlap setting, if possible.
+                                */     
+                               /*trash_cache(p->data, lSector, SectorBurst);*/
+                               if (global.overlap < global.nsectors - 1) {
+                                       global.overlap++;
+                                       lSector--;
+                                       SectorBurst = calc_SectorBurst();
+#ifdef DEBUG_DYN_OVERLAP
+fprintf(stderr, "using increased overlap of %u\n", global.overlap);
+#endif
+                               } else {
+                                       lSector += global.overlap - 1;
+                                       global.overlap = 1;
+                                       SectorBurst =  calc_SectorBurst();
+                               }
+                       } else
+                               break;
+               } while (++retry_count < MAX_READRETRY);
+
+               if (retry_count == MAX_READRETRY && newbuf == NULL && global.verbose != 0) {
+                       (*total_unsuccessful_retries)++;
+               }
+
+               if (newbuf) {
+                       offset = newbuf - ((unsigned char *)p->data);
+               } else {
+                       offset = global.overlap * CD_FRAMESIZE_RAW;
+               }
+               set_offset(p,offset);
+
+               /* how much has been added? */
+               added_size = SectorBurst * CD_FRAMESAMPLES - offset/4;
+
+               if (newbuf && *nSamplesToDo != global.iloop) {
+                       minover = min(global.overlap, minover);
+                       maxover = max(global.overlap, maxover);
+
+
+                       /* should we reduce the overlap setting ? */
+                       if (offset > CD_FRAMESIZE_RAW && global.overlap > 1) {
+#ifdef DEBUG_DYN_OVERLAP
+fprintf(stderr, "decreasing overlap from %u to %u (jitter %d)\n", global.overlap, global.overlap-1, offset - (global.overlap)*CD_FRAMESIZE_RAW);
+#endif
+                               global.overlap--;
+                               SectorBurst =  calc_SectorBurst();
+                       }
+               }
+       }
+       if (global.iloop >= added_size) {
+               global.iloop -= added_size;
+       } else {
+               global.iloop = 0;
+       }
+
+       lSector += SectorBurst - global.overlap;
+
+#if    defined PERCENTAGE_PER_TRACK && defined HAVE_FORK_AND_SHAREDMEM
+       {
+               int as;
+               while ((as = Get_StartSector(current_track+1)) != -1
+                       && lSector >= as) {
+                       current_track++;
+               }
+       }
+#endif
+
+       return offset;
+}
+
+static void
+print_percentage(unsigned *poper, int c_offset);
+
+static void print_percentage(unsigned *poper, int c_offset)
+{
+       unsigned per;
+#ifdef PERCENTAGE_PER_TRACK
+       /* Thomas Niederreiter wants percentage per track */
+       unsigned start_in_track = max(BeginAtSample,
+               Get_AudioStartSector(current_track)*CD_FRAMESAMPLES);
+
+       per = min(BeginAtSample + (long)*nSamplesToDo,
+               Get_StartSector(current_track+1)*CD_FRAMESAMPLES)
+               - (long)start_in_track;
+
+       per = (BeginAtSample+nSamplesDone
+               - start_in_track
+               )/(per/100);
+
+#else
+       per = global.iloop ? (nSamplesDone)/(*nSamplesToDo/100) : 100;
+#endif
+
+       if (global.overlap > 0) {
+               fprintf(stderr, "\r%2d/%2d/%2d/%7d %3d%%",
+                       minover, maxover, global.overlap,
+                       c_offset - global.overlap*CD_FRAMESIZE_RAW,
+                       per);
+       } else if (*poper != per) {
+               fprintf(stderr, "\r%3d%%", per);
+       }
+       *poper = per;
+       fflush(stderr);
+}
+
+static unsigned long do_write(myringbuff *p);
+static unsigned long do_write(myringbuff *p)
+{
+       int current_offset;
+       unsigned int InSamples;
+       static unsigned oper = 200;
+
+       current_offset = get_offset(p);
+
+       /* how many bytes are available? */
+       InSamples = global.nsectors*CD_FRAMESAMPLES - current_offset/4;
+       /* how many samples are wanted? */
+       InSamples = min((*nSamplesToDo-nSamplesDone),InSamples);
+
+       /* when track end is reached, close current file and start a new one */
+       while ((nSamplesDone < *nSamplesToDo) && (InSamples != 0)) {
+               long unsigned int how_much = InSamples;
+
+               long int left_in_track;
+               left_in_track  = Get_StartSector(current_track+1)*CD_FRAMESAMPLES
+                                - (int)(BeginAtSample+nSamplesDone);
+
+               if (*eorecording != 0 && current_track == cdtracks+1 &&
+                           (*total_segments_read) == (*total_segments_written)+1) {
+                       /* limit, if the actual end of the last track is
+                        * not known from the toc. */
+                       left_in_track = InSamples;
+               }
+
+if (left_in_track < 0) {
+       fprintf(stderr, "internal error: negative left_in_track:%ld, current_track=%d\n",left_in_track, current_track);
+}
+
+               if (bulk) {
+                       how_much = min(how_much, (unsigned long) left_in_track);
+               }
+
+#ifdef MD5_SIGNATURES
+               if (global.md5count) {
+                       MD5Update (&global.context, ((unsigned char *)p->data) +current_offset, min(global.md5count,how_much));
+                       global.md5count -= min(global.md5count,how_much);
+               }
+#endif
+               if ( SaveBuffer ( p->data + current_offset/4,
+                        how_much,
+                        &nSamplesDone) ) {
+                       if (global.have_forked == 1) {
+                               pid_t   ppid;
+                               /*
+                                * Kill the parent too if we are not orphaned.
+                                */
+                               ppid = getppid();
+                               if (ppid > 1)
+                                       kill(ppid, SIGINT);
+                       }
+                       exit(WRITE_ERROR);
+               }
+
+               global.nSamplesDoneInTrack += how_much;
+               SamplesToWrite -= how_much;
+
+               /* move residual samples upto buffer start */
+               if (how_much < InSamples) {
+                       memmove(
+                         (char *)(p->data) + current_offset,
+                         (char *)(p->data) + current_offset + how_much*4,
+                         (InSamples - how_much) * 4);
+               }
+
+               if ((unsigned long) left_in_track <= InSamples || SamplesToWrite == 0) {
+                       /* the current portion to be handled is 
+                          the end of a track */
+
+                       if (bulk) {
+                               /* finish sample file for this track */
+                               CloseAudio(global.channels,
+                                 global.nSamplesDoneInTrack, global.audio_out);
+                       } else if (SamplesToWrite == 0) {
+                               /* finish sample file for this track */
+                               CloseAudio(global.channels,
+                                 (unsigned int) *nSamplesToDo, global.audio_out);
+                       }
+
+                       if (global.verbose) {
+#ifdef USE_PARANOIA
+                               double  f;
+#endif
+                               print_percentage(&oper, current_offset);
+                               fputc(' ', stderr);
+#ifndef        THOMAS_SCHAU_MAL
+                               if ((unsigned long)left_in_track > InSamples) {
+                                       fputs(" incomplete", stderr);
+                               }
+#endif
+                               if (global.tracktitle[current_track] != NULL) {
+                                       fprintf( stderr,
+                                               " track %2u '%s' recorded", 
+                                               current_track,
+                                               global.tracktitle[current_track]);
+                               } else {
+                                       fprintf( stderr,
+                                               " track %2u recorded",
+                                               current_track);
+                               }
+#ifdef USE_PARANOIA
+                               oper = para_stat->readerrs + para_stat->skips +
+                                         para_stat->fixup_edges + para_stat->fixup_atoms + 
+                                         para_stat->fixup_droppeds + para_stat->fixup_dupeds + 
+                                         para_stat->drifts;
+                               f = (100.0 * oper) / (((double)global.nSamplesDoneInTrack)/588.0);
+
+                               if (para_stat->readerrs) {
+                                       fprintf(stderr, " with audible hard errors");
+                               } else if ((para_stat->skips) > 0) {
+                                       fprintf(stderr, " with %sretry/skip errors",
+                                                       f < 2.0 ? "":"audible ");
+                               } else if (oper > 0) {
+                                       oper = f;
+                                       
+                                       fprintf(stderr, " with ");
+                                       if (oper < 2)
+                                               fprintf(stderr, "minor");
+                                       else if (oper < 10)
+                                               fprintf(stderr, "medium");
+                                       else if (oper < 67)
+                                               fprintf(stderr, "noticable audible");
+                                       else if (oper < 100)
+                                               fprintf(stderr, "major audible");
+                                       else
+                                               fprintf(stderr, "extreme audible");
+                                       fprintf(stderr, " problems");
+                               } else {
+                                       fprintf(stderr, " successfully");
+                               }
+                               if (f >= 0.1)
+                                       fprintf(stderr, " (%.1f%% problem sectors)", f);
+#else
+                               fprintf(stderr, " successfully");
+#endif
+
+                               if (waitforsignal == 1) {
+                                       fprintf(stderr, ". %d silent samples omitted", global.SkippedSamples);
+                               }
+                               fputs("\n", stderr);
+
+                               if (global.reads_illleadout && *eorecording == 1) {
+                                       fprintf(stderr, "Real lead out at: %ld sectors\n", 
+                                         (*nSamplesToDo+BeginAtSample)/CD_FRAMESAMPLES);
+                               }
+#ifdef USE_PARANOIA
+                               if (global.paranoia_selected) {
+                                       oper = 200;     /* force new output */
+                                       print_percentage(&oper, current_offset);
+                                       if (para_stat->minoverlap == 0x7FFFFFFF)
+                                               para_stat->minoverlap = 0;
+                                       fprintf(stderr, "  %u rderr, %u skip, %u atom, %u edge, %u drop, %u dup, %u drift\n"
+                                               ,para_stat->readerrs
+                                               ,para_stat->skips
+                                               ,para_stat->fixup_atoms
+                                               ,para_stat->fixup_edges
+                                               ,para_stat->fixup_droppeds
+                                               ,para_stat->fixup_dupeds
+                                               ,para_stat->drifts);
+                                       oper = 200;     /* force new output */
+                                       print_percentage(&oper, current_offset);
+                                       fprintf(stderr, "  %u overlap(%.4g .. %.4g)\n",
+                                               para_stat->overlaps,
+                                               (float)para_stat->minoverlap / (2352.0/2.0),
+                                               (float)para_stat->maxoverlap / (2352.0/2.0));
+                                       paranoia_reset();
+                               }
+#endif
+                       }
+
+                       global.nSamplesDoneInTrack = 0;
+                       if ( bulk && SamplesToWrite > 0 ) {
+                               if ( !global.no_file ) {
+                                       char *tmp_fname;
+
+                                       /* build next filename */
+                                       tmp_fname = get_next_name();
+                                       if (tmp_fname != NULL) {
+                                               strncpy(global.fname_base,
+                                                       tmp_fname,
+                                                       sizeof global.fname_base);
+                                               global.fname_base[
+                                                       sizeof(global.fname_base)-1] =
+                                                       '\0';
+                                       }
+
+                                       tmp_fname = cut_extension(global.fname_base);
+                                       tmp_fname[0] = '\0';
+
+                                       if (global.multiname == 0) {
+                                               sprintf(fname, "%s_%02u.%s",
+                                                       global.fname_base,
+                                                       current_track+1,
+                                                       audio_type);
+                                       } else {
+                                               sprintf(fname, "%s.%s",
+                                                       global.fname_base,
+                                                       audio_type);
+                                       }
+
+                                       OpenAudio( fname, rate, bits, global.channels,
+                                               (Get_AudioStartSector(current_track+1) -
+                                                Get_AudioStartSector(current_track))
+                                                       *CD_FRAMESIZE_RAW,
+                                               global.audio_out);
+                               } /* global.nofile */
+                       } /* if ( bulk && SamplesToWrite > 0 ) */
+                       current_track++;
+
+               } /* left_in_track <= InSamples */
+               InSamples -= how_much;
+
+       }  /* end while */
+       if (!global.quiet && *nSamplesToDo != nSamplesDone) {
+               print_percentage(&oper, current_offset);
+       }
+       return nSamplesDone;
+}
+
+#define PRINT_OVERLAP_INIT \
+   if (global.verbose) { \
+       if (global.overlap > 0) \
+               fprintf(stderr, "overlap:min/max/cur, jitter, percent_done:\n  /  /  /          0%%"); \
+       else \
+               fputs("percent_done:\n  0%", stderr); \
+   }
+
+#if defined HAVE_FORK_AND_SHAREDMEM
+static void forked_read(void);
+
+/* This function does all audio cdrom reads
+ * until there is nothing more to do
+ */
+static void forked_read()
+{
+   unsigned total_unsuccessful_retries = 0;
+
+#if !defined(HAVE_SEMGET) || !defined(USE_SEMAPHORES)
+   init_child();
+#endif
+
+   minover = global.nsectors;
+
+   PRINT_OVERLAP_INIT
+   while (global.iloop) { 
+
+      do_read(get_next_buffer(), &total_unsuccessful_retries);
+
+      define_buffer();
+
+   } /* while (global.iloop) */
+
+   if (total_unsuccessful_retries) {
+      fprintf(stderr,"%u unsuccessful matches while reading\n",total_unsuccessful_retries);
+   }
+}
+
+static void forked_write(void);
+
+static void forked_write()
+{
+
+    /* don't need these anymore.  Good security policy says we get rid
+       of them ASAP */
+       priv_off();
+       neverneedroot();
+       neverneedgroup();
+
+#if defined(HAVE_SEMGET) && defined(USE_SEMAPHORES)
+#else
+    init_parent();
+#endif
+
+    for (;nSamplesDone < *nSamplesToDo;) {
+       if (*eorecording == 1 && (*total_segments_read) == (*total_segments_written)) break;
+
+       /* get oldest buffers */
+      
+       nSamplesDone = do_write(get_oldest_buffer());
+
+        drop_buffer();
+
+    } /* end for */
+
+}
+#endif
+
+/* This function implements the read and write calls in one loop (in case
+ * there is no fork/thread_create system call).
+ * This means reads and writes have to wait for each other to complete.
+ */
+static void nonforked_loop(void);
+
+static void nonforked_loop()
+{
+    unsigned total_unsuccessful_retries = 0;
+
+    minover = global.nsectors;
+
+    PRINT_OVERLAP_INIT
+    while (global.iloop) { 
+
+      do_read(get_next_buffer(), &total_unsuccessful_retries);
+
+      do_write(get_oldest_buffer());
+
+    }
+
+    if (total_unsuccessful_retries) {
+      fprintf(stderr,"%u unsuccessful matches while reading\n",total_unsuccessful_retries);
+    }
+
+}
+
+void verbose_usage(void);
+
+void verbose_usage()
+{
+       fputs("\
+       help            lists all verbose options.\n\
+       disable         disables verbose mode.\n\
+       all             enables all verbose options.\n\
+       toc             display the table of contents.\n\
+       summary         display a summary of track parameters.\n\
+       indices         retrieve/display index positions.\n\
+       catalog         retrieve/display media catalog number.\n\
+       trackid         retrieve/display international standard recording code.\n\
+       sectors         display the start sectors of each track.\n\
+       titles          display any known track titles.\n\
+", stderr);
+}
+
+#ifdef USE_PARANOIA
+void paranoia_usage(void);
+
+void paranoia_usage()
+{
+       fputs("\
+       help            lists all paranoia options.\n\
+       disable         disables paranoia mode. Paranoia is still being used.\n\
+       no-verify       switches verify off, and overlap on.\n\
+       retries=amount  set the number of maximum retries per sector.\n\
+       overlap=amount  set the number of sectors used for statical paranoia overlap.\n\
+       minoverlap=amt  set the min. number of sectors used for dynamic paranoia overlap.\n\
+       maxoverlap=amt  set the max. number of sectors used for dynamic paranoia overlap.\n\
+", stderr);
+}
+#endif
+
+int
+handle_verbose_opts(char *optstr, long *flagp);
+
+int handle_verbose_opts(char *optstr, long *flagp)
+{
+       char    *ep;
+       char    *np;
+       int     optlen;
+
+       *flagp = 0;
+       while (*optstr) {
+               if ((ep = strchr(optstr, ',')) != NULL) {
+                       optlen = ep - optstr;
+                       np = ep + 1;
+               } else {
+                       optlen = strlen(optstr);
+                       np = optstr + optlen;
+               }
+               if (strncmp(optstr, "toc", optlen) == 0) {
+                       *flagp |= SHOW_TOC;
+               }
+               else if (strncmp(optstr, "summary", optlen) == 0) {
+                       *flagp |= SHOW_SUMMARY;
+               }
+               else if (strncmp(optstr, "indices", optlen) == 0) {
+                       *flagp |= SHOW_INDICES;
+               }
+               else if (strncmp(optstr, "catalog", optlen) == 0) {
+                       *flagp |= SHOW_MCN;
+               }
+               else if (strncmp(optstr, "trackid", optlen) == 0) {
+                       *flagp |= SHOW_ISRC;
+               }
+               else if (strncmp(optstr, "sectors", optlen) == 0) {
+                       *flagp |= SHOW_STARTPOSITIONS;
+               }
+               else if (strncmp(optstr, "titles", optlen) == 0) {
+                       *flagp |= SHOW_TITLES;
+               }
+               else if (strncmp(optstr, "all", optlen) == 0) {
+                       *flagp |= SHOW_MAX;
+               }
+               else if (strncmp(optstr, "disable", optlen) == 0) {
+                       *flagp = 0;
+               }
+               else if (strncmp(optstr, "help", optlen) == 0) {
+                       verbose_usage();
+                       exit(NO_ERROR);
+               }
+               else {
+                       char    *endptr;
+                       unsigned arg = strtoul(optstr, &endptr, 10);
+                       if (optstr != endptr
+                               && arg <= SHOW_MAX) {
+                               *flagp |= arg;
+                               fprintf(stderr, "Warning: numerical parameters for -v are no more supported in the next releases!\n");
+                       }
+                       else {
+                               fprintf(stderr, "unknown option %s\n", optstr);
+                               verbose_usage();
+                               exit(SYNTAX_ERROR);
+                       }
+               }
+               optstr = np;
+       }
+       return 1;
+}
+
+
+int
+handle_paranoia_opts(char *optstr, long *flagp);
+
+int handle_paranoia_opts(char *optstr, long *flagp)
+{
+#ifdef USE_PARANOIA
+       char    *ep;
+       char    *np;
+       int     optlen;
+
+       while (*optstr) {
+               if ((ep = strchr(optstr, ',')) != NULL) {
+                       optlen = ep - optstr;
+                       np = ep + 1;
+               } else {
+                       optlen = strlen(optstr);
+                       np = optstr + optlen;
+               }
+               if (strncmp(optstr, "retries=", min(8,optlen)) == 0) {
+                       char *eqp = strchr(optstr, '=');
+                       int   rets;
+
+                       astoi(eqp+1, &rets);
+                       if (rets >= 0) {
+                               global.paranoia_parms.retries = rets;
+                       }
+               }
+               else if (strncmp(optstr, "overlap=", min(8, optlen)) == 0) {
+                       char *eqp = strchr(optstr, '=');
+                       int   rets;
+
+                       astoi(eqp+1, &rets);
+                       if (rets >= 0) {
+                               global.paranoia_parms.overlap = rets;
+                       }
+               }
+               else if (strncmp(optstr, "minoverlap=", min(11, optlen)) == 0) {
+                       char *eqp = strchr(optstr, '=');
+                       int   rets;
+
+                       astoi(eqp+1, &rets);
+                       if (rets >= 0) {
+                               global.paranoia_parms.mindynoverlap = rets;
+                       }
+               }
+               else if (strncmp(optstr, "maxoverlap=", min(11, optlen)) == 0) {
+                       char *eqp = strchr(optstr, '=');
+                       int   rets;
+
+                       astoi(eqp+1, &rets);
+                       if (rets >= 0) {
+                               global.paranoia_parms.maxdynoverlap = rets;
+                       }
+               }
+               else if (strncmp(optstr, "no-verify", optlen) == 0) {
+                       global.paranoia_parms.disable_extra_paranoia = 1;
+               }
+               else if (strncmp(optstr, "disable", optlen) == 0) {
+                       global.paranoia_parms.disable_paranoia = 1;
+               }
+               else if (strncmp(optstr, "help", optlen) == 0) {
+                       paranoia_usage();
+                       exit(NO_ERROR);
+               }
+               else {
+                       fprintf(stderr, "unknown option %s\n", optstr);
+                       paranoia_usage();
+                       exit(SYNTAX_ERROR);
+               }
+               optstr = np;
+       }
+       return 1;
+#else
+       fputs("lib paranoia support is not configured!\n", stderr);
+       return 0;
+#endif
+}
+
+
+/* and finally: the MAIN program */
+int main(int argc, char *argv[])
+{
+  long lSector_p1;
+  long sector_offset = 0;
+  unsigned long endtrack = 1;
+  double rectime = DURATION;
+  int cd_index = -1;
+  double int_part;
+  int littleendian = -1;
+  char *int_name;
+  static char *user_sound_device = "";
+  char * env_p;
+  int tracks_included;
+       int     moreargs;
+
+  int_name = DEF_INTERFACE;
+  audio_type = AUDIOTYPE;
+  save_args(argc, argv);
+
+  /* init global variables */
+  init_globals();
+{
+  int am_i_cdda2wav;
+  /* When being invoked as list_audio_tracks, just dump a list of
+     audio tracks. */
+  am_i_cdda2wav = !(strlen(argv[0]) >= sizeof("list_audio_tracks")-1
+       && !strcmp(argv[0]+strlen(argv[0])+1-sizeof("list_audio_tracks"),"list_audio_tracks"));
+  if (!am_i_cdda2wav) global.verbose = SHOW_JUSTAUDIOTRACKS;
+}
+  /* Control those set-id privileges... */
+  initsecurity();
+
+  env_p = getenv("CDDA_DEVICE");
+  if (env_p != NULL) {
+    global.dev_name = env_p;
+  }
+
+  env_p = getenv("CDDBP_SERVER");
+  if (env_p != NULL) {
+    global.cddbp_server = env_p;
+  }
+
+  env_p = getenv("CDDBP_PORT");
+  if (env_p != NULL) {
+    global.cddbp_port = env_p;
+  }
+
+{
+       int     cac;
+       char    *const*cav;
+
+       BOOL    version = FALSE;
+       BOOL    help = FALSE;
+       char    *channels = NULL;
+       int     irate = -1;
+       char    *divider = NULL;
+       char    *trackspec = NULL;
+       char    *duration = NULL;
+
+       char    *oendianess = NULL;
+       char    *cendianess = NULL;
+       int     cddbp = -1;
+       BOOL    stereo = FALSE;
+       BOOL    mono = FALSE;
+       BOOL    domax = FALSE;
+       BOOL    dump_rates = FALSE;
+       int     userverbose = -1;
+       long    paraopts = 0;
+
+       cac = argc;
+       cav = argv;
+       cac--;
+       cav++;
+       if (getargs(&cac, &cav, opts
+                       , &global.paranoia_selected
+                       , handle_paranoia_opts, &paraopts
+                       , &version
+                       , &help, &help
+
+                       , &global.no_file, &global.no_file
+                       , &dump_rates, &dump_rates
+                       , &bulk, &bulk, &bulk
+                       , &global.scsi_verbose, &global.scsi_verbose
+
+                       , &global.findminmax, &global.findminmax
+                       , &global.findmono, &global.findmono
+                       , &global.no_infofile, &global.no_infofile
+
+                       , &global.deemphasize, &global.deemphasize
+                       , &global.just_the_toc, &global.just_the_toc
+                       , &global.scsi_silent, &global.scsi_silent
+
+                       , &global.cddbp_server, &global.cddbp_port
+                       , &global.scanbus
+                       , &global.scandevs
+                       , &global.dev_name, &global.dev_name, &global.dev_name
+                       , &global.aux_name, &global.aux_name
+                       , &int_name, &int_name
+                       , &audio_type, &audio_type
+
+                       , &oendianess, &oendianess
+                       , &cendianess, &cendianess
+                       , &global.userspeed, &global.userspeed
+
+                       , &global.playback_rate, &global.playback_rate
+                       , &global.md5blocksize, &global.md5blocksize
+                       , &global.useroverlap, &global.useroverlap
+                       , &user_sound_device, &user_sound_device
+
+                       , &cddbp, &cddbp
+                       , &channels, &channels
+                       , &bits, &bits
+                       , &irate, &irate
+                       , &global.gui, &global.gui
+
+                       , &divider, &divider
+                       , &trackspec, &trackspec
+                       , &cd_index, &cd_index
+                       , &duration, &duration
+                       , &sector_offset, &sector_offset
+
+                       , &global.nsectors, &global.nsectors
+                       , handle_verbose_opts, &userverbose
+                       , handle_verbose_opts, &userverbose
+                       , &global.buffers, &global.buffers
+
+                       , &stereo, &stereo
+                       , &mono, &mono
+                       , &waitforsignal, &waitforsignal
+                       , &global.echo, &global.echo
+                       , &global.quiet, &global.quiet
+                       , &domax, &domax
+
+                       ) < 0) {
+               errmsgno(EX_BAD, "Bad Option: %s.\n", cav[0]);
+               fputs ("use 'icedax -help' to get more information.\n", stderr);
+               exit (SYNTAX_ERROR);
+       }
+       if (getfiles(&cac, &cav, opts) == 0)
+               /* No more file type arguments */;
+       moreargs = cav - argv;
+       if (version) {
+     fprintf(stderr, "icedax " CDRKIT_VERSION "\n");
+     exit(EXIT_SUCCESS);
+  }
+       if (help) {
+               usage();
+       }
+       if (!global.scanbus)
+               cdr_defaults(&global.dev_name, NULL, NULL, NULL); 
+       if (dump_rates) {       /* list available rates */
+               int ii;
+
+               fputs("\
+Available rates are:\n\
+Rate   Divider      Rate   Divider      Rate   Divider      Rate   Divider\n\
+"                      , stderr );
+               for (ii = 1; ii <= 44100 / 880 / 2; ii++) {
+                       long i2 = ii;
+                       fprintf(stderr, "%7.1f  %2ld         %7.1f  %2ld.5       ",
+                               44100.0/i2, i2, 44100.0/(i2+0.5), i2);
+                       i2 += 25;
+                       fprintf(stderr, "%7.1f  %2ld         %7.1f  %2ld.5\n",
+                               44100.0/i2, i2, 44100.0/(i2+0.5), i2);
+                       i2 -= 25;
+               }
+               exit(NO_ERROR);
+       }
+       if (channels) {
+               if (*channels == 's') {
+                       global.channels = 2;
+                       global.swapchannels = 1;
+               } else {
+                       global.channels = strtol(channels, NULL, 10);
+               }
+       }
+       if (irate >= 0) {
+               rate = irate;
+       }
+       if (divider) {
+               double divider_d;
+               divider_d = strtod(divider , NULL);
+               if (divider_d > 0.0) {
+                       rate = 44100.0 / divider_d;
+               } else {
+                       fputs("E option -divider requires a nonzero, positive argument.\nSee -dump-rates.", stderr);
+                       exit(SYNTAX_ERROR);
+               }
+       }
+       if (trackspec) {
+               char * endptr;
+               char * endptr2;
+               track = strtoul(trackspec, &endptr, 10 );
+               endtrack = strtoul(endptr, &endptr2, 10 );
+               if (endptr2 == endptr) {
+                       endtrack = track;
+               } else if (track == endtrack) {
+                       bulk = -1;
+               }
+       }
+       if (duration) {
+               char *end_ptr = NULL;
+               rectime = strtod(duration, &end_ptr );
+               if (*end_ptr == 'f') {
+                       rectime = rectime / 75.0;
+                       /* TODO: add an absolute end of recording. */
+#if    0
+               } else if (*end_ptr == 'F') {
+                       rectime = rectime / 75.0;
+#endif
+               } else if (*end_ptr != '\0') {
+                       rectime = -1.0;
+               }
+       }
+       if (oendianess) {
+               if (strcasecmp(oendianess, "little") == 0) {
+                       global.outputendianess = LITTLE;
+               } else if (strcasecmp(oendianess, "big") == 0) {
+                       global.outputendianess = BIG;
+               } else {
+                       usage2("wrong parameter '%s' for option -E", oendianess);
+               }
+       }
+       if (cendianess) {
+               if (strcasecmp(cendianess, "little") == 0) {
+                       littleendian = 1;
+               } else if (strcasecmp(cendianess, "big") == 0) {
+                       littleendian = 0;
+               } else if (strcasecmp(cendianess, "guess") == 0) {
+                       littleendian = -2;
+               } else {
+                       usage2("wrong parameter '%s' for option -C", cendianess);
+               }
+       }
+       if (cddbp >= 0) {
+               global.cddbp = 1 + cddbp;
+       }
+       if (stereo) {
+               global.channels = 2;
+       }
+       if (mono) {
+               global.channels = 1;
+               global.need_hostorder = 1;
+       }
+       if (global.echo) {
+#ifdef ECHO_TO_SOUNDCARD
+               if (global.playback_rate != 100) {
+                       RestrictPlaybackRate( global.playback_rate );
+               }
+                       global.need_hostorder = 1;
+#else
+               fprintf(stderr, "There is no sound support compiled into %s.\n",argv[0]);
+               global.echo = 0;
+#endif
+       }
+       if (global.quiet) {
+               global.verbose = 0;
+       }
+       if (domax) {
+               global.channels = 2; bits = 16; rate = 44100;
+       }
+       if (global.findminmax) {
+               global.need_hostorder = 1;
+       }
+       if (global.deemphasize) {
+               global.need_hostorder = 1;
+       }
+       if (global.just_the_toc) {
+               global.verbose = SHOW_MAX;
+               bulk = 1;
+       }
+       if (global.gui) {
+#ifdef Thomas_will_es
+               global.no_file = 1;
+               global.no_infofile = 1;
+               global.verbose = SHOW_MAX;
+#endif
+               global.no_cddbfile = 1;
+       }
+       if (global.no_file) {
+               global.no_infofile = 1;
+               global.no_cddbfile = 1;
+       }
+       if (global.no_infofile) {
+               global.no_cddbfile = 1;
+       }
+       if (global.md5blocksize) {
+#ifdef MD5_SIGNATURES
+               fputs("MD5 signatures are currently broken! Sorry\n", stderr);
+#else
+               fputs("MD5 signatures are currently broken! Sorry\n", stderr);
+#endif
+       }
+       if (user_sound_device) {
+#ifndef        ECHO_TO_SOUNDCARD
+               fputs("There is no sound support configured!\n", stderr);
+#endif
+       }
+       if (global.paranoia_selected) {
+               global.useroverlap = 0;
+       }
+       if (userverbose >= 0) {
+               global.verbose = userverbose;
+       }
+}
+
+  /* check all parameters */
+  if (global.buffers < 1) {
+    usage2("Incorrect buffer setting: %d", global.buffers);
+  }
+
+  if (global.nsectors < 1) {
+    usage2("Incorrect nsectors setting: %d", global.nsectors);
+  }
+
+  if (global.verbose < 0 || global.verbose > SHOW_MAX) {
+    usage2("Incorrect verbose level setting: %d",global.verbose);
+  }
+  if (global.verbose == 0) global.quiet = 1;
+
+  if ( rectime < 0.0 ) {
+    usage2("Incorrect recording time setting: %d.%02d",
+                       (int)rectime, (int)(rectime*100+0.5) % 100);
+  }
+
+  if ( global.channels != 1 && global.channels != 2 ) {
+    usage2("Incorrect channel setting: %d",global.channels);
+  }
+
+  if ( bits != 8 && bits != 12 && bits != 16 ) {
+    usage2("Incorrect bits_per_sample setting: %d",bits);
+  }
+
+  if ( rate < 827.0 || rate > 44100.0 ) {
+    usage2("Incorrect sample rate setting: %d.%02d",
+       (int)rate, ((int)rate*100) % 100);
+  }
+
+  int_part = (double)(long) (2*44100.0 / rate);
+  
+  if (2*44100.0 / rate - int_part >= 0.5 ) {
+      int_part += 1.0;
+      fprintf( stderr, "Nearest available sample rate is %d.%02d Hertz\n",
+             2*44100 / (int)int_part,
+             (2*4410000 / (int)int_part) % 100);
+  }
+  Halved = ((int) int_part) & 1;
+  rate = 2*44100.0 / int_part;
+  undersampling = (int) int_part / 2.0;
+  samples_to_do = undersampling;
+
+  if (!strcmp((char *)int_name,"generic_scsi"))
+      interface = GENERIC_SCSI;
+  else if (!strcmp((char *)int_name,"cooked_ioctl"))
+      interface = COOKED_IOCTL;
+  else  {
+    usage2("Incorrect interface setting: %s",int_name);
+  }
+
+  /* check * init audio file */
+  if (!strncmp(audio_type,"wav",3)) {
+    global.audio_out = &wavsound;
+  } else if (!strncmp(audio_type, "sun", 3) || !strncmp(audio_type, "au", 2)) {
+    /* Enhanced compatibility */
+    audio_type = "au";
+    global.audio_out = &sunsound;
+  } else if (!strncmp(audio_type, "cdr", 3) || 
+             !strncmp(audio_type, "raw", 3)) {
+    global.audio_out = &rawsound;
+  } else if (!strncmp(audio_type, "aiff", 4)) {
+    global.audio_out = &aiffsound;
+  } else if (!strncmp(audio_type, "aifc", 4)) {
+    global.audio_out = &aifcsound;
+#ifdef USE_LAME
+  } else if (!strncmp(audio_type, "mp3", 3)) {
+    global.audio_out = &mp3sound;
+    if (!global.quiet) {
+       unsigned char Lame_version[20];
+
+       fetch_lame_version(Lame_version);
+       fprintf(stderr, "Using LAME version %s.\n", Lame_version);
+    }
+    if (bits < 9) {
+       bits = 16;
+       fprintf(stderr, "Warning: sample size forced to 16 bit for MP3 format.\n");
+    }
+#endif /* USE_LAME */
+  } else {
+    usage2("Incorrect audio type setting: %3s", audio_type);
+  }
+
+  if (bulk == -1) bulk = 0;
+
+  global.need_big_endian = global.audio_out->need_big_endian;
+  if (global.outputendianess != NONE)
+    global.need_big_endian = global.outputendianess == BIG;
+
+  if (global.no_file) global.fname_base[0] = '\0';
+
+  if (!bulk) {
+    strcat(global.fname_base, ".");
+    strcat(global.fname_base, audio_type);
+  }
+
+  /* If we need to calculate with samples or write them to a soundcard,
+   * we need a conversion to host byte order.
+   */ 
+  if (global.channels != 2 
+      || bits != 16
+      || rate != 44100)
+       global.need_hostorder = 1;
+
+  /* Bad hack!!
+   * Remove for release 2.0
+   * this is a bug compatibility feature.
+   */
+  if (global.gui && global.verbose == SHOW_TOC)
+       global.verbose |= SHOW_STARTPOSITIONS | SHOW_SUMMARY | SHOW_TITLES;
+
+  /*
+   * all options processed.
+   * Now a file name per track may follow 
+   */
+  argc2 = argc3 = argc - moreargs;
+  argv2 = argv + moreargs;
+  if ( moreargs < argc ) {
+    if (!strcmp(argv[moreargs],"-")) {
+#ifdef NEED_O_BINARY
+      setmode(fileno(stdout), O_BINARY);
+#endif
+      global.audio = dup (fileno(stdout));
+      strncpy( global.fname_base, "standard_output", sizeof(global.fname_base) );
+      global.fname_base[sizeof(global.fname_base)-1]=0;
+    } else if (!is_fifo(argv[moreargs])) {
+       /* we do have at least one argument */
+       global.multiname = 1;
+    }
+  }
+
+#define SETSIGHAND(PROC, SIG, SIGNAME) if (signal(SIG, PROC) == SIG_ERR) \
+       { fprintf(stderr, "cannot set signal %s handler\n", SIGNAME); exit(SETSIG_ERROR); }
+    SETSIGHAND(exit_wrapper, SIGINT, "SIGINT")
+    SETSIGHAND(exit_wrapper, SIGQUIT, "SIGQUIT")
+    SETSIGHAND(exit_wrapper, SIGTERM, "SIGTERM")
+    SETSIGHAND(exit_wrapper, SIGHUP, "SIGHUP")
+
+    SETSIGHAND(set_nonforked, SIGPIPE, "SIGPIPE")
+
+  /* setup interface and open cdrom device */
+  /* request sychronization facilities and shared memory */
+  SetupInterface( );
+
+  /* use global.useroverlap to set our overlap */
+  if (global.useroverlap != -1)
+       global.overlap = global.useroverlap;
+
+  /* check for more valid option combinations */
+
+  if (global.nsectors < 1+global.overlap) {
+       fprintf( stderr, "Warning: Setting #nsectors to minimum of %d, due to jitter correction!\n", global.overlap+1);
+         global.nsectors = global.overlap+1;
+  }
+
+  if (global.overlap > 0 && global.buffers < 2) {
+       fprintf( stderr, "Warning: Setting #buffers to minimum of 2, due to jitter correction!\n");
+         global.buffers = 2;
+  }
+
+    /* Value of 'nsectors' must be defined here */
+
+    global.shmsize = 0;
+#ifdef USE_PARANOIA
+    while (global.shmsize < sizeof (struct paranoia_statistics))
+               global.shmsize += global.pagesize;
+#endif
+    global.shmsize += 10*global.pagesize;      /* XXX Der Speicherfehler ist nicht in libparanoia sondern in cdda2wav :-( */
+    global.shmsize += HEADER_SIZE + ENTRY_SIZE_PAGE_AL * global.buffers;
+
+#if    defined (HAVE_FORK_AND_SHAREDMEM)
+       /*
+        * The (void *) cast is to avoid a GCC warning like:
+        * warning: dereferencing type-punned pointer will break strict-aliasing rules
+        * which does not apply to this code. (void *) introduces a compatible
+        * intermediate type in the cast list.
+        */
+    he_fill_buffer = request_shm_sem(global.shmsize, (unsigned char **)(void *)&he_fill_buffer);
+    if (he_fill_buffer == NULL) {
+       fprintf( stderr, "no shared memory available!\n");
+       exit(SHMMEM_ERROR);
+    }
+#else /* do not have fork() and shared memory */
+    he_fill_buffer = malloc(global.shmsize);
+    if (he_fill_buffer == NULL) {
+       fprintf( stderr, "no buffer memory available!\n");
+       exit(NOMEM_ERROR);
+    }
+#endif
+#ifdef USE_PARANOIA
+    {
+       int     i = 0;
+
+       para_stat = (struct paranoia_statistics *)he_fill_buffer;
+       while (i < sizeof (struct paranoia_statistics)) {
+                       i += global.pagesize;
+                       he_fill_buffer += global.pagesize;
+                       global.shmsize -= global.pagesize;
+       }
+    }
+#endif
+
+    if (global.verbose != 0)
+        fprintf(stderr,
+                "%u bytes buffer memory requested, %d buffers, %d sectors\n",
+                global.shmsize, global.buffers, global.nsectors);
+
+    /* initialize pointers into shared memory segment */
+    last_buffer = he_fill_buffer + 1;
+    total_segments_read = (unsigned long *) (last_buffer + 1);
+    total_segments_written = total_segments_read + 1;
+    child_waits = (int *) (total_segments_written + 1);
+    parent_waits = child_waits + 1;
+    in_lendian = parent_waits + 1;
+    eorecording = in_lendian + 1;
+    *total_segments_read = *total_segments_written = 0;
+    nSamplesToDo = (unsigned long *)(eorecording + 1);
+    *eorecording = 0;
+    *in_lendian = global.in_lendian;
+
+    set_total_buffers(global.buffers, sem_id);
+
+
+#if defined(HAVE_SEMGET) && defined(USE_SEMAPHORES)
+  atexit ( free_sem );
+#endif
+
+  /*
+   * set input endian default
+   */
+  if (littleendian != -1)
+    *in_lendian = littleendian;
+
+  /* get table of contents */
+  cdtracks = ReadToc();
+  if (cdtracks == 0) {
+    fprintf(stderr, "No track in table of contents! Aborting...\n");
+    exit(MEDIA_ERROR);
+  }
+
+  calc_cddb_id();
+  calc_cdindex_id();
+
+#if    1
+  Check_Toc();
+#endif
+
+  if (ReadTocText != NULL && FirstAudioTrack () != -1) {
+       ReadTocText(get_scsi_p());
+       handle_cdtext();
+  }
+  if ( global.verbose == SHOW_JUSTAUDIOTRACKS ) {
+    unsigned int z;
+
+    for (z = 0; z < cdtracks; z++)
+       if (Get_Datatrack(z) == 0)
+         printf("%02d\t%06ld\n", Get_Tracknumber(z), Get_AudioStartSector(z));
+    exit(NO_ERROR);
+  }
+
+  if ( global.verbose != 0 ) {
+    fputs( "#icedax version ", stderr );
+    fputs( VERSION, stderr );
+#if defined USE_POSIX_PRIORITY_SCHEDULING || defined HAVE_SYS_PRIOCNTL_H
+    fputs( ", real time sched.", stderr );
+#endif
+#if defined ECHO_TO_SOUNDCARD
+    fputs( ", soundcard", stderr );
+#endif
+#if defined USE_PARANOIA
+    fputs( ", libparanoia", stderr );
+#endif
+    fputs( " support\n", stderr );
+  }
+
+  FixupTOC(cdtracks + 1);
+
+#if    0
+  if (!global.paranoia_selected) {
+    fprintf(stderr, "NICE\n");
+    /* try to get some extra kicks */
+    priv_on();
+    needroot(0);
+#if defined HAVE_SETPRIORITY
+    setpriority(PRIO_PROCESS, 0, -20);
+#else
+# if defined(HAVE_NICE) && (HAVE_NICE == 1)
+    nice(-20);
+# endif
+#endif
+    priv_off();
+    dontneedroot();
+  }
+#endif
+
+  /* switch cdrom to audio mode */
+  EnableCdda (get_scsi_p(), 1, CD_FRAMESIZE_RAW);
+
+  atexit ( CloseAll );
+
+  DisplayToc();
+  if ( FirstAudioTrack () == -1 ) {
+    if (no_disguised_audiotracks()) {
+      FatalError ( "This disk has no audio tracks\n" );
+    }
+  }
+
+  Read_MCN_ISRC();
+
+  /* check if start track is in range */
+  if ( track < 1 || track > cdtracks ) {
+    usage2("Incorrect start track setting: %d",track);
+  }
+
+  /* check if end track is in range */
+  if ( endtrack < track || endtrack > cdtracks ) {
+    usage2("Incorrect end track setting: %ld",endtrack);
+  }
+
+  do {
+    lSector = Get_AudioStartSector ( track );
+    lSector_p1 = Get_EndSector ( track ) + 1;
+
+    if ( lSector < 0 ) {
+      if ( bulk == 0 ) {
+        FatalError ( "Track %d not found\n", track );
+      } else {
+        fprintf(stderr, "Skipping data track %d...\n", track);
+       if (endtrack == track) endtrack++;
+        track++;
+      }
+    }
+  } while (bulk != 0 && track <= cdtracks && lSector < 0);
+
+  if ((global.illleadout_cd == 0 || global.reads_illleadout != 0) && cd_index != -1) {
+    if (global.verbose && !global.quiet) {
+      global.verbose |= SHOW_INDICES;
+    }
+    sector_offset += ScanIndices( track, cd_index, bulk );
+  } else {
+    cd_index = 1;
+    if (global.deemphasize || (global.verbose & SHOW_INDICES)) {
+      ScanIndices( track, cd_index, bulk );
+    }
+  }
+
+  lSector += sector_offset;
+  /* check against end sector of track */
+  if ( lSector >= lSector_p1 ) {
+    fprintf(stderr, "W Sector offset %lu exceeds track size (ignored)\n", sector_offset );
+    lSector -= sector_offset;
+  }
+
+  if ( lSector < 0L ) {
+    fputs( "Negative start sector! Set to zero.\n", stderr );
+    lSector = 0L;
+  }
+
+  lSector_p2 = Get_LastSectorOnCd( track );
+  if (bulk == 1 && track == endtrack && rectime == 0.0)
+     rectime = 99999.0;
+  if ( rectime == 0.0 ) {
+    /* set time to track time */
+    *nSamplesToDo = (lSector_p1 - lSector) * CD_FRAMESAMPLES;
+    rectime = (lSector_p1 - lSector) / 75.0;
+    if (CheckTrackrange( track, endtrack) == 1) {
+      lSector_p2 = Get_EndSector ( endtrack ) + 1;
+
+      if (lSector_p2 >= 0) {
+        rectime = (lSector_p2 - lSector) / 75.0;
+        *nSamplesToDo = (long)(rectime*44100.0 + 0.5);
+      } else {
+        fputs( "End track is no valid audio track (ignored)\n", stderr );
+      }
+    } else {
+      fputs( "Track range does not consist of audio tracks only (ignored)\n", stderr );
+    }
+  } else {
+    /* Prepare the maximum recording duration.
+     * It is defined as the biggest amount of
+     * adjacent audio sectors beginning with the
+     * specified track/index/offset. */
+
+    if ( rectime > (lSector_p2 - lSector) / 75.0 ) {
+      rectime = (lSector_p2 - lSector) / 75.0;
+      lSector_p1 = lSector_p2;
+    }
+
+    /* calculate # of samples to read */
+    *nSamplesToDo = (long)(rectime*44100.0 + 0.5);
+  }
+
+  global.OutSampleSize = (1+bits/12);
+  if (*nSamplesToDo/undersampling == 0L) {
+      usage2("Time interval is too short. Choose a duration greater than %d.%02d secs!", 
+              undersampling/44100, (int)(undersampling/44100) % 100);
+  }
+  if ( moreargs < argc ) {
+    if (!strcmp(argv[moreargs],"-") || is_fifo(argv[moreargs])) {
+      /*
+       * pipe mode
+       */
+      if (bulk == 1) {
+        fprintf(stderr, "W Bulk mode is disabled while outputting to a %spipe\n",
+               is_fifo(argv[moreargs]) ? "named " : "");
+        bulk = 0;
+      }
+      global.no_cddbfile = 1;
+    }
+  }
+  if (global.no_infofile == 0) {
+    global.no_infofile = 1;
+    if (global.channels == 1 || bits != 16 || rate != 44100) {
+      fprintf(stderr, "W Sample conversions disable generation of info files!\n");
+    } else if (waitforsignal == 1) {
+      fprintf(stderr, "W Option -w 'wait for signal' disables generation of info files!\n");
+    } else if (sector_offset != 0) {
+      fprintf(stderr, "W Using an start offset (option -o) disables generation of info files!\n");
+    } else if (!bulk &&
+      !((lSector == Get_AudioStartSector(track)) &&
+        ((long)(lSector + rectime*75.0 + 0.5) == Get_EndSector(track) + 1))) {
+      fprintf(stderr, "W Duration is not set for complete tracks (option -d), this disables generation\n  of info files!\n");
+    } else {
+      global.no_infofile = 0;
+    }
+  }
+
+  SamplesToWrite = *nSamplesToDo*2/(int)int_part;
+
+  {
+       int first = FirstAudioTrack();
+       tracks_included = Get_Track(
+             (unsigned) (lSector + *nSamplesToDo/CD_FRAMESAMPLES -1))
+                                    - max((int)track,first) +1;
+  }
+
+  if (global.multiname != 0 && moreargs + tracks_included > argc) {
+       global.multiname = 0;
+  }
+
+  if ( !waitforsignal ) {
+
+#ifdef INFOFILES
+      if (!global.no_infofile) {
+       int i;
+
+       for (i = track; i < (int)track + tracks_included; i++) {
+               unsigned minsec, maxsec;
+               char *tmp_fname;
+
+               /* build next filename */
+
+               tmp_fname = get_next_name();
+               if (tmp_fname != NULL)
+                 strncpy( global.fname_base, tmp_fname, sizeof(global.fname_base)-8 );
+               global.fname_base[sizeof(global.fname_base)-1]=0;
+               minsec = max(lSector, Get_AudioStartSector(i));
+               maxsec = min(lSector + rectime*75.0 + 0.5, 1+Get_EndSector(i));
+               if ((int)minsec == Get_AudioStartSector(i) &&
+                   (int)maxsec == 1+Get_EndSector(i)) {
+                       write_info_file(global.fname_base,i,(maxsec-minsec)*CD_FRAMESAMPLES, bulk && global.multiname == 0);
+               } else {
+                       fprintf(stderr,
+                                "Partial length copy for track %d, no info file will be generated for this track!\n", i);
+               }
+               if (!bulk) break;
+       }
+       reset_name_iterator();
+      }
+#endif
+
+  }
+
+  if (global.just_the_toc) exit(NO_ERROR);
+
+#ifdef  ECHO_TO_SOUNDCARD
+  if (user_sound_device[0] != '\0') {
+      set_snd_device(user_sound_device);
+  }
+  init_soundcard(rate, bits);
+#endif /* ECHO_TO_SOUNDCARD */
+
+  if (global.userspeed > -1)
+     global.speed = global.userspeed;
+
+  if (global.speed != 0 && SelectSpeed != NULL) {
+     SelectSpeed(get_scsi_p(), global.speed);
+  }
+
+  current_track = track;
+
+  if ( !global.no_file ) {
+    {
+      char *myfname;
+
+      myfname = get_next_name();
+
+      if (myfname != NULL) {
+        strncpy( global.fname_base, myfname, sizeof(global.fname_base)-8 );
+        global.fname_base[sizeof(global.fname_base)-1]=0;
+      }
+    }
+
+    /* strip audio_type extension */
+    {
+      char *cp = global.fname_base;
+
+      cp = strrchr(cp, '.');
+      if (cp == NULL) {
+       cp = global.fname_base + strlen(global.fname_base);
+      }
+      *cp = '\0';
+    }
+    if (bulk && global.multiname == 0) {
+      sprintf(fname, "%s_%02u.%s",global.fname_base,current_track,audio_type);
+    } else {
+      sprintf(fname, "%s.%s",global.fname_base,audio_type);
+    }
+
+    OpenAudio( fname, rate, bits, global.channels, 
+             (unsigned)(SamplesToWrite*global.OutSampleSize*global.channels),
+               global.audio_out);
+  }
+
+  global.Remainder = (75 % global.nsectors)+1;
+
+  global.sh_bits = 16 - bits;          /* shift counter */
+
+  global.iloop = *nSamplesToDo;
+  if (Halved && (global.iloop&1))
+      global.iloop += 2;
+
+  BeginAtSample = lSector * CD_FRAMESAMPLES;
+
+#if    1
+       if ( (global.verbose & SHOW_SUMMARY) && !global.just_the_toc &&
+            (global.reads_illleadout == 0 ||
+             lSector+*nSamplesToDo/CD_FRAMESAMPLES
+              <= (unsigned) Get_AudioStartSector(cdtracks-1))) {
+
+               fprintf(stderr, "samplefile size will be %lu bytes.\n",
+                       global.audio_out->GetHdrSize() +
+                       global.audio_out->InSizeToOutSize(SamplesToWrite*global.OutSampleSize*global.channels)  ); 
+               fprintf (stderr, "recording %d.%04d seconds %s with %d bits @ %5d.%01d Hz"
+                       ,(int)rectime , (int)(rectime * 10000) % 10000,
+                       global.channels == 1 ? "mono":"stereo", bits, (int)rate, (int)(rate*10)%10);
+               if (!global.no_file && *global.fname_base)
+                       fprintf(stderr, " ->'%s'...", global.fname_base );
+               fputs("\n", stderr);
+       }
+#endif
+
+#if defined(HAVE_SEMGET) && defined(USE_SEMAPHORES)
+#else
+       init_pipes();
+#endif
+
+#ifdef USE_PARANOIA
+       if (global.paranoia_selected) {
+               long paranoia_mode;
+
+               global.cdp = paranoia_init(get_scsi_p(), global.nsectors);
+
+               if (global.paranoia_parms.overlap >= 0) {
+                       int     overlap = global.paranoia_parms.overlap;
+
+                       if (overlap > global.nsectors - 1) 
+                               overlap = global.nsectors - 1;
+                       paranoia_overlapset(global.cdp, overlap);
+               }
+               /*
+                * Default to a  minimum of dynamic overlapping == 0.5 sectors.
+                * If we don't do this, we get the default from libparanoia
+                * which is approx. 0.1.
+                */
+               if (global.paranoia_parms.mindynoverlap < 0)
+                       paranoia_dynoverlapset(global.cdp, CD_FRAMEWORDS/2, -1);
+               paranoia_dynoverlapset(global.cdp,
+                       global.paranoia_parms.mindynoverlap * CD_FRAMEWORDS,
+                       global.paranoia_parms.maxdynoverlap * CD_FRAMEWORDS);
+
+               paranoia_mode = PARANOIA_MODE_FULL ^ PARANOIA_MODE_NEVERSKIP;
+
+               if (global.paranoia_parms.disable_paranoia) {
+                       paranoia_mode = PARANOIA_MODE_DISABLE;
+               }
+               if (global.paranoia_parms.disable_extra_paranoia) {
+                       paranoia_mode |= PARANOIA_MODE_OVERLAP;
+                       paranoia_mode &= ~PARANOIA_MODE_VERIFY;
+               }
+               /* not yet implemented */
+               if (global.paranoia_parms.disable_scratch_detect) {
+                       paranoia_mode &= ~(PARANOIA_MODE_SCRATCH|PARANOIA_MODE_REPAIR);
+               }
+               /* not yet implemented */
+               if (global.paranoia_parms.disable_scratch_repair) {
+                       paranoia_mode &= ~PARANOIA_MODE_REPAIR;
+               }
+
+               paranoia_modeset(global.cdp, paranoia_mode);
+               if (global.verbose)
+                       fprintf(stderr, "using lib paranoia for reading.\n");
+               paranoia_seek(global.cdp, lSector, SEEK_SET);
+               paranoia_reset();
+       }
+#endif
+#if defined(HAVE_FORK_AND_SHAREDMEM)
+
+       /* Everything is set up. Now fork and let one process read cdda sectors
+          and let the other one store them in a wav file */
+
+       /* forking */
+       child_pid = fork();
+       if (child_pid > 0 && global.gui > 0 && global.verbose > 0)
+               fprintf( stderr, "child pid is %d\n", child_pid);
+
+       /*********************** fork **************************************/
+       if (child_pid == 0) {
+               /* child WRITER section */
+
+#ifdef HAVE_AREAS
+               /* Under BeOS a fork() with shared memory does not work as
+                * it does under System V Rel. 4. The mapping of the child
+                * works with copy on write semantics, so changes do not propagate
+                * back and forth. The existing mapping has to be deleted
+                * and replaced by an clone without copy on write semantics.
+                * This is done with clone_area(...,B_CLONE_ADDRESS,...).
+                * Thanks to file support.c from the postgreSQL project.
+                */
+               area_info inf;
+               int32 cook = 0;
+               /* iterate over all mappings to find our shared memory mapping. */
+               while (get_next_area_info(0, &cook, &inf) == B_OK)
+               {
+                       /* check the name of the mapping. */
+                       if (!strcmp(inf.name, AREA_NAME))
+                       {
+                               void *area_address;
+                               area_id area_parent;
+
+                               /* kill the cow mapping. */
+                               area_address = inf.address;
+                               if (B_OK != delete_area(inf.area))
+                               {
+                                       fprintf(stderr, "delete_area: no valid area.\n");
+                                       exit(SHMMEM_ERROR);
+                               }
+                               /* get the parent mapping. */
+                               area_parent = find_area(inf.name);
+                               if (area_parent == B_NAME_NOT_FOUND)
+                               {
+                                       fprintf(stderr, "find_area: no such area name.\n");
+                                       exit(SHMMEM_ERROR);
+                               }
+                               /* clone the parent mapping without cow. */
+                               if (B_OK > clone_area("shm_child", &area_address, B_CLONE_ADDRESS,
+                                       B_READ_AREA | B_WRITE_AREA, area_parent))
+                               {
+                                       fprintf(stderr,"clone_area failed\n");
+                                       exit(SHMMEM_ERROR);
+                               }
+                       }
+               }
+#endif
+#ifdef __EMX__
+               if (DosGetSharedMem(he_fill_buffer, 3)) {
+                       comerr("DosGetSharedMem() failed.\n");
+               }
+#endif
+               global.have_forked = 1;
+               forked_write();
+#ifdef __EMX__
+               DosFreeMem(he_fill_buffer);
+               _exit(NO_ERROR);
+               /* NOTREACHED */
+#endif
+               exit_wrapper(NO_ERROR);
+               /* NOTREACHED */
+       } else if (child_pid > 0) {
+               /* parent READER section */
+    
+               global.have_forked = 1;
+               switch_to_realtime_priority();
+
+               forked_read();
+#ifdef HAVE_AREAS
+               {
+                       area_id aid;
+                       aid = find_area(AREA_NAME);
+                       if (aid < B_OK) {
+                               comerrno(aid, "find_area() failed.\n");
+                       }
+                       delete_area(aid);
+               }
+#endif
+#ifdef __EMX__
+               DosFreeMem(he_fill_buffer);
+#endif
+               exit_wrapper(NO_ERROR);
+               /* NOTREACHED */
+       } else
+               perror("fork error.");
+
+#endif
+       /* version without fork */
+       {
+               global.have_forked = 0;
+#if    0
+               if (!global.paranoia_selected) {
+                       fprintf(stderr, "REAL\n");
+                       switch_to_realtime_priority();
+               }
+#endif
+               fprintf(stderr, "a nonforking version is running...\n");
+               nonforked_loop();
+               exit_wrapper(NO_ERROR);
+               /* NOTREACHED */
+       }
+#ifdef USE_PARANOIA
+       if (global.paranoia_selected)
+               paranoia_free(global.cdp);
+#endif
+
+       return 0;
+}
diff --git a/icedax/icedax.h b/icedax/icedax.h
new file mode 100644 (file)
index 0000000..9795aac
--- /dev/null
@@ -0,0 +1,150 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)icedax.h        1.4 00/02/13 Copyright 1998,1999,2000 Heiko Eissfeldt */
+/***
+ * CopyPolicy: GNU Public License 2 applies
+ * Copyright (C) by Heiko Eissfeldt
+ *
+ * prototypes from cdda2wav.c
+ */
+
+#ifdef max
+#undef max
+#endif
+#ifdef min
+#undef min
+#endif
+#define max(a,b) ((a) > (b) ? (a) : (b))
+#define min(a,b) ((a) < (b) ? (a) : (b))
+
+
+/* verbose levels */
+#define SHOW_TOC       1
+#define SHOW_SUMMARY   2
+#define SHOW_INDICES   4
+#define SHOW_MCN       8
+#define SHOW_ISRC      16
+#define SHOW_STARTPOSITIONS    32
+#define SHOW_TITLES    64
+#define SHOW_JUSTAUDIOTRACKS   128
+#define SHOW_MAX       255
+
+/* Endianess */
+#define GUESS (-2)
+#define NONE (-1)
+#define LITTLE 0
+#define BIG 1
+
+void FatalError(const char *szMessage, ...);
+void AnalyzeQchannel(unsigned frame);
+long SamplesNeeded(long amount, long undersampling);
+unsigned int get_current_track(void);
+
+#if defined (sun) && !defined(SVR4)
+#define  atexit(f) on_exit(f, 0)
+#endif
+
+#ifndef        _LINUX_CDROM_H
+#define        _LINUX_CDROM_H
+
+/*
+ * some fix numbers
+ */
+#define CD_MINS             74 /* max. minutes per CD, not really a limit */
+#define CD_SECS             60 /* seconds per minute */
+#define CD_FRAMES           75 /* frames per second */
+
+#define CD_SYNC_SIZE        12 /* 12 sync bytes per raw data frame, not transfered by the drive */
+#define CD_HEAD_SIZE         4 /* header (address) bytes per raw data frame */
+#define CD_SUBHEAD_SIZE      8 /* subheader bytes per raw XA data frame */
+#define CD_XA_HEAD        (CD_HEAD_SIZE+CD_SUBHEAD_SIZE) /* "before data" part of raw XA frame */
+#define CD_XA_SYNC_HEAD   (CD_SYNC_SIZE+CD_XA_HEAD)/* sync bytes + header of XA frame */
+
+#define CD_FRAMESIZE      2048 /* bytes per frame, "cooked" mode */
+#define CD_FRAMESIZE_RAW  2352 /* bytes per frame, "raw" mode */
+/* most drives don't deliver everything: */
+#define CD_FRAMESIZE_RAW1 (CD_FRAMESIZE_RAW-CD_SYNC_SIZE) /* 2340 */
+#define CD_FRAMESIZE_RAW0 (CD_FRAMESIZE_RAW-CD_SYNC_SIZE-CD_HEAD_SIZE) /* 2336 */
+/* Optics drive also has a 'read all' mode: */
+#define CD_FRAMESIZE_RAWER 2646 /* bytes per frame */
+
+#define CD_EDC_SIZE         4 /* bytes EDC per most raw data frame types */
+#define CD_ZERO_SIZE        8 /* bytes zero per yellow book mode 1 frame */
+#define CD_ECC_SIZE       276 /* bytes ECC per most raw data frame types */
+#define CD_XA_TAIL        (CD_EDC_SIZE+CD_ECC_SIZE) /* "after data" part of raw XA frame */
+
+#define CD_FRAMESIZE_SUB    96 /* subchannel data "frame" size */
+#define CD_MSF_OFFSET      150 /* MSF numbering offset of first frame */
+
+#define CD_CHUNK_SIZE       24 /* lowest-level "data bytes piece" */
+#define CD_NUM_OF_CHUNKS    98 /* chunks per frame */
+
+#define CD_FRAMESIZE_XA CD_FRAMESIZE_RAW1 /* obsolete name */
+#define CD_BLOCK_OFFSET    CD_MSF_OFFSET /* obsolete name */
+
+/*
+ * the raw frame layout:
+ *
+ * - audio (red):                  | audio_sample_bytes |
+ *                                 |        2352        |
+ *
+ * - data (yellow, mode1):         | sync - head - data - EDC - zero - ECC |
+ *                                 |  12  -   4  - 2048 -  4  -   8  - 276 |
+ *
+ * - data (yellow, mode2):         | sync - head - data |
+ *                                 |  12  -   4  - 2336 |
+ *
+ * - XA data (green, mode2 form1): | sync - head - sub - data - EDC - ECC |
+ *                                 |  12  -   4  -  8  - 2048 -  4  - 276 |
+ *
+ * - XA data (green, mode2 form2): | sync - head - sub - data - EDC |
+ *                                 |  12  -   4  -  8  - 2324 -  4  |
+ */
+
+
+/*
+ * CD-ROM address types (cdrom_tocentry.cdte_format)
+ */
+#if    !defined CDROM_LBA
+#define        CDROM_LBA 0x01 /* "logical block": first frame is #0 */
+#define        CDROM_MSF 0x02 /* "minute-second-frame": binary, not bcd here! */
+#endif
+/*
+ * bit to tell whether track is data or audio (cdrom_tocentry.cdte_ctrl)
+ */
+#define        CDROM_DATA_TRACK        0x04
+
+/*
+ * The leadout track is always 0xAA, regardless of # of tracks on disc
+ */
+#define        CDROM_LEADOUT   0xAA
+
+/*
+ * audio states (from SCSI-2, but seen with other drives, too)
+ */
+#define        CDROM_AUDIO_INVALID     0x00    /* audio status not supported */
+#define        CDROM_AUDIO_PLAY        0x11    /* audio play operation in progress */
+#define        CDROM_AUDIO_PAUSED      0x12    /* audio play operation paused */
+#define        CDROM_AUDIO_COMPLETED   0x13    /* audio play successfully completed */
+#define        CDROM_AUDIO_ERROR       0x14    /* audio play stopped due to error */
+#define        CDROM_AUDIO_NO_STATUS   0x15    /* no current audio status to return */
+
+#ifdef FIVETWELVE
+#define        CDROM_MODE1_SIZE        512
+#else
+#define        CDROM_MODE1_SIZE        2048
+#endif /*FIVETWELVE*/
+#define        CDROM_MODE2_SIZE        2336
+
+#endif
+
diff --git a/icedax/inf2cdtext.pl b/icedax/inf2cdtext.pl
new file mode 100755 (executable)
index 0000000..483713f
--- /dev/null
@@ -0,0 +1,241 @@
+#!/usr/bin/perl -w
+# Copyright 2002 by Heiko Eißfeldt (Eissfeldt)
+use strict;
+use integer;
+
+# read all .inf files and generate the binary cdtext block
+# for cdrecord.
+
+my @results;
+
+sub fill_packet
+{
+       my $ID = shift;
+       my $track = shift;
+       my $seq_nr = shift;
+       my $charpos = shift;
+       my $text = shift;
+       my $todo = shift;
+
+       return if (!defined($$text));
+
+       my @packet = ();
+       push @packet, chr($ID); # track title, performer, ...
+       push @packet, chr($$track);
+       push @packet, chr($$seq_nr);
+       $$charpos = 15 if ($$charpos > 15);
+       push @packet, chr($$charpos);
+
+       my $cp = 0;
+       my $tracks_inp = 0;
+       while (length($$text) + 1 < 12 - $cp) {
+               push @packet, split(//, $$text);
+               push @packet, chr(0);
+               $cp += length($$text) + 1;
+               $$charpos = 0;
+               $tracks_inp++;
+
+               $$text = shift @$todo;
+               if ($#$todo < 1 && (!defined($$text) || $$text eq "") ) {
+                       push @packet, (chr(0)) x (12 - $cp);
+                       $$seq_nr++;
+                       print_packet(@packet);
+                       return;
+               }
+               $$text = "" if (!defined($$text));
+               $$track++;
+       }
+
+       # packet gets full
+       my $left = 12 - $cp;
+       if ($left > length($$text)) {
+               # title fits into packet
+               push @packet, split(//, $$text);
+               push @packet, chr(0);
+               $tracks_inp++;
+               print_packet(@packet);
+
+               $$charpos = 0;
+               $$text = shift @$todo;
+               unless ((!defined($$text) || $$text eq "") && $#$todo < 1) { $$track++; }
+               $$seq_nr++;
+       } else {
+               # print current packet and more if more entries are present
+               push @packet, split(//, substr($$text, 0, $left));
+               print_packet(@packet);
+
+               $$text = substr($$text, $left);
+               $$charpos += $left;
+               $$seq_nr++;
+       }
+}
+
+my @crctab =(
+    0x0000,  0x1021,  0x2042,  0x3063,  0x4084,  0x50a5,  0x60c6,  0x70e7,
+    0x8108,  0x9129,  0xa14a,  0xb16b,  0xc18c,  0xd1ad,  0xe1ce,  0xf1ef,
+    0x1231,  0x0210,  0x3273,  0x2252,  0x52b5,  0x4294,  0x72f7,  0x62d6,
+    0x9339,  0x8318,  0xb37b,  0xa35a,  0xd3bd,  0xc39c,  0xf3ff,  0xe3de,
+    0x2462,  0x3443,  0x0420,  0x1401,  0x64e6,  0x74c7,  0x44a4,  0x5485,
+    0xa56a,  0xb54b,  0x8528,  0x9509,  0xe5ee,  0xf5cf,  0xc5ac,  0xd58d,
+    0x3653,  0x2672,  0x1611,  0x0630,  0x76d7,  0x66f6,  0x5695,  0x46b4,
+    0xb75b,  0xa77a,  0x9719,  0x8738,  0xf7df,  0xe7fe,  0xd79d,  0xc7bc,
+    0x48c4,  0x58e5,  0x6886,  0x78a7,  0x0840,  0x1861,  0x2802,  0x3823,
+    0xc9cc,  0xd9ed,  0xe98e,  0xf9af,  0x8948,  0x9969,  0xa90a,  0xb92b,
+    0x5af5,  0x4ad4,  0x7ab7,  0x6a96,  0x1a71,  0x0a50,  0x3a33,  0x2a12,
+    0xdbfd,  0xcbdc,  0xfbbf,  0xeb9e,  0x9b79,  0x8b58,  0xbb3b,  0xab1a,
+    0x6ca6,  0x7c87,  0x4ce4,  0x5cc5,  0x2c22,  0x3c03,  0x0c60,  0x1c41,
+    0xedae,  0xfd8f,  0xcdec,  0xddcd,  0xad2a,  0xbd0b,  0x8d68,  0x9d49,
+    0x7e97,  0x6eb6,  0x5ed5,  0x4ef4,  0x3e13,  0x2e32,  0x1e51,  0x0e70,
+    0xff9f,  0xefbe,  0xdfdd,  0xcffc,  0xbf1b,  0xaf3a,  0x9f59,  0x8f78,
+    0x9188,  0x81a9,  0xb1ca,  0xa1eb,  0xd10c,  0xc12d,  0xf14e,  0xe16f,
+    0x1080,  0x00a1,  0x30c2,  0x20e3,  0x5004,  0x4025,  0x7046,  0x6067,
+    0x83b9,  0x9398,  0xa3fb,  0xb3da,  0xc33d,  0xd31c,  0xe37f,  0xf35e,
+    0x02b1,  0x1290,  0x22f3,  0x32d2,  0x4235,  0x5214,  0x6277,  0x7256,
+    0xb5ea,  0xa5cb,  0x95a8,  0x8589,  0xf56e,  0xe54f,  0xd52c,  0xc50d,
+    0x34e2,  0x24c3,  0x14a0,  0x0481,  0x7466,  0x6447,  0x5424,  0x4405,
+    0xa7db,  0xb7fa,  0x8799,  0x97b8,  0xe75f,  0xf77e,  0xc71d,  0xd73c,
+    0x26d3,  0x36f2,  0x0691,  0x16b0,  0x6657,  0x7676,  0x4615,  0x5634,
+    0xd94c,  0xc96d,  0xf90e,  0xe92f,  0x99c8,  0x89e9,  0xb98a,  0xa9ab,
+    0x5844,  0x4865,  0x7806,  0x6827,  0x18c0,  0x08e1,  0x3882,  0x28a3,
+    0xcb7d,  0xdb5c,  0xeb3f,  0xfb1e,  0x8bf9,  0x9bd8,  0xabbb,  0xbb9a,
+    0x4a75,  0x5a54,  0x6a37,  0x7a16,  0x0af1,  0x1ad0,  0x2ab3,  0x3a92,
+    0xfd2e,  0xed0f,  0xdd6c,  0xcd4d,  0xbdaa,  0xad8b,  0x9de8,  0x8dc9,
+    0x7c26,  0x6c07,  0x5c64,  0x4c45,  0x3ca2,  0x2c83,  0x1ce0,  0x0cc1,
+    0xef1f,  0xff3e,  0xcf5d,  0xdf7c,  0xaf9b,  0xbfba,  0x8fd9,  0x9ff8,
+    0x6e17,  0x7e36,  0x4e55,  0x5e74,  0x2e93,  0x3eb2,  0x0ed1,  0x1ef0,
+);
+
+sub add_crc
+{
+       # crc with polynomial: x^16 + x^12 + x^5 + 1
+       # 1,0001,0000,0010,0001
+       my $packref = shift;
+       my $crc = 0;
+
+       foreach (@$packref) {
+               $crc = ($crc << 8) ^ $crctab[
+                                       ( ($crc >> (16-8)) ^ ord($_) ) & 0xff
+                                       ];
+               $crc &= 0xffff;
+       }
+       $$packref[16] = chr((($crc >> 8) & 0xff) ^ 0xff);
+       $$packref[17] = chr(($crc & 0xff) ^ 0xff);
+}
+
+sub print_packet
+{
+       return if ($#_ < 1);
+       my @packet = (@_);
+       add_crc(\@packet);
+       if ($packet[0] ne chr(0x8f)) {
+               printf STDERR ("%02x "x4 ." "."%c "x12 ." "."%02x "x2), map( defined($_) ? ord($_) : "___undef", @packet );
+       } else {
+               printf STDERR ("%02x "x4 ." "."%02x "x12 ." "."%02x "x2), map( defined($_) ? ord($_) : "___undef", @packet );
+       }
+       printf STDERR "\n";
+       push @results, @packet;
+}
+
+my $defaultperformer = $ARGV[0] || die "usage: ", $^X, " defaultperformer_name\n";
+my $prefix = $ARGV[1] || "audio";
+@ARGV = glob("${prefix}_??.inf");
+my @albumtitles;
+my @tracktitles;
+my @performers;
+my $ISRC;
+my @ISRCs;
+my $MCN;
+
+my $performer;
+while (<>) {
+       if (/^Performer=\s+'(.*?)'$/) {
+               $performer = $1;
+       }
+       if (/^Albumtitle=\s+'(.*?)'$/) {
+               push @albumtitles, $1;
+       }
+       if (/^Tracktitle=\s+'(.*?)'$/) {
+               push @tracktitles, $1;
+       }
+       if (/^ISRC=\s+(\S+?)$/) {
+               $ISRC = $1;
+       }
+       if (/^MCN=\s+(\S+?)$/) {
+               $MCN = $1;
+       }
+       if (eof) {
+               close ARGV;
+               $performer = $defaultperformer if (!defined($performer));
+               push @performers, $performer;
+               $performer = undef;
+               push @ISRCs, $ISRC;
+               $ISRC = undef;
+       }
+}
+
+#
+my $seq_nr = 0;
+
+my @todo;
+my $text;
+my $track;
+my $charpos;
+
+# build cdtext packets
+
+# build track titles
+@todo = ($albumtitles[0], @tracktitles);
+$text = shift @todo;
+$track = 0;
+$charpos = 0;
+
+while ($#todo > 1 || defined($text)) {
+       fill_packet(0x80, \$track, \$seq_nr, \$charpos, \$text, \@todo);
+}
+
+my $trackpacks = $seq_nr;      # store for later reference
+my $last_track = $track;
+
+# build performer entries
+#@todo = ($performer) x (1 + scalar(@tracktitles));
+@todo = ($defaultperformer, @performers);
+$text = shift @todo;
+$track = 0;
+$charpos = 0;
+
+while ($#todo > 1 || defined($text)) {
+       fill_packet(0x81, \$track, \$seq_nr, \$charpos, \$text, \@todo);
+}
+
+my $perfpacks = $seq_nr - $trackpacks; # store for later reference
+
+# build ISRC entries
+@todo = ($MCN, @ISRCs);
+$text = shift @todo;
+$track = 0;
+$charpos = 0;
+
+while ($#todo > 1 || defined($text)) {
+       $text = "" if (!defined($text));
+       fill_packet(0x8e, \$track, \$seq_nr, \$charpos, \$text, \@todo);
+}
+
+my $isrcpacks = $seq_nr - $trackpacks - $perfpacks;    # store for later reference
+
+# build size information blocks
+my $size1 = chr(0) . chr(1) . chr($last_track) . chr(0)
+        . chr($trackpacks) . chr($perfpacks) . chr(0) x 5;
+my $size2 = chr(0) x 6 . chr($isrcpacks) . chr(3) . chr($seq_nr+2) . chr(0) x 2;
+my $size3 = chr(0) x 4 . chr(9);       # hard coded language 09 = english
+@todo = ($size1, $size2, $size3);
+$text = shift @todo;
+$track = 0;
+$charpos = 0;
+
+while ((defined($text) && $text ne "") ) {
+       fill_packet(0x8f, \$track, \$seq_nr, \$charpos, \$text, \@todo);
+}
+
+# write out the results
+my $size = @results + 2;
+print chr($size >> 8), chr($size & 0xff), chr(0), chr(0), @results;
diff --git a/icedax/interface.c b/icedax/interface.c
new file mode 100644 (file)
index 0000000..ef7278a
--- /dev/null
@@ -0,0 +1,1050 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)interface.c     1.40 06/02/19 Copyright 1998-2002 Heiko Eissfeldt, Copyright 2006 J. Schilling */
+/***
+ * CopyPolicy: GNU Public License 2 applies
+ * Copyright (C) 1994-1997 Heiko Eissfeldt heiko@colossus.escape.de
+ *
+ * Interface module for cdrom drive access
+ *
+ * Two interfaces are possible.
+ *
+ * 1. using 'cooked' ioctls() (Linux only)
+ *    : available for atapi, sbpcd and cdu31a drives only.
+ *
+ * 2. using the generic scsi device (for details see SCSI Prog. HOWTO).
+ *    NOTE: a bug/misfeature in the kernel requires blocking signal
+ *          SIGINT during SCSI command handling. Once this flaw has
+ *          been removed, the sigprocmask SIG_BLOCK and SIG_UNBLOCK calls
+ *          should removed, thus saving context switches.
+ *
+ * For testing purposes I have added a third simulation interface.
+ *
+ * Version 0.8: used experiences of Jochen Karrer.
+ *              SparcLinux port fixes
+ *              AlphaLinux port fixes
+ *
+ */
+#if 0
+#define SIM_CD
+#endif
+
+#include "config.h"
+#include <stdio.h>
+#include <standard.h>
+#include <stdxlib.h>
+#include <unixstd.h>
+#include <strdefs.h>
+#include <errno.h>
+#include <signal.h>
+#include <fctldefs.h>
+#include <assert.h>
+#include <schily.h>
+#include <device.h>
+
+#include <sys/ioctl.h>
+#include <statdefs.h>
+
+
+#include "mycdrom.h"
+#include "lowlevel.h"
+/* some include file locations have changed with newer kernels */
+#if defined (__linux__)
+# if LINUX_VERSION_CODE > 0x10300 + 97
+#  if LINUX_VERSION_CODE < 0x200ff
+#   include <linux/sbpcd.h>
+#   include <linux/ucdrom.h>
+#  endif
+#  if !defined(CDROM_SELECT_SPEED)
+#   include <linux/ucdrom.h>
+#  endif
+# endif
+#endif
+
+#include <usal/scsitransp.h>
+
+#include "mytype.h"
+#include "byteorder.h"
+#include "interface.h"
+#include "icedax.h"
+#include "semshm.h"
+#include "setuid.h"
+#include "ringbuff.h"
+#include "toc.h"
+#include "global.h"
+#include "ioctl.h"
+#include "exitcodes.h"
+#include "scsi_cmds.h"
+
+#include <utypes.h>
+#include <wodim.h>
+#include "scsi_scan.h"
+
+unsigned interface;
+
+int trackindex_disp = 0;
+
+void   priv_init(void);
+void   priv_on(void);
+void   priv_off(void);
+
+void           (*EnableCdda)(SCSI *, int Switch, unsigned uSectorsize);
+unsigned (*doReadToc)(SCSI *usalp);
+void           (*ReadTocText)(SCSI *usalp);
+unsigned (*ReadLastAudio)(SCSI *usalp);
+int      (*ReadCdRom)(SCSI *usalp, UINT4 *p, unsigned lSector, 
+                                                        unsigned SectorBurstVal);
+int      (*ReadCdRomData)(SCSI *usalp, unsigned char *p, unsigned lSector, 
+                                                                 unsigned SectorBurstVal);
+int      (*ReadCdRomSub)(SCSI *usalp, UINT4 *p, unsigned lSector, 
+                                                                unsigned SectorBurstVal);
+subq_chnl *(*ReadSubChannels)(SCSI *usalp, unsigned lSector);
+subq_chnl *(*ReadSubQ)(SCSI *usalp, unsigned char sq_format, 
+                                                         unsigned char track);
+void     (*SelectSpeed)(SCSI *usalp, unsigned speed);
+int            (*Play_at)(SCSI *usalp, unsigned int from_sector, unsigned int sectors);
+int            (*StopPlay)(SCSI *usalp);
+void           (*trash_cache)(UINT4 *p, unsigned lSector, unsigned SectorBurstVal);
+
+#if    defined USE_PARANOIA
+long cdda_read(void *d, void *buffer, long beginsector, long sectors);
+
+long cdda_read(void *d, void *buffer, long beginsector, long sectors)
+{
+       long ret = ReadCdRom(d, buffer, beginsector, sectors);
+       return ret;
+}
+#endif
+
+typedef struct string_len {
+  char *str;
+  unsigned int sl;
+} mystring;
+
+static mystring drv_is_not_mmc[] = {
+       {"DEC     RRD47   (C) DEC ",24},
+/*     {"SONY    CD-ROM CDU625    1.0",28}, */
+       {NULL,0}        /* must be last entry */
+};
+
+static mystring drv_has_mmc_cdda[] = {
+       {"HITACHI CDR-7930",16},
+/*     {"TOSHIBA CD-ROM XM-5402TA3605",28}, */
+       {NULL,0}        /* must be last entry */
+};
+
+static int     Is_a_Toshiba3401;
+
+int Toshiba3401(void);
+
+int Toshiba3401() 
+{
+  return Is_a_Toshiba3401;
+}
+
+/* hook */
+static void Dummy(void);
+static void Dummy()
+{
+}
+
+static SCSI    *usalp;
+
+SCSI *get_scsi_p(void);
+
+SCSI *get_scsi_p()
+{
+    return usalp;
+}
+
+#if !defined(SIM_CD)
+
+static void trash_cache_SCSI(UINT4 *p, unsigned lSector, 
+                                                                         unsigned SectorBurstVal);
+
+static void trash_cache_SCSI(UINT4 *p, unsigned lSector, 
+                                                                         unsigned SectorBurstVal)
+{
+      /* trash the cache */
+      ReadCdRom(get_scsi_p(), p, find_an_off_sector(lSector, SectorBurstVal), min(global.nsectors,6));
+}
+
+
+
+static void Check_interface_for_device(struct stat *statstruct, 
+                                                                                                       char *pdev_name);
+static int OpenCdRom(char *pdev_name);
+
+static void SetupSCSI(void);
+
+static void SetupSCSI()
+{
+    unsigned char *p;
+
+    if (interface != GENERIC_SCSI) {
+       /* unfortunately we have the wrong interface and are
+        * not able to change on the fly */
+       fprintf(stderr, "The generic SCSI interface and devices are required\n");
+       exit(SYNTAX_ERROR);
+    }
+
+    /* do a test unit ready to 'init' the device. */
+    TestForMedium(usalp);
+
+    /* check for the correct type of unit. */
+    p = Inquiry(usalp);
+
+#undef TYPE_ROM
+#define TYPE_ROM 5
+#undef TYPE_WORM
+#define TYPE_WORM  4
+    if (p == NULL) {
+       fprintf(stderr, "Inquiry command failed. Aborting...\n");
+       exit(DEVICE_ERROR);
+    }
+
+    if ((*p != TYPE_ROM && *p != TYPE_WORM)) {
+       fprintf(stderr, "this is neither a scsi cdrom nor a worm device\n");
+       exit(SYNTAX_ERROR);
+    }
+
+    if (global.quiet == 0) {
+       fprintf(stderr,
+                "Type: %s, Vendor '%8.8s' Model '%16.16s' Revision '%4.4s' ",
+                *p == TYPE_ROM ? "ROM" : "WORM"
+                ,p+8
+                ,p+16
+                ,p+32);
+    }
+    /* generic Sony type defaults */
+    density = 0x0;
+    accepts_fua_bit = -1;
+    EnableCdda = (void (*)(SCSI *, int, unsigned))Dummy;
+    ReadCdRom = ReadCdda12;
+    ReadCdRomSub = ReadCddaSubSony;
+    ReadCdRomData = (int (*)(SCSI *, unsigned char *, unsigned, unsigned))ReadStandardData;
+    ReadLastAudio = ReadFirstSessionTOCSony;
+    SelectSpeed = SpeedSelectSCSISony;
+    Play_at = Play_atSCSI;
+    StopPlay = StopPlaySCSI;
+    trash_cache = trash_cache_SCSI;
+    ReadTocText = ReadTocTextSCSIMMC;
+    doReadToc = ReadTocSCSI;
+    ReadSubQ = ReadSubQSCSI;
+    ReadSubChannels = NULL;
+
+    /* check for brands and adjust special peculiaritites */
+
+    /* If your drive is not treated correctly, you can adjust some things
+       here:
+
+       global.in_lendian: should be to 1, if the CDROM drive or CD-Writer
+                 delivers the samples in the native byteorder of the audio cd
+                 (LSB first).
+                 HP CD-Writers need it set to 0.
+       NOTE: If you get correct wav files when using sox with the '-x' option,
+             the endianess is wrong. You can use the -C option to specify
+            the value of global.in_lendian.
+
+     */
+
+    {
+      int mmc_code;
+
+      usalp->silent ++;
+      allow_atapi(usalp, 1);
+      if (*p == TYPE_ROM) {
+        mmc_code = heiko_mmc(usalp);
+      } else {
+        mmc_code = 0;
+      }
+      usalp->silent --;
+
+      /* Exceptions for drives that report incorrect MMC capability */
+      if (mmc_code != 0) {
+       /* these drives are NOT capable of MMC commands */
+        mystring *pp = drv_is_not_mmc;
+       while (pp->str != NULL) {
+         if (!strncmp(pp->str, (char *)p+8,pp->sl)) {
+           mmc_code = 0;
+           break;
+         }
+         pp++;
+        }
+      }
+      {
+       /* these drives flag themselves as non-MMC, but offer CDDA reading
+          only with a MMC method. */
+        mystring *pp = drv_has_mmc_cdda;
+       while (pp->str != NULL) {
+         if (!strncmp(pp->str, (char *)p+8,pp->sl)) {
+           mmc_code = 1;
+           break;
+         }
+         pp++;
+        }
+      }
+
+      switch (mmc_code) {
+       case 2:      /* SCSI-3 cdrom drive with accurate audio stream */
+       /* fall through */
+       case 1:      /* SCSI-3 cdrom drive with no accurate audio stream */
+       /* fall through */
+lost_toshibas:
+        global.in_lendian = 1;
+         if (mmc_code == 2)
+          global.overlap = 0;
+        else
+           global.overlap = 1;
+         ReadCdRom = ReadCddaFallbackMMC;
+        ReadCdRomSub = ReadCddaSubSony;
+         ReadLastAudio = ReadFirstSessionTOCMMC;
+         SelectSpeed = SpeedSelectSCSIMMC;
+        ReadTocText = ReadTocTextSCSIMMC;
+        doReadToc = ReadTocMMC;
+        ReadSubChannels = ReadSubChannelsFallbackMMC;
+        if (!memcmp(p+8,"SONY    CD-RW  CRX100E  1.0", 27)) ReadTocText = NULL;
+        if (!global.quiet) fprintf(stderr, "MMC+CDDA\n");
+       break;
+       case -1: /* "MMC drive does not support cdda reading, sorry\n." */
+        doReadToc = ReadTocMMC;
+        if (!global.quiet) fprintf(stderr, "MMC-CDDA\n");
+        /* FALLTHROUGH */
+       case 0:      /* non SCSI-3 cdrom drive */
+        if (!global.quiet) fprintf(stderr, "no MMC\n");
+         ReadLastAudio = NULL;
+    if (!memcmp(p+8,"TOSHIBA", 7) ||
+        !memcmp(p+8,"IBM", 3) ||
+        !memcmp(p+8,"DEC", 3)) {
+           /*
+            * older Toshiba ATAPI drives don't identify themselves as MMC.
+            * The last digit of the model number is '2' for ATAPI drives.
+            * These are treated as MMC.
+            */
+           if (!memcmp(p+15, " CD-ROM XM-", 11) && p[29] == '2') {
+               goto lost_toshibas;
+           }
+       density = 0x82;
+       EnableCdda = EnableCddaModeSelect;
+       ReadSubChannels = ReadStandardSub;
+       ReadCdRom = ReadStandard;
+        SelectSpeed = SpeedSelectSCSIToshiba;
+        if (!memcmp(p+15, " CD-ROM XM-3401",15)) {
+          Is_a_Toshiba3401 = 1;
+       }
+       global.in_lendian = 1;
+    } else if (!memcmp(p+8,"IMS",3) ||
+               !memcmp(p+8,"KODAK",5) ||
+               !memcmp(p+8,"RICOH",5) ||
+               !memcmp(p+8,"HP",2) ||
+               !memcmp(p+8,"PHILIPS",7) ||
+               !memcmp(p+8,"PLASMON",7) ||
+               !memcmp(p+8,"GRUNDIG CDR100IPW",17) ||
+               !memcmp(p+8,"MITSUMI CD-R ",13)) {
+       EnableCdda = EnableCddaModeSelect;
+       ReadCdRom = ReadStandard;
+        SelectSpeed = SpeedSelectSCSIPhilipsCDD2600;
+
+       /* treat all of these as bigendian */
+       global.in_lendian = 0;
+
+       /* no overlap reading for cd-writers */
+       global.overlap = 0;
+    } else if (!memcmp(p+8,"NRC",3)) {
+        SelectSpeed = NULL;
+    } else if (!memcmp(p+8,"YAMAHA",6)) {
+       EnableCdda = EnableCddaModeSelect;
+        SelectSpeed = SpeedSelectSCSIYamaha;
+
+       /* no overlap reading for cd-writers */
+       global.overlap = 0;
+       global.in_lendian = 1;
+    } else if (!memcmp(p+8,"PLEXTOR",7)) {
+       global.in_lendian = 1;
+       global.overlap = 0;
+        ReadLastAudio = ReadFirstSessionTOCSony;
+       ReadTocText = ReadTocTextSCSIMMC;
+       doReadToc = ReadTocSony;
+       ReadSubChannels = ReadSubChannelsSony;
+    } else if (!memcmp(p+8,"SONY",4)) {
+       global.in_lendian = 1;
+        if (!memcmp(p+16, "CD-ROM CDU55E",13)) {
+          ReadCdRom = ReadCddaMMC12;
+       }
+        ReadLastAudio = ReadFirstSessionTOCSony;
+       ReadTocText = ReadTocTextSCSIMMC;
+       doReadToc = ReadTocSony;
+       ReadSubChannels = ReadSubChannelsSony;
+    } else if (!memcmp(p+8,"NEC",3)) {
+       ReadCdRom = ReadCdda10;
+        ReadTocText = NULL;
+        SelectSpeed = SpeedSelectSCSINEC;
+       global.in_lendian = 1;
+        if (!memcmp(p+29,"5022.0r",3)) /* I assume all versions of the 502 require this? */
+               global.overlap = 0;           /* no overlap reading for NEC CD-ROM 502 */
+    } else if (!memcmp(p+8,"MATSHITA",8)) {
+       ReadCdRom = ReadCdda12Matsushita;
+       global.in_lendian = 1;
+    }
+    } /* switch (get_mmc) */
+    }
+
+
+    /* look if caddy is loaded */
+    if (interface == GENERIC_SCSI) {
+       usalp->silent++;
+       while (!wait_unit_ready(usalp, 60)) {
+               fprintf(stderr,"load cdrom please and press enter");
+               getchar();
+       }
+       usalp->silent--;
+    }
+}
+
+/* Check to see if the device will support SCSI generic commands. A
+ * better check than simply looking at the device name. Open the
+ * device, issue an inquiry. If they both succeed, there's a good
+ * chance that the device works... */
+#if defined(__linux__)
+static int check_linux_scsi_interface(char *pdev_name)
+{
+    SCSI *dev = NULL;
+    unsigned char *p = NULL;
+       char    errstr[80];
+    
+       dev = usal_open(pdev_name, errstr, sizeof(errstr), 0, 0);
+    if (NULL == dev)
+        return EINVAL;
+    p = Inquiry(dev);
+    if (p)
+    {
+        usal_close(dev);
+        return 0;
+    }
+    usal_close(dev);
+    return EINVAL;
+}
+#endif
+
+/********************** General setup *******************************/
+
+/* As the name implies, interfaces and devices are checked.  We also
+   adjust nsectors, overlap, and interface for the first time here.
+   Any unnecessary privileges (setuid, setgid) are also dropped here.
+*/
+static void Check_interface_for_device(struct stat *statstruct, char *pdev_name)
+{
+#if defined(__linux__)
+    int is_scsi = 1;
+#endif
+#ifndef STAT_MACROS_BROKEN
+    if (!S_ISCHR(statstruct->st_mode) &&
+       !S_ISBLK(statstruct->st_mode)) {
+      fprintf(stderr, "%s is not a device\n",pdev_name);
+      exit(SYNTAX_ERROR);
+    }
+#endif
+
+/* Check what type of device we have */
+#if defined (__linux__)
+    if (check_linux_scsi_interface(pdev_name))
+        is_scsi = 0;
+    if (interface == GENERIC_SCSI && !is_scsi)
+    {
+        fprintf(stderr, "device %s does not support generic_scsi; falling back to cooked_ioctl instead\n", pdev_name);
+        interface = COOKED_IOCTL;
+    }
+    if ((interface == COOKED_IOCTL) &&
+        is_scsi &&
+        (SCSI_GENERIC_MAJOR == major(statstruct->st_rdev)))
+    {
+        fprintf(stderr, "device %s is generic_scsi NOT cooked_ioctl\n", pdev_name);
+        interface = GENERIC_SCSI;
+    }
+#else
+    
+#if defined (HAVE_ST_RDEV)
+    switch (major(statstruct->st_rdev)) {
+#if defined (__linux__)
+    case SCSI_GENERIC_MAJOR:   /* generic */
+#else
+    default:                   /* ??? what is the proper value here */
+#endif
+#ifndef STAT_MACROS_BROKEN
+#if defined (__linux__)
+       if (!S_ISCHR(statstruct->st_mode)) {
+        fprintf(stderr, "%s is not a char device\n",pdev_name);
+        exit(SYNTAX_ERROR);
+       }
+
+       if (interface != GENERIC_SCSI) {
+        fprintf(stderr, "wrong interface (cooked_ioctl) for this device (%s)\nset to generic_scsi\n", pdev_name);
+        interface = GENERIC_SCSI;
+       }
+#endif
+#else
+    default:                   /* ??? what is the proper value here */
+#endif
+       break;
+
+#if defined (__linux__) || defined (__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__)
+#if defined (__linux__)
+    case SCSI_CDROM_MAJOR:     /* scsi cd */
+    default:                   /* for example ATAPI cds */
+#else
+#if defined (__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__)
+#if __FreeBSD_version >= 600021
+    case 0:    /* majors abandoned */
+       /* FALLTHROUGH */
+#endif
+#if __FreeBSD_version >= 501113
+    case 4:    /* GEOM */
+       /* FALLTHROUGH */
+#endif
+    case 117:  /* pre-GEOM atapi cd */
+       if (!S_ISCHR(statstruct->st_mode)) {
+           fprintf(stderr, "%s is not a char device\n",pdev_name);
+           exit(SYNTAX_ERROR);
+       }
+       if (interface != COOKED_IOCTL) {
+           fprintf(stderr,
+"cdrom device (%s) is not of type generic SCSI. \
+Setting interface to cooked_ioctl.\n", pdev_name);
+           interface = COOKED_IOCTL;
+       }
+       break;
+    case 19:     /* first atapi cd */
+#endif
+#endif
+       if (!S_ISBLK(statstruct->st_mode)) {
+           fprintf(stderr, "%s is not a block device\n",pdev_name);
+           exit(SYNTAX_ERROR);
+       }
+#if defined (__linux__)
+#if LINUX_VERSION_CODE >= 0x20600
+       /* In Linux kernel 2.6 it is better to use the SCSI interface
+        * with the device.
+        */
+       break;
+#endif
+#endif
+       if (interface != COOKED_IOCTL) {
+           fprintf(stderr, 
+"cdrom device (%s) is not of type generic SCSI. \
+Setting interface to cooked_ioctl.\n", pdev_name);
+           interface = COOKED_IOCTL;
+       }
+
+       if (interface == COOKED_IOCTL) {
+               fprintf(stderr, "\nW: The cooked_ioctl interface is functionally very limited!!\n");
+#if    defined (__linux__)
+               fprintf(stderr, "\nW: For good sampling quality simply use the generic SCSI interface!\n"
+                               "For example dev=ATA:1,0,0\n");
+#endif
+       }
+
+       break;
+#endif
+    }
+#endif
+#endif 
+    if (global.overlap >= global.nsectors)
+      global.overlap = global.nsectors-1;
+}
+
+/* open the cdrom device */
+static int OpenCdRom(char *pdev_name)
+{
+  int retval = 0;
+  struct stat fstatstruct;
+
+  /*  The device (given by pdevname) can be:
+      a. an SCSI device specified with a /dev/xxx name,
+      b. an SCSI device specified with bus,target,lun numbers,
+      c. a non-SCSI device such as ATAPI or proprietary CDROM devices.
+   */
+#ifdef HAVE_IOCTL_INTERFACE
+  struct stat statstruct;
+  int have_named_device = 0;
+
+       have_named_device = FALSE;
+       if (pdev_name) {
+               have_named_device = strchr(pdev_name, ':') == NULL
+                                       && memcmp(pdev_name, "/dev/", 5) == 0;
+       }
+
+  if (have_named_device) {
+    if (stat(pdev_name, &statstruct)) {
+      fprintf(stderr, "cannot stat device %s\n", pdev_name);
+      exit(STAT_ERROR);
+    } else {
+      Check_interface_for_device( &statstruct, pdev_name );
+    }
+  }
+#endif
+
+  if (interface == GENERIC_SCSI) {
+       char    errstr[80];
+
+       priv_on();
+       needroot(0);
+       needgroup(0);
+       /*
+        * Call usal_remote() to force loading the remote SCSI transport library
+        * code that is located in librusal instead of the dummy remote routines
+        * that are located inside libusal.
+        */
+       usal_remote();
+       if (pdev_name != NULL &&
+           ((strncmp(pdev_name, "HELP", 4) == 0) ||
+            (strncmp(pdev_name, "help", 4) == 0))) {
+               usal_help(stderr);
+               exit(NO_ERROR);
+       }
+       /* device name, debug, verboseopen */
+       usalp = usal_open(pdev_name, errstr, sizeof(errstr), 0, 0);
+
+       if (usalp == NULL) {
+               int     err = geterrno();
+
+               errmsgno(err, "%s%sCannot open SCSI driver.\n", errstr, errstr[0]?". ":"");
+               errmsgno(EX_BAD, "For possible targets try 'wodim -scanbus'.%s\n",
+                                       geteuid() ? " Make sure you are root.":"");
+               priv_off();
+               dontneedgroup();
+               dontneedroot();
+#if defined(sun) || defined(__sun)
+               fprintf(stderr, "On SunOS/Solaris make sure you have Joerg Schillings usal SCSI driver installed.\n");
+#endif
+#if defined (__linux__)
+               fprintf(stderr, "Use the script scan_scsi.linux to find out more.\n");
+#endif
+               fprintf(stderr, "Probably you did not define your SCSI device.\n");
+               fprintf(stderr, "Set the CDDA_DEVICE environment variable or use the -D option.\n");
+               fprintf(stderr, "You can also define the default device in the Makefile.\n");
+               fprintf(stderr, "For possible transport specifiers try 'wodim dev=help'.\n");
+               exit(SYNTAX_ERROR);
+       }
+       usal_settimeout(usalp, 300);
+       usal_settimeout(usalp, 60);
+       usalp->silent = global.scsi_silent;
+       usalp->verbose = global.scsi_verbose;
+
+       if (global.nsectors > (unsigned) usal_bufsize(usalp, 3*1024*1024)/CD_FRAMESIZE_RAW)
+               global.nsectors = usal_bufsize(usalp, 3*1024*1024)/CD_FRAMESIZE_RAW;
+       if (global.overlap >= global.nsectors)
+               global.overlap = global.nsectors-1;
+
+       /*
+        * Newer versions of Linux seem to introduce an incompatible change
+        * and require root privileges or limit RLIMIT_MEMLOCK infinity
+        * in order to get a SCSI buffer in case we did call mlockall(MCL_FUTURE).
+        */
+       init_scsibuf(usalp, global.nsectors*CD_FRAMESIZE_RAW);
+       priv_off();
+       dontneedgroup();
+       dontneedroot();
+
+       if (global.scandevs) {
+               list_devices(usalp, stdout, 0);
+               exit(0);
+       }
+
+       if (global.scanbus) {
+               select_target(usalp, stdout);
+               exit(0);
+       }
+  } else {
+      needgroup(0);
+      retval = open(pdev_name,O_RDONLY
+#ifdef linux
+                               | O_NONBLOCK
+#endif
+       );
+      dontneedgroup();
+
+      if (retval < 0) {
+        fprintf(stderr, "while opening %s :", pdev_name);
+        perror("");
+        exit(DEVICEOPEN_ERROR);
+      }
+
+      /* Do final security checks here */
+      if (fstat(retval, &fstatstruct)) {
+        fprintf(stderr, "Could not fstat %s (fd %d): ", pdev_name, retval);
+        perror("");
+        exit(STAT_ERROR);
+      }
+      Check_interface_for_device( &fstatstruct, pdev_name );
+
+#if defined HAVE_IOCTL_INTERFACE
+      /* Watch for race conditions */
+      if (have_named_device 
+          && (fstatstruct.st_dev != statstruct.st_dev ||
+              fstatstruct.st_ino != statstruct.st_ino)) {
+         fprintf(stderr,"Race condition attempted in OpenCdRom.  Exiting now.\n");
+         exit(RACE_ERROR);
+      }
+#endif
+       /*
+        * The structure looks like a desaster :-(
+        * We do this more than once as it is impossible to understand where
+        * the right place would be to do this....
+        */
+       if (usalp != NULL) {
+               usalp->verbose = global.scsi_verbose;
+       }
+  }
+  return retval;
+}
+#endif /* SIM_CD */
+
+/******************* Simulation interface *****************/
+#if    defined SIM_CD
+#include "toc.h"
+static unsigned long sim_pos=0;
+
+/* read 'SectorBurst' adjacent sectors of audio sectors 
+ * to Buffer '*p' beginning at sector 'lSector'
+ */
+static int ReadCdRom_sim(SCSI *x, UINT4 *p, unsigned lSector, 
+                                                                unsigned SectorBurstVal);
+static int ReadCdRom_sim(SCSI *x, UINT4 *p, unsigned lSector, 
+                                                                unsigned SectorBurstVal)
+{
+  unsigned int loop=0;
+  Int16_t *q = (Int16_t *) p;
+  int joffset = 0;
+
+  if (lSector > g_toc[cdtracks].dwStartSector || lSector + SectorBurstVal > g_toc[cdtracks].dwStartSector + 1) {
+    fprintf(stderr, "Read request out of bounds: %u - %u (%d - %d allowed)\n",
+       lSector, lSector + SectorBurstVal, 0, g_toc[cdtracks].dwStartSector);
+  }
+#if 0
+  /* jitter with a probability of jprob */
+  if (random() <= jprob) {
+    /* jitter up to jmax samples */
+    joffset = random();
+  }
+#endif
+
+#ifdef DEBUG_SHM
+  fprintf(stderr, ", last_b = %p\n", *last_buffer);
+#endif
+  for (loop = lSector*CD_FRAMESAMPLES + joffset; 
+       loop < (lSector+SectorBurstVal)*CD_FRAMESAMPLES + joffset; 
+       loop++) {
+    *q++ = loop;
+    *q++ = ~loop;
+  }
+#ifdef DEBUG_SHM
+  fprintf(stderr, "sim wrote from %p upto %p - 4 (%d), last_b = %p\n",
+          p, q, SectorBurstVal*CD_FRAMESAMPLES, *last_buffer);
+#endif
+  sim_pos = (lSector+SectorBurstVal)*CD_FRAMESAMPLES + joffset; 
+  return SectorBurstVal;
+}
+
+static int Play_at_sim(SCSI *x, unsigned int from_sector, unsigned int sectors);
+static int Play_at_sim(SCSI *x, unsigned int from_sector, unsigned int sectors)
+{
+  sim_pos = from_sector*CD_FRAMESAMPLES; 
+  return 0;
+}
+
+static unsigned sim_indices;
+
+
+/* read the table of contents (toc) via the ioctl interface */
+static unsigned ReadToc_sim(SCSI *x, TOC *toc);
+static unsigned ReadToc_sim(SCSI *x, TOC *toc)
+{
+    unsigned int scenario;
+    int scen[12][3] = { 
+      {1,1,500}, 
+      {1,2,500}, 
+      {1,99,150*99}, 
+      {2,1,500}, 
+      {2,2,500}, 
+      {2,99,150*99},
+      {2,1,500}, 
+      {5,2,500}, 
+      {5,99,150*99}, 
+      {99,1,1000}, 
+      {99,2,1000}, 
+      {99,99,150*99}, 
+    };
+    unsigned int i;
+    unsigned trcks;
+#if 0
+    fprintf(stderr, "select one of the following TOCs\n"
+           "0 :  1 track  with  1 index\n"
+           "1 :  1 track  with  2 indices\n"
+           "2 :  1 track  with 99 indices\n"
+           "3 :  2 tracks with  1 index each\n"
+           "4 :  2 tracks with  2 indices each\n"
+           "5 :  2 tracks with 99 indices each\n"
+           "6 :  2 tracks (data and audio) with  1 index each\n"
+           "7 :  5 tracks with  2 indices each\n"
+           "8 :  5 tracks with 99 indices each\n"
+           "9 : 99 tracks with  1 index each\n"
+           "10: 99 tracks with  2 indices each\n"
+           "11: 99 tracks with 99 indices each\n"
+           );
+
+    do {
+      scanf("%u", &scenario);
+    } while (scenario > sizeof(scen)/2/sizeof(int));
+#else
+    scenario = 6;
+#endif
+    /* build table of contents */
+
+#if 0
+    trcks = scen[scenario][0] + 1;
+    sim_indices = scen[scenario][1];
+
+    for (i = 0; i < trcks; i++) {
+        toc[i].bFlags = (scenario == 6 && i == 0) ? 0x40 : 0xb1;
+        toc[i].bTrack = i + 1;
+        toc[i].dwStartSector = i * scen[scenario][2];
+        toc[i].mins = (toc[i].dwStartSector+150) / (60*75);
+        toc[i].secs = (toc[i].dwStartSector+150 / 75) % (60);
+        toc[i].frms = (toc[i].dwStartSector+150) % (75);
+    }
+    toc[i].bTrack = 0xaa;
+    toc[i].dwStartSector = i * scen[scenario][2];
+    toc[i].mins = (toc[i].dwStartSector+150) / (60*75);
+    toc[i].secs = (toc[i].dwStartSector+150 / 75) % (60);
+    toc[i].frms = (toc[i].dwStartSector+150) % (75);
+#else
+    {
+      int starts[15] = { 23625, 30115, 39050, 51777, 67507, 
+               88612, 112962, 116840, 143387, 162662,
+               173990, 186427, 188077, 209757, 257120};
+      trcks = 14 + 1;
+      sim_indices = 1;
+
+      for (i = 0; i < trcks; i++) {
+        toc[i].bFlags = 0x0;
+        toc[i].bTrack = i + 1;
+        toc[i].dwStartSector = starts[i];
+        toc[i].mins = (starts[i]+150) / (60*75);
+        toc[i].secs = (starts[i]+150 / 75) % (60);
+        toc[i].frms = (starts[i]+150) % (75);
+      }
+      toc[i].bTrack = 0xaa;
+      toc[i].dwStartSector = starts[i];
+      toc[i].mins = (starts[i]) / (60*75);
+      toc[i].secs = (starts[i] / 75) % (60);
+      toc[i].frms = (starts[i]) % (75);
+    }
+#endif
+    return --trcks;           /* without lead-out */
+}
+
+
+static subq_chnl *ReadSubQ_sim(SCSI *usalp, unsigned char sq_format, 
+                                                                                unsigned char track);
+/* request sub-q-channel information. This function may cause confusion
+ * for a drive, when called in the sampling process.
+ */
+static subq_chnl *ReadSubQ_sim(SCSI *usalp, unsigned char sq_format, 
+                                                                                unsigned char track)
+{
+    subq_chnl *SQp = (subq_chnl *) (SubQbuffer);
+    subq_position *SQPp = (subq_position *) &SQp->data;
+    unsigned long sim_pos1;
+    unsigned long sim_pos2;
+
+    if ( sq_format != GET_POSITIONDATA ) return NULL;  /* not supported by sim */
+
+    /* simulate CDROMSUBCHNL ioctl */
+
+    /* copy to SubQbuffer */
+    SQp->audio_status  = 0;
+    SQp->format        = 0xff;
+    SQp->control_adr   = 0xff;
+    sim_pos1 = sim_pos/CD_FRAMESAMPLES;
+    sim_pos2 = sim_pos1 % 150;
+    SQp->track                 = (sim_pos1 / 5000) + 1;
+    SQp->index                 = ((sim_pos1 / 150) % sim_indices) + 1;
+    sim_pos1 += 150;
+    SQPp->abs_min      = sim_pos1 / (75*60);
+    SQPp->abs_sec      = (sim_pos1 / 75) % 60;
+    SQPp->abs_frame    = sim_pos1 % 75;
+    SQPp->trel_min     = sim_pos2 / (75*60);
+    SQPp->trel_sec     = (sim_pos2 / 75) % 60;
+    SQPp->trel_frame   = sim_pos2 % 75;
+
+    return (subq_chnl *)(SubQbuffer);
+}
+
+static void SelectSpeed_sim(SCSI *x, unsigned sp);
+/* ARGSUSED */
+static void SelectSpeed_sim(SCSI *x, unsigned sp)
+{
+}
+
+static void trash_cache_sim(UINT4 *p, unsigned lSector, 
+                                                                        unsigned SectorBurstVal);
+
+/* ARGSUSED */
+static void trash_cache_sim(UINT4 *p, unsigned lSector, 
+                                                                        unsigned SectorBurstVal)
+{
+}
+
+static void SetupSimCd(void);
+
+static void SetupSimCd()
+{
+    EnableCdda = (void (*)(SCSI *, int, unsigned))Dummy;
+    ReadCdRom = ReadCdRom_sim;
+    ReadCdRomData = (int (*)(SCSI *, unsigned char *, unsigned, unsigned))ReadCdRom_sim;
+    doReadToc = ReadToc_sim;
+    ReadTocText = NULL;
+    ReadSubQ = ReadSubQ_sim;
+    ReadSubChannels = NULL;
+    ReadLastAudio = NULL;
+    SelectSpeed = SelectSpeed_sim;
+    Play_at = Play_at_sim;
+    StopPlay = (int (*)(SCSI *))Dummy;
+    trash_cache = trash_cache_sim;
+}
+
+#endif /* def SIM_CD */
+
+/* perform initialization depending on the interface used. */
+void SetupInterface()
+{
+#if    defined SIM_CD
+    fprintf( stderr, "SIMULATION MODE !!!!!!!!!!!\n");
+#else
+    /* ensure interface is setup correctly */
+    global.cooked_fd = OpenCdRom ( global.dev_name );
+#endif
+
+    global.pagesize = getpagesize();
+
+    /* request one sector for table of contents */
+    bufferTOC = malloc( CD_FRAMESIZE_RAW + 96 );      /* assumes sufficient aligned addresses */
+    /* SubQchannel buffer */
+    SubQbuffer = malloc( 48 );               /* assumes sufficient aligned addresses */
+    cmd = malloc( 18 );                      /* assumes sufficient aligned addresses */
+    if ( !bufferTOC || !SubQbuffer || !cmd ) {
+       fprintf( stderr, "Too low on memory. Giving up.\n");
+       exit(NOMEM_ERROR);
+    }
+
+#if    defined SIM_CD
+    usalp = malloc(sizeof(* usalp));
+    if (usalp == NULL) {
+       FatalError("No memory for SCSI structure.\n");
+    }
+    usalp->silent = 0;
+    SetupSimCd();
+#else
+    /* if drive is of type scsi, get vendor name */
+    if (interface == GENERIC_SCSI) {
+        unsigned sector_size;
+
+       SetupSCSI();
+        sector_size = get_orig_sectorsize(usalp, &orgmode4, &orgmode10, &orgmode11);
+       if (!SCSI_emulated_ATAPI_on(usalp)) {
+          if ( sector_size != 2048 && set_sectorsize(usalp, 2048) ) {
+           fprintf( stderr, "Could not change sector size from %d to 2048\n", sector_size );
+          }
+        } else {
+          sector_size = 2048;
+        }
+
+       /* get cache setting */
+
+       /* set cache to zero */
+
+    } else {
+#if defined (HAVE_IOCTL_INTERFACE)
+       usalp = malloc(sizeof(* usalp));
+       if (usalp == NULL) {
+               FatalError("No memory for SCSI structure.\n");
+       }
+       usalp->silent = 0;
+       SetupCookedIoctl( global.dev_name );
+#else
+       FatalError("Sorry, there is no known method to access the device.\n");
+#endif
+    }
+#endif /* if def SIM_CD */
+       /*
+        * The structure looks like a desaster :-(
+        * We do this more than once as it is impossible to understand where
+        * the right place would be to do this....
+        */
+       if (usalp != NULL) {
+               usalp->verbose = global.scsi_verbose;
+       }
+}
+
+#ifdef HAVE_PRIV_H
+#include <priv.h>
+#endif
+
+void
+priv_init()
+{
+#ifdef HAVE_PRIV_SET
+       /*
+        * Give up privs we do not need anymore.
+        * We no longer need:
+        *      file_dac_read,sys_devices,proc_priocntl,net_privaddr
+        */
+       priv_set(PRIV_OFF, PRIV_EFFECTIVE,
+               PRIV_FILE_DAC_READ, PRIV_PROC_PRIOCNTL,
+               PRIV_NET_PRIVADDR, NULL);
+       priv_set(PRIV_OFF, PRIV_INHERITABLE,
+               PRIV_FILE_DAC_READ, PRIV_PROC_PRIOCNTL,
+               PRIV_NET_PRIVADDR, PRIV_SYS_DEVICES, NULL);
+#endif
+}
+
+void
+priv_on()
+{
+#ifdef HAVE_PRIV_SET
+       /*
+        * Get back privs we may need now.
+        * We need:
+        *      file_dac_read,sys_devices,proc_priocntl,net_privaddr
+        */
+       priv_set(PRIV_ON, PRIV_EFFECTIVE,
+               PRIV_FILE_DAC_READ, PRIV_PROC_PRIOCNTL,
+               PRIV_NET_PRIVADDR, NULL);
+#endif
+}
+
+void
+priv_off()
+{
+#ifdef HAVE_PRIV_SET
+       /*
+        * Give up privs we do not need anymore.
+        * We no longer need:
+        *      file_dac_read,sys_devices,proc_priocntl,net_privaddr
+        */
+       priv_set(PRIV_OFF, PRIV_EFFECTIVE,
+               PRIV_FILE_DAC_READ, PRIV_PROC_PRIOCNTL,
+               PRIV_NET_PRIVADDR, NULL);
+#endif
+}
diff --git a/icedax/interface.h b/icedax/interface.h
new file mode 100644 (file)
index 0000000..b285b71
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)interface.h     1.14 06/02/19 Copyright 1998-2001 Heiko Eissfeldt, Copyright 2005-2006 J. Schilling */
+
+/***
+ * CopyPolicy: GNU Public License 2 applies
+ * Copyright (C) by Heiko Eissfeldt
+ *
+ * header file interface.h for cdda2wav */
+
+#ifndef CD_FRAMESIZE
+#define CD_FRAMESIZE 2048
+#endif
+
+#ifndef CD_FRAMESIZE_RAW
+#define CD_FRAMESIZE_RAW 2352
+#endif
+
+#define CD_FRAMESAMPLES (CD_FRAMESIZE_RAW / 4)
+
+extern unsigned interface;
+
+extern int trackindex_disp;
+#ifndef NSECTORS
+#define NSECTORS 75
+#endif
+
+/* interface types */
+#define GENERIC_SCSI   0
+#define COOKED_IOCTL   1
+
+/* constants for sub-q-channel info */
+#define GET_ALL                        0
+#define GET_POSITIONDATA       1
+#define GET_CATALOGNUMBER      2
+#define GET_TRACK_ISRC         3
+
+typedef struct subq_chnl {
+    unsigned char reserved;
+    unsigned char audio_status;
+    unsigned short subq_length;
+    unsigned char format;
+    unsigned char control_adr;
+    unsigned char track;
+    unsigned char index;
+    unsigned char data[40];    /* this has subq_all, subq_position,
+                                  subq_catalog or subq_track_isrc format */
+} subq_chnl;
+
+typedef struct subq_all {
+    unsigned char abs_min;
+    unsigned char abs_sec;
+    unsigned char abs_frame;
+    unsigned char abs_reserved;
+    unsigned char trel_min;
+    unsigned char trel_sec;
+    unsigned char trel_frame;
+    unsigned char trel_reserved;
+    unsigned char mc_valid;     /* MSB */
+    unsigned char media_catalog_number[13];
+    unsigned char zero;
+    unsigned char aframe;
+    unsigned char tc_valid;    /* MSB */
+    unsigned char track_ISRC[15];
+} subq_all;
+
+typedef struct subq_position {
+    unsigned char abs_reserved;
+    unsigned char abs_min;
+    unsigned char abs_sec;
+    unsigned char abs_frame;
+    unsigned char trel_reserved;
+    unsigned char trel_min;
+    unsigned char trel_sec;
+    unsigned char trel_frame;
+} subq_position;
+
+typedef struct subq_catalog {
+    unsigned char mc_valid;    /* MSB */
+    unsigned char media_catalog_number[13];
+    unsigned char zero;
+    unsigned char aframe;
+} subq_catalog;
+
+typedef struct subq_track_isrc {
+    unsigned char tc_valid;    /* MSB */
+    unsigned char track_isrc[15];
+} subq_track_isrc;
+
+#if    !defined        NO_SCSI_STUFF
+
+struct TOC;
+
+/* cdrom access function pointer */
+extern void     (*EnableCdda)(SCSI *usalp, int Switch, unsigned uSectorsize);
+extern unsigned (*doReadToc)(SCSI *usalp);
+extern void    (*ReadTocText)(SCSI *usalp);
+extern unsigned (*ReadLastAudio)(SCSI *usalp);
+extern int      (*ReadCdRom)(SCSI *usalp, UINT4 *p, unsigned lSector, 
+                                                                         unsigned SectorBurstVal);
+extern int      (*ReadCdRomSub)(SCSI *usalp, UINT4 *p, unsigned lSector, 
+                                                                                 unsigned SectorBurstVal);
+extern int      (*ReadCdRomData)(SCSI *usalp, unsigned char *p, unsigned lSector,
+                                                                                       unsigned SectorBurstVal);
+extern subq_chnl *(*ReadSubQ)(SCSI *usalp, unsigned char sq_format, 
+                                                                               unsigned char track);
+extern subq_chnl *(*ReadSubChannels)(SCSI *usalp, unsigned lSector);
+extern void     (*SelectSpeed)(SCSI *usalp, unsigned speed);
+extern int     (*Play_at)(SCSI *usalp, unsigned from_sector, unsigned sectors);
+extern int     (*StopPlay)(SCSI *usalp);
+extern void    (*trash_cache)(UINT4 *p, unsigned lSector, unsigned SectorBurstVal);
+
+SCSI    *get_scsi_p(void);
+#endif
+
+extern unsigned char *bufferTOC;
+extern subq_chnl *SubQbuffer;
+
+
+void SetupInterface(void);
+int    Toshiba3401(void);
+
+void   priv_init(void);
+void   priv_on(void);
+void   priv_off(void);
diff --git a/icedax/ioctl.c b/icedax/ioctl.c
new file mode 100644 (file)
index 0000000..c3bd627
--- /dev/null
@@ -0,0 +1,578 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)ioctl.c 1.22 06/02/19 Copyright 1998,1999,2000 Heiko Eissfeldt, Copyright 2006 J. Schilling */
+/***
+ * CopyPolicy: GNU Public License 2 applies
+ * Copyright (C) 1999 Heiko Eissfeldt heiko@colossus.escape.de
+ *
+ * Ioctl interface module for cdrom drive access
+ *
+ * Solaris ATAPI cdrom drives are untested!
+ *
+ */
+#include "config.h"
+#include <stdio.h>
+#include <standard.h>
+#include <stdxlib.h>
+#include <unixstd.h>
+#include <strdefs.h>
+#include <errno.h>
+#include <signal.h>
+#include <fctldefs.h>
+#include <assert.h>
+
+#include <sys/ioctl.h>
+#include <statdefs.h>
+#include <schily.h>
+#include <device.h>
+
+#include <usal/scsitransp.h>
+
+#include "mycdrom.h"
+#include "lowlevel.h"
+/* some include file locations have changed with newer kernels */
+#if defined (__linux__)
+# if LINUX_VERSION_CODE > 0x10300 + 97
+#  if LINUX_VERSION_CODE < 0x200ff
+#   include <linux/sbpcd.h>
+#   include <linux/ucdrom.h>
+#  endif
+#  if !defined(CDROM_SELECT_SPEED)
+#   include <linux/ucdrom.h>
+#  endif
+# endif
+#endif
+
+#include "mytype.h"
+#include "byteorder.h"
+#include "interface.h"
+#include "toc.h"
+#include "icedax.h"
+#include "ioctl.h"
+#include "global.h"
+#include "exitcodes.h"
+
+#include <utypes.h>
+#include <wodim.h>
+
+#if defined (HAVE_IOCTL_INTERFACE)
+#if  !defined(sun) && !defined(__sun) && !(defined(__FreeBSD__) && (__FreeBSD_version >= 501112))
+static struct cdrom_read_audio arg;
+#endif
+
+#if (defined(__FreeBSD__) && __FreeBSD_version >= 400014) || defined(__DragonFly__) || defined(__FreeBSD_kernel__)
+static unsigned sector_size;
+#endif
+
+static int err;
+
+static void EnableCdda_cooked(SCSI *usalp, int fAudioMode, unsigned uSectorsize);
+/* ARGSUSED */
+static void EnableCdda_cooked(SCSI *usalp, int fAudioMode, unsigned uSectorsize)
+{
+#if    (defined(__FreeBSD__) && __FreeBSD_version >= 400014) || defined(__DragonFly__)  || defined(__FreeBSD_kernel__)
+       if (usalp && usalp->verbose)
+               fprintf(stderr, "EnableCdda_cooked (CDRIOCSETBLOCKSIZE)...\n");
+
+       if (fAudioMode) {
+               if (ioctl(global.cooked_fd, CDRIOCGETBLOCKSIZE, &sector_size) ==-1)
+                       sector_size = CD_FRAMESIZE;
+               ioctl(global.cooked_fd, CDRIOCSETBLOCKSIZE, &uSectorsize);
+       } else
+               ioctl(global.cooked_fd, CDRIOCSETBLOCKSIZE, &sector_size);
+#else
+#if    defined CDIOCSETCDDA
+       if (usalp && usalp->verbose) {
+               fprintf(stderr, "EnableCdda_cooked (CDIOCSETCDDA)...\n");
+               if (uSectorsize != CD_FRAMESIZE_RAW)
+                       fprintf(stderr, "non audio sector size is ignored.\n");
+       }
+
+       ioctl(global.cooked_fd, CDIOCSETCDDA, &fAudioMode);
+#else
+       fprintf(stderr, "EnableCdda_cooked (CDIOCSETCDDA) is not available...\n");
+#endif
+#endif
+
+}
+
+
+static unsigned ReadToc_cooked(SCSI *x);
+
+/* read the table of contents (toc) via the ioctl interface */
+static unsigned ReadToc_cooked(SCSI *x)
+{
+    unsigned i;
+    unsigned tracks;
+    struct cdrom_tochdr hdr;
+    struct cdrom_tocentry entry[100];
+    struct cdrom_tocentry entryMSF[100];
+
+    if (x && x->verbose) {
+       fprintf(stderr, "ReadToc_cooked (CDROMREADTOCHDR)...\n");
+    }
+
+    /* get TocHeader to find out how many entries there are */
+    err = ioctl( global.cooked_fd, CDROMREADTOCHDR, &hdr );
+    if ( err != 0 ) {
+       /* error handling */
+       if (err == -1) {
+           if (errno == EPERM)
+               fprintf( stderr, "Please run this program setuid root.\n");
+           perror("cooked: Read TOC ");
+           exit( DEVICE_ERROR );
+       } else {
+           fprintf( stderr, "can't get TocHeader (error %d).\n", err );
+           exit( MEDIA_ERROR );
+       }
+    }
+    /* get all TocEntries */
+    for ( i = 0; i < hdr.cdth_trk1; i++ ) {
+       entryMSF[i].cdte_track = 1+i;
+       entryMSF[i].cdte_format = CDROM_MSF;
+       err = ioctl( global.cooked_fd, CDROMREADTOCENTRY, &entryMSF[i] );
+       if ( err != 0 ) {
+           /* error handling */
+           fprintf( stderr, "can't get TocEntry #%d msf (error %d).\n", i+1, err );
+           exit( MEDIA_ERROR );
+       }
+    }
+    entryMSF[i].cdte_track = CDROM_LEADOUT;
+    entryMSF[i].cdte_format = CDROM_MSF;
+    err = ioctl( global.cooked_fd, CDROMREADTOCENTRY, &entryMSF[i] );
+    if ( err != 0 ) {
+       /* error handling */
+       fprintf( stderr, "can't get TocEntry LEADOUT msf (error %d).\n", err );
+       exit( MEDIA_ERROR );
+    }
+    tracks = hdr.cdth_trk1+1;
+/*
+    for (i = 0; i < tracks; i++) {
+        toc[i].bFlags = (entry[i].cdte_adr << 4) | (entry[i].cdte_ctrl & 0x0f);
+        toc[i].bTrack = entry[i].cdte_track;
+       toc[i].mins = entry[i].cdte_addr.msf.minute;
+       toc[i].secs = entry[i].cdte_addr.msf.second;
+       toc[i].frms = entry[i].cdte_addr.msf.frame;
+    }
+*/
+    /* get all TocEntries now in lba format */
+    for ( i = 0; i < hdr.cdth_trk1; i++ ) {
+       entry[i].cdte_track = 1+i;
+       entry[i].cdte_format = CDROM_LBA;
+       err = ioctl( global.cooked_fd, CDROMREADTOCENTRY, &entry[i] );
+       if ( err != 0 ) {
+           /* error handling */
+           fprintf( stderr, "can't get TocEntry #%d lba (error %d).\n", i+1, err );
+           exit( MEDIA_ERROR );
+       }
+#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__)
+       entry[i].cdte_addr.lba = be32_to_cpu(entry[i].cdte_addr.lba);
+#endif
+    }
+    entry[i].cdte_track = CDROM_LEADOUT;
+    entry[i].cdte_format = CDROM_LBA;
+    err = ioctl( global.cooked_fd, CDROMREADTOCENTRY, &entry[i] );
+    if ( err != 0 ) {
+       /* error handling */
+       fprintf( stderr, "can't get TocEntry LEADOUT lba (error %d).\n", err );
+       exit( MEDIA_ERROR );
+    }
+#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__)
+    entry[i].cdte_addr.lba = be32_to_cpu(entry[i].cdte_addr.lba);
+#endif
+
+    for (i = 0; i < tracks; i++) {
+        toc_entry(i+1,
+                 (entry[i].cdte_adr << 4) | (entry[i].cdte_ctrl & 0x0f),
+                 entry[i].cdte_track,
+                 NULL /* ISRC */,
+                 entry[i].cdte_addr.lba,
+                 entryMSF[i].cdte_addr.msf.minute,
+                 entryMSF[i].cdte_addr.msf.second,
+                 entryMSF[i].cdte_addr.msf.frame);
+    }
+    bufferTOC[0] = '\0';
+    bufferTOC[1] = '\0';
+    return --tracks;           /* without lead-out */
+}
+
+static void trash_cache_cooked(UINT4 *p, unsigned lSector, 
+                                                                                unsigned SectorBurstVal);
+
+static void trash_cache_cooked(UINT4 *p, unsigned lSector, 
+                               unsigned SectorBurstVal)
+{
+      /* trash the cache */
+
+#if    defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__)
+#if    defined(__FreeBSD__) && __FreeBSD_version >= 501112
+      pread(global.cooked_fd, (void *) &p[0], 3*CD_FRAMESIZE_RAW,
+          find_an_off_sector(lSector, SectorBurstVal)*CD_FRAMESIZE_RAW);
+#else
+      static struct cdrom_read_audio arg2;
+
+      arg2.address.lba = find_an_off_sector(lSector, SectorBurstVal);
+      arg2.addr_format = CDROM_LBA;
+      arg2.nframes = 3;
+      arg2.buffer = (unsigned char *) &p[0];
+
+      ioctl(global.cooked_fd, CDROMREADAUDIO, &arg2);
+#endif
+#endif
+#if    defined __linux__
+      static struct cdrom_read_audio arg2;
+
+      arg2.addr.lba = find_an_off_sector(lSector, SectorBurstVal);
+      arg2.addr_format = CDROM_LBA;
+      arg2.nframes = 3;
+      arg2.buf = (unsigned char *) &p[0];
+
+      ioctl(global.cooked_fd, CDROMREADAUDIO, &arg2);
+#endif
+#if    defined __sun || (defined HAVE_SYS_CDIO_H && defined CDROM_DA_NO_SUBCODE)
+      struct cdrom_cdda suncdda;
+
+      suncdda.cdda_addr = lSector;
+      suncdda.cdda_length = SectorBurstVal*CD_FRAMESIZE_RAW;
+      suncdda.cdda_data = (char *) &p[0];
+      suncdda.cdda_subcode = CDROM_DA_NO_SUBCODE;
+      ioctl(global.cooked_fd, CDROMCDDA, &suncdda);
+#endif
+}
+
+static void ReadCdRomData_cooked(SCSI *x, UINT4 *p, unsigned lSector, 
+                                                                                       unsigned SectorBurstVal);
+/* read 'SectorBurst' adjacent sectors of data sectors 
+ * to Buffer '*p' beginning at sector 'lSector'
+ */
+static void ReadCdRomData_cooked(SCSI *x, UINT4 *p, unsigned lSector, 
+                                 unsigned SectorBurstVal)
+{
+       int     retval;
+
+       if (x && x->verbose) {
+               fprintf(stderr, "ReadCdRomData_cooked (lseek & read)...\n");
+       }
+
+       if ((retval = lseek(global.cooked_fd, lSector*CD_FRAMESIZE, SEEK_SET))
+               != (int)lSector*CD_FRAMESIZE) { perror("cannot seek sector"); }
+       if ((retval = read(global.cooked_fd, p, SectorBurstVal*CD_FRAMESIZE))
+               != (int)SectorBurstVal*CD_FRAMESIZE) { perror("cannot read sector"); }
+
+       return;
+}
+
+static int ReadCdRom_cooked(SCSI *x, UINT4 *p, unsigned lSector, 
+                                                                        unsigned SectorBurstVal);
+/* read 'SectorBurst' adjacent sectors of audio sectors 
+ * to Buffer '*p' beginning at sector 'lSector'
+ */
+static int ReadCdRom_cooked(SCSI *x, UINT4 *p, unsigned lSector, 
+                            unsigned SectorBurstVal)
+{
+  int retry_count=0;
+  static int nothing_read = 1;
+
+/* read 2352 bytes audio data */
+#if    defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__)
+#if    defined(__FreeBSD__) && __FreeBSD_version >= 501112
+    if (x && x->verbose) {
+       fprintf(stderr, "ReadCdRom_cooked (pread)...\n");
+    }
+
+  do {
+    err = 0;
+    if (pread(global.cooked_fd, (void *) &p[0], SectorBurstVal*CD_FRAMESIZE_RAW,
+       lSector*CD_FRAMESIZE_RAW) == -1)
+               err = -1;
+#else
+  arg.address.lba = lSector;
+  arg.addr_format = CDROM_LBA;
+  arg.nframes = SectorBurstVal;
+  arg.buffer = (unsigned char *) &p[0];
+
+    if (x && x->verbose) {
+       fprintf(stderr, "ReadCdRom_cooked (CDROMREADAUDIO)...\n");
+    }
+
+  do {
+    err = ioctl(global.cooked_fd, CDROMREADAUDIO, &arg);
+#endif
+#endif
+#if    defined __linux__
+  arg.addr.lba = lSector;
+  arg.addr_format = CDROM_LBA;
+  arg.nframes = SectorBurstVal;
+  arg.buf = (unsigned char *) &p[0];
+
+    if (x && x->verbose) {
+       fprintf(stderr, "ReadCdRom_cooked (CDROMREADAUDIO)...\n");
+    }
+
+  do {
+    err = ioctl(global.cooked_fd, CDROMREADAUDIO, &arg);
+#endif
+#if    defined __sun || (defined HAVE_SYS_CDIO_H && defined CDROM_DA_NO_SUBCODE)
+  struct cdrom_cdda suncdda;
+
+  suncdda.cdda_addr = lSector;
+  suncdda.cdda_length = SectorBurstVal*CD_FRAMESIZE_RAW;
+  suncdda.cdda_data = (char *) &p[0];
+  suncdda.cdda_subcode = CDROM_DA_NO_SUBCODE;
+    if (x && x->verbose) {
+       fprintf(stderr, "ReadCdRom_cooked (CDROMCDDA)...\n");
+    }
+
+  do {
+    err = ioctl(global.cooked_fd, CDROMCDDA, &suncdda);
+#endif
+    retry_count++;
+
+    if (err) { 
+      trash_cache_cooked(p, lSector, SectorBurstVal);
+    }
+
+  } while ((err) && (retry_count < 30));
+  if (err != 0) {
+       if (x->silent == 0) {
+               /* error handling */
+               if (err == -1) {
+                       if (nothing_read && (errno == EINVAL || errno == EIO))
+                               fprintf( stderr, "Sorry, this driver and/or drive does not support cdda reading.\n");
+                       perror("cooked: Read cdda ");
+                       fprintf(stderr, " sector %u + %u, buffer %p + %x\n", lSector, SectorBurstVal, p, global.shmsize);
+               } else {
+                       fprintf(stderr, "can't read frame #%u (error %d).\n", 
+                               lSector, err);
+               }
+       }
+       return SectorBurstVal - 1;
+  } else {
+    nothing_read = 0;
+  }
+
+  return SectorBurstVal;
+}
+
+static int StopPlay_cooked(SCSI *x);
+static int StopPlay_cooked(SCSI *x)
+{
+    if (x && x->verbose) {
+       fprintf(stderr, "StopPlay_cooked (CDROMSTOP)...\n");
+    }
+
+       return ioctl( global.cooked_fd, CDROMSTOP, 0 ) ? 0 : -1; 
+}
+
+static int Play_at_cooked(SCSI *x, unsigned int from_sector, 
+                                                                 unsigned int sectors);
+static int Play_at_cooked(SCSI *x, unsigned int from_sector, 
+                          unsigned int sectors)
+{
+       struct cdrom_msf cmsf;
+       int retval;
+
+    if (x && x->verbose) {
+       fprintf(stderr, "Play_at_cooked (CDROMSTART & CDROMPLAYMSF)... (%u-%u)",
+               from_sector, from_sector+sectors-1);
+       
+       fprintf(stderr, "\n");
+    }
+
+       cmsf.cdmsf_min0 = (from_sector + 150) / (60*75);
+       cmsf.cdmsf_sec0 = ((from_sector + 150) / 75) % 60;
+       cmsf.cdmsf_frame0 = (from_sector + 150) % 75;
+       cmsf.cdmsf_min1 = (from_sector + 150 + sectors) / (60*75);
+       cmsf.cdmsf_sec1 = ((from_sector + 150 + sectors) / 75) % 60;
+       cmsf.cdmsf_frame1 = (from_sector + 150 + sectors) % 75;
+
+#if    0
+/* makes index scanning under FreeBSD too slow */
+       if (( retval = ioctl( global.cooked_fd, CDROMSTART, 0 )) != 0){
+               perror("");
+       }
+#endif
+       if (( retval = ioctl( global.cooked_fd, CDROMPLAYMSF, &cmsf )) != 0){
+               perror("");
+       }
+       return retval;
+}
+
+/* request sub-q-channel information. This function may cause confusion
+ * for a drive, when called in the sampling process.
+ */
+static subq_chnl *ReadSubQ_cooked(SCSI *x, unsigned char sq_format, 
+                                                                                        unsigned char track)
+{
+    struct cdrom_subchnl sub_ch;
+
+#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__)
+    struct cd_sub_channel_info sub_ch_info;
+
+    if (x && x->verbose) {
+       fprintf(stderr, "ReadSubQ_cooked (CDROM_GET_MCN or CDROMSUBCHNL)...\n");
+    }
+
+    sub_ch.address_format = CD_MSF_FORMAT;
+    sub_ch.track = track;
+    sub_ch.data_len = sizeof(struct cd_sub_channel_info);
+    sub_ch.data = &sub_ch_info;
+
+    switch (sq_format) {
+      case GET_CATALOGNUMBER:
+      sub_ch.data_format = CD_MEDIA_CATALOG;
+#else
+    if (x && x->verbose) {
+       fprintf(stderr, "ReadSubQ_cooked (CDROM_GET_MCN or CDROMSUBCHNL)...\n");
+    }
+
+    switch (sq_format) {
+      case GET_CATALOGNUMBER:
+#endif
+#if    defined CDROM_GET_MCN
+      if (!(err = ioctl(global.cooked_fd, CDROM_GET_MCN, (struct cdrom_mcn *) SubQbuffer))) {
+          subq_chnl *SQp = (subq_chnl *) SubQbuffer;
+         subq_catalog *SQPp = (subq_catalog *) &SQp->data;
+
+          memmove(SQPp->media_catalog_number, SQp, sizeof (SQPp->media_catalog_number));
+          SQPp->zero = 0;
+          SQPp->mc_valid = 0x80;
+          break;
+      } else
+#endif
+      {
+          return NULL;
+      }
+      case GET_POSITIONDATA:
+#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__)
+      sub_ch.data_format = CD_CURRENT_POSITION;
+#endif
+#if defined (__linux__)
+      sub_ch.cdsc_format = CDROM_MSF;
+#endif
+      if (!(err = ioctl(global.cooked_fd, CDROMSUBCHNL, &sub_ch))) {
+         /* copy to SubQbuffer */
+         subq_chnl *SQp = (subq_chnl *) (SubQbuffer);
+         subq_position *SQPp = (subq_position *) SQp->data;
+         SQp->audio_status     = sub_ch.cdsc_audiostatus;
+         SQp->format           = sub_ch.cdsc_format;
+         SQp->control_adr      = (sub_ch.cdsc_adr << 4) | (sub_ch.cdsc_ctrl & 0x0f);
+         SQp->track            = sub_ch.cdsc_trk;
+         SQp->index            = sub_ch.cdsc_ind;
+         SQPp->abs_min         = sub_ch.cdsc_absaddr.msf.minute;
+         SQPp->abs_sec         = sub_ch.cdsc_absaddr.msf.second;
+         SQPp->abs_frame       = sub_ch.cdsc_absaddr.msf.frame;
+         SQPp->trel_min        = sub_ch.cdsc_reladdr.msf.minute;
+         SQPp->trel_sec        = sub_ch.cdsc_reladdr.msf.second;
+         SQPp->trel_frame      = sub_ch.cdsc_reladdr.msf.frame;
+      } else {
+         if (err == -1) {
+             if (errno == EPERM)
+                 fprintf( stderr, "Please run this program setuid root.\n");
+             perror("cooked: Read subq ");
+             exit( DEVICE_ERROR );
+         } else {
+             fprintf(stderr, "can't read sub q channel (error %d).\n", err);
+             exit( DEVICE_ERROR );
+         }
+      }
+      break;
+      default:
+          return NULL;
+    } /* switch */
+  return (subq_chnl *)(SubQbuffer);
+}
+
+/* Speed control */
+static void SpeedSelect_cooked(SCSI *x, unsigned speed);
+/* ARGSUSED */
+static void SpeedSelect_cooked(SCSI *x, unsigned speed)
+{
+       if (x && x->verbose) {
+               fprintf(stderr, "SpeedSelect_cooked (CDROM_SELECT_SPEED)...\n");
+       }
+
+#ifdef CDROM_SELECT_SPEED
+       /* CAUTION!!!!! Non standard ioctl parameter types here!!!! */
+       if ((err = ioctl(global.cooked_fd, CDROM_SELECT_SPEED, speed))) {
+               if (err == -1) {
+                       if (errno == EPERM)
+                               fprintf( stderr, "Please run this program setuid root.\n");
+                       perror("cooked: Speed select ");
+                       /*exit( err ); */
+               } else {
+                       fprintf(stderr, "can't set speed %d (error %d).\n", speed, err);
+                       exit( DEVICE_ERROR );
+               }
+       }
+#endif
+}
+
+/* set function pointers to use the ioctl routines */
+void SetupCookedIoctl(char *pdev_name)
+{
+#if (HAVE_ST_RDEV == 1)
+    struct stat statstruct;
+
+    if (fstat(global.cooked_fd, &statstruct)) {
+      fprintf(stderr, "cannot stat cd %d (%s)\n",global.cooked_fd, pdev_name);
+      exit(STAT_ERROR);
+    }
+#if    defined __linux__
+    switch (major(statstruct.st_rdev)) {
+    case CDU31A_CDROM_MAJOR:   /* sony cdu-31a/33a */
+        global.nsectors = 13;
+        if (global.nsectors >= 14) {
+         global.overlap = 10;
+       }
+        break;
+    case MATSUSHITA_CDROM_MAJOR:       /* sbpcd 1 */
+    case MATSUSHITA_CDROM2_MAJOR:      /* sbpcd 2 */
+    case MATSUSHITA_CDROM3_MAJOR:      /* sbpcd 3 */
+    case MATSUSHITA_CDROM4_MAJOR:      /* sbpcd 4 */
+        /* some are more compatible than others */
+        global.nsectors = 13;
+       break;
+    default:
+        global.nsectors = 8;
+       break;
+    }
+    err = ioctl(global.cooked_fd, CDROMAUDIOBUFSIZ, global.nsectors);
+
+    switch (major(statstruct.st_rdev)) {
+    case MATSUSHITA_CDROM_MAJOR:       /* sbpcd 1 */
+    case MATSUSHITA_CDROM2_MAJOR:      /* sbpcd 2 */
+    case MATSUSHITA_CDROM3_MAJOR:      /* sbpcd 3 */
+    case MATSUSHITA_CDROM4_MAJOR:      /* sbpcd 4 */
+      if (err == -1) {
+        perror("ioctl(CDROMAUDIOBUFSIZ)");
+      }
+    }
+#endif
+#endif
+    EnableCdda = EnableCdda_cooked;
+    ReadCdRom = ReadCdRom_cooked;
+    ReadCdRomData = (int (*)(SCSI *, unsigned char *, unsigned, unsigned)) ReadCdRomData_cooked;
+    doReadToc = ReadToc_cooked;
+    ReadTocText = NULL;
+    ReadSubQ = ReadSubQ_cooked;
+    ReadSubChannels = NULL;
+    SelectSpeed = SpeedSelect_cooked;
+    Play_at = Play_at_cooked;
+    StopPlay = StopPlay_cooked;
+    trash_cache = trash_cache_cooked;
+    ReadLastAudio = NULL;
+}
+#endif
diff --git a/icedax/ioctl.h b/icedax/ioctl.h
new file mode 100644 (file)
index 0000000..0fc4e92
--- /dev/null
@@ -0,0 +1,14 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)ioctl.h 1.2 99/12/19 Copyright 1998,1999 Heiko Eissfeldt */
+void SetupCookedIoctl(char *pdev_name);
diff --git a/icedax/lconfig.h b/icedax/lconfig.h
new file mode 100644 (file)
index 0000000..07326c8
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* lconfig.h.  Generated automatically by configure.  */
+#if 0
+/* @(#)lconfig.h.in    1.5 03/09/04 Copyright 1998-2003 Heiko Eissfeldt */
+#endif
+/* #undef HAVE_SYS_CDIO_H */           /* if we should use sys/cdio.h */
+
+/* #undef HAVE_SUNDEV_SRREG_H */       /* if we should use sundev/srreg.h */
+
+/* #undef HAVE_SYS_AUDIOIO_H */        /* if we should use sys/audioio.h */
+
+/* #undef HAVE_SUN_AUDIOIO_H */        /* if we should use sun/audioio.h */
+
+/* #undef HAVE_SOUNDCARD_H */          /* if we should use soundcard.h */
+
+/* TESTED BY CMAKE */
+/*#define HAVE_SYS_SOUNDCARD_H 1       if we should use sys/soundcard.h */
+/*define HAVE_LINUX_SOUNDCARD_H 1      if we should use linux/soundcard.h */
+
+/* #undef HAVE_MACHINE_SOUNDCARD_H */  /* if we should use machine/soundcard.h */
+
+/* #undef HAVE_SYS_ASOUNDLIB_H */      /* if we should use sys/asoundlib.h */
+
+/* #undef HAVE_WINDOWS_H */            /* if we should use windows.h */
+
+/* #undef HAVE_MMSYSTEM_H */           /* if we should use mmsystem.h */
+
+/* #undef HAVE_OS2_H */                /* if we should use os2.h */
+
+/* #undef HAVE_OS2ME_H */              /* if we should use os2me.h */
+
+#if    defined HAVE_SOUNDCARD_H || defined HAVE_SYS_SOUNDCARD_H  || defined HAVE_LINUX_SOUNDCARD_H || defined HAVE_MACHINE_SOUNDCARD_H
+#define HAVE_OSS       1
+#endif
+
+/*
+#if    defined HAVE_WINDOWS_H && defined HAVE_MMSYSTEM_H
+#define HAVE_WINSOUND  1
+#endif
+
+#if    defined HAVE_OS2_H && defined HAVE_OS2ME_H
+#define HAVE_OS2SOUND  1
+#endif
+*/
+
+#define HAVE_STRTOUL 1
+
+
+/* EB, some defaults, fixme
+ */
+
+#define CD_DEVICE "/dev/cdrom"
+#define FILENAME "audio"
+#define UNDERSAMPLING 1
+#define VERSION CDRKIT_VERSION
+#define BITS_P_S 16
+#define CHANNELS 2
+#define AUDIOTYPE "wav"
+#define DURATION 0
+#define DEF_INTERFACE "generic_scsi"
+#define USE_PARANOIA 1
+#define DEFAULT_SPEED 0
+#define CDINDEX_SUPPORT
+#define CDDB_SUPPORT
+#define CDDBHOST "freedb.freedb.org"
+#define CDDBPORT 8880
+#define HAVE_IOCTL_INTERFACE
+#define ECHO_TO_SOUNDCARD
+#define SOUND_DEV "/dev/dsp"
+#define NSECTORS 75
+#define INFOFILES
+/* #undef MD5_SIGNATURES */             /* not implemented */
+#define AUX_DEVICE "/dev/cdrom"
+
diff --git a/icedax/lconfig.h.in b/icedax/lconfig.h.in
new file mode 100644 (file)
index 0000000..9ef9230
--- /dev/null
@@ -0,0 +1,44 @@
+#if 0
+/* @(#)lconfig.h.in    1.6 06/02/15 Copyright 1998-2003 Heiko Eissfeldt */
+#endif
+#undef HAVE_SYS_CDIO_H         /* if we should use sys/cdio.h */
+
+#undef HAVE_SYS_CDRIO_H                /* if we should use sys/cdrio.h */
+
+#undef HAVE_SUNDEV_SRREG_H     /* if we should use sundev/srreg.h */
+
+#undef HAVE_SYS_AUDIOIO_H      /* if we should use sys/audioio.h */
+
+#undef HAVE_SUN_AUDIOIO_H      /* if we should use sun/audioio.h */
+
+#undef HAVE_SOUNDCARD_H                /* if we should use soundcard.h */
+
+#undef HAVE_SYS_SOUNDCARD_H    /* if we should use sys/soundcard.h */
+
+#undef HAVE_LINUX_SOUNDCARD_H  /* if we should use linux/soundcard.h */
+
+#undef HAVE_MACHINE_SOUNDCARD_H        /* if we should use machine/soundcard.h */
+
+#undef HAVE_SYS_ASOUNDLIB_H    /* if we should use sys/asoundlib.h */
+
+#undef HAVE_WINDOWS_H          /* if we should use windows.h */
+
+#undef HAVE_MMSYSTEM_H         /* if we should use mmsystem.h */
+
+#undef HAVE_OS2_H              /* if we should use os2.h */
+
+#undef HAVE_OS2ME_H            /* if we should use os2me.h */
+
+#if    defined HAVE_SOUNDCARD_H || defined HAVE_SYS_SOUNDCARD_H  || defined HAVE_LINUX_SOUNDCARD_H || defined HAVE_MACHINE_SOUNDCARD_H
+#define HAVE_OSS       1
+#endif
+
+#if    defined HAVE_WINDOWS_H && defined HAVE_MMSYSTEM_H
+#define HAVE_WINSOUND  1
+#endif
+
+#if    defined HAVE_OS2_H && defined HAVE_OS2ME_H
+#define HAVE_OS2SOUND  1
+#endif
+
+#undef HAVE_STRTOUL
diff --git a/icedax/list_audio_tracks.1 b/icedax/list_audio_tracks.1
new file mode 100644 (file)
index 0000000..b4a1dd0
--- /dev/null
@@ -0,0 +1,54 @@
+.TH "LIST_AUDIO_TRACKS" "1" "Tue Feb 15 13:03:51 MST 2005" "" "list_audio_tracks"
+
+.PP
+.SH "NAME"
+list_audio_tracks is an alias for icedax.
+.PP
+.SH "SYNOPSIS"
+.PP
+\fBlist_audio-tracks\fP
+.PP
+.SH "DESCRIPTION"
+.PP
+\fBlist_audio_tracks\fP equals to the invocation of icedax, so all the
+arguments for the latter can be used.
+.PP
+.SH SEE ALSO
+icedax(1)
+.PP 
+.SH "AUTHOR" 
+.PP 
+\fBicedax\fP was written by Heiko Eissfeldt and others.
+.PP 
+This manpage describes the program implementation of
+.B
+list_audio_tracks
+as shipped by the cdrkit distribution. See
+.B
+http://alioth.debian.org/projects/debburn/
+for details. It is a spinoff from the original program called cdda2wav
+distributed by the cdrtools project. However, the cdrtools developers are not
+involved in the development of this spinoff and therefore shall not be made
+responsible for any problem caused by it. Do not try to get support for this
+program by contacting the original authors.
+.PP
+If you have support questions, send them to
+.PP
+.B
+debburn-devel@lists.alioth.debian.org
+.br
+.PP
+If you have definitely found a bug, send a mail to this list or to
+.PP
+.B
+submit@bugs.debian.org
+.br
+.PP
+writing at least a short description into the Subject and "Package: cdrkit" into the first line of the mail body.
+.PP
+This manual page was written by Oleksandr Moskalenko
+<malex@tagancha\&.org>, for
+the Debian GNU/Linux system\&.  It may be used by other distributions
+without contacting the author\&.  Any mistakes or omissions in the
+manual page are my fault; inquiries about or corrections to this
+manual page should be directed to me (and not to the primary author)\&.
diff --git a/icedax/local.cnf.in b/icedax/local.cnf.in
new file mode 100644 (file)
index 0000000..5c126a7
--- /dev/null
@@ -0,0 +1,141 @@
+# @(#)local.cnf.in       1.6 03/09/04 Copyright 1998-2002 Heiko Eissfeldt
+#
+# Makefile for cdda2wav, a sampling utility.
+#
+
+# ############ interface
+# choose one of the following interfacing and device types.
+# generic_scsi is for scsi cdrom devices.
+# uncomment one INTERFACE and one DEF_DEVICE line
+# (for details consult the README)
+INTERFACE='"generic_scsi"'
+#INTERFACE='"cooked_ioctl"'
+
+# set the default cdrom device
+SUN_OS_DEFAULT_DEV=    '"0,6,0"'
+YOUR_DEFAULT_DEV=      '"yourSCSI_Bus,yourSCSI_ID,yourSCSI_LUN"'
+
+_DEF_DEVICE=   $(_UNIQ)$(HAVE_SUN_OS)
+__DEF_DEVICE=  $(_DEF_DEVICE:$(_UNIQ)=$(YOUR_DEFAULT_DEV))
+DEF_DEVICE=    $(__DEF_DEVICE:$(_UNIQ)$(HAVE_SUN_OS)=$(SUN_OS_DEFAULT_DEV))
+
+# optional matching device used for a MULTISESSION ioctl
+LINUX_AUX_DEV= '"/dev/cdrom"'
+
+_AUX_DEVICE=   $(_UNIQ)$(HAVE_LINUX)
+__AUX_DEVICE=  $(_AUX_DEVICE:$(_UNIQ)='""')
+AUX_DEVICE=    $(__AUX_DEVICE:$(_UNIQ)$(HAVE_LINUX)=$(LINUX_AUX_DEV))
+
+# number of sectors to request
+# under BSD better use < 128 K of shared memory
+SECTORS=75
+BSD_SECTORS=27
+
+_SECTORS=      $(_UNIQ)$(HAVE_BSD_OS)
+__SECTORS=     $(_SECTORS:$(_UNIQ)=$(SECTORS))
+NSECTORS=      $(__SECTORS:$(_UNIQ)$(HAVE_BSD_OS)=$(BSD_SECTORS))
+
+# some architectures can use the ioctl() interface cooked_ioctl
+HAVE_SUN_IOCTL=        @HAVE_SUN_IOCTL@
+_HAVE_IOCTL=   $(_UNIQ)$(HAVE_BSD_OS)$(HAVE_SUN_IOCTL)$(HAVE_LINUX)
+__HAVE_IOCTL=  $(_HAVE_IOCTL:$(_UNIQ)=)
+HAVE_IOCTL=    $(__HAVE_IOCTL:$(_UNIQ)$(HAVE_BSD_OS)$(HAVE_SUN_IOCTL)$(HAVE_LINUX)=-DHAVE_IOCTL_INTERFACE)
+
+############# Sound device support
+#to disable sound support comment out the corresponding line with HAVE_SOUND
+OSS_SOUND_DEV= '"/dev/dsp"'
+SUN_SOUND_DEV= '"/dev/audio"'
+
+HAVE_OSS=      @HAVE_OSS@
+HAVE_SUNSOUND= @HAVE_SUNSOUND@
+HAVE_WINSOUND= @HAVE_WINSOUND@
+HAVE_OS2SOUND= @HAVE_OS2SOUND@
+HAVE_QNXSOUND= @HAVE_SYS_ASOUNDLIB_H@
+#_HAVE_SOUND=  $(_UNIQ)$(HAVE_OSS)$(HAVE_SUNSOUND)
+_HAVE_SOUND=   $(_UNIQ)$(HAVE_OSS)$(HAVE_SUNSOUND)$(HAVE_WINSOUND)$(HAVE_OS2SOUND)$(HAVE_QNXSOUND)
+__HAVE_SOUND=  $(_HAVE_SOUND:$(_UNIQ)=)
+#HAVE_SOUND=   $(__HAVE_SOUND:$(_UNIQ)$(HAVE_OSS)$(HAVE_SUNSOUND)=-DECHO_TO_SOUNDCARD)
+HAVE_SOUND=    $(__HAVE_SOUND:$(_UNIQ)$(HAVE_OSS)$(HAVE_SUNSOUND)$(HAVE_WINSOUND)$(HAVE_OS2SOUND)$(HAVE_QNXSOUND)=-DECHO_TO_SOUNDCARD)
+
+_SOUND_DEVICE= $(_UNIQ)$(HAVE_OSS)$(HAVE_SOUND)$(HAVE_SUNSOUND)
+__SOUND_DEVICE=        $(_SOUND_DEVICE:$(_UNIQ)='""')
+___SOUND_DEVICE=       $(__SOUND_DEVICE:$(_UNIQ)$(HAVE_OSS)$(HAVE_SOUND)=$(OSS_SOUND_DEV))
+____SOUND_DEVICE=      $(___SOUND_DEVICE:$(_UNIQ)$(HAVE_SOUND)$(HAVE_SUNSOUND)=$(SUN_SOUND_DEV))
+SOUND_DEVICE=  $(____SOUND_DEVICE:$(_UNIQ)$(HAVE_OSS)$(HAVE_SOUND)$(HAVE_SUNSOUND)=$(OSS_SOUND_DEV))
+
+_EXTRALIB=     $(_UNIQ)$(HAVE_WINSOUND)$(HAVE_OS2SOUND)$(HAVE_QNXSOUND)
+__EXTRALIB=    $(_EXTRALIB:$(_UNIQ)=@EXTRALIBS@)
+___EXTRALIB=   $(__EXTRALIB:$(_UNIQ)$(HAVE_WINSOUND)=@EXTRALIBS@ -lwinmm)
+____EXTRALIB=  $(___EXTRALIB:$(_UNIQ)$(HAVE_QNXSOUND)=@EXTRALIBS@ -lasound)
+EXTRALIB=      $(____EXTRALIB:$(_UNIQ)$(HAVE_OS2SOUND)=@EXTRALIBS@ -los2me)
+
+############# sound file defaults
+# Defaults for wav/au/cdr output file formats
+# default divider for 44.1 KHz
+DEF_UNDERSAMPLING=1
+
+# 16, 12 or 8 bits per sample
+DEF_BITS=16
+# 1 = mono, 2 = stereo
+DEF_CHANNELS=2
+
+DEF_TIME=0                      # number of seconds to record
+
+DEF_SPEED=0                    # default reading speed
+#DEF_SPEED=0xFFFF              # default reading speed
+
+############## output file types: wav, aiff, aifc, sun au or cdr ###########
+# enable one DEF_TYPE and one DEF_FILE
+# first are for wav sound files, second are for sun au pcm sound files,
+# third are for headerless sound files (raw samples in bigendian format)
+# default audio file type
+
+_DEF_TYPE=     $(_UNIQ)$(HAVE_SUN_OS)
+__DEF_TYPE=    $(_DEF_TYPE:$(_UNIQ)='"wav"')
+DEF_TYPE=      $(__DEF_TYPE:$(_UNIQ)$(HAVE_SUN_OS)='"au"')
+#DEF_TYPE=     "wav"
+#DEF_TYPE=     "au"
+#DEF_TYPE=     "cdr"
+#DEF_TYPE=     "aiff"
+#DEF_TYPE=     "aifc"
+
+# default file name for sound file
+DEF_FILE='"audio"'
+
+############## enable/disable info files ####################################
+# Info files contain date/time, track, recording time, ISRC, optional MD5 
+# signature and more, each item in one line. These files are generated one
+# per track.
+# Comment out if you don't want this.
+WANT_INFOFILES=-DINFOFILES
+
+############## enable/disable MD5 signatures in info files ##################
+# Comment out if you don't want this.
+WANT_MD5=-DMD5_SIGNATURES
+MD5OBJECTS=md5c.o
+
+# CDINDEX server support
+# Comment out if you don't want a disk description file for the cdindex server
+WANT_CDINDEX_SUPPORT=-DCDINDEX_SUPPORT
+
+# CDDB server support
+# Comment out if you don't want a network access to the cddb server
+WANT_CDDB_SUPPORT=-DCDDB_SUPPORT
+CDDB_SERVERHOST='"freedb.freedb.org"'
+CDDB_SERVERPORT=8880
+
+# end of tunable parameters
+#
+CDDA2WAVDEFS=-DCD_DEVICE=$(DEF_DEVICE) -DFILENAME=$(DEF_FILE) \
+-DUNDERSAMPLING=$(DEF_UNDERSAMPLING) -DVERSION=$(CUR_VERSION) \
+-DBITS_P_S=$(DEF_BITS) -DCHANNELS=$(DEF_CHANNELS) -DAUDIOTYPE=$(DEF_TYPE) \
+-DDURATION=$(DEF_TIME) -DDEF_INTERFACE=$(INTERFACE) -DUSE_PARANOIA=1 \
+-DDEFAULT_SPEED=$(DEF_SPEED) $(WANT_CDINDEX_SUPPORT) $(WANT_CDDB_SUPPORT) \
+-DCDDBHOST=$(CDDB_SERVERHOST) -DCDDBPORT=$(CDDB_SERVERPORT) $(HAVE_IOCTL) \
+$(HAVE_SOUND) -DSOUND_DEV=$(SOUND_DEVICE) -DNSECTORS=$(NSECTORS) \
+$(WANT_INFOFILES) $(WANT_MD5) -DAUX_DEVICE=$(AUX_DEVICE)
+
+LIBS +=        @LIBS@
+
+VERSION_OS=@CDRTOOLS_VERSION@_$(O_ARCH)_$(OSREL)_$(K_ARCH)_$(P_ARCH)
+CUR_VERSION='"$(VERSION_OS)"'
diff --git a/icedax/lowlevel.h b/icedax/lowlevel.h
new file mode 100644 (file)
index 0000000..084ef34
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)lowlevel.h      1.2 99/12/19 Copyright 1998,1999 Heiko Eissfeldt */
+/* os dependent functions */
+
+#ifndef LOWLEVEL
+# define LOWLEVEL 1
+
+# if defined(__linux__)
+#  include <linux/version.h>
+#  include <linux/major.h>
+
+# endif /* defined __linux__ */
+
+#endif /* ifndef LOWLEVEL */
diff --git a/icedax/mycdrom.h b/icedax/mycdrom.h
new file mode 100644 (file)
index 0000000..1819321
--- /dev/null
@@ -0,0 +1,150 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)mycdrom.h       1.10 06/05/07 Copyright 1998,1999 Heiko Eissfeldt, Copyright 2005-2006 J. Schilling */
+#if defined(__linux__)
+# include <linux/cdrom.h>
+#else
+# if defined HAVE_SYS_CDIO_H
+#  include <sys/cdio.h>
+#  if defined(__FreeBSD__) && __FreeBSD__ >= 2
+#   include <osreldate.h>
+#  endif
+#  if defined HAVE_SYS_CDRIO_H /* Was: if __FreeBSD_version >= 400014 */
+#   include <sys/cdrio.h>
+#  endif
+
+#  if (defined (__sun) && defined (SVR4))
+#   if 0
+/* just for info */
+/* Sun has this cdda reading ioctl: CDROMCDDA */
+/*
+ * Definition of CD-DA structure
+ */
+struct cdrom_cdda {
+ unsigned int cdda_addr;
+ unsigned int cdda_length;
+ caddr_t  cdda_data;
+ unsigned char cdda_subcode;
+};
+/*
+To get the subcode information related to CD-DA data, the following values are
+ appropriate for the cdda_subcode field:
+
+CDROM_DA_NO_SUBCODE
+CD-DA data with no subcode.
+
+CDROM_DA_SUBQ
+CD-DA data with sub Q code.
+
+CDROM_DA_ALL_SUBCODE
+CD-DA data with all subcode.
+
+CDROM_DA_SUBCODE_ONLY
+All subcode only.
+
+To allocate the memory related to CD-DA and/or subcode data, the following
+ values are appropriate for each data block transferred:
+
+CD-DA data with no subcode
+2352 bytes
+
+CD-DA data with sub Q code
+2368 bytes
+
+CD-DA data with all subcode
+2448 bytes
+
+All subcode only
+96 bytes
+*/
+
+#   endif /* if 0 */
+#  else /* not Sun SVR4 */
+#   if defined __FreeBSD__ || defined __NetBSD__ || defined __OpenBSD__ || defined __DragonFly__  || defined __OpenBSD__
+#    if (defined(__FreeBSD__) && __FreeBSD_version < 228000) || !defined(CDIOCREADAUDIO)
+       /*
+        * FreeBSD_version >= 501112 has no CDIOCREADAUDIO but uses pread()
+        */
+#      if !(defined(__FreeBSD__) && __FreeBSD_version >= 501112)
+#              undef HAVE_IOCTL_INTERFACE
+#      endif
+#    endif /* __FreeBSD_version < 228000 || !CDIOCREADAUDIO */
+
+#ifdef HAVE_IOCTL_INTERFACE
+
+#define CDROM_LBA      CD_LBA_FORMAT
+#define CDROM_MSF      CD_MSF_FORMAT
+#define CDROM_DATA_TRACK       0x04
+#define CDROM_LEADOUT  0xAA
+
+#define CDROMSTOP      CDIOCSTOP
+#define CDROMSTART     CDIOCSTART
+#define CDROMREADTOCHDR        CDIOREADTOCHEADER
+#define CDROMREADTOCENTRY      CDIOREADTOCENTRY
+#define CDROMPLAYMSF   CDIOCPLAYMSF
+#define CDROMREADAUDIO CDIOCREADAUDIO
+#define CDROM_GET_MCN  CDIOCREADSUBCHANNEL
+#define CDROMSUBCHNL   CDIOCREADSUBCHANNEL
+
+#ifndef        CDIOREADTOCENTRY
+#define CDIOREADTOCENTRY       CDIOREADTOCENTRYS
+#endif
+
+#define cdrom_tochdr ioc_toc_header
+#define cdth_trk0      starting_track
+#define cdth_trk1      ending_track
+
+#define cdrom_tocentry ioc_read_toc_single_entry
+#define cdte_track     track
+#define cdte_format    address_format
+#define cdte_adr       entry.addr_type
+#define cdte_ctrl      entry.control
+#define cdte_addr      entry.addr
+
+#define cdrom_read_audio ioc_read_audio
+#define addr_format    address_format
+#define buff           buffer
+
+#define cdrom_msf      ioc_play_msf
+#define cdmsf_min0     start_m
+#define cdmsf_sec0     start_s
+#define cdmsf_frame0   start_f
+#define cdmsf_min1     end_m
+#define cdmsf_sec1     end_s
+#define cdmsf_frame1   end_f
+
+#define cdrom_subchnl  ioc_read_subchannel
+#define cdsc_audiostatus data->header.audio_status
+#define cdsc_format    data->what.position.data_format
+#define cdsc_adr       data->what.position.addr_type
+#define cdsc_ctrl      data->what.position.control
+#define cdsc_trk       data->what.position.track_number
+#define cdsc_ind       data->what.position.index_number
+#define cdsc_absaddr   data->what.position.absaddr
+#define cdsc_reladdr   data->what.position.reladdr
+#      endif   /* HAVE_IOCTL_INTERFACE */
+#   else /* not *BSD */
+#    undef HAVE_IOCTL_INTERFACE
+#   endif /* not *BSD */
+#  endif /* not SUN SVR4 */
+# else /* HAVE_SYS_CDIO_H */
+#  if defined HAVE_SUNDEV_SRREG_H
+#   include <sundev/srreg.h>
+#   if !defined CDROMCDDA
+#    undef HAVE_IOCTL_INTERFACE
+#   endif
+#  else
+#    undef HAVE_IOCTL_INTERFACE
+#  endif
+# endif /* not HAVE_SYS_CDIO_H */
+#endif /* not linux */
diff --git a/icedax/mytype.h b/icedax/mytype.h
new file mode 100644 (file)
index 0000000..189f1c9
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)mytype.h        1.2 99/12/19 Copyright 1998,1999 Heiko Eissfeldt */
+#if 4 == SIZEOF_LONG_INT
+#define UINT4 long unsigned int
+#define UINT4_C ULONG_C
+#else
+#if 4 == SIZEOF_INT
+#define UINT4 unsigned int
+#define UINT4_C UINT_C
+#else
+#if 4 == SIZEOF_SHORT_INT
+#define UINT4 short unsigned int
+#define UINT4_C USHORT_C
+#else
+error need an integer type with 32 bits, but do not know one!
+#endif
+#endif
+#endif
+#define TRUE 1
+#define FALSE 0
+
+#ifndef offset_of
+#define offset_of(TYPE, MEMBER) ((size_t) ((TYPE *)0)->MEMBER)
+#endif
+#ifndef offsetof
+#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+#endif
+
diff --git a/icedax/pitchplay b/icedax/pitchplay
new file mode 100755 (executable)
index 0000000..a9f3dc2
--- /dev/null
@@ -0,0 +1,39 @@
+#! /bin/sh
+#
+# Script to play audio tracks with different pitches 
+# through a soundcard (cdda2wav must have soundcard
+# support enabled).
+#
+# Pitches are specified in percentage with 100% being
+# the original pitch, 50% being one octave lower, 200%
+# one octave higher.
+#
+# based on a script from Raul Sobon, who created the pitch
+# feature. Thanks Raul.
+#
+# usage: pitchplay <track a> <pitch a> <track b> <pitch b> ...
+#
+# example: pitchplay 1 90  3 140  5 50
+# will play track 1 with a pitch of 90%,
+#           track 3 with a pitch of 140%, and
+#           track 5 with a pitch of 50%.
+#
+CDDA2WAV=icedax
+#CDDA2WAVOPTS="-qeNP0 -n75"
+CDDA2WAVOPTS="-qeNP0 -n40"
+
+if [ $(( $# % 2 )) -eq 0 ]; then
+  while [ $# -ge 2 ]; do
+    echo playing track $1 with a pitch of $2%
+    $CDDA2WAV $CDDA2WAVOPTS -t $1 -p $2
+    RES=$?
+    if [ $RES -ne 0 ]; then
+      echo "$CDDA2WAV error, return value "$RES". Aborted." >&2
+      break
+    fi
+    shift 2
+  done
+else
+  echo "usage: $0 [<Tracknr> <Pitch>] ..." >&2
+fi
+
diff --git a/icedax/pitchplay.1 b/icedax/pitchplay.1
new file mode 100644 (file)
index 0000000..dee13ea
--- /dev/null
@@ -0,0 +1,59 @@
+.TH "PITCHPLAY" "1" "Tue Feb 15 12:53:23 MST 2005" "" "pitchplay"
+
+.PP
+.SH "NAME"
+pitchplay \- wrapper script to play audio tracks with cdda2wav with different
+pitches through a soundcard (cdda2wav must have soundcard support enabled).
+.PP
+.SH "SYNOPSIS"
+.PP
+\fBpitchplay\fP <track a> <pitch a> <track b> <pitch b>...
+.PP
+.SH "DESCRIPTION"
+.PP
+\fBpitchplay\fP allows playback of audio tracks with cdda2wav with pitches
+specified in percentage with 100% being the original pitch, 50% being one
+octave lower, 200% one octave higher.
+.PP
+.SH "EXAMPLES"
+.PP
+\fBpitchplay\fP 1 90  3 140  5 50
+.br
+will play track 1 with a pitch of 90%, track 3 with a pitch of 140%, and track 5 with a pitch of 50%.
+.PP
+.SH SEE ALSO
+cdda2wav(1)
+.PP 
+.SH "AUTHOR" 
+.PP 
+\fBcdda2was\fP was written by Joerg Schilling <js@cs\&.tu-berlin\&.de> and
+others.
+.PP
+This manpage describes the program implementation of
+.B
+pitchplay
+as shipped by the cdrkit distribution. See
+.B
+http://alioth.debian.org/projects/debburn/
+for details. It is a spinoff from the original program distributed by the cdrtools project. However, the cdrtools developers are not involved in the development of this spinoff and therefore shall not be made responsible for any problem caused by it. Do not try to get support for this program by contacting the original authors.
+.PP
+If you have support questions, send them to
+.PP
+.B
+debburn-devel@lists.alioth.debian.org
+.br
+.PP
+If you have definitely found a bug, send a mail to this list or to
+.PP
+.B
+submit@bugs.debian.org
+.br
+.PP
+writing at least a short description into the Subject and "Package: cdrkit" into the first line of the mail body.
+.PP 
+This manual page was written by Oleksandr Moskalenko
+<malex@tagancha\&.org>, for
+the Debian GNU/Linux system\&.  It may be used by other distributions
+without contacting the author\&.  Any mistakes or omissions in the
+manual page are my fault; inquiries about or corrections to this
+manual page should be directed to me (and not to the primary author)\&.
diff --git a/icedax/raw.c b/icedax/raw.c
new file mode 100644 (file)
index 0000000..b56841e
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)raw.c   1.4 01/10/27 Copyright 1998,1999 Heiko Eissfeldt */
+#include "config.h"
+#include <unixstd.h>
+#include "sndfile.h"
+
+static int InitSound(void);
+
+static int InitSound()
+{
+  return 0;
+}
+
+static int ExitSound(void);
+
+static int ExitSound()
+{
+  return 0;
+}
+
+static unsigned long GetHdrSize(void);
+
+static unsigned long GetHdrSize()
+{
+  return 0L;
+}
+
+static unsigned long InSizeToOutSize(unsigned long BytesToDo);
+
+static unsigned long InSizeToOutSize(unsigned long BytesToDo)
+{
+        return BytesToDo;
+}
+
+struct soundfile rawsound =
+{
+  (int (*)(int audio, long channels,
+                 unsigned long myrate, long nBitsPerSample,
+                 unsigned long expected_bytes)) InitSound,
+
+  (int (*)(int audio, unsigned long nBytesDone)) ExitSound,
+
+  GetHdrSize,
+
+  (int (*)(int audio, unsigned char *buf, unsigned long BytesToDo)) write,             /* get sound samples out */
+
+  InSizeToOutSize,     /* compressed? output file size */
+
+  1            /* needs big endian samples */
+};
diff --git a/icedax/raw.h b/icedax/raw.h
new file mode 100644 (file)
index 0000000..2a9ef8b
--- /dev/null
@@ -0,0 +1,14 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)raw.h   1.2 99/12/19 Copyright 1998,1999 Heiko Eissfeldt */
+extern struct soundfile rawsound;
diff --git a/icedax/readmult b/icedax/readmult
new file mode 100755 (executable)
index 0000000..6f0884e
--- /dev/null
@@ -0,0 +1,31 @@
+#! /bin/sh
+#
+# Script to read more than 1 song with icedax
+# Each file gets an individual name from the command line
+#
+# based on a perl script from Matthias Schniedermeyer
+#
+# usage: readmult <track a> <title a> <track b> <title b> ...
+#
+# example: readmult 1 intro 3 lovesong 5 medley
+# will produce a file named intro.wav for track 1,
+#              a file named lovesong.wav for track 3, and
+#              a file named medley.wav for track 5.
+#
+CDDA2WAV=icedax
+CDDA2WAVOPTS="-P0"
+
+if [ $(( $# % 2 )) -eq 0 ]; then
+  while [ $# -ge 2 ]; do
+    $CDDA2WAV $CDDA2WAVOPTS -Owav -t $1 $PREFIX$2".wav"
+    RES=$?
+    if [ $RES -ne 0 ]; then
+      echo "$CDDA2WAV error, return value "$RES". Aborted." >&2
+      break
+    fi
+    shift 2
+  done
+else
+  echo "usage: $0 [<Tracknr> <Filename>] ..." >&2
+fi
+
diff --git a/icedax/readmult.1 b/icedax/readmult.1
new file mode 100644 (file)
index 0000000..8801736
--- /dev/null
@@ -0,0 +1,52 @@
+.TH "READMULT" "1" "Tue Feb 15 12:34:06 MST 2005" "" "readmult"
+
+.PP
+.SH "NAME"
+readmult \- a multitrack wrapper for cdda2wav
+.PP
+.SH "SYNOPSIS"
+.PP
+\fBreadmult\fP <track a> <title a> <track b> <title b> ...
+.PP
+.SH "DESCRIPTION"
+.PP
+\fBreadmult\fP allows simultaneous extraction and naming of multiple tracks
+with cdda2wav
+.PP
+.SH SEE ALSO
+cdda2wav(1)
+.PP 
+.SH "AUTHOR" 
+.PP 
+\fBcdda2was\fP was written by Joerg Schilling <js@cs\&.tu-berlin\&.de> and
+others.
+.PP
+This describes the program as shipped with cdrkit, see
+This manpage describes the program implementation of
+.B
+readmult
+as shipped by the cdrkit distribution. See
+.B
+http://alioth.debian.org/projects/debburn/
+for details. It is a spinoff from the original program distributed by the cdrtools project. However, the cdrtools developers are not involved in the development of this spinoff and therefore shall not be made responsible for any problem caused by it. Do not try to get support for this program by contacting the original authors.
+.PP
+If you have support questions, send them to
+.PP
+.B
+debburn-devel@lists.alioth.debian.org
+.br
+.PP
+If you have definitely found a bug, send a mail to this list or to
+.PP
+.B
+submit@bugs.debian.org
+.br
+.PP
+writing at least a short description into the Subject and "Package: cdrkit" into the first line of the mail body.
+.PP 
+This manual page was written by Oleksandr Moskalenko
+<malex@tagancha\&.org>, for
+the Debian GNU/Linux system\&.  It may be used by other distributions
+without contacting the author\&.  Any mistakes or omissions in the
+manual page are my fault; inquiries about or corrections to this
+manual page should be directed to me (and not to the primary author)\&.
diff --git a/icedax/resample.c b/icedax/resample.c
new file mode 100644 (file)
index 0000000..3f5b5d0
--- /dev/null
@@ -0,0 +1,985 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)resample.c      1.15 02/11/21 Copyright 1998,1999,2000 Heiko Eissfeldt */
+/* resampling module 
+ *
+ * The audio data has been read. Here are the
+ * functions to ensure a correct continuation
+ * of the output stream and to convert to a
+ * lower sample rate.
+ *
+ */
+
+#undef DEBUG_VOTE_ENDIANESS
+#undef DEBUG_SHIFTS            /* simulate bad cdrom drives */
+#undef DEBUG_MATCHING
+#undef SHOW_JITTER
+#undef CHECK_MEM
+
+#include "config.h"
+#include <timedefs.h>
+#include <stdio.h>
+#include <stdxlib.h>
+#include <utypes.h>
+#include <unixstd.h>
+#include <standard.h>
+#include <strdefs.h>
+#include <limits.h>
+#include <assert.h>
+#include <math.h>
+
+#include <usal/scsitransp.h>
+
+#include "mytype.h"
+#include "icedax.h"
+#include "interface.h"
+#include "byteorder.h"
+#include "ringbuff.h"
+#include "resample.h"
+#include "toc.h"
+#include "sndfile.h"
+#include "sndconfig.h"
+#include "global.h"
+#include "exitcodes.h"
+
+
+int waitforsignal = 0; /* flag: wait for any audio response */
+int any_signal = 0;
+
+short undersampling;   /* conversion factor */
+short samples_to_do;   /* loop variable for conversion */
+int Halved;            /* interpolate due to non integral divider */
+
+static long lsum = 0, rsum = 0;               /* accumulator for left/right channel */
+static long ls2 = 0, rs2 = 0, ls3 = 0, rs3 = 0, auxl = 0, auxr = 0;
+
+static const unsigned char *my_symmemmem(const unsigned char *HAYSTACK, 
+                                                                                                         const size_t HAYSTACK_LEN, 
+                                                                                                         const unsigned char *const NEEDLE, 
+                                                                                                         const size_t NEEDLE_LEN);
+static const unsigned char *my_memmem(const unsigned char *HAYSTACK, 
+                                                                                                 const size_t HAYSTACK_LEN, 
+                                                                                                 const unsigned char *const NEEDLE, 
+                                                                                                 const size_t NEEDLE_LEN);
+static const unsigned char *my_memrmem(const unsigned char *HAYSTACK, 
+                                                                                                       const size_t HAYSTACK_LEN, 
+                                                                                                       const unsigned char *const NEEDLE, 
+                                                                                                       const size_t NEEDLE_LEN);
+static const unsigned char *sync_buffers(const unsigned char *const newbuf);
+static long interpolate(long p1, long p2, long p3);
+static void emit_sample(long lsumval, long rsumval, long channels);
+static void change_endianness(UINT4 *pSam, unsigned int Samples);
+static void swap_channels(UINT4 *pSam, unsigned int Samples);
+static int guess_endianess(UINT4 *p, Int16_t *p2, unsigned int SamplesToDo);
+
+
+#ifdef CHECK_MEM
+static void check_mem(const unsigned char *p, unsigned long amount, 
+                                                        const unsigned char *q, unsigned line, char *file);
+
+static void check_mem(const unsigned char *p, unsigned long amount, 
+                      const unsigned char *q, unsigned line, char *file)
+{
+       if (p < q || p+amount > q + ENTRY_SIZE) {
+               fprintf(stderr, "file %s, line %u: invalid buffer range (%p - %p), allowed is (%p - %p)\n",
+                       file,line,p, p+amount-1, q, q + ENTRY_SIZE-1);
+               exit(INTERNAL_ERROR);
+       }
+}
+#endif
+
+
+#ifdef DEBUG_MATCHING
+int memcmp(const void * a, const void * b, size_t c)
+{
+  return 1;
+}
+#endif
+
+static const unsigned char *
+my_symmemmem(const unsigned char *HAYSTACK, const size_t HAYSTACK_LEN, 
+             const unsigned char * const NEEDLE, const size_t NEEDLE_LEN)
+{
+  const unsigned char * const UPPER_LIMIT = HAYSTACK + HAYSTACK_LEN - NEEDLE_LEN - 1;
+  const unsigned char * HAYSTACK2 = HAYSTACK-1;
+
+  while (HAYSTACK <= UPPER_LIMIT) {
+    if (memcmp(NEEDLE, HAYSTACK, NEEDLE_LEN) == 0) {
+      return HAYSTACK;
+    } else {
+      if (memcmp(NEEDLE, HAYSTACK2, NEEDLE_LEN) == 0) {
+        return HAYSTACK2;
+      }
+      HAYSTACK2--;
+      HAYSTACK++;
+    }
+  }
+#ifdef DEBUG_MATCHING
+  HAYSTACK2++;
+  HAYSTACK--;
+  fprintf(stderr, "scompared %p-%p with %p-%p (%p)\n",
+        NEEDLE, NEEDLE + NEEDLE_LEN-1,
+        HAYSTACK2, HAYSTACK + NEEDLE_LEN-1, HAYSTACK);
+#endif
+  return NULL;
+}
+
+static const unsigned char *
+my_memmem(const unsigned char *HAYSTACK, const size_t HAYSTACK_LEN, 
+          const unsigned char * const NEEDLE, const size_t NEEDLE_LEN)
+{
+  const unsigned char * const UPPER_LIMIT = HAYSTACK + HAYSTACK_LEN - NEEDLE_LEN;
+
+  while (HAYSTACK <= UPPER_LIMIT) {
+    if (memcmp(NEEDLE, HAYSTACK, NEEDLE_LEN) == 0) {
+      return HAYSTACK;
+    } else {
+      HAYSTACK++;
+    }
+  }
+#ifdef DEBUG_MATCHING
+  HAYSTACK--;
+  fprintf(stderr, "fcompared %p-%p with %p-%p (%p)\n",
+        NEEDLE, NEEDLE + NEEDLE_LEN-1,
+        HAYSTACK - HAYSTACK_LEN + NEEDLE_LEN, HAYSTACK + NEEDLE_LEN-1,
+        HAYSTACK);
+#endif
+  return NULL;
+}
+
+static const unsigned char *
+my_memrmem(const unsigned char *HAYSTACK, const size_t HAYSTACK_LEN, 
+           const unsigned char * const NEEDLE, const size_t NEEDLE_LEN)
+{
+  const unsigned char * const LOWER_LIMIT = HAYSTACK - (HAYSTACK_LEN - 1);
+
+  while (HAYSTACK >= LOWER_LIMIT) {
+    if (memcmp(NEEDLE, HAYSTACK, NEEDLE_LEN) == 0) {
+      return HAYSTACK;
+    } else {
+      HAYSTACK--;
+    }
+  }
+#ifdef DEBUG_MATCHING
+  HAYSTACK++;
+  fprintf(stderr, "bcompared %p-%p with %p-%p (%p)\n",
+        NEEDLE, NEEDLE + NEEDLE_LEN-1,
+        HAYSTACK, HAYSTACK + (HAYSTACK_LEN - 1),
+        HAYSTACK + (HAYSTACK_LEN - 1) - NEEDLE_LEN - 1);
+#endif
+  return NULL;
+}
+
+/* find continuation in new buffer */
+static const unsigned char *
+sync_buffers(const unsigned char * const newbuf)
+{
+    const unsigned char *retval = newbuf;
+
+    if (global.overlap != 0) {
+      /* find position of SYNC_SIZE bytes 
+        of the old buffer in the new buffer */
+      size_t haystack_len;
+      const size_t needle_len = SYNC_SIZE;
+      const unsigned char * const oldbuf = (const unsigned char *) (get_previous_read_buffer()->data);
+      const unsigned char * haystack;
+      const unsigned char * needle;
+
+      /* compare the previous buffer with the new one
+       *
+       * 1. symmetrical search:
+       *   look for the last SYNC_SIZE bytes of the previous buffer
+       *   in the new buffer (from the optimum to the outer positions).
+       *
+       * 2. if the first approach did not find anything do forward search
+       *   look for the last SYNC_SIZE bytes of the previous buffer
+       *   in the new buffer (from behind the overlap to the end).
+       *   
+       */
+
+      haystack_len = min((global.nsectors - global.overlap)*CD_FRAMESIZE_RAW
+                        +SYNC_SIZE+1,
+                        global.overlap*CD_FRAMESIZE_RAW);
+      /* expected here */
+      haystack = newbuf + CD_FRAMESIZE_RAW*global.overlap - SYNC_SIZE;
+      needle = oldbuf + CD_FRAMESIZE_RAW*global.nsectors - SYNC_SIZE; 
+
+#ifdef DEBUG_MATCHING
+       fprintf(stderr, "oldbuf    %p-%p  new %p-%p %u %u %u\n",
+               oldbuf, oldbuf + CD_FRAMESIZE_RAW*global.nsectors - 1,
+               newbuf, newbuf + CD_FRAMESIZE_RAW*global.nsectors - 1,
+               CD_FRAMESIZE_RAW*global.nsectors, global.nsectors, global.overlap);
+#endif
+
+      retval = my_symmemmem(haystack, haystack_len, needle, needle_len);
+      if (retval != NULL) {
+       retval += SYNC_SIZE;
+      } else {
+       /* fallback to asymmetrical search */
+
+       /* if there is no asymmetrical part left, return with 'not found' */
+       if (2*global.overlap == global.nsectors) {
+         retval = NULL;
+       } else if (2*global.overlap > global.nsectors) {
+         /* the asymmetrical part is in front, search backwards */
+          haystack_len = (2*global.overlap-global.nsectors)*CD_FRAMESIZE_RAW;
+          haystack = newbuf + haystack_len - 1;
+          retval = my_memrmem(haystack, haystack_len, needle, needle_len);
+       } else {
+         /* the asymmetrical part is at the end, search forward */
+          haystack = newbuf + 2*(global.overlap*CD_FRAMESIZE_RAW - SYNC_SIZE);
+          haystack_len = (global.nsectors-2*global.overlap)*CD_FRAMESIZE_RAW + 2*SYNC_SIZE;
+          retval = my_memmem(haystack, haystack_len, needle, needle_len);
+       }
+        if (retval != NULL)
+         retval += SYNC_SIZE;
+      }
+
+#ifdef SHOW_JITTER
+      if (retval) {
+       fprintf(stderr,"%d\n",
+               retval-(newbuf+global.overlap*CD_FRAMESIZE_RAW));
+      } else {
+       fprintf(stderr,"no match\n");
+      }
+#endif
+    }
+
+    return retval;
+}
+
+/* quadratic interpolation
+ * p1, p3 span the interval 0 - 2. give interpolated value for 1/2 */
+static long int 
+interpolate(long int p1, long int p2, long int p3)
+{
+  return (3L*p1 + 6L*p2 - p3)/8L;
+}
+
+static unsigned char *pStart;  /* running ptr defining end of output buffer */
+static unsigned char *pDst;    /* start of output buffer */
+/*
+ * Write the filtered sample into the output buffer.
+ */
+static void 
+emit_sample(long lsumval, long rsumval, long channels)
+{
+    if (global.findminmax) {
+       if (rsumval > global.maxamp[0]) global.maxamp[0] = rsumval;
+       if (rsumval < global.minamp[0]) global.minamp[0] = rsumval;
+       if (lsumval < global.minamp[1]) global.minamp[1] = lsumval;
+       if (lsumval > global.maxamp[1]) global.maxamp[1] = lsumval;
+    }
+    /* convert to output format */
+    if ( channels == 1 ) {
+       Int16_t sum;       /* mono section */
+       sum = ( lsumval + rsumval ) >> (global.sh_bits + 1);
+       if ( global.sh_bits == 8 ) {
+           if ( waitforsignal == 1 ) {
+             if ( any_signal == 0 ) {
+               if ( ( (char) sum) != '\0' ) {
+                   pStart = (unsigned char *) pDst;
+                   any_signal = 1;
+                   *pDst++ = ( unsigned char ) sum + ( 1 << 7 );
+               } else global.SkippedSamples++;
+             } else *pDst++ = ( unsigned char ) sum + ( 1 << 7 );
+            } else *pDst++ = ( unsigned char ) sum + ( 1 << 7 );
+       } else {
+           Int16_t * myptr = (Int16_t *) pDst;
+           if ( waitforsignal == 1 ) {
+             if ( any_signal == 0 ) {
+               if ( sum != 0 ) {
+                   pStart = (unsigned char *) pDst;
+                   any_signal = 1;
+                   *myptr = sum; pDst += sizeof( Int16_t );
+               } else global.SkippedSamples++;
+             } else { *myptr = sum; pDst += sizeof( Int16_t ); }
+           } else { *myptr = sum; pDst += sizeof( Int16_t ); }
+       }
+    } else {
+       /* stereo section */
+       lsumval >>= global.sh_bits;
+       rsumval >>= global.sh_bits;
+       if ( global.sh_bits == 8 ) {
+           if ( waitforsignal == 1 ) {
+             if ( any_signal == 0 ) {
+               if ( ((( char ) lsumval != '\0') || (( char ) rsumval != '\0'))) {
+                   pStart = (unsigned char *) pDst;
+                   any_signal = 1;
+                   *pDst++ = ( unsigned char )( short ) lsumval + ( 1 << 7 );
+                   *pDst++ = ( unsigned char )( short ) rsumval + ( 1 << 7 );
+               } else global.SkippedSamples++;
+             } else {
+               *pDst++ = ( unsigned char )( short ) lsumval + ( 1 << 7 );
+               *pDst++ = ( unsigned char )( short ) rsumval + ( 1 << 7 );
+             }
+           } else {
+               *pDst++ = ( unsigned char )( short ) lsumval + ( 1 << 7 );
+               *pDst++ = ( unsigned char )( short ) rsumval + ( 1 << 7 );
+           }
+       } else {
+           Int16_t * myptr = (Int16_t *) pDst;
+           if ( waitforsignal == 1 ) {
+             if ( any_signal == 0 ) {
+               if ( ((( Int16_t ) lsumval != 0) || (( Int16_t ) rsumval != 0))) {
+                   pStart = (unsigned char *) pDst;
+                   any_signal = 1;
+                   *myptr++ = ( Int16_t ) lsumval;
+                   *myptr   = ( Int16_t ) rsumval;
+                   pDst += 2*sizeof( Int16_t );
+               } else global.SkippedSamples++;
+             } else {
+               *myptr++ = ( Int16_t ) lsumval;
+               *myptr   = ( Int16_t ) rsumval;
+               pDst += 2*sizeof( Int16_t );
+             }
+           } else {
+             *myptr++ = ( Int16_t ) lsumval;
+             *myptr   = ( Int16_t ) rsumval;
+             pDst += 2*sizeof( Int16_t );
+           }
+       }
+    }
+}
+
+static void change_endianness(UINT4 *pSam, unsigned int Samples)
+{
+  UINT4 *pend = (pSam + Samples);
+
+  /* type UINT4 may not be greater than the assumed biggest type */
+#if (SIZEOF_LONG_INT < 4)
+error type unsigned long is too small
+#endif
+
+#if (SIZEOF_LONG_INT == 4)
+
+  unsigned long *plong = (unsigned long *)pSam;
+
+  for (; plong < pend;) {
+    *plong = ((*plong >> 8L) & UINT_C(0x00ff00ff)) |
+             ((*plong << 8L) & UINT_C(0xff00ff00));
+    plong++;
+  }
+#else  /* sizeof long unsigned > 4 bytes */
+#if (SIZEOF_LONG_INT == 8)
+#define INTEGRAL_LONGS (SIZEOF_LONG_INT-1UL)
+  register unsigned long *plong;
+  unsigned long *pend0 = (unsigned long *) (((unsigned long) pend) & ~ INTEGRAL_LONGS);
+
+  if (((unsigned long) pSam) & INTEGRAL_LONGS) {
+    *pSam = ((*pSam >> 8L) & UINT_C(0x00ff00ff)) |
+            ((*pSam << 8L) & UINT_C(0xff00ff00));
+    pSam++;
+  }
+
+  plong = (unsigned long *)pSam;
+
+  for (; plong < pend0;) {
+    *plong = ((*plong >> 8L) & ULONG_C(0x00ff00ff00ff00ff)) |
+             ((*plong << 8L) & ULONG_C(0xff00ff00ff00ff00));
+    plong++;
+  }
+
+  if (((unsigned long *) pend) != pend0) {
+    UINT4 *pint = (UINT4 *) pend0;
+
+    for (;pint < pend;) {
+      *pint = ((*pint >> 8) & UINT_C(0x00ff00ff)) |
+              ((*pint << 8) & UINT_C(0xff00ff00));
+      pint++;
+    }
+  }
+#else  /* sizeof long unsigned > 4 bytes but not 8 */
+  {
+    UINT4 *pint = pSam;
+
+    for (;pint < pend;) {
+      *pint = ((*pint >> 8) & UINT_C(0x00ff00ff)) |
+              ((*pint << 8) & UINT_C(0xff00ff00));
+      pint++;
+    }
+  }
+#endif
+#endif
+}
+
+static void swap_channels(UINT4 *pSam, unsigned int Samples)
+{
+  UINT4 *pend = (pSam + Samples);
+
+  /* type UINT4 may not be greater than the assumed biggest type */
+#if (SIZEOF_LONG_INT < 4)
+error type unsigned long is too small
+#endif
+
+#if (SIZEOF_LONG_INT == 4)
+
+  unsigned long *plong = (unsigned long *)pSam;
+
+  for (; plong < pend;) {
+    *plong = ((*plong >> 16L) & UINT_C(0x0000ffff)) |
+             ((*plong << 16L) & UINT_C(0xffff0000));
+    plong++;
+  }
+#else  /* sizeof long unsigned > 4 bytes */
+#if (SIZEOF_LONG_INT == 8)
+#define INTEGRAL_LONGS (SIZEOF_LONG_INT-1UL)
+  register unsigned long *plong;
+  unsigned long *pend0 = (unsigned long *) (((unsigned long) pend) & ~ INTEGRAL_LONGS);
+
+  if (((unsigned long) pSam) & INTEGRAL_LONGS) {
+    *pSam = ((*pSam >> 16L) & UINT_C(0x0000ffff)) |
+            ((*pSam << 16L) & UINT_C(0xffff0000));
+    pSam++;
+  }
+
+  plong = (unsigned long *)pSam;
+
+  for (; plong < pend0;) {
+    *plong = ((*plong >> 16L) & ULONG_C(0x0000ffff0000ffff)) |
+             ((*plong << 16L) & ULONG_C(0xffff0000ffff0000));
+    plong++;
+  }
+
+  if (((unsigned long *) pend) != pend0) {
+    UINT4 *pint = (UINT4 *) pend0;
+
+    for (;pint < pend;) {
+      *pint = ((*pint >> 16L) & UINT_C(0x0000ffff)) |
+              ((*pint << 16L) & UINT_C(0xffff0000));
+      pint++;
+    }
+  }
+#else  /* sizeof long unsigned > 4 bytes but not 8 */
+  {
+    UINT4 *pint = pSam;
+
+    for (;pint < pend;) {
+      *pint = ((*pint >> 16L) & UINT_C(0x0000ffff)) |
+              ((*pint << 16L) & UINT_C(0xffff0000));
+      pint++;
+    }
+  }
+#endif
+#endif
+}
+
+#ifdef ECHO_TO_SOUNDCARD
+static long ReSampleBuffer(unsigned char *p, unsigned char *newp, 
+                                                                       long samples, int samplesize);
+static long ReSampleBuffer(unsigned char *p, unsigned char *newp, 
+                           long samples, int samplesize)
+{
+       double idx=0.0;
+       UINT4  di=0,si=0;
+
+       if (global.playback_rate == 100.0) {
+               memcpy(newp, p, samplesize* samples);
+               di = samples;
+       } else while( si < (UINT4)samples ){
+               memcpy( newp+(di*samplesize), p+(si*samplesize), samplesize );
+               idx += (double)(global.playback_rate/100.0);
+               si = (UINT4)idx;
+               di++;
+       }
+       return di*samplesize;
+}
+#endif
+
+static int guess_endianess(UINT4 *p, Int16_t *p2, unsigned SamplesToDo)
+{
+    /* analyse samples */
+    int vote_for_little = 0;
+    int vote_for_big = 0;
+    int total_votes;
+
+    while (((UINT4 *)p2 - p) + (unsigned) 1 < SamplesToDo) {
+      unsigned char *p3 = (unsigned char *)p2;
+#if MY_LITTLE_ENDIAN == 1
+      int diff_lowl = *(p2+0) - *(p2+2);
+      int diff_lowr = *(p2+1) - *(p2+3);
+      int diff_bigl = ((*(p3  ) << 8) + *(p3+1)) - ((*(p3+4) << 8) + *(p3+5));
+      int diff_bigr = ((*(p3+2) << 8) + *(p3+3)) - ((*(p3+6) << 8) + *(p3+7));
+#else
+      int diff_lowl = ((*(p3+1) << 8) + *(p3  )) - ((*(p3+5) << 8) + *(p3+4));
+      int diff_lowr = ((*(p3+3) << 8) + *(p3+2)) - ((*(p3+7) << 8) + *(p3+6));
+      int diff_bigl = *(p2+0) - *(p2+2);
+      int diff_bigr = *(p2+1) - *(p2+3);
+#endif
+
+      if ((abs(diff_lowl) + abs(diff_lowr)) <
+         (abs(diff_bigl) + abs(diff_bigr))) {
+       vote_for_little++;
+      } else {
+       if ((abs(diff_lowl) + abs(diff_lowr)) >
+           (abs(diff_bigl) + abs(diff_bigr))) {
+         vote_for_big++;
+       }
+      }
+      p2 += 2;
+   }
+#ifdef DEBUG_VOTE_ENDIANESS
+   if (global.quiet != 1)
+     fprintf(stderr, "votes for little: %4d,  votes for big: %4d\n", 
+               vote_for_little, vote_for_big);
+#endif
+   total_votes = vote_for_big + vote_for_little;
+   if (total_votes < 3
+       || abs(vote_for_big - vote_for_little) < total_votes/3) {
+     return -1;
+   } else {
+       if (vote_for_big > vote_for_little)
+               return 1;
+       else
+               return 0;
+   }
+}
+
+int jitterShift = 0; 
+
+void handle_inputendianess(UINT4 *p, unsigned SamplesToDo)
+{
+  /* if endianess is unknown, guess endianess based on 
+     differences between succesive samples. If endianess
+     is correct, the differences are smaller than with the
+     opposite byte order.
+   */
+  if ((*in_lendian) < 0) {
+    Int16_t *p2 = (Int16_t *)p;
+
+    /* skip constant samples */
+    while ((((UINT4 *)p2 - p) + (unsigned) 1 < SamplesToDo)
+           && *p2 == *(p2+2)) p2++;
+
+    if (((UINT4 *)p2 - p) + (unsigned) 1 < SamplesToDo) {
+      switch (guess_endianess(p, p2, SamplesToDo)) {
+        case -1: break;
+        case  1: (*in_lendian) = 0;
+#if 0
+                if (global.quiet != 1)
+                  fprintf(stderr, "big endian detected\n");
+#endif
+       break;
+        case  0: (*in_lendian) = 1;
+#if 0
+                if (global.quiet != 1)
+                  fprintf(stderr, "little endian detected\n");
+#endif
+       break;
+      }
+    }
+  }
+
+  /* ENDIAN ISSUES:
+   * the individual endianess of cdrom/cd-writer, cpu, 
+   * sound card and audio output format need a careful treatment.
+   *
+   * For possible sample processing (rate conversion) we need
+   * the samples in cpu byte order. This is the first conversion.
+   *
+   * After processing it depends on the endianness of the output
+   * format, whether a second conversion is needed.
+   *
+   */
+
+  if (global.need_hostorder && (*in_lendian) != MY_LITTLE_ENDIAN) {
+    /* change endianess of delivered samples to native cpu order */
+    change_endianness(p, SamplesToDo);
+  }
+}
+
+unsigned char *
+synchronize(UINT4 *p, unsigned SamplesToDo, unsigned TotSamplesDone)
+{
+  static int jitter = 0;
+  char *pSrc;                   /* start of cdrom buffer */
+
+  /* synchronisation code */
+  if (TotSamplesDone != 0 && global.overlap != 0 && SamplesToDo > CD_FRAMESAMPLES) {
+
+    pSrc = (char *) sync_buffers((unsigned char *)p);
+    if (!pSrc ) {
+      return NULL;
+    }
+    if (pSrc) {
+      jitter = ((unsigned char *)pSrc - (((unsigned char *)p) + global.overlap*CD_FRAMESIZE_RAW))/4;
+      jitterShift += jitter;
+      SamplesToDo -= jitter + global.overlap*CD_FRAMESAMPLES;
+#if 0
+      fprintf(stderr,
+           "Length: pre %d, diff1 %ld, diff2 %ld, min %ld\n", SamplesToDo,
+          (TotSamplesWanted - TotSamplesDone),
+          SamplesNeeded((TotSamplesWanted - TotSamplesDone), undersampling),
+          min(SamplesToDo, SamplesNeeded((TotSamplesWanted - TotSamplesDone), undersampling)));
+#endif
+    }
+  } else {
+    pSrc = ( char * ) p;
+  }
+  return (unsigned char *) pSrc;
+}
+
+/* convert cdda data to required output format
+ * sync code for unreliable cdroms included
+ * 
+ */
+long 
+SaveBuffer(UINT4 *p, unsigned long SamplesToDo, unsigned long *TotSamplesDone)
+{
+  UINT4 *pSrc;                   /* start of cdrom buffer */
+  UINT4 *pSrcStop;               /* end of cdrom buffer */
+
+  /* in case of different endianness between host and output format,
+     or channel swaps, or deemphasizing
+     copy in a seperate buffer and modify the local copy */
+  if ( ((((!global.need_hostorder && global.need_big_endian == (*in_lendian)) ||
+         (global.need_hostorder && global.need_big_endian != MY_BIG_ENDIAN)
+         ) || (global.deemphasize != 0)
+        ) && (global.OutSampleSize > 1)
+       ) || global.swapchannels != 0) {
+     static UINT4 *localoutputbuffer;
+     if (localoutputbuffer == NULL) {
+       localoutputbuffer = malloc(global.nsectors*CD_FRAMESIZE_RAW);
+       if (localoutputbuffer == NULL) {
+         perror("cannot allocate local buffer");
+         return 1;
+       }
+     }
+     memcpy(localoutputbuffer, p, SamplesToDo*4);
+     p = localoutputbuffer;
+  }
+
+  pSrc = p;
+  pDst = (unsigned char *) p;
+  pStart = ( unsigned char * ) pSrc;
+  pSrcStop = pSrc + SamplesToDo;
+
+  /* code for subsampling and output stage */
+
+  if (global.ismono && global.findmono) {
+    Int16_t *pmm;
+    for (pmm = (Int16_t *)pStart; (UINT4 *) pmm < pSrcStop; pmm += 2) {
+      if (*pmm != *(pmm+1)) {
+        global.ismono = 0;
+        break;
+      }
+    }
+  }
+  /* optimize the case of no conversion */
+  if (1 && undersampling == 1 && samples_to_do == 1 &&
+       global.channels == 2 && global.OutSampleSize == 2 && Halved == 0) {
+    /* output format is the original cdda format ->
+     * just forward the buffer 
+     */
+      
+    if ( waitforsignal != 0 && any_signal == 0) {
+      UINT4 *myptr = (UINT4 *)pStart;
+      while (myptr < pSrcStop && *myptr == 0) myptr++;
+      pStart = (unsigned char *) myptr;
+      /* scan for first signal */
+      if ( (UINT4 *)pStart != pSrcStop ) {
+       /* first non null amplitude is found in buffer */
+       any_signal = 1;
+       global.SkippedSamples += ((UINT4 *)pStart - p);
+      } else {
+       global.SkippedSamples += (pSrcStop - p);
+      }
+    }
+    pDst = (unsigned char *) pSrcStop;         /* set pDst to end */
+
+    if (global.deemphasize && (Get_Preemphasis(get_current_track())) ) {
+      /* this implements an attenuation treble shelving filter 
+         to undo the effect of pre-emphasis. The filter is of
+         a recursive first order */
+      static Int16_t lastin[2] = { 0, 0 };
+      static double lastout[2] = { 0.0, 0.0 };
+      Int16_t *pmm;
+
+      /* Here is the gnuplot file for the frequency response
+         of the deemphasis. The error is below +-0.1dB
+
+# first define the ideal filter. We use the tenfold sampling frequency.
+T=1./441000.
+OmegaU=1./15E-6
+OmegaL=15./50.*OmegaU
+V0=OmegaL/OmegaU
+H0=V0-1.
+B=V0*tan(OmegaU*T/2.)
+# the coefficients follow
+a1=(B - 1.)/(B + 1.)
+b0=(1.0 + (1.0 - a1) * H0/2.)
+b1=(a1 + (a1 - 1.0) * H0/2.)
+# helper variables
+D=b1/b0
+o=2*pi*T
+H2(f)=b0*sqrt((1+2*cos(f*o)*D+D*D)/(1+2*cos(f*o)*a1+a1*a1))
+# now approximate the ideal curve with a fitted one for sampling frequency
+# of 44100 Hz.
+T2=1./44100.
+V02=0.3365
+OmegaU2=1./19E-6
+B2=V02*tan(OmegaU2*T2/2.)
+# the coefficients follow
+a12=(B2 - 1.)/(B2 + 1.)
+b02=(1.0 + (1.0 - a12) * (V02-1.)/2.)
+b12=(a12 + (a12 - 1.0) * (V02-1.)/2.)
+# helper variables
+D2=b12/b02
+o2=2*pi*T2
+H(f)=b02*sqrt((1+2*cos(f*o2)*D2+D2*D2)/(1+2*cos(f*o2)*a12+a12*a12))
+# plot best, real, ideal, level with halved attenuation,
+#      level at full attentuation, 10fold magnified error
+set logscale x
+set grid xtics ytics mxtics mytics
+plot [f=1000:20000] [-12:2] 20*log10(H(f)),20*log10(H2(f)),  20*log10(OmegaL/(2*pi*f)), 0.5*20*log10(V0), 20*log10(V0), 200*log10(H(f)/H2(f))
+pause -1 "Hit return to continue"
+       */
+
+#ifdef TEST
+#define V0     0.3365
+#define OMEGAG (1./19e-6)
+#define T      (1./44100.)
+#define H0     (V0-1.)
+#define B      (V0*tan((OMEGAG * T)/2.0))
+#define a1     ((B - 1.)/(B + 1.))
+#define b0     (1.0 + (1.0 - a1) * H0/2.0)
+#define b1     (a1 + (a1 - 1.0) * H0/2.0)
+#undef V0
+#undef OMEGAG
+#undef T
+#undef H0
+#undef B
+#else
+#define a1     -0.62786881719628784282
+#define b0     0.45995451989513153057
+#define b1     -0.08782333709141937339
+#endif
+
+      for (pmm = (Int16_t *)pStart; pmm < (Int16_t *)pDst;) {
+        lastout[0] = *pmm * b0 + lastin[0] * b1 - lastout[0] * a1;
+        lastin[0] = *pmm;
+        *pmm++ = lastout[0] > 0.0 ? lastout[0] + 0.5 : lastout[0] - 0.5;
+        lastout[1] = *pmm * b0 + lastin[1] * b1 - lastout[1] * a1;
+        lastin[1] = *pmm;
+        *pmm++ = lastout[1] > 0.0 ? lastout[1] + 0.5 : lastout[1] - 0.5;
+      }
+#undef a1
+#undef b0
+#undef b1
+    }
+
+    if (global.swapchannels == 1) {
+       swap_channels((UINT4 *)pStart, SamplesToDo);
+    }
+
+    if (global.findminmax) {
+      Int16_t *pmm;
+      for (pmm = (Int16_t *)pStart; pmm < (Int16_t *)pDst; pmm++) {
+        if (*pmm < global.minamp[1]) global.minamp[1] = *pmm;
+        if (*pmm > global.maxamp[1]) global.maxamp[1] = *pmm;
+        pmm++;
+        if (*pmm < global.minamp[0]) global.minamp[0] = *pmm;
+        if (*pmm > global.maxamp[0]) global.maxamp[0] = *pmm;
+      }
+    }
+  } else {
+
+#define none_missing   0
+#define one_missing    1
+#define two_missing    2
+#define collecting     3
+
+    static int sample_state = collecting;
+    static int Toggle_on = 0;
+
+    if (global.channels == 2 && global.swapchannels == 1) {
+       swap_channels((UINT4 *)pStart, SamplesToDo);
+    }
+
+    /* conversion required */
+    while ( pSrc < pSrcStop ) {
+         
+       long l,r;
+
+       long iSamples_left = (pSrcStop - pSrc) / sizeof(Int16_t) / 2;
+       Int16_t *myptr = (Int16_t *) pSrc;
+
+       /* LSB l, MSB l */
+       l = *myptr++;   /* left channel */
+       r = *myptr++;   /* right channel */
+       pSrc = (UINT4 *) myptr;
+
+       switch (sample_state) {
+       case two_missing:
+two__missing:
+           ls2 += l; rs2 += r;
+           if (undersampling > 1) {
+               ls3 += l; rs3 += r;
+           }
+           sample_state = one_missing;
+           break;
+       case one_missing:
+           auxl = l; auxr = r;
+
+           ls3 += l; rs3 += r;
+           sample_state = none_missing;
+
+           /* FALLTHROUGH */
+none__missing:
+       case none_missing:
+           /* Filtered samples are complete. Now interpolate and scale. */
+
+           if (Halved != 0 && Toggle_on == 0) {
+                lsum = interpolate(lsum, ls2, ls3)/(int) undersampling;
+               rsum = interpolate(rsum, rs2, rs3)/(int) undersampling;
+            } else {
+               lsum /= (int) undersampling;
+               rsum /= (int) undersampling;
+            }
+           emit_sample(lsum, rsum, global.channels);
+           /* reload counter */
+           samples_to_do = undersampling - 1;
+           lsum = auxl;
+           rsum = auxr;
+           /* reset sample register */
+           auxl = ls2 = ls3 = 0;
+           auxr = rs2 = rs3 = 0;
+           Toggle_on ^= 1;
+           sample_state = collecting;
+           break;
+       case collecting:
+           if ( samples_to_do > 0) {
+               samples_to_do--;
+               if (Halved != 0 && Toggle_on == 0) {
+                   /* Divider x.5 : we need data for quadratic interpolation */
+                   iSamples_left--;
+
+                   lsum += l; rsum += r;
+                   if ( samples_to_do < undersampling - 1) {
+                       ls2 += l; rs2 += r;
+                   }
+                   if ( samples_to_do < undersampling - 2) {
+                       ls3 += l; rs3 += r;
+                   }
+               } else {
+                   /* integral divider */
+                   lsum += l;
+                   rsum += r;
+                   iSamples_left--;
+               }
+           } else {
+               if (Halved != 0 && Toggle_on == 0) {
+                   sample_state = two_missing;
+                   goto two__missing;
+               } else {
+                   auxl = l;
+                   auxr = r;
+                   sample_state = none_missing;
+                   goto none__missing;
+               }
+           }
+           break;
+       } /* switch state */
+
+    } /* while */
+
+    /* flush_buffer */
+    if ((samples_to_do == 0 && Halved == 0))
+    {
+       if (Halved != 0 && Toggle_on == 0) {
+           lsum = interpolate(lsum, ls2, ls3)/(int) undersampling;
+           rsum = interpolate(rsum, rs2, rs3)/(int) undersampling;
+       } else {
+           lsum /= (int) undersampling;
+           rsum /= (int) undersampling;
+       }
+       emit_sample(lsum, rsum, global.channels);
+       
+       /* reload counter */
+       samples_to_do = undersampling;
+       
+       /* reset sample register */
+       lsum = auxl = ls2 = ls3 = 0;
+       rsum = auxr = rs2 = rs3 = 0;
+       Toggle_on ^= 1;
+       sample_state = collecting;
+    }
+
+  } /* if optimize else */
+
+  if ( waitforsignal == 0 ) pStart = (unsigned char *)p;
+
+  if ( waitforsignal == 0 || any_signal != 0) {
+    int retval = 0;
+    unsigned outlen;
+    unsigned todo;
+
+    assert(pDst >= pStart);
+    outlen = (size_t) (pDst - pStart);
+
+    if (outlen <= 0) return 0;
+
+#ifdef ECHO_TO_SOUNDCARD
+
+    /* this assumes the soundcard needs samples in native cpu byte order */
+    if (global.echo != 0) {
+               static unsigned char *newp;
+               unsigned    newlen;
+
+               newlen = (100*(outlen/4))/global.playback_rate;
+               newlen = (newlen*4);
+               if ( (newp != NULL) || (newp = malloc( 2*global.nsectors*CD_FRAMESIZE_RAW+32 )) ) {
+                       newlen = ReSampleBuffer( pStart, newp, outlen/4, global.OutSampleSize*global.channels );
+                       write_snd_device((char *)newp, newlen);
+               }
+    }
+#endif
+
+    if ( global.no_file != 0 ) {
+        *TotSamplesDone += SamplesToDo;
+        return 0;
+    }
+    if ( (!global.need_hostorder && global.need_big_endian == (*in_lendian)) ||
+        (global.need_hostorder && global.need_big_endian != MY_BIG_ENDIAN)) {
+      if ( global.OutSampleSize > 1) {
+        /* change endianness from input sample or native cpu order 
+           to required output endianness */
+        change_endianness((UINT4 *)pStart, outlen/4);
+      }
+    }
+    {
+      unsigned char * p2 = pStart;
+
+      todo = outlen;
+      while (todo != 0) {
+       int retval_;
+       retval_ = global.audio_out->WriteSound ( global.audio, p2, todo );
+       if (retval_ < 0) break;
+
+       p2 += retval_;
+       todo -= retval_;
+      }
+    }
+    if (todo == 0) {
+        *TotSamplesDone += SamplesToDo;
+       return 0;
+    } else {
+        fprintf(stderr, "write(audio, 0x%p, %u) = %d\n",pStart,outlen,retval);
+        perror("Probably disk space exhausted");
+        return 1;
+    }
+  } else {
+    *TotSamplesDone += SamplesToDo;
+    return 0;
+  }
+}
diff --git a/icedax/resample.h b/icedax/resample.h
new file mode 100644 (file)
index 0000000..d25216c
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)resample.h      1.3 02/08/02 Copyright 1998,1999 Heiko Eissfeldt */
+#define SYNC_SIZE      600     /* has to be smaller than CD_FRAMESAMPLES */
+
+extern int waitforsignal;      /* flag: wait for any audio response */
+extern int any_signal;
+
+extern short undersampling;    /* conversion factor */
+extern short samples_to_do;    /* loop variable for conversion */
+extern int Halved;             /* interpolate due to non integral divider */
+extern int jitterShift;                /* track accumulated jitter */
+long SaveBuffer(UINT4 *p, unsigned long SecsToDo, unsigned long *BytesDone);
+unsigned char *synchronize(UINT4 *p, unsigned SamplesToDo, 
+                                                                       unsigned TotSamplesDone);
+void   handle_inputendianess(UINT4 *p, unsigned SamplesToDo);
diff --git a/icedax/ringbuff.c b/icedax/ringbuff.c
new file mode 100644 (file)
index 0000000..6678ffb
--- /dev/null
@@ -0,0 +1,231 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)ringbuff.c      1.8 02/11/21 Copyright 1998,1999,2000 Heiko Eissfeldt */
+#include "config.h"
+
+#include <stdxlib.h>
+#include <stdio.h>
+#include <standard.h>
+#include <unixstd.h>
+
+#if defined(HAVE_SEMGET) && defined(USE_SEMAPHORES)
+#include <sys/ipc.h>
+#include <sys/sem.h>
+#endif
+
+#include <usal/scsitransp.h>
+
+#include "mytype.h"
+#include "global.h"
+#include "interface.h"
+#include "ringbuff.h"
+#include "semshm.h"
+#include "exitcodes.h"
+
+#undef WARN_INTERRUPT
+#undef _DEBUG
+#include <assert.h>
+
+static void occupy_buffer(void);
+
+myringbuff **he_fill_buffer;
+myringbuff **last_buffer;
+volatile unsigned long *total_segments_read;
+volatile unsigned long *total_segments_written;
+volatile int *child_waits;
+volatile int *parent_waits;
+volatile int *in_lendian;
+volatile int *eorecording;
+
+static myringbuff *previous_read_buffer;
+static unsigned int total_buffers;
+
+#define SEMS 2
+
+#define defined_buffers() ((*total_segments_read) - (*total_segments_written))
+#define free_buffers() (total_buffers - defined_buffers())
+#define occupied_buffers() (defined_buffers())
+
+/* ARGSUSED */
+void set_total_buffers(unsigned int num_buffers, int mysem_id)
+{
+#if defined(HAVE_SEMGET) && defined(USE_SEMAPHORES)
+  union my_semun mysemun;
+
+  mysemun.val   = 0;
+  if (semctl(mysem_id,(int) DEF_SEM,SETVAL,mysemun) < 0) {
+    perror("semctl DEF_SEM");
+  }
+
+  mysemun.val   = num_buffers;
+  if (semctl(mysem_id,(int) FREE_SEM,SETVAL,mysemun) < 0) {
+    perror("semctl FREE_SEM");
+  }
+#endif
+
+  total_buffers = num_buffers;
+
+  /* initialize pointers */
+  *he_fill_buffer = *last_buffer = previous_read_buffer = NULL;
+#ifdef DEBUG_SHM
+fprintf(stderr, "init: fill_b = %p,  last_b = %p\n", *he_fill_buffer, *last_buffer);
+#endif
+}
+
+const myringbuff *get_previous_read_buffer()
+{
+  assert(previous_read_buffer != NULL);
+  assert(previous_read_buffer != *he_fill_buffer);
+  return previous_read_buffer;
+}
+
+const myringbuff *get_he_fill_buffer()
+{
+  assert(*he_fill_buffer != NULL);
+  assert(previous_read_buffer != *he_fill_buffer);
+  return *he_fill_buffer;
+}
+
+void define_buffer()
+{
+  assert(defined_buffers() < total_buffers);
+
+#ifdef _DEBUG
+#if 0
+  fprintf(stderr,"stop  reading  %p - %p\n",
+                 *he_fill_buffer, (char *)(*he_fill_buffer) + ENTRY_SIZE -1);
+#endif
+#endif
+
+  if (*last_buffer == NULL)
+    *last_buffer = *he_fill_buffer;
+#ifdef DEBUG_SHM
+fprintf(stderr, "define: fill_b = %p,  last_b = %p\n", *he_fill_buffer, *last_buffer);
+#endif
+
+  (*total_segments_read)++;
+  semrelease(sem_id,DEF_SEM,1);
+}
+
+void drop_buffer()
+{
+  assert(free_buffers() < total_buffers);
+  assert(occupied_buffers() > 0);
+
+#ifdef _DEBUG
+#if 0
+  fprintf(stderr," stop  writing %p - %p ",
+                 *last_buffer, (char *)(*last_buffer) + ENTRY_SIZE -1);
+#endif
+#endif
+
+  if (*last_buffer == NULL)
+    *last_buffer = *he_fill_buffer;
+  else
+    *last_buffer = INC(*last_buffer);
+#ifdef DEBUG_SHM
+fprintf(stderr, "drop: fill_b = %p,  last_b = %p\n", *he_fill_buffer, *last_buffer);
+#endif
+  (*total_segments_written)++;
+  semrelease(sem_id,FREE_SEM, 1);
+}
+
+void drop_all_buffers()
+{
+  (*total_segments_written) = (*total_segments_read);
+  semrelease(sem_id,FREE_SEM, total_buffers);
+}
+
+static void occupy_buffer()
+{
+  assert(occupied_buffers() <= total_buffers);
+
+  previous_read_buffer = *he_fill_buffer;
+
+  if (*he_fill_buffer == NULL) {
+    *he_fill_buffer = RB_BASE;
+  } else {
+    *he_fill_buffer = INC(*he_fill_buffer);
+  }
+}
+
+#if defined HAVE_FORK_AND_SHAREDMEM
+myringbuff * get_next_buffer()
+{
+#ifdef WARN_INTERRUPT
+  if (free_buffers() <= 0) {
+    fprintf(stderr, "READER waits!! r=%lu, w=%lu\n", *total_segments_read,
+*total_segments_written);
+  }
+#endif
+
+  /* wait for a new buffer to become available */
+  if (semrequest(sem_id,FREE_SEM) != 0) {
+    /* semaphore operation failed.
+       try again...
+       */
+    fprintf(stderr, "child reader sem request failed\n");
+    exit(SEMAPHORE_ERROR);
+  }
+#if 0
+  fprintf(stderr,"start reading  %p - %p\n",
+                 *he_fill_buffer, (char *)(*fill_buffer) + ENTRY_SIZE -1);
+#endif
+
+  occupy_buffer();
+
+#ifdef DEBUG_SHM
+fprintf(stderr, "next: fill_b = %p,  last_b = %p, @last = %p\n", *he_fill_buffer, *last_buffer, last_buffer);
+#endif
+  return *he_fill_buffer;
+}
+
+myringbuff *get_oldest_buffer()
+{
+  myringbuff *retval;
+
+#ifdef WARN_INTERRUPT
+  if (free_buffers() == total_buffers) {
+    fprintf(stderr, "WRITER waits!! r=%lu, w=%lu\n", *total_segments_read,
+                       *total_segments_written);
+  }
+#endif
+  /* wait for buffer to be defined */
+  if (semrequest(sem_id,DEF_SEM) != 0) {
+    /* semaphore operation failed. */
+    perror("request defined buff:");
+    fprintf(stderr, "parent writer sem request failed\n");
+  }
+
+  retval = *last_buffer;
+
+#if 0
+  fprintf(stderr," begin writing %p - %p\n",
+                  retval, (char *)retval + ENTRY_SIZE -1);
+#endif
+
+  return retval;
+}
+#else /* HAVE_FORK_AND_SHAREDMEM */
+myringbuff * get_next_buffer()
+{
+  occupy_buffer();
+  return *he_fill_buffer;
+}
+
+myringbuff * get_oldest_buffer()
+{
+  return *he_fill_buffer;
+}
+#endif /* HAVE_FORK_AND_SHAREDMEM */
+
diff --git a/icedax/ringbuff.h b/icedax/ringbuff.h
new file mode 100644 (file)
index 0000000..6c85b3a
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)ringbuff.h      1.5 01/10/20 Copyright 1998,1999,2000 Heiko Eissfeldt */
+/* This file contains data structures that reside in the shared memory
+ * segment.
+ */
+
+
+/* the linux semctl prototype is broken as is the definition
+   of union semun in sys/sem.h. */
+
+#ifdef HAVE_UNION_SEMUN
+#      define  my_semun        semun
+#else
+union my_semun {
+  int val;
+  struct semid_ds *pid;
+  unsigned short *array;
+};
+#endif
+
+/* Ringbuffer structures.
+   Space for the ringbuffer is allocated page aligned
+        and contains the following
+
+       -------------------- start of page
+       header (once for the ring buffer) \\
+       space for page alignment          ||+- HEADER_SIZE
+RB_BASE -+v                              ||
+       myringbuffer.offset               |/
+       -------------------- start of page/-- pagesize
+       myringbuffer.data (SEGMENT_SIZE)\
+       space for page alignment        |+- ENTRY_SIZE_PAGE_AL
+       myringbuffer.offset             /
+       -------------------- start of page
+       myringbuffer.data
+       space for page alignment
+       ...
+*/     
+typedef struct {
+  int offset;
+  UINT4 data[CD_FRAMESAMPLES];
+} myringbuff;
+
+struct ringbuffheader {
+  myringbuff *p1;
+  myringbuff *p2;
+  volatile unsigned long total_read;
+  volatile unsigned long total_written;
+  volatile int child_waitstate;
+  volatile int parent_waitstate;
+  volatile int input_littleendian;
+  volatile int end_is_reached;
+  volatile unsigned long nSamplesToDo;
+  int offset;
+  UINT4 data[CD_FRAMESAMPLES];
+};
+
+extern myringbuff **he_fill_buffer;
+extern myringbuff **last_buffer;
+extern volatile unsigned long *total_segments_read;
+extern volatile unsigned long *total_segments_written;
+extern volatile int *child_waits;
+extern volatile int *parent_waits;
+extern volatile int *in_lendian;
+extern volatile int *eorecording;
+
+#define palign(x, a)    (((char *)(x)) + ((a) - 1 - (((unsigned)((x)-1))%(a))))
+#define multpage(x, a)    ((((x) + (a) - 1) / (a)) * (a))
+
+#define HEADER_SIZE multpage(offset_of(struct ringbuffheader, data), global.pagesize)
+#define SEGMENT_SIZE (global.nsectors*CD_FRAMESIZE_RAW)
+#define ENTRY_SIZE_PAGE_AL multpage(SEGMENT_SIZE + offset_of(myringbuff, data), global.pagesize)
+
+#define RB_BASE ((myringbuff *)(((unsigned char *)he_fill_buffer) + HEADER_SIZE - offset_of(myringbuff, data)))
+
+#define INC(a) (myringbuff *)(((char *)RB_BASE) + (((((char *) (a))-((char *)RB_BASE))/ENTRY_SIZE_PAGE_AL + 1) % total_buffers)*ENTRY_SIZE_PAGE_AL)
+
+
+void set_total_buffers(unsigned int num_buffers, int mysem_id);
+const myringbuff *get_previous_read_buffer(void);
+const myringbuff *get_he_fill_buffer(void);
+myringbuff *get_next_buffer(void);
+myringbuff *get_oldest_buffer(void);
+void define_buffer(void);
+void drop_buffer(void);
+void drop_all_buffers(void);
diff --git a/icedax/scsi_cmds.c b/icedax/scsi_cmds.c
new file mode 100644 (file)
index 0000000..e77b3af
--- /dev/null
@@ -0,0 +1,1720 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)scsi_cmds.c     1.29 03/03/31 Copyright 1998-2002 Heiko Eissfeldt */
+/* file for all SCSI commands
+ * FUA (Force Unit Access) bit handling copied from Monty's cdparanoia.
+ */
+#undef DEBUG_FULLTOC
+#undef WARN_FULLTOC
+#define TESTSUBQFALLBACK       0
+
+#include "config.h"
+#include <stdio.h>
+#include <standard.h>
+#include <stdxlib.h>
+#include <strdefs.h>
+#include <schily.h>
+
+#include <btorder.h>
+
+#define        g5x_cdblen(cdb, len)    ((cdb)->count[0] = ((len) >> 16L)& 0xFF,\
+                                (cdb)->count[1] = ((len) >> 8L) & 0xFF,\
+                                (cdb)->count[2] = (len) & 0xFF)
+
+
+#include <usal/usalcmd.h>
+#include <usal/scsidefs.h>
+#include <usal/scsireg.h>
+
+#include <usal/scsitransp.h>
+
+#include "mytype.h"
+#include "icedax.h"
+#include "interface.h"
+#include "byteorder.h"
+#include "global.h"
+#include "wodim.h"
+#include "toc.h"
+#include "scsi_cmds.h"
+#include "exitcodes.h"
+
+unsigned char *bufferTOC;
+subq_chnl *SubQbuffer;
+unsigned char *cmd;
+
+static unsigned ReadFullTOCSony(SCSI *usalp);
+static unsigned ReadFullTOCMMC(SCSI *usalp);
+
+
+int SCSI_emulated_ATAPI_on(SCSI *usalp)
+{
+/*     return is_atapi;*/
+       if (usal_isatapi(usalp) > 0)
+               return (TRUE);
+
+       (void) allow_atapi(usalp, TRUE);
+       return (allow_atapi(usalp, TRUE));
+}
+
+int heiko_mmc(SCSI *usalp)
+{
+        unsigned char  mode[0x100];
+       int             was_atapi;
+        struct  cd_mode_page_2A *mp;
+       int retval;
+
+        fillbytes((caddr_t)mode, sizeof(mode), '\0');
+
+        was_atapi = allow_atapi(usalp, 1);
+        usalp->silent++;
+        mp = mmc_cap(usalp, mode);
+        usalp->silent--;
+        allow_atapi(usalp, was_atapi);
+        if (mp == NULL)
+                return (0);
+
+        /* have a look at the capabilities */
+       if (mp->cd_da_supported == 0) {
+         retval = -1;
+       } else {
+         retval = 1 + mp->cd_da_accurate;
+        }
+       return retval;
+}
+
+
+int accepts_fua_bit;
+unsigned char density = 0;
+unsigned char orgmode4 = 0;
+unsigned char orgmode10, orgmode11;
+
+/* get current sector size from SCSI cdrom drive */
+unsigned int 
+get_orig_sectorsize(SCSI *usalp, unsigned char *m4, unsigned char *m10, 
+                    unsigned char *m11)
+{
+      /* first get current values for density, etc. */
+
+      static unsigned char *modesense = NULL;
+   
+      if (modesense == NULL) {
+        modesense = malloc(12);
+        if (modesense == NULL) {
+          fprintf(stderr, "Cannot allocate memory for mode sense command in line %d\n", __LINE__);
+          return 0;
+        }
+      }
+
+      /* do the scsi cmd */
+      if (usalp->verbose) fprintf(stderr, "\nget density and sector size...");
+      if (mode_sense(usalp, modesense, 12, 0x01, 0) < 0)
+         fprintf(stderr, "get_orig_sectorsize mode sense failed\n");
+
+      /* FIXME: some drives dont deliver block descriptors !!! */
+      if (modesense[3] == 0)
+        return 0;
+
+#if    0
+       modesense[4] = 0x81;
+       modesense[10] = 0x08;
+       modesense[11] = 0x00;
+#endif
+
+      if (m4 != NULL)                       /* density */
+        *m4 = modesense[4];
+      if (m10 != NULL)                      /* MSB sector size */
+        *m10 = modesense[10];
+      if (m11 != NULL)                      /* LSB sector size */
+        *m11 = modesense[11];
+
+      return (modesense[10] << 8) + modesense[11];
+}
+
+
+
+/* switch CDROM scsi drives to given sector size  */
+int set_sectorsize(SCSI *usalp, unsigned int secsize)
+{
+  static unsigned char mode [4 + 8];
+  int retval;
+
+  if (orgmode4 == 0xff) {
+    get_orig_sectorsize(usalp, &orgmode4, &orgmode10, &orgmode11);
+  }
+  if (orgmode4 == 0x82 && secsize == 2048)
+    orgmode4 = 0x81;
+
+  /* prepare to read cds in the previous mode */
+
+  fillbytes((caddr_t)mode, sizeof(mode), '\0');
+  mode[ 3] = 8;               /* Block Descriptor Length */
+  mode[ 4] = orgmode4;                /* normal density */
+  mode[10] =  secsize >> 8;   /* block length "msb" */
+  mode[11] =  secsize & 0xFF; /* block length lsb */
+
+  if (usalp->verbose) fprintf(stderr, "\nset density and sector size...");
+  /* do the scsi cmd */
+  if ((retval = mode_select(usalp, mode, 12, 0, usalp->inq->data_format >= 2)) < 0)
+        fprintf (stderr, "setting sector size failed\n");
+
+  return retval;
+}
+
+
+/* switch Toshiba/DEC and HP drives from/to cdda density */
+void EnableCddaModeSelect(SCSI *usalp, int fAudioMode, unsigned uSectorsize)
+{
+  /* reserved, Medium type=0, Dev spec Parm = 0, block descriptor len 0 oder 8,
+     Density (cd format) 
+     (0=YellowBook, XA Mode 2=81h, XA Mode1=83h and raw audio via SCSI=82h),
+     # blks msb, #blks, #blks lsb, reserved,
+     blocksize, blocklen msb, blocklen lsb,
+   */
+
+  /* MODE_SELECT, page = SCSI-2  save page disabled, reserved, reserved, 
+     parm list len, flags */
+  static unsigned char mode [4 + 8] = { 
+       /* mode section */
+                           0, 
+                            0, 0, 
+                            8,       /* Block Descriptor Length */
+       /* block descriptor */
+                            0,       /* Density Code */
+                            0, 0, 0, /* # of Blocks */
+                            0,       /* reserved */
+                            0, 0, 0};/* Blocklen */
+
+  if (orgmode4 == 0 && fAudioMode) {
+    if (0 == get_orig_sectorsize(usalp, &orgmode4, &orgmode10, &orgmode11)) {
+        /* cannot retrieve density, sectorsize */
+       orgmode10 = (CD_FRAMESIZE >> 8L);
+       orgmode11 = (CD_FRAMESIZE & 0xFF);
+    }
+  }
+
+  if (fAudioMode) {
+    /* prepare to read audio cdda */
+    mode [4] = density;                        /* cdda density */
+    mode [10] = (uSectorsize >> 8L);   /* block length "msb" */
+    mode [11] = (uSectorsize & 0xFF);  /* block length "lsb" */
+  } else {
+    /* prepare to read cds in the previous mode */
+    mode [4] = orgmode4; /* 0x00;                      \* normal density */
+    mode [10] = orgmode10; /* (CD_FRAMESIZE >> 8L);  \* block length "msb" */
+    mode [11] = orgmode11; /* (CD_FRAMESIZE & 0xFF); \* block length lsb */
+  }
+
+  if (usalp->verbose) fprintf(stderr, "\nset density/sector size (EnableCddaModeSelect)...\n");
+  /* do the scsi cmd */
+  if (mode_select(usalp, mode, 12, 0, usalp->inq->data_format >= 2) < 0)
+        fprintf (stderr, "Audio mode switch failed\n");
+}
+
+
+/* read CD Text information from the table of contents */
+void ReadTocTextSCSIMMC(SCSI *usalp)
+{
+    short datalength;
+
+#if 1
+  /* READTOC, MSF, format, res, res, res, Start track/session, len msb,
+     len lsb, control */
+       unsigned char *p = bufferTOC;
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)scmd, sizeof(*scmd), '\0');
+        scmd->addr = (caddr_t)bufferTOC;
+        scmd->size = 4;
+        scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
+        scmd->cdb_len = SC_G1_CDBLEN;
+        scmd->sense_len = CCS_SENSE_LEN;
+        scmd->cdb.g1_cdb.cmd = 0x43;           /* Read TOC command */
+        scmd->cdb.g1_cdb.lun = usal_lun(usalp);
+        scmd->cdb.g1_cdb.addr[0] = 5;          /* format field */
+        scmd->cdb.g1_cdb.res6 = 0;     /* track/session is reserved */
+        g1_cdblen(&scmd->cdb.g1_cdb, 4);
+
+        usalp->silent++;
+        if (usalp->verbose) fprintf(stderr, "\nRead TOC CD Text size ...");
+
+       usalp->cmdname = "read toc size (text)";
+
+        if (usal_cmd(usalp) < 0) {
+          usalp->silent--;
+         if (global.quiet != 1)
+            fprintf (stderr, "Read TOC CD Text failed (probably not supported).\n");
+         p[0] = p[1] = '\0';
+          return ;
+        }
+        usalp->silent--;
+
+       datalength  = (p[0] << 8) | (p[1]);
+       if (datalength <= 2)
+               return;
+
+       fillbytes((caddr_t)scmd, sizeof(*scmd), '\0');
+        scmd->addr = (caddr_t)bufferTOC;
+        scmd->size = 2+datalength;
+        scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
+        scmd->cdb_len = SC_G1_CDBLEN;
+        scmd->sense_len = CCS_SENSE_LEN;
+        scmd->cdb.g1_cdb.cmd = 0x43;           /* Read TOC command */
+        scmd->cdb.g1_cdb.lun = usal_lun(usalp);
+        scmd->cdb.g1_cdb.addr[0] = 5;          /* format field */
+        scmd->cdb.g1_cdb.res6 = 0;     /* track/session is reserved */
+        g1_cdblen(&scmd->cdb.g1_cdb, 2+datalength);
+
+        usalp->silent++;
+        if (usalp->verbose) fprintf(stderr, "\nRead TOC CD Text data (length %hd)...", 2+datalength);
+
+       usalp->cmdname = "read toc data (text)";
+
+        if (usal_cmd(usalp) < 0) {
+          usalp->silent--;
+         if (global.quiet != 1)
+            fprintf (stderr,  "Read TOC CD Text data failed (probably not supported).\n");
+         p[0] = p[1] = '\0';
+          return ;
+        }
+        usalp->silent--;
+#else
+       { FILE *fp;
+       int read_;
+       /*fp = fopen("PearlJam.cdtext", "rb");*/
+       /*fp = fopen("celine.cdtext", "rb");*/
+       fp = fopen("japan.cdtext", "rb");
+       if (fp == NULL) { perror(""); return; }
+       fillbytes(bufferTOC, CD_FRAMESIZE, '\0');
+       read_ = fread(bufferTOC, 1, CD_FRAMESIZE, fp );
+fprintf(stderr, "read %d bytes. sizeof(bufferTOC)=%u\n", read_, CD_FRAMESIZE);
+        datalength  = (bufferTOC[0] << 8) | (bufferTOC[1]);
+       fclose(fp);
+       }
+#endif
+}
+
+/* read the full TOC */
+static unsigned ReadFullTOCSony(SCSI *usalp)
+{
+  /* READTOC, MSF, format, res, res, res, Start track/session, len msb,
+     len lsb, control */
+       register struct usal_cmd        *scmd = usalp->scmd;
+       unsigned tracks = 99;
+
+       fillbytes((caddr_t)scmd, sizeof(*scmd), '\0');
+        scmd->addr = (caddr_t)bufferTOC;
+        scmd->size = 4 + (3 + tracks + 6) * 11;
+        scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
+        scmd->cdb_len = SC_G1_CDBLEN;
+        scmd->sense_len = CCS_SENSE_LEN;
+        scmd->cdb.g1_cdb.cmd = 0x43;           /* Read TOC command */
+        scmd->cdb.g1_cdb.lun = usal_lun(usalp);
+        scmd->cdb.g1_cdb.res6 = 1;             /* session */
+        g1_cdblen(&scmd->cdb.g1_cdb, 4 + (3 + tracks + 6) * 11);
+        scmd->cdb.g1_cdb.vu_97 = 1;            /* format */
+
+        usalp->silent++;
+        if (usalp->verbose) fprintf(stderr, "\nRead Full TOC Sony ...");
+
+       usalp->cmdname = "read full toc sony";
+
+        if (usal_cmd(usalp) < 0) {
+          usalp->silent--;
+         if (global.quiet != 1)
+            fprintf (stderr, "Read Full TOC Sony failed (probably not supported).\n");
+          return 0;
+        }
+        usalp->silent--;
+
+       return (unsigned)((bufferTOC[0] << 8) | bufferTOC[1]);
+}
+
+struct msf_address {
+       unsigned char   mins;
+       unsigned char   secs;
+       unsigned char   frame;
+};
+
+struct zmsf_address {
+       unsigned char   zero;
+       unsigned char   mins;
+       unsigned char   secs;
+       unsigned char   frame;
+};
+
+#ifdef WARN_FULLTOC
+static unsigned lba(struct msf_address *ad);
+
+static unsigned lba(struct msf_address *ad)
+{
+       return  ad->mins*60*75 + ad->secs*75 + ad->frame;
+}
+#endif
+
+static unsigned dvd_lba(struct zmsf_address *ad);
+
+static unsigned dvd_lba(struct zmsf_address *ad)
+{
+       return  ad->zero*1053696 + ad->mins*60*75 + ad->secs*75 + ad->frame;
+}
+
+struct tocdesc {
+       unsigned char   session;
+       unsigned char   adrctl;
+       unsigned char   tno;
+       unsigned char   point;
+       struct msf_address      adr1;
+       struct zmsf_address     padr2;
+};
+
+struct outer {
+       unsigned char   len_msb;
+       unsigned char   len_lsb;
+       unsigned char   first_track;
+       unsigned char   last_track;
+       struct tocdesc ent[1];
+};
+
+static unsigned long first_session_leadout = 0;
+
+static unsigned collect_tracks(struct outer *po, unsigned entries, 
+                                                                                BOOL bcd_flag);
+
+static unsigned collect_tracks(struct outer *po, unsigned entries, 
+                               BOOL bcd_flag)
+{
+       unsigned tracks = 0;
+       int i;
+       unsigned session;
+       unsigned last_start;
+       unsigned leadout_start_orig;
+       unsigned leadout_start;
+       unsigned max_leadout = 0;
+
+#ifdef DEBUG_FULLTOC
+       for (i = 0; i < entries; i++) {
+fprintf(stderr, "%3d: %d %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n" 
+       ,i
+       ,bufferTOC[4+0 + (i * 11)]
+       ,bufferTOC[4+1 + (i * 11)]
+       ,bufferTOC[4+2 + (i * 11)]
+       ,bufferTOC[4+3 + (i * 11)]
+       ,bufferTOC[4+4 + (i * 11)]
+       ,bufferTOC[4+5 + (i * 11)]
+       ,bufferTOC[4+6 + (i * 11)]
+       ,bufferTOC[4+7 + (i * 11)]
+       ,bufferTOC[4+8 + (i * 11)]
+       ,bufferTOC[4+9 + (i * 11)]
+       ,bufferTOC[4+10 + (i * 11)]
+       );
+       }
+#endif
+       /* reformat to standard toc format */
+
+       bufferTOC[2] = 0;
+       bufferTOC[3] = 0;
+       session = 0;
+       last_start = 0;
+       leadout_start_orig = 0;
+       leadout_start = 0;
+
+       for (i = 0; i < entries; i++) {
+#ifdef WARN_FULLTOC
+               if (po->ent[i].tno != 0) {
+                       fprintf(stderr,
+"entry %d, tno is not 0: %d!\n",
+i, po->ent[i].tno);
+               }
+#endif
+               if (bcd_flag) {
+                       po->ent[i].session     = from_bcd(po->ent[i].session);
+                       po->ent[i].adr1.mins    = from_bcd(po->ent[i].adr1.mins);
+                       po->ent[i].adr1.secs    = from_bcd(po->ent[i].adr1.secs);
+                       po->ent[i].adr1.frame  = from_bcd(po->ent[i].adr1.frame);
+                       po->ent[i].padr2.mins   = from_bcd(po->ent[i].padr2.mins);
+                       po->ent[i].padr2.secs   = from_bcd(po->ent[i].padr2.secs);
+                       po->ent[i].padr2.frame = from_bcd(po->ent[i].padr2.frame);
+               }
+               switch (po->ent[i].point) {
+               case    0xa0:
+
+                       /* check if session is monotonous increasing */
+
+                       if (session+1 == po->ent[i].session) {
+                               session = po->ent[i].session;
+                       }
+#ifdef WARN_FULLTOC
+                       else fprintf(stderr,
+"entry %d, session anomaly %d != %d!\n",
+i, session+1, po->ent[i].session);
+
+                       /* check the adrctl field */
+                       if (0x10 != (po->ent[i].adrctl & 0x10)) {
+                               fprintf(stderr,
+"entry %d, incorrect adrctl field %x!\n",
+i, po->ent[i].adrctl);
+                       }
+#endif
+                       /* first track number */
+                       if (bufferTOC[2] < po->ent[i].padr2.mins
+                           && bufferTOC[3] < po->ent[i].padr2.mins) {
+                               bufferTOC[2] = po->ent[i].padr2.mins;
+                       }
+#ifdef WARN_FULLTOC
+                       else
+                               fprintf(stderr,
+"entry %d, session %d: start tracknumber anomaly: %d <= %d,%d(last)!\n",
+i, session, po->ent[i].padr2.mins, bufferTOC[2], bufferTOC[3]);
+#endif
+                       break;
+
+               case    0xa1:
+#ifdef WARN_FULLTOC
+                       /* check if session is constant */
+                       if (session != po->ent[i].session) {
+                               fprintf(stderr,
+"entry %d, session anomaly %d != %d!\n",
+i, session, po->ent[i].session);
+                       }
+
+                       /* check the adrctl field */
+                       if (0x10 != (po->ent[i].adrctl & 0x10)) {
+                               fprintf(stderr,
+"entry %d, incorrect adrctl field %x!\n",
+i, po->ent[i].adrctl);
+                       }
+#endif
+                       /* last track number */
+                       if (bufferTOC[2] <= po->ent[i].padr2.mins
+                           && bufferTOC[3] < po->ent[i].padr2.mins) {
+                               bufferTOC[3] = po->ent[i].padr2.mins;
+                       }
+#ifdef WARN_FULLTOC
+                       else
+                               fprintf(stderr,
+"entry %d, session %d: end tracknumber anomaly: %d <= %d,%d(last)!\n",
+i, session, po->ent[i].padr2.mins, bufferTOC[2], bufferTOC[3]);
+#endif
+                       break;
+
+               case    0xa2:
+#ifdef WARN_FULLTOC
+                       /* check if session is constant */
+                       if (session != po->ent[i].session) {
+                               fprintf(stderr,
+"entry %d, session anomaly %d != %d!\n",
+i, session, po->ent[i].session);
+                       }
+
+                       /* check the adrctl field */
+                       if (0x10 != (po->ent[i].adrctl & 0x10)) {
+                               fprintf(stderr,
+"entry %d, incorrect adrctl field %x!\n",
+i, po->ent[i].adrctl);
+                       }
+#endif
+                       /* register leadout position */
+               {
+                       unsigned leadout_start_tmp  = 
+                               dvd_lba(&po->ent[i].padr2);
+
+                       if (first_session_leadout  == 0)
+                               first_session_leadout = leadout_start_tmp - 150;
+
+                       if (leadout_start_tmp > leadout_start) {
+                               leadout_start_orig = leadout_start_tmp;
+                               leadout_start = leadout_start_tmp;
+                       }
+#ifdef WARN_FULLTOC
+                       else
+                               fprintf(stderr,
+"entry %d, leadout position anomaly %u!\n",
+i, leadout_start_tmp);
+#endif
+               }
+                       break;
+
+               case    0xb0:
+#ifdef WARN_FULLTOC
+                       /* check if session is constant */
+                       if (session != po->ent[i].session) {
+                               fprintf(stderr,
+"entry %d, session anomaly %d != %d!\n",
+i, session, po->ent[i].session);
+                       }
+
+                       /* check the adrctl field */
+                       if (0x50 != (po->ent[i].adrctl & 0x50)) {
+                               fprintf(stderr,
+"entry %d, incorrect adrctl field %x!\n",
+i, po->ent[i].adrctl);
+                       }
+
+                       /* check the next program area */
+                       if (lba(&po->ent[i].adr1) < 6750 + leadout_start) {
+                               fprintf(stderr,
+"entry %d, next program area %u < leadout_start + 6750 = %u!\n",
+i, lba(&po->ent[i].adr1), 6750 + leadout_start);
+                       }
+
+                       /* check the maximum leadout_start */
+                       if (max_leadout != 0 && dvd_lba(&po->ent[i].padr2) != max_leadout) {
+                               fprintf(stderr,
+"entry %d, max leadout_start %u != last max_leadout_start %u!\n",
+i, dvd_lba(&po->ent[i].padr2), max_leadout);
+                       }
+#endif
+                       if (max_leadout == 0)
+                               max_leadout = dvd_lba(&po->ent[i].padr2);
+
+                       break;
+               case    0xb1:
+               case    0xb2:
+               case    0xb3:
+               case    0xb4:
+               case    0xb5:
+               case    0xb6:
+                       break;
+               case    0xc0:
+               case    0xc1:
+                       break;
+               default:
+                       /* check if session is constant */
+                       if (session != po->ent[i].session) {
+#ifdef WARN_FULLTOC
+                               fprintf(stderr,
+"entry %d, session anomaly %d != %d!\n",
+i, session, po->ent[i].session);
+#endif
+                               continue;
+                       }
+
+                       /* check tno */
+                       if (bcd_flag)
+                               po->ent[i].point  = from_bcd(po->ent[i].point);
+
+                       if (po->ent[i].point < bufferTOC[2]
+                           || po->ent[i].point > bufferTOC[3]) {
+#ifdef WARN_FULLTOC
+                               fprintf(stderr,
+"entry %d, track number anomaly %d - %d - %d!\n",
+i, bufferTOC[2], po->ent[i].point, bufferTOC[3]);
+#endif
+                       } else {
+                               /* check start position */
+                               unsigned trackstart = dvd_lba(&po->ent[i].padr2);
+
+                               /* correct illegal leadouts */
+                               if (leadout_start < trackstart) {
+                                       leadout_start = trackstart+1;
+                               }
+                               if (trackstart < last_start || trackstart >= leadout_start) {
+#ifdef WARN_FULLTOC
+                                       fprintf(stderr,
+"entry %d, track %d start position anomaly %d - %d - %d!\n",
+i, po->ent[i].point, last_start, trackstart, leadout_start);
+#endif
+                               } else {
+                                       last_start = trackstart;
+                                       memcpy(&po->ent[tracks], &po->ent[i], sizeof(struct tocdesc));
+                                       tracks++;
+                               }
+                       }
+               }       /* switch */
+       }       /* for */
+
+       /* patch leadout track */
+       po->ent[tracks].session = session;
+       po->ent[tracks].adrctl = 0x10;
+       po->ent[tracks].tno = 0;
+       po->ent[tracks].point = 0xAA;
+       po->ent[tracks].adr1.mins = 0;
+       po->ent[tracks].adr1.secs = 0;
+       po->ent[tracks].adr1.frame = 0;
+       po->ent[tracks].padr2.zero = leadout_start_orig / (1053696);
+       po->ent[tracks].padr2.mins = (leadout_start_orig / (60*75)) % 100;
+       po->ent[tracks].padr2.secs = (leadout_start_orig / 75) % 60;
+       po->ent[tracks].padr2.frame = leadout_start_orig % 75;
+       tracks++;
+
+       /* length */
+       bufferTOC[0] = ((tracks * 8) + 2) >> 8;
+       bufferTOC[1] = ((tracks * 8) + 2) & 0xff;
+
+
+       /* reformat 11 byte blocks to 8 byte entries */
+
+       /* 1: Session   \       /       reserved
+          2: adr ctrl  |       |       adr ctrl
+          3: TNO       |       |       track number
+          4: Point     |       |       reserved
+          5: Min       +-->----+       0
+          6: Sec       |       |       Min
+          7: Frame     |       |       Sec
+          8: Zero      |       \       Frame
+          9: PMin      |
+          10: PSec     |
+          11: PFrame   /
+       */
+       for (i = 0; i < tracks; i++) {
+               bufferTOC[4+0 + (i << 3)] = 0;
+               bufferTOC[4+1 + (i << 3)] = bufferTOC[4+1 + (i*11)];
+               bufferTOC[4+1 + (i << 3)] = (bufferTOC[4+1 + (i << 3)] >> 4) | (bufferTOC[4+1 + (i << 3)] << 4);
+               bufferTOC[4+2 + (i << 3)] = bufferTOC[4+3 + (i*11)];
+               bufferTOC[4+3 + (i << 3)] = 0;
+               bufferTOC[4+4 + (i << 3)] = bufferTOC[4+7 + (i*11)];
+               bufferTOC[4+5 + (i << 3)] = bufferTOC[4+8 + (i*11)];
+               bufferTOC[4+6 + (i << 3)] = bufferTOC[4+9 + (i*11)];
+               bufferTOC[4+7 + (i << 3)] = bufferTOC[4+10 + (i*11)];
+#ifdef DEBUG_FULLTOC
+fprintf(stderr, "%02x %02x %02x %02x %02x %02x\n"
+       ,bufferTOC[4+ 1 + i*8]
+       ,bufferTOC[4+ 2 + i*8]
+       ,bufferTOC[4+ 4 + i*8]
+       ,bufferTOC[4+ 5 + i*8]
+       ,bufferTOC[4+ 6 + i*8]
+       ,bufferTOC[4+ 7 + i*8]
+);
+#endif
+       }
+
+       TOC_entries(tracks, NULL, bufferTOC+4, 0);
+       return tracks;
+}
+
+/* read the table of contents from the cd and fill the TOC array */
+unsigned ReadTocSony(SCSI *usalp)
+{
+       unsigned tracks = 0;
+       unsigned return_length;
+
+       struct outer *po = (struct outer *)bufferTOC;
+
+       return_length = ReadFullTOCSony(usalp);
+
+       /* Check if the format was understood */
+       if ((return_length & 7) == 2 && (bufferTOC[3] - bufferTOC[2]) == (return_length >> 3)) {
+               /* The extended format seems not be understood, fallback to
+                * the classical format. */
+               return ReadTocSCSI( usalp );
+       }
+
+       tracks = collect_tracks(po, ((return_length - 2) / 11), TRUE);
+
+       return --tracks;           /* without lead-out */
+}
+
+/* read the start of the lead-out from the first session TOC */
+unsigned ReadFirstSessionTOCSony(SCSI *usalp)
+{
+       unsigned return_length;
+       
+       if (first_session_leadout != 0)
+               return first_session_leadout;
+
+       return_length = ReadFullTOCSony(usalp);
+        if (return_length >= 4 + (3 * 11) -2) {
+          unsigned off;
+
+          /* We want the entry with POINT = 0xA2, which has the start position
+             of the first session lead out */
+          off = 4 + 2 * 11 + 3;
+          if (bufferTOC[off-3] == 1 && bufferTOC[off] == 0xA2) {
+            unsigned retval;
+
+            off = 4 + 2 * 11 + 8;
+            retval = bufferTOC[off] >> 4;
+           retval *= 10; retval += bufferTOC[off] & 0xf;
+           retval *= 60;
+           off++;
+            retval += 10 * (bufferTOC[off] >> 4) + (bufferTOC[off] & 0xf);
+           retval *= 75;
+           off++;
+            retval += 10 * (bufferTOC[off] >> 4) + (bufferTOC[off] & 0xf);
+           retval -= 150;
+
+            return retval;
+          }
+        }
+        return 0;
+}
+
+/* read the full TOC */
+static unsigned ReadFullTOCMMC(SCSI *usalp)
+{
+
+  /* READTOC, MSF, format, res, res, res, Start track/session, len msb,
+     len lsb, control */
+       register struct usal_cmd        *scmd = usalp->scmd;
+       unsigned tracks = 99;
+
+       fillbytes((caddr_t)scmd, sizeof(*scmd), '\0');
+        scmd->addr = (caddr_t)bufferTOC;
+        scmd->size = 4 + (tracks + 8) * 11;
+        scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
+        scmd->cdb_len = SC_G1_CDBLEN;
+        scmd->sense_len = CCS_SENSE_LEN;
+        scmd->cdb.g1_cdb.cmd = 0x43;           /* Read TOC command */
+        scmd->cdb.g1_cdb.lun = usal_lun(usalp);
+        scmd->cdb.g1_cdb.addr[0] = 2;          /* format */
+        scmd->cdb.g1_cdb.res6 = 1;             /* session */
+        g1_cdblen(&scmd->cdb.g1_cdb, 4 + (tracks + 8) * 11);
+
+        usalp->silent++;
+        if (usalp->verbose) fprintf(stderr, "\nRead Full TOC MMC...");
+
+       usalp->cmdname = "read full toc mmc";
+
+        if (usal_cmd(usalp) < 0) {
+         if (global.quiet != 1)
+            fprintf (stderr, "Read Full TOC MMC failed (probably not supported).\n");
+#ifdef B_BEOS_VERSION
+#else
+          usalp->silent--;
+          return 0;
+#endif
+        }
+        usalp->silent--;
+
+       return (unsigned)((bufferTOC[0] << 8) | bufferTOC[1]);
+}
+
+/* read the start of the lead-out from the first session TOC */
+unsigned ReadFirstSessionTOCMMC(SCSI *usalp)
+{
+        unsigned off;
+       unsigned return_length;
+
+       if (first_session_leadout != 0)
+               return first_session_leadout;
+
+       return_length = ReadFullTOCMMC(usalp);
+
+        /* We want the entry with POINT = 0xA2, which has the start position
+             of the first session lead out */
+        off = 4 + 3;
+        while (off < return_length && bufferTOC[off] != 0xA2) {
+          off += 11;
+        }
+        if (off < return_length) {
+          off += 5;
+          return (bufferTOC[off]*60 + bufferTOC[off+1])*75 + bufferTOC[off+2] - 150;
+        }
+        return 0;
+}
+
+/* read the table of contents from the cd and fill the TOC array */
+unsigned ReadTocMMC(SCSI *usalp)
+{
+       unsigned tracks = 0;
+       unsigned return_length;
+
+       struct outer *po = (struct outer *)bufferTOC;
+
+       return_length = ReadFullTOCMMC(usalp);
+       if (return_length - 2 < 4*11 || ((return_length - 2) % 11) != 0)
+               return ReadTocSCSI(usalp);
+
+       tracks = collect_tracks(po, ((return_length - 2) / 11), FALSE);
+       return --tracks;           /* without lead-out */
+}
+
+/* read the table of contents from the cd and fill the TOC array */
+unsigned ReadTocSCSI(SCSI *usalp)
+{
+    unsigned tracks;
+    int        result;
+    unsigned char bufferTOCMSF[CD_FRAMESIZE];
+
+    /* first read the first and last track number */
+    /* READTOC, MSF format flag, res, res, res, res, Start track, len msb,
+       len lsb, flags */
+    register struct    usal_cmd        *scmd = usalp->scmd;
+
+    fillbytes((caddr_t)scmd, sizeof(*scmd), '\0');
+    scmd->addr = (caddr_t)bufferTOC;
+    scmd->size = 4;
+    scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
+    scmd->cdb_len = SC_G1_CDBLEN;
+    scmd->sense_len = CCS_SENSE_LEN;
+    scmd->cdb.g1_cdb.cmd = 0x43;               /* read TOC command */
+    scmd->cdb.g1_cdb.lun = usal_lun(usalp);
+    scmd->cdb.g1_cdb.res6 = 1;         /* start track */
+    g1_cdblen(&scmd->cdb.g1_cdb, 4);
+
+    if (usalp->verbose) fprintf(stderr, "\nRead TOC size (standard)...");
+    /* do the scsi cmd (read table of contents) */
+
+    usalp->cmdname = "read toc size";
+    if (usal_cmd(usalp) < 0)
+       FatalError ("Read TOC size failed.\n");
+    
+
+    tracks = ((bufferTOC [3] ) - bufferTOC [2] + 2) ;
+    if (tracks > MAXTRK) return 0;
+    if (tracks == 0) return 0;
+    
+    
+    memset(bufferTOCMSF, 0, sizeof(bufferTOCMSF));
+    fillbytes((caddr_t)scmd, sizeof(*scmd), '\0');
+    scmd->addr = (caddr_t)bufferTOCMSF;
+    scmd->size = 4 + tracks * 8;
+    scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
+    scmd->cdb_len = SC_G1_CDBLEN;
+    scmd->sense_len = CCS_SENSE_LEN;
+    scmd->cdb.g1_cdb.cmd = 0x43;               /* read TOC command */
+    scmd->cdb.g1_cdb.lun = usal_lun(usalp);
+    scmd->cdb.g1_cdb.res = 1;          /* MSF format */
+    scmd->cdb.g1_cdb.res6 = 1;         /* start track */
+    g1_cdblen(&scmd->cdb.g1_cdb, 4 + tracks * 8);
+
+    if (usalp->verbose) fprintf(stderr, "\nRead TOC tracks (standard MSF)...");
+    /* do the scsi cmd (read table of contents) */
+
+    usalp->cmdname = "read toc tracks ";
+    result = usal_cmd(usalp);
+
+    if (result < 0) {
+       /* MSF format did not succeeded */
+       memset(bufferTOCMSF, 0, sizeof(bufferTOCMSF));
+    } else {
+       int     i;
+       for (i = 0; i < tracks; i++) {
+               bufferTOCMSF[4+1 + (i << 3)] = (bufferTOCMSF[4+1 + (i << 3)] >> 4) | (bufferTOCMSF[4+1 + (i << 3)] << 4);
+#if    0
+fprintf(stderr, "MSF %d %02x %02x %02x %02x %02x %02x %02x %02x\n" 
+       ,i
+       ,bufferTOCMSF[4+0 + (i * 8)]
+       ,bufferTOCMSF[4+1 + (i * 8)]
+       ,bufferTOCMSF[4+2 + (i * 8)]
+       ,bufferTOCMSF[4+3 + (i * 8)]
+       ,bufferTOCMSF[4+4 + (i * 8)]
+       ,bufferTOCMSF[4+5 + (i * 8)]
+       ,bufferTOCMSF[4+6 + (i * 8)]
+       ,bufferTOCMSF[4+7 + (i * 8)]
+       );
+#endif
+       }
+    }
+
+    /* LBA format for cd burners like Philips CD-522 */
+    fillbytes((caddr_t)scmd, sizeof(*scmd), '\0');
+    scmd->addr = (caddr_t)bufferTOC;
+    scmd->size = 4 + tracks * 8;
+    scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
+    scmd->cdb_len = SC_G1_CDBLEN;
+    scmd->sense_len = CCS_SENSE_LEN;
+    scmd->cdb.g1_cdb.cmd = 0x43;               /* read TOC command */
+    scmd->cdb.g1_cdb.lun = usal_lun(usalp);
+    scmd->cdb.g1_cdb.res = 0;          /* LBA format */
+    scmd->cdb.g1_cdb.res6 = 1;         /* start track */
+    g1_cdblen(&scmd->cdb.g1_cdb, 4 + tracks * 8);
+
+    if (usalp->verbose) fprintf(stderr, "\nRead TOC tracks (standard LBA)...");
+    /* do the scsi cmd (read table of contents) */
+
+    usalp->cmdname = "read toc tracks ";
+    if (usal_cmd(usalp) < 0) {
+       FatalError ("Read TOC tracks (lba) failed.\n");
+    }
+    {
+       int     i;
+       for (i = 0; i < tracks; i++) {
+               bufferTOC[4+1 + (i << 3)] = (bufferTOC[4+1 + (i << 3)] >> 4) | (bufferTOC[4+1 + (i << 3)] << 4);
+#if    0
+fprintf(stderr, "LBA %d %02x %02x %02x %02x %02x %02x %02x %02x\n" 
+       ,i
+       ,bufferTOC[4+0 + (i * 8)]
+       ,bufferTOC[4+1 + (i * 8)]
+       ,bufferTOC[4+2 + (i * 8)]
+       ,bufferTOC[4+3 + (i * 8)]
+       ,bufferTOC[4+4 + (i * 8)]
+       ,bufferTOC[4+5 + (i * 8)]
+       ,bufferTOC[4+6 + (i * 8)]
+       ,bufferTOC[4+7 + (i * 8)]
+       );
+#endif
+       }
+    }
+    TOC_entries(tracks, bufferTOC+4, bufferTOCMSF+4, result);
+    return --tracks;           /* without lead-out */
+}
+
+/* ---------------- Read methods ------------------------------ */
+
+/* Read max. SectorBurst of cdda sectors to buffer
+   via standard SCSI-2 Read(10) command */
+static int ReadStandardLowlevel(SCSI *usalp, UINT4 *p, unsigned lSector, 
+                                                                                 unsigned SectorBurstVal, unsigned secsize);
+
+static int ReadStandardLowlevel(SCSI *usalp, UINT4 *p, unsigned lSector, 
+                                                                                 unsigned SectorBurstVal, unsigned secsize)
+{
+  /* READ10, flags, block1 msb, block2, block3, block4 lsb, reserved, 
+     transfer len msb, transfer len lsb, block addressing mode */
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)scmd, sizeof(*scmd), '\0');
+        scmd->addr = (caddr_t)p;
+        scmd->size = SectorBurstVal * secsize;
+        scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
+        scmd->cdb_len = SC_G1_CDBLEN;
+        scmd->sense_len = CCS_SENSE_LEN;
+        scmd->cdb.g1_cdb.cmd = 0x28;           /* read 10 command */
+        scmd->cdb.g1_cdb.lun = usal_lun(usalp);
+       scmd->cdb.g1_cdb.res |= (accepts_fua_bit == 1 ? 1 << 2 : 0);
+        g1_cdbaddr(&scmd->cdb.g1_cdb, lSector);
+        g1_cdblen(&scmd->cdb.g1_cdb, SectorBurstVal);
+        if (usalp->verbose) fprintf(stderr, "\nReadStandard10 %s (%u)...", secsize > 2048 ? "CDDA" : "CD_DATA", secsize);
+
+       usalp->cmdname = "ReadStandard10";
+
+       if (usal_cmd(usalp)) return 0;
+
+       /* has all or something been read? */
+       return SectorBurstVal - usal_getresid(usalp)/secsize;
+}
+
+
+int 
+ReadStandard(SCSI *usalp, UINT4 *p, unsigned lSector, unsigned SectorBurstVal)
+{
+       return ReadStandardLowlevel(usalp, p, lSector, SectorBurstVal, CD_FRAMESIZE_RAW);
+}
+
+int 
+ReadStandardData(SCSI *usalp, UINT4 *p, unsigned lSector, unsigned SectorBurstVal)
+{
+       return ReadStandardLowlevel(usalp, p, lSector, SectorBurstVal, CD_FRAMESIZE);
+}
+
+/* Read max. SectorBurst of cdda sectors to buffer
+   via vendor-specific ReadCdda(10) command */
+int ReadCdda10(SCSI *usalp, UINT4 *p, unsigned lSector, unsigned SectorBurstVal)
+{
+  /* READ10, flags, block1 msb, block2, block3, block4 lsb, reserved, 
+     transfer len msb, transfer len lsb, block addressing mode */
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)scmd, sizeof(*scmd), '\0');
+        scmd->addr = (caddr_t)p;
+        scmd->size = SectorBurstVal*CD_FRAMESIZE_RAW;
+        scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
+        scmd->cdb_len = SC_G1_CDBLEN;
+        scmd->sense_len = CCS_SENSE_LEN;
+        scmd->cdb.g1_cdb.cmd = 0xd4;           /* Read audio command */
+        scmd->cdb.g1_cdb.lun = usal_lun(usalp);
+       scmd->cdb.g1_cdb.res |= (accepts_fua_bit == 1 ? 1 << 2 : 0);
+        g1_cdbaddr(&scmd->cdb.g1_cdb, lSector);
+        g1_cdblen(&scmd->cdb.g1_cdb, SectorBurstVal);
+        if (usalp->verbose) fprintf(stderr, "\nReadNEC10 CDDA...");
+
+       usalp->cmdname = "Read10 NEC";
+
+       if (usal_cmd(usalp)) return 0;
+
+       /* has all or something been read? */
+       return SectorBurstVal - usal_getresid(usalp)/CD_FRAMESIZE_RAW;
+}
+
+
+/* Read max. SectorBurst of cdda sectors to buffer
+   via vendor-specific ReadCdda(12) command */
+int ReadCdda12(SCSI *usalp, UINT4 *p, unsigned lSector, unsigned SectorBurstVal)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)scmd, sizeof(*scmd), '\0');
+        scmd->addr = (caddr_t)p;
+        scmd->size = SectorBurstVal*CD_FRAMESIZE_RAW;
+        scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
+        scmd->cdb_len = SC_G5_CDBLEN;
+        scmd->sense_len = CCS_SENSE_LEN;
+        scmd->cdb.g5_cdb.cmd = 0xd8;           /* read audio command */
+        scmd->cdb.g5_cdb.lun = usal_lun(usalp);
+       scmd->cdb.g5_cdb.res |= (accepts_fua_bit == 1 ? 1 << 2 : 0);
+        g5_cdbaddr(&scmd->cdb.g5_cdb, lSector);
+        g5_cdblen(&scmd->cdb.g5_cdb, SectorBurstVal);
+
+        if (usalp->verbose) fprintf(stderr, "\nReadSony12 CDDA...");
+
+       usalp->cmdname = "Read12";
+
+       if (usal_cmd(usalp)) return 0;
+
+       /* has all or something been read? */
+       return SectorBurstVal - usal_getresid(usalp)/CD_FRAMESIZE_RAW;
+}
+
+/* Read max. SectorBurst of cdda sectors to buffer
+   via vendor-specific ReadCdda(12) command */
+/*
+> It uses a 12 Byte CDB with 0xd4 as opcode, the start sector is coded as
+> normal and the number of sectors is coded in Byte 8 and 9 (begining with 0).
+*/
+
+int ReadCdda12Matsushita(SCSI *usalp, UINT4 *p, unsigned lSector, 
+                         unsigned SectorBurstVal)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+        fillbytes((caddr_t)scmd, sizeof(*scmd), '\0');
+        scmd->addr = (caddr_t)p;
+        scmd->size = SectorBurstVal*CD_FRAMESIZE_RAW;
+        scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
+        scmd->cdb_len = SC_G5_CDBLEN;
+        scmd->sense_len = CCS_SENSE_LEN;
+        scmd->cdb.g5_cdb.cmd = 0xd4;           /* read audio command */
+        scmd->cdb.g5_cdb.lun = usal_lun(usalp);
+       scmd->cdb.g5_cdb.res |= (accepts_fua_bit == 1 ? 1 << 2 : 0);
+        g5_cdbaddr(&scmd->cdb.g5_cdb, lSector);
+        g5_cdblen(&scmd->cdb.g5_cdb, SectorBurstVal);
+
+        if (usalp->verbose) fprintf(stderr, "\nReadMatsushita12 CDDA...");
+
+       usalp->cmdname = "Read12Matsushita";
+
+       if (usal_cmd(usalp)) return 0;
+
+       /* has all or something been read? */
+       return SectorBurstVal - usal_getresid(usalp)/CD_FRAMESIZE_RAW;
+}
+
+/* Read max. SectorBurst of cdda sectors to buffer
+   via MMC standard READ CD command */
+int ReadCddaMMC12(SCSI *usalp, UINT4 *p, unsigned lSector, 
+                  unsigned SectorBurstVal)
+{
+       register struct usal_cmd        *scmd;
+       scmd = usalp->scmd;
+
+       fillbytes((caddr_t)scmd, sizeof(*scmd), '\0');
+        scmd->addr = (caddr_t)p;
+        scmd->size = SectorBurstVal*CD_FRAMESIZE_RAW;
+        scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
+        scmd->cdb_len = SC_G5_CDBLEN;
+        scmd->sense_len = CCS_SENSE_LEN;
+        scmd->cdb.g5_cdb.cmd = 0xbe;           /* read cd command */
+        scmd->cdb.g5_cdb.lun = usal_lun(usalp);
+        scmd->cdb.g5_cdb.res = 1 << 1; /* expected sector type field CDDA */
+        g5_cdbaddr(&scmd->cdb.g5_cdb, lSector);
+        g5x_cdblen(&scmd->cdb.g5_cdb, SectorBurstVal);
+       scmd->cdb.g5_cdb.count[3] = 1 << 4;     /* User data */
+
+        if (usalp->verbose) fprintf(stderr, "\nReadMMC12 CDDA...");
+
+       usalp->cmdname = "ReadCD MMC 12";
+
+       if (usal_cmd(usalp)) return 0;
+
+       /* has all or something been read? */
+       return SectorBurstVal - usal_getresid(usalp)/CD_FRAMESIZE_RAW;
+}
+
+int ReadCddaFallbackMMC(SCSI *usalp, UINT4 *p, unsigned lSector, 
+                        unsigned SectorBurstVal)
+{
+       static int ReadCdda12_unknown = 0;
+       int retval = -999;
+
+       usalp->silent++;
+       if (ReadCdda12_unknown 
+           || ((retval = ReadCdda12(usalp, p, lSector, SectorBurstVal)) <= 0)) {
+               /* if the command is not available, use the regular
+                * MMC ReadCd 
+                */
+               if (retval <= 0 && usal_sense_key(usalp) == 0x05) {
+                       ReadCdda12_unknown = 1;
+               }
+               usalp->silent--;
+               ReadCdRom = ReadCddaMMC12;
+               ReadCdRomSub = ReadCddaSubMMC12;
+               return ReadCddaMMC12(usalp, p, lSector, SectorBurstVal);
+       }
+       usalp->silent--;
+       return retval;
+}
+
+/* Read the Sub-Q-Channel to SubQbuffer. This is the method for
+ * drives that do not support subchannel parameters. */
+#ifdef PROTOTYPES
+static subq_chnl *ReadSubQFallback (SCSI *usalp, unsigned char sq_format, unsigned char track)
+#else
+static subq_chnl *
+ReadSubQFallback(SCSI *usalp, unsigned char sq_format, unsigned char track)
+#endif
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)scmd, sizeof(*scmd), '\0');
+        scmd->addr = (caddr_t)SubQbuffer;
+        scmd->size = 24;
+        scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
+        scmd->cdb_len = SC_G1_CDBLEN;
+        scmd->sense_len = CCS_SENSE_LEN;
+        scmd->cdb.g1_cdb.cmd = 0x42;           /* Read SubQChannel */
+                                               /* use LBA */
+        scmd->cdb.g1_cdb.lun = usal_lun(usalp);
+        scmd->cdb.g1_cdb.addr[0] = 0x40;       /* SubQ info */
+        scmd->cdb.g1_cdb.addr[1] = 0;          /* parameter list: all */
+        scmd->cdb.g1_cdb.res6 = track;         /* track number */
+        g1_cdblen(&scmd->cdb.g1_cdb, 24);
+
+        if (usalp->verbose) fprintf(stderr, "\nRead Subchannel_dumb...");
+
+       usalp->cmdname = "Read Subchannel_dumb";
+
+       if (usal_cmd(usalp) < 0) {
+         fprintf( stderr, "Read SubQ failed\n");
+       }
+
+       /* check, if the requested format is delivered */
+       { unsigned char *p = (unsigned char *) SubQbuffer;
+         if ((((unsigned)p[2] << 8) | p[3]) /* LENGTH */ > ULONG_C(11) &&
+           (p[5] >> 4) /* ADR */ == sq_format) {
+           if (sq_format == GET_POSITIONDATA)
+               p[5] = (p[5] << 4) | (p[5] >> 4);
+           return SubQbuffer;
+         }
+       }
+
+       /* FIXME: we might actively search for the requested info ... */
+       return NULL;
+}
+
+/* Read the Sub-Q-Channel to SubQbuffer */
+#ifdef PROTOTYPES
+subq_chnl *ReadSubQSCSI (SCSI *usalp, unsigned char sq_format, unsigned char track)
+#else
+subq_chnl *
+ReadSubQSCSI(SCSI *usalp, unsigned char sq_format, unsigned char track)
+#endif
+{
+        int resp_size;
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+        switch (sq_format) {
+          case GET_POSITIONDATA:
+            resp_size = 16;
+           track = 0;
+          break;
+          case GET_CATALOGNUMBER:
+            resp_size = 24;
+           track = 0;
+          break;
+          case GET_TRACK_ISRC:
+            resp_size = 24;
+          break;
+          default:
+                fprintf(stderr, "ReadSubQSCSI: unknown format %d\n", sq_format);
+                return NULL;
+        }
+
+       fillbytes((caddr_t)scmd, sizeof(*scmd), '\0');
+        scmd->addr = (caddr_t)SubQbuffer;
+        scmd->size = resp_size;
+        scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
+        scmd->cdb_len = SC_G1_CDBLEN;
+        scmd->sense_len = CCS_SENSE_LEN;
+        scmd->cdb.g1_cdb.cmd = 0x42;
+                                               /* use LBA */
+        scmd->cdb.g1_cdb.lun = usal_lun(usalp);
+        scmd->cdb.g1_cdb.addr[0] = 0x40;       /* SubQ info */
+        scmd->cdb.g1_cdb.addr[1] = sq_format;  /* parameter list: all */
+        scmd->cdb.g1_cdb.res6 = track;         /* track number */
+        g1_cdblen(&scmd->cdb.g1_cdb, resp_size);
+
+        if (usalp->verbose) fprintf(stderr, "\nRead Subchannel...");
+
+       usalp->cmdname = "Read Subchannel";
+
+  if (usal_cmd(usalp) < 0) {
+    /* in case of error do a fallback for dumb firmwares */
+    return ReadSubQFallback(usalp, sq_format, track);
+  }
+
+       if (sq_format == GET_POSITIONDATA)
+               SubQbuffer->control_adr = (SubQbuffer->control_adr << 4) | (SubQbuffer->control_adr >> 4);
+  return SubQbuffer;
+}
+
+static subq_chnl sc;
+
+static subq_chnl* fill_subchannel(unsigned char bufferwithQ[]);
+static subq_chnl* fill_subchannel(unsigned char bufferwithQ[])
+{
+       sc.subq_length = 0;
+       sc.control_adr = bufferwithQ[CD_FRAMESIZE_RAW + 0];
+       sc.track = bufferwithQ[CD_FRAMESIZE_RAW + 1];
+       sc.index = bufferwithQ[CD_FRAMESIZE_RAW + 2];
+       return &sc;
+}
+
+int 
+ReadCddaSubSony(SCSI *usalp, UINT4 *p, unsigned lSector, unsigned SectorBurstVal)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)scmd, sizeof(*scmd), '\0');
+        scmd->addr = (caddr_t)p;
+       scmd->size = SectorBurstVal*(CD_FRAMESIZE_RAW + 16);
+        scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
+        scmd->cdb_len = SC_G5_CDBLEN;
+        scmd->sense_len = CCS_SENSE_LEN;
+        scmd->cdb.g5_cdb.cmd = 0xd8;           /* read audio command */
+        scmd->cdb.g5_cdb.lun = usal_lun(usalp);
+       scmd->cdb.g5_cdb.res |= (accepts_fua_bit == 1 ? 1 << 2 : 0);
+       scmd->cdb.g5_cdb.res10 = 0x01;  /* subcode 1 -> cdda + 16 * q sub */
+        g5_cdbaddr(&scmd->cdb.g5_cdb, lSector);
+        g5_cdblen(&scmd->cdb.g5_cdb, SectorBurstVal);
+
+        if (usalp->verbose) fprintf(stderr, "\nReadSony12 CDDA + SubChannels...");
+
+       usalp->cmdname = "Read12SubChannelsSony";
+
+       if (usal_cmd(usalp)) return -1;
+
+       /* has all or something been read? */
+       return usal_getresid(usalp) != 0;
+}
+
+int ReadCddaSub96Sony(SCSI *usalp, UINT4 *p, unsigned lSector, 
+                                                        unsigned SectorBurstVal);
+
+int ReadCddaSub96Sony(SCSI *usalp, UINT4 *p, unsigned lSector, 
+                      unsigned SectorBurstVal)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)scmd, sizeof(*scmd), '\0');
+        scmd->addr = (caddr_t)p;
+       scmd->size = SectorBurstVal*(CD_FRAMESIZE_RAW + 96);
+        scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
+        scmd->cdb_len = SC_G5_CDBLEN;
+        scmd->sense_len = CCS_SENSE_LEN;
+        scmd->cdb.g5_cdb.cmd = 0xd8;           /* read audio command */
+        scmd->cdb.g5_cdb.lun = usal_lun(usalp);
+       scmd->cdb.g5_cdb.res |= (accepts_fua_bit == 1 ? 1 << 2 : 0);
+       scmd->cdb.g5_cdb.res10 = 0x02;  /* subcode 2 -> cdda + 96 * q sub */
+        g5_cdbaddr(&scmd->cdb.g5_cdb, lSector);
+        g5_cdblen(&scmd->cdb.g5_cdb, SectorBurstVal);
+
+        if (usalp->verbose) fprintf(stderr, "\nReadSony12 CDDA + 96 byte SubChannels...");
+
+       usalp->cmdname = "Read12SubChannelsSony";
+
+       if (usal_cmd(usalp)) return -1;
+
+       /* has all or something been read? */
+       return usal_getresid(usalp) != 0;
+}
+
+subq_chnl *ReadSubChannelsSony(SCSI *usalp, unsigned lSector)
+{
+       /*int retval = ReadCddaSub96Sony(usalp, (UINT4 *)bufferTOC, lSector, 1);*/
+       int retval = ReadCddaSubSony(usalp, (UINT4 *)bufferTOC, lSector, 1);
+       if (retval != 0) return NULL;
+
+       return fill_subchannel(bufferTOC);
+}
+
+/* Read max. SectorBurst of cdda sectors to buffer
+   via MMC standard READ CD command */
+int ReadCddaSubMMC12(SCSI *usalp, UINT4 *p, unsigned lSector, unsigned SectorBurstVal)
+{
+       register struct usal_cmd        *scmd;
+       scmd = usalp->scmd;
+
+       fillbytes((caddr_t)scmd, sizeof(*scmd), '\0');
+        scmd->addr = (caddr_t)p;
+        scmd->size = SectorBurstVal*(CD_FRAMESIZE_RAW + 16);
+        scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
+        scmd->cdb_len = SC_G5_CDBLEN;
+        scmd->sense_len = CCS_SENSE_LEN;
+        scmd->cdb.g5_cdb.cmd = 0xbe;           /* read cd command */
+        scmd->cdb.g5_cdb.lun = usal_lun(usalp);
+        scmd->cdb.g5_cdb.res = 1 << 1; /* expected sector type field CDDA */
+        g5_cdbaddr(&scmd->cdb.g5_cdb, lSector);
+        g5x_cdblen(&scmd->cdb.g5_cdb, SectorBurstVal);
+       scmd->cdb.g5_cdb.count[3] = 1 << 4;     /* User data */
+       scmd->cdb.g5_cdb.res10 = 0x02;  /* subcode 2 -> cdda + 16 * q sub */
+
+        if (usalp->verbose) fprintf(stderr, "\nReadMMC12 CDDA + SUB...");
+
+       usalp->cmdname = "ReadCD Sub MMC 12";
+
+       if (usal_cmd(usalp)) return -1;
+
+       /* has all or something been read? */
+       return usal_getresid(usalp) != 0;
+}
+
+static subq_chnl *ReadSubChannelsMMC(SCSI *usalp, unsigned lSector);
+static subq_chnl *ReadSubChannelsMMC(SCSI *usalp, unsigned lSector)
+{
+       int retval = ReadCddaSubMMC12(usalp, (UINT4 *)bufferTOC, lSector, 1);
+       if (retval != 0) return NULL;
+
+       return fill_subchannel(bufferTOC);
+}
+
+subq_chnl *ReadSubChannelsFallbackMMC(SCSI *usalp, unsigned lSector)
+{
+       static int ReadSubSony_unknown = 0;
+       subq_chnl *retval = NULL;
+
+       usalp->silent++;
+       if (ReadSubSony_unknown 
+           || ((retval = ReadSubChannelsSony(usalp, lSector)) == NULL)) {
+               /* if the command is not available, use the regular
+                * MMC ReadCd 
+                */
+               if (retval == NULL && usal_sense_key(usalp) == 0x05) {
+                       ReadSubSony_unknown = 1;
+               }
+               usalp->silent--;
+               return ReadSubChannelsMMC(usalp, lSector);
+       }
+       usalp->silent--;
+       return retval;
+}
+
+subq_chnl *ReadStandardSub(usalp, lSector)
+       SCSI *usalp;
+       unsigned lSector;
+{
+       if (0 == ReadStandardLowlevel (usalp, (UINT4 *)bufferTOC, lSector, 1, CD_FRAMESIZE_RAW + 16 )) {
+               return NULL;
+       }
+#if    0
+fprintf(stderr, "Subchannel Sec %x: %02x %02x %02x %02x\n"
+       ,lSector
+       ,bufferTOC[CD_FRAMESIZE_RAW + 0]
+       ,bufferTOC[CD_FRAMESIZE_RAW + 1]
+       ,bufferTOC[CD_FRAMESIZE_RAW + 2]
+       ,bufferTOC[CD_FRAMESIZE_RAW + 3]
+       );
+#endif
+       sc.control_adr = (bufferTOC[CD_FRAMESIZE_RAW + 0] << 4)
+               | bufferTOC[CD_FRAMESIZE_RAW + 1];
+       sc.track = from_bcd(bufferTOC[CD_FRAMESIZE_RAW + 2]);
+       sc.index = from_bcd(bufferTOC[CD_FRAMESIZE_RAW + 3]);
+       return &sc;
+}
+/********* non standardized speed selects ***********************/
+
+void SpeedSelectSCSIToshiba(SCSI *usalp, unsigned speed)
+{
+  static unsigned char mode [4 + 3];
+  unsigned char *page = mode + 4;
+  int retval;
+
+  fillbytes((caddr_t)mode, sizeof(mode), '\0');
+  /* the first 4 mode bytes are zero. */
+  page[0] = 0x20;
+  page[1] = 1;
+  page[2] = speed;   /* 0 for single speed, 1 for double speed (3401) */
+
+  if (usalp->verbose) fprintf(stderr, "\nspeed select Toshiba...");
+
+  usalp->silent++;
+  /* do the scsi cmd */
+  if ((retval = mode_select(usalp, mode, 7, 0, usalp->inq->data_format >= 2)) < 0)
+        fprintf (stderr, "speed select Toshiba failed\n");
+  usalp->silent--;
+}
+
+void SpeedSelectSCSINEC(SCSI *usalp, unsigned speed)
+{
+  static unsigned char mode [4 + 8];
+  unsigned char *page = mode + 4;
+  int retval;
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+  fillbytes((caddr_t)mode, sizeof(mode), '\0');
+  /* the first 4 mode bytes are zero. */
+  page [0] = 0x0f; /* page code */
+  page [1] = 6;    /* parameter length */
+  /* bit 5 == 1 for single speed, otherwise double speed */
+  page [2] = speed == 1 ? 1 << 5 : 0;
+
+       fillbytes((caddr_t)scmd, sizeof(*scmd), '\0');
+  scmd->addr = (caddr_t)mode;
+  scmd->size = 12;
+  scmd->flags = SCG_DISRE_ENA;
+  scmd->cdb_len = SC_G1_CDBLEN;
+  scmd->sense_len = CCS_SENSE_LEN;
+  scmd->cdb.g1_cdb.cmd = 0xC5;
+  scmd->cdb.g1_cdb.lun = usal_lun(usalp);
+  scmd->cdb.g1_cdb.addr[0] = 0 ? 1 : 0 | 1 ? 0x10 : 0;
+  g1_cdblen(&scmd->cdb.g1_cdb, 12);
+
+  if (usalp->verbose) fprintf(stderr, "\nspeed select NEC...");
+  /* do the scsi cmd */
+
+       usalp->cmdname = "speed select NEC";
+
+  if ((retval = usal_cmd(usalp)) < 0)
+        fprintf(stderr ,"speed select NEC failed\n");
+}
+
+void SpeedSelectSCSIPhilipsCDD2600(SCSI *usalp, unsigned speed)
+{
+  /* MODE_SELECT, page = SCSI-2  save page disabled, reserved, reserved,
+     parm list len, flags */
+  static unsigned char mode [4 + 8];
+  unsigned char *page = mode + 4;
+  int retval;
+
+  fillbytes((caddr_t)mode, sizeof(mode), '\0');
+  /* the first 4 mode bytes are zero. */
+  page[0] = 0x23;
+  page[1] = 6;
+  page[2] = page [4] = speed;
+  page[3] = 1;
+
+  if (usalp->verbose) fprintf(stderr, "\nspeed select Philips...");
+  /* do the scsi cmd */
+  if ((retval = mode_select(usalp, mode, 12, 0, usalp->inq->data_format >= 2)) < 0)
+        fprintf (stderr, "speed select PhilipsCDD2600 failed\n");
+}
+
+void SpeedSelectSCSISony(SCSI *usalp, unsigned speed)
+{
+  static unsigned char mode [4 + 4];
+  unsigned char *page = mode + 4;
+  int retval;
+
+  fillbytes((caddr_t)mode, sizeof(mode), '\0');
+  /* the first 4 mode bytes are zero. */
+  page[0] = 0x31;
+  page[1] = 2;
+  page[2] = speed;
+
+  if (usalp->verbose) fprintf(stderr, "\nspeed select Sony...");
+  /* do the scsi cmd */
+  usalp->silent++;
+  if ((retval = mode_select(usalp, mode, 8, 0, usalp->inq->data_format >= 2)) < 0)
+        fprintf (stderr, "speed select Sony failed\n");
+  usalp->silent--;
+}
+
+void SpeedSelectSCSIYamaha (usalp, speed)
+       SCSI *usalp;
+       unsigned speed;
+{
+  static unsigned char mode [4 + 4];
+  unsigned char *page = mode + 4;
+  int retval;
+
+  fillbytes((caddr_t)mode, sizeof(mode), '\0');
+  /* the first 4 mode bytes are zero. */
+  page[0] = 0x31;
+  page[1] = 2;
+  page[2] = speed;
+
+  if (usalp->verbose) fprintf(stderr, "\nspeed select Yamaha...");
+  /* do the scsi cmd */
+  if ((retval = mode_select(usalp, mode, 8, 0, usalp->inq->data_format >= 2)) < 0)
+        fprintf (stderr, "speed select Yamaha failed\n");
+}
+
+void SpeedSelectSCSIMMC(SCSI *usalp, unsigned speed)
+{
+  int spd;
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+   if (speed == 0 || speed == 0xFFFF) {
+      spd = 0xFFFF;
+   } else {
+      spd = (1764 * speed) / 10;
+   }
+       fillbytes((caddr_t)scmd, sizeof(*scmd), '\0');
+        scmd->flags = SCG_DISRE_ENA;
+        scmd->cdb_len = SC_G5_CDBLEN;
+        scmd->sense_len = CCS_SENSE_LEN;
+        scmd->cdb.g5_cdb.cmd = 0xBB;
+        scmd->cdb.g5_cdb.lun = usal_lun(usalp);
+        i_to_2_byte(&scmd->cdb.g5_cdb.addr[0], spd);
+        i_to_2_byte(&scmd->cdb.g5_cdb.addr[2], 0xffff);
+
+        if (usalp->verbose) fprintf(stderr, "\nspeed select MMC...");
+
+       usalp->cmdname = "set cd speed";
+
+       usalp->silent++;
+        if (usal_cmd(usalp) < 0) {
+               if (usal_sense_key(usalp) == 0x05 &&
+                   usal_sense_code(usalp) == 0x20 &&
+                   usal_sense_qual(usalp) == 0x00) {
+                       /* this optional command is not implemented */
+               } else {
+                       usal_printerr(usalp);
+                       fprintf (stderr, "speed select MMC failed\n");
+               }
+       }
+       usalp->silent--;
+}
+
+/* request vendor brand and model */
+unsigned char *Inquiry(SCSI *usalp)
+{
+  static unsigned char *Inqbuffer = NULL;
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+  if (Inqbuffer == NULL) {
+    Inqbuffer = malloc(36);
+    if (Inqbuffer == NULL) {
+      fprintf(stderr, "Cannot allocate memory for inquiry command in line %d\n", __LINE__);
+        return NULL;
+    }
+  }
+
+  fillbytes(Inqbuffer, 36, '\0');
+       fillbytes((caddr_t)scmd, sizeof(*scmd), '\0');
+  scmd->addr = (caddr_t)Inqbuffer;
+  scmd->size = 36;
+  scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
+  scmd->cdb_len = SC_G0_CDBLEN;
+  scmd->sense_len = CCS_SENSE_LEN;
+  scmd->cdb.g0_cdb.cmd = SC_INQUIRY;
+  scmd->cdb.g0_cdb.lun = usal_lun(usalp);
+  scmd->cdb.g0_cdb.count = 36;
+        
+       usalp->cmdname = "inquiry";
+
+  if (usal_cmd(usalp) < 0)
+     return (NULL);
+
+  /* define structure with inquiry data */
+  memcpy(usalp->inq, Inqbuffer, sizeof(*usalp->inq)); 
+
+  if (usalp->verbose)
+     usal_prbytes("Inquiry Data   :", (Uchar *)Inqbuffer, 22 - scmd->resid);
+
+  return (Inqbuffer);
+}
+
+#define SC_CLASS_EXTENDED_SENSE 0x07
+#define TESTUNITREADY_CMD 0
+#define TESTUNITREADY_CMDLEN 6
+
+#define ADD_SENSECODE 12
+#define ADD_SC_QUALIFIER 13
+#define NO_MEDIA_SC 0x3a
+#define NO_MEDIA_SCQ 0x00
+
+int TestForMedium(SCSI *usalp)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+  if (interface != GENERIC_SCSI) {
+    return 1;
+  }
+
+  /* request READY status */
+       fillbytes((caddr_t)scmd, sizeof(*scmd), '\0');
+  scmd->addr = (caddr_t)0;
+  scmd->size = 0;
+  scmd->flags = SCG_DISRE_ENA | (1 ? SCG_SILENT:0);
+  scmd->cdb_len = SC_G0_CDBLEN;
+  scmd->sense_len = CCS_SENSE_LEN;
+  scmd->cdb.g0_cdb.cmd = SC_TEST_UNIT_READY;
+  scmd->cdb.g0_cdb.lun = usal_lun(usalp);
+        
+  if (usalp->verbose) fprintf(stderr, "\ntest unit ready...");
+  usalp->silent++;
+
+       usalp->cmdname = "test unit ready";
+
+  if (usal_cmd(usalp) >= 0) {
+    usalp->silent--;
+    return 1;
+  }
+  usalp->silent--;
+
+  if (scmd->sense.code >= SC_CLASS_EXTENDED_SENSE) {
+    return 
+      scmd->u_sense.cmd_sense[ADD_SENSECODE] != NO_MEDIA_SC ||
+      scmd->u_sense.cmd_sense[ADD_SC_QUALIFIER] != NO_MEDIA_SCQ;
+  } else {
+    /* analyse status. */
+    /* 'check condition' is interpreted as not ready. */
+    return (scmd->u_scb.cmd_scb[0] & 0x1e) != 0x02;
+  }
+}
+
+int StopPlaySCSI(SCSI *usalp)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)scmd, sizeof(*scmd), '\0');
+  scmd->addr = NULL;
+  scmd->size = 0;
+  scmd->flags = SCG_DISRE_ENA;
+  scmd->cdb_len = SC_G0_CDBLEN;
+  scmd->sense_len = CCS_SENSE_LEN;
+  scmd->cdb.g0_cdb.cmd = 0x1b;
+  scmd->cdb.g0_cdb.lun = usal_lun(usalp);
+
+  if (usalp->verbose) fprintf(stderr, "\nstop audio play");
+  /* do the scsi cmd */
+
+       usalp->cmdname = "stop audio play";
+
+  return usal_cmd(usalp) >= 0 ? 0 : -1;
+}
+
+int Play_atSCSI(SCSI *usalp, unsigned int from_sector, unsigned int sectors)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)scmd, sizeof(*scmd), '\0');
+  scmd->addr = NULL;
+  scmd->size = 0;
+  scmd->flags = SCG_DISRE_ENA;
+  scmd->cdb_len = SC_G1_CDBLEN;
+  scmd->sense_len = CCS_SENSE_LEN;
+  scmd->cdb.g1_cdb.cmd = 0x47;
+  scmd->cdb.g1_cdb.lun = usal_lun(usalp);
+  scmd->cdb.g1_cdb.addr[1] = (from_sector + 150) / (60*75);
+  scmd->cdb.g1_cdb.addr[2] = ((from_sector + 150) / 75) % 60;
+  scmd->cdb.g1_cdb.addr[3] = (from_sector + 150) % 75;
+  scmd->cdb.g1_cdb.res6 = (from_sector + 150 + sectors) / (60*75);
+  scmd->cdb.g1_cdb.count[0] = ((from_sector + 150 + sectors) / 75) % 60;
+  scmd->cdb.g1_cdb.count[1] = (from_sector + 150 + sectors) % 75;
+
+  if (usalp->verbose) fprintf(stderr, "\nplay sectors...");
+  /* do the scsi cmd */
+
+       usalp->cmdname = "play sectors";
+
+  return usal_cmd(usalp) >= 0 ? 0 : -1;
+}
+
+static caddr_t scsibuffer;     /* page aligned scsi transfer buffer */
+
+void init_scsibuf(SCSI *scsp, unsigned amt);
+
+void init_scsibuf(SCSI *usalp, unsigned amt)
+{
+       if (scsibuffer != NULL) {
+               fprintf(stderr, "the SCSI transfer buffer has already been allocated!\n");
+               exit(SETUPSCSI_ERROR);
+       }
+       scsibuffer = usal_getbuf(usalp, amt);
+       if (scsibuffer == NULL) {
+               fprintf(stderr, "could not get SCSI transfer buffer!\n");
+               exit(SETUPSCSI_ERROR);
+       }
+}
diff --git a/icedax/scsi_cmds.h b/icedax/scsi_cmds.h
new file mode 100644 (file)
index 0000000..d82d1c9
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)scsi_cmds.h     1.11 03/03/02 Copyright 1998,1999 Heiko Eissfeldt */
+/* header file for scsi_cmds.c */
+
+extern unsigned char *cmd;
+struct TOC;
+int SCSI_emulated_ATAPI_on(SCSI *usalp);
+unsigned char *Inquiry(SCSI *usalp);
+int TestForMedium(SCSI *usalp);
+void SpeedSelectSCSIMMC(SCSI *usalp, unsigned speed);
+void SpeedSelectSCSIYamaha(SCSI *usalp, unsigned speed);
+void SpeedSelectSCSISony(SCSI *usalp, unsigned speed);
+void SpeedSelectSCSIPhilipsCDD2600(SCSI *usalp, unsigned speed);
+void SpeedSelectSCSINEC(SCSI *usalp, unsigned speed);
+void SpeedSelectSCSIToshiba(SCSI *usalp, unsigned speed);
+subq_chnl *ReadSubQSCSI(SCSI *usalp, unsigned char sq_format, 
+                                                               unsigned char ltrack);
+subq_chnl *ReadSubChannelsSony(SCSI *usalp, unsigned lSector);
+subq_chnl *ReadSubChannelsFallbackMMC(SCSI *usalp, unsigned lSector);
+subq_chnl *ReadStandardSub(SCSI *usalp, unsigned lSector);
+int ReadCddaMMC12(SCSI *usalp, UINT4 *p, unsigned lSector, 
+                                               unsigned SectorBurstVal);
+int ReadCdda12Matsushita(SCSI *usalp, UINT4 *p, unsigned lSector, 
+                                                                unsigned SectorBurstVal);
+int ReadCdda12(SCSI *usalp, UINT4 *p, unsigned lSector, unsigned SecorBurstVal);
+int ReadCdda10(SCSI *usalp, UINT4 *p, unsigned lSector, unsigned SecorBurstVal);
+int ReadStandard(SCSI *usalp, UINT4 *p, unsigned lSector, 
+                                         unsigned SctorBurstVal);
+int ReadStandardData(SCSI *usalp, UINT4 *p, unsigned lSector, 
+                                                       unsigned SctorBurstVal);
+int ReadCddaFallbackMMC(SCSI *usalp, UINT4 *p, unsigned lSector, 
+                                                               unsigned SctorBurstVal);
+int ReadCddaSubSony(SCSI *usalp, UINT4 *p, unsigned lSector, 
+                                                 unsigned SectorBurstVal);
+int ReadCddaSub96Sony(SCSI *usalp, UINT4 *p, unsigned lSector, 
+                                                        unsigned SectorBurstVal);
+int ReadCddaSubMMC12(SCSI *usalp, UINT4 *p, unsigned lSector, 
+                                                       unsigned SectorBurstVal);
+unsigned ReadTocSony(SCSI *usalp);
+unsigned ReadTocMMC(SCSI *usalp);
+unsigned ReadTocSCSI(SCSI *usalp);
+unsigned ReadFirstSessionTOCSony(SCSI *usalp);
+unsigned ReadFirstSessionTOCMMC(SCSI *usalp);
+void ReadTocTextSCSIMMC(SCSI *usalp);
+int Play_atSCSI(SCSI *usalp, unsigned int from_sector, unsigned int sectors);
+int StopPlaySCSI(SCSI *usalp);
+void EnableCddaModeSelect(SCSI *usalp, int fAudioMode, unsigned uSectorsize);
+int set_sectorsize(SCSI *usalp, unsigned int secsize);
+unsigned int
+get_orig_sectorsize(SCSI *usalp, unsigned char *m4, unsigned char *m10,
+                    unsigned char *m11);
+int heiko_mmc(SCSI *usalp);
+void init_scsibuf(SCSI *usalp, unsigned amt);
+int    myscsierr(SCSI *usalp);
+
+extern int accepts_fua_bit;
+extern unsigned char density;
+extern unsigned char orgmode4;
+extern unsigned char orgmode10, orgmode11;
+
diff --git a/icedax/semshm.c b/icedax/semshm.c
new file mode 100644 (file)
index 0000000..6c6edc7
--- /dev/null
@@ -0,0 +1,473 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/*
+ * Copyright 1998-2002 Heiko Eissfeldt
+ */
+
+#define IPCTST
+#undef IPCTST
+/* -------------------------------------------------------------------- */
+/*        semshm.c                                                      */
+/* -------------------------------------------------------------------- */
+/*               int seminstall(key,amount)                             */
+/*               int semrequest(semid,semnum)                           */
+/*               int semrelease(semid,semnum)                           */
+/* -------------------------------------------------------------------- */
+
+#include "config.h"
+
+#if     !defined(HAVE_SMMAP) && !defined(HAVE_USGSHM) && !defined(HAVE_DOSALLOCSHAREDMEM) && !defined(HAVE_AREAS)
+#undef  FIFO                    /* We cannot have a FIFO on this platform */
+#endif
+
+#if !defined(USE_MMAP) && !defined(USE_USGSHM)
+#define USE_MMAP
+#endif
+
+#if    !defined HAVE_SMMAP && defined FIFO
+#       undef   USE_MMAP
+#       define  USE_USGSHM      /* SYSV shared memory is the default    */
+#endif
+
+#ifdef  USE_MMAP                /* Only want to have one implementation */
+#       undef   USE_USGSHM      /* mmap() is preferred                  */
+#endif
+
+#ifdef HAVE_DOSALLOCSHAREDMEM
+#       undef   USE_MMAP
+#       undef   USE_USGSHM
+#      define  USE_OS2SHM
+#      undef   USE_BEOS_AREAS
+#endif
+
+#ifdef HAVE_AREAS
+#       undef   USE_MMAP
+#       undef   USE_USGSHM
+#      undef   USE_OS2SHM
+#      define  USE_BEOS_AREAS
+#endif
+
+#include <stdio.h>
+#include <stdxlib.h>
+#include <unixstd.h>
+#include <fctldefs.h>
+#include <errno.h>
+#include <standard.h>
+#include <schily.h>
+
+#if defined(HAVE_SEMGET) && defined(USE_SEMAPHORES)
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/sem.h>
+#endif
+
+#if defined(HAVE_SHMAT) && (HAVE_SHMAT == 1)
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#endif
+
+#ifdef  USE_MMAP
+#if defined(HAVE_SMMAP) && defined(USE_MMAP)
+#include <mmapdefs.h>
+#endif
+#endif
+
+#include <usal/scsitransp.h>
+
+#ifdef USE_BEOS_AREAS
+#include       <be/kernel/OS.h>
+#endif
+
+#include "mytype.h"
+#include "interface.h"
+#include "ringbuff.h"
+#include "global.h"
+#include "exitcodes.h"
+#include "semshm.h"
+
+#ifdef DEBUG_SHM
+char *start_of_shm;
+char *end_of_shm;
+#endif
+
+int flush_buffers(void);
+
+
+/*------ Semaphore interfacing (for special cases only) ----------*/
+/*------ Synchronization with pipes is preferred        ----------*/
+
+#if defined(HAVE_SEMGET) && defined(USE_SEMAPHORES)
+
+int sem_id;
+static int seminstall(key_t key, int amount);
+
+static int seminstall(key_t key, int amount)
+{
+  int           ret_val;
+  int           semflag;
+
+  semflag = IPC_CREAT | 0600;
+#ifdef IPCTST
+  fprintf(stderr,"seminstall: key: %d, #sems %d, flags %4x\n",
+          key,amount,semflag);
+#endif
+  ret_val = semget(key,amount,semflag);
+  if ( ret_val == -1 )
+  {
+    fprintf(stderr,"semget: (Key %lx, #%d) failed: ",
+            (long)key,amount);
+    perror("");
+  }
+  return ret_val;
+}
+
+/*-----------------------------------------------------------------*/
+int semrequest(int semid, int semnum)
+{
+  struct sembuf sops[1];
+  int    ret_val;
+
+#ifdef IPCTST
+  fprintf(stderr,"pid %d, ReQuest id:num %d:%d\n",getpid(),semid,semnum);
+#endif
+  sops[0].sem_op  = -1;
+  sops[0].sem_num = (short) semnum;
+  sops[0].sem_flg = 0;
+
+  do {
+    errno = 0;
+    ret_val = semop(semid,sops,1);
+    if (ret_val == -1 && errno != EAGAIN && errno != EINTR)
+      {
+       fprintf(stderr,"Request Sema %d(%d) failed: ",semid,semnum);
+       perror("");
+      }
+  } while (errno == EAGAIN || errno == EINTR);
+  return(ret_val);
+}
+
+/*-----------------------------------------------------------------*/
+int semrelease(int semid, int semnum, int amount)
+{
+  struct sembuf sops[1];
+  int    ret_val;
+
+#ifdef IPCTST
+  fprintf(stderr,"%d RL %d:%d\n",getpid(),semid,semnum);
+#endif
+  sops[0].sem_op  = amount;
+  sops[0].sem_num = (short) semnum;
+  sops[0].sem_flg = 0;
+  ret_val = semop(semid,sops,1);
+  if ( ret_val == -1 && errno != EAGAIN)
+  {
+    fprintf(stderr,"Release Sema %d(%d) failed: ",semid,semnum);
+    perror("");
+  }
+  return(ret_val);
+}
+
+int flush_buffers()
+{
+       return 0;
+}
+#else
+/*------ Synchronization with pipes ----------*/
+int pipefdp2c[2];
+int pipefdc2p[2];
+
+void init_pipes()
+{
+  if (pipe(pipefdp2c) < 0) {
+    perror("cannot create pipe parent to child");
+    exit(PIPE_ERROR);
+  }
+  if (pipe(pipefdc2p) < 0) {
+    perror("cannot create pipe child to parent");
+    exit(PIPE_ERROR);
+  }
+}
+
+void init_parent()
+{
+  close(pipefdp2c[0]);
+  close(pipefdc2p[1]);
+}
+
+void init_child()
+{
+  close(pipefdp2c[1]);
+  close(pipefdc2p[0]);
+}
+
+int semrequest(int dummy, int semnum)
+{
+
+  if (semnum == FREE_SEM /* 0 */)  {
+      int retval;
+    if ((*total_segments_read) - (*total_segments_written) >= global.buffers) {
+      /* parent/reader waits for freed buffers from the child/writer */
+      *parent_waits = 1;
+      retval = read(pipefdp2c[0], &dummy, 1) != 1;
+      return retval;
+    }
+  } else {
+      int retval;
+
+    if ((*total_segments_read) == (*total_segments_written)) {
+      /* child/writer waits for defined buffers from the parent/reader */
+      *child_waits = 1;
+      retval = read(pipefdc2p[0], &dummy, 1) != 1;
+      return retval;
+    }
+  }
+  return 0;
+}
+
+/* ARGSUSED */
+int semrelease(int dummy, int semnum, int amount)
+{
+  if (semnum == FREE_SEM /* 0 */)  {
+    if (*parent_waits == 1) {
+      int retval;
+      /* child/writer signals freed buffer to the parent/reader */
+      *parent_waits = 0;
+      retval = write(pipefdp2c[1], "12345678901234567890", amount) != amount;
+      return retval;
+    }
+  } else {
+    if (*child_waits == 1) {
+      int retval;
+      /* parent/reader signals defined buffers to the child/writer */
+      *child_waits = 0;
+      retval = write(pipefdc2p[1], "12345678901234567890", amount) != amount;
+      return retval;
+    }
+  }
+  return 0;
+}
+
+int flush_buffers()
+{
+       if ((*total_segments_read) > (*total_segments_written)) {
+               return write(pipefdc2p[1], "1", 1) != 1;
+       }
+       return 0;
+}
+
+#endif
+
+/*------------------- Shared memory interfacing -----------------------*/
+
+
+
+#if defined(HAVE_SHMAT) && (HAVE_SHMAT == 1)
+static int shm_request_nommap(int size, unsigned char **memptr);
+
+/* request a shared memory block */
+static int shm_request_nommap(int size, unsigned char **memptr)
+{
+  int   ret_val;
+  int   shmflag;
+  int   SHMEM_ID;
+  int    cmd;
+  struct shmid_ds buf;
+  key_t key = IPC_PRIVATE;
+
+  shmflag = IPC_CREAT | 0600;
+  ret_val = shmget(key,size,shmflag);
+  if ( ret_val == -1 )
+  {
+    perror("shmget");
+    return -1;
+  }
+
+  SHMEM_ID = ret_val;
+  cmd = IPC_STAT;
+  ret_val = shmctl(SHMEM_ID,cmd,&buf);
+#ifdef IPCTST
+  fprintf(stderr, "%d: shmctl STAT= %d, SHM_ID: %d, key %ld cuid %d cgid %d mode %3o size %d\n",
+          getpid(),ret_val,SHMEM_ID,
+          (long) buf.shm_perm.key,buf.shm_perm.cuid,buf.shm_perm.cgid,
+          buf.shm_perm.mode,buf.shm_segsz);
+#endif
+
+  *memptr = (unsigned char *) shmat(SHMEM_ID, NULL, 0);
+  if (*memptr == (unsigned char *) -1) {
+    *memptr = NULL;
+    fprintf( stderr, "shmat failed for %d bytes\n", size);
+    return -1;
+  }
+
+  if (shmctl(SHMEM_ID, IPC_RMID, 0) < 0) {
+    fprintf( stderr, "shmctl failed to detach shared memory segment\n");
+    return -1;
+  }
+
+
+#ifdef DEBUG_SHM
+  start_of_shm = *memptr;
+  end_of_shm = (char *)(*memptr) + size;
+
+  fprintf(stderr, "Shared memory from %p to %p (%d bytes)\n", start_of_shm, end_of_shm, size);
+#endif
+  return 0;
+}
+
+
+#endif /* #if defined(HAVE_SHMAT) && (HAVE_SHMAT == 1) */
+
+
+static int shm_request(int size, unsigned char **memptr);
+
+#ifdef  USE_USGSHM
+/* request a shared memory block */
+static int shm_request(int size, unsigned char **memptr)
+{
+       return shm_request_nommap(size, memptr);
+}
+#endif
+
+/* release semaphores */
+void free_sem(void);
+void free_sem()
+{
+#if defined(HAVE_SEMGET) && defined(USE_SEMAPHORES)
+  int   mycmd;
+  union my_semun unused_arg;
+
+  mycmd = IPC_RMID;
+
+  /* HP-UX warns here, but 'unused_arg' is not used for this operation */
+  /* This warning is difficult to avoid, since the structure of the union
+   * generally is not known (os dependent). So we cannot initialize it
+   * properly.
+   */
+  semctl(sem_id,0,mycmd,unused_arg);
+#endif
+
+}
+
+#ifdef  USE_MMAP
+#if defined(HAVE_SMMAP)
+
+int shm_id;
+/* request a shared memory block */
+static int shm_request(int size, unsigned char **memptr)
+{
+       int     f;
+       char    *addr;
+
+#ifdef  MAP_ANONYMOUS   /* HP/UX */
+       f = -1;
+       addr = mmap(0, mmap_sizeparm(size), PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, f, 0);
+#else
+       if ((f = open("/dev/zero", O_RDWR)) < 0)
+               comerr("Cannot open '/dev/zero'.\n");
+       addr = mmap(0, mmap_sizeparm(size), PROT_READ|PROT_WRITE, MAP_SHARED, f, 0);
+#endif
+
+       if (addr == (char *)-1) {
+#if    defined HAVE_SHMAT && (HAVE_SHMAT == 1)
+               unsigned char *address;
+               /* fallback to alternate method */
+               if (0 != shm_request_nommap(size, &address) || (addr = (char *)address) == NULL)
+#endif
+                       comerr("Cannot get mmap for %d Bytes on /dev/zero.\n", size);
+       }
+       close(f);
+
+       if (memptr != NULL)
+               *memptr = (unsigned char *)addr;
+
+       return 0;
+}
+#endif /* HAVE_SMMAP */
+#endif /* USE_MMAP */
+
+#ifdef USE_OS2SHM
+
+/* request a shared memory block */
+static int shm_request(int size, unsigned char **memptr)
+{
+       char    *addr;
+
+       /*
+        * The OS/2 implementation of shm (using shm.dll) limits the size of one
+         * memory segment to 0x3fa000 (aprox. 4MBytes). Using OS/2 native API we
+         * no such restriction so I decided to use it allowing fifos of arbitrary size
+         */
+       if(DosAllocSharedMem(&addr,NULL,size,0X100L | 0x1L | 0x2L | 0x10L))
+               comerr("DosAllocSharedMem() failed\n");
+
+       if (memptr != NULL)
+               *memptr = (unsigned char *)addr;
+
+       return 0;
+}
+#endif
+
+#ifdef USE_BEOS_AREAS
+
+/* request a shared memory block */
+static int shm_request(int size, unsigned char **memptr)
+{
+       char    *addr;
+       area_id aid;    /* positive id of the mapping */
+
+       /* round up to a multiple of pagesize. */
+       size = ((size - 1) | (B_PAGE_SIZE - 1)) + 1;
+       /*
+        *      request a shared memory area in user space.
+         */
+       aid = create_area(AREA_NAME,    /* name of the mapping */
+               (void *)&addr,          /* address of shared memory */
+               B_ANY_ADDRESS,          /* type of address constraint */
+               size,                   /* size in bytes (multiple of pagesize) */
+               B_NO_LOCK, /* B_FULL_LOCK, */ /* memory locking */
+               B_READ_AREA | B_WRITE_AREA);    /* read and write permissions */
+
+       if (aid < B_OK)
+               comerrno(aid, "create_area() failed\n");
+
+       if (memptr != NULL)
+               *memptr = (unsigned char *)addr;
+
+       return 0;
+}
+#endif
+
+void *request_shm_sem(unsigned amount_of_sh_mem, unsigned char **pointer)
+{
+#if defined(HAVE_SEMGET) && defined(USE_SEMAPHORES)
+    /* install semaphores for double buffer usage */
+    sem_id = seminstall(IPC_PRIVATE,2);
+    if ( sem_id == -1 ) {
+      perror("seminstall");
+      exit(SEMAPHORE_ERROR);
+    }
+
+#endif
+
+#if defined(FIFO)
+    if (-1 == shm_request(amount_of_sh_mem, pointer)) {
+       perror("shm_request");
+       exit(SHMMEM_ERROR);
+    }
+
+    return *pointer;
+#else
+    return NULL;
+#endif
+}
diff --git a/icedax/semshm.h b/icedax/semshm.h
new file mode 100644 (file)
index 0000000..2007f82
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)semshm.h        1.3 03/08/29 Copyright 1998,1999 Heiko Eissfeldt */
+#undef DEBUG_SHM
+#ifdef DEBUG_SHM
+extern char *start_of_shm;
+extern char *end_of_shm;
+#endif
+
+#define FREE_SEM       0
+#define DEF_SEM        1
+
+#if defined (HAVE_SEMGET) && defined(USE_SEMAPHORES)
+extern int sem_id;
+#else
+#define sem_id 42      /* nearly any other number would do it too */
+void init_pipes(void);
+void init_parent(void);
+void init_child(void);
+#endif
+
+
+#ifdef HAVE_AREAS
+/* the name of the shared memory mapping for the FIFO under BeOS. */
+#define        AREA_NAME       "shmfifo"
+#endif
+
+void free_sem(void);
+int semrequest(int semid, int semnum);
+int semrelease(int semid, int semnum, int amount);
+int flush_buffers(void);
+void * request_shm_sem(unsigned amount_of_sh_mem, unsigned char **pointer);
+
diff --git a/icedax/setuid.c b/icedax/setuid.c
new file mode 100644 (file)
index 0000000..7f3e63c
--- /dev/null
@@ -0,0 +1,332 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)setuid.c        1.11 06/02/19 Copyright 1998,1999,2004 Heiko Eissfeldt, Copyright 2004-2006 J. Schilling */
+/* Security functions by zblaxell
+
+   If these functions fail, it is because there was an installation error
+   or a programming error, and we can't be sure about what privileges
+   we do or do not have.  This means we might not be able to recover
+   the privileges we need to fix anything that may be broken (e.g. the
+   CDDA state of some interface types), and we may in fact do something
+   quite dangerous (like write to the WAV file as root).
+
+   In any case, it is unsafe to do anything but exit *now*.  Ideally we'd
+   kill -9 our process group too, just to be sure.  Root privileges are not
+   something you want floating around at random in user-level applications.
+
+   If any signal handlers or child processes are introduced into this
+   program, it will be necessary to call dontneedroot() or neverneedroot()
+   on entry, respectively; otherwise, it will be possible to trick
+   the program into executing the signal handler or child process with
+   root privileges by sending signals at the right time.
+ */
+
+#include "config.h"
+#include <unixstd.h>
+#include <stdio.h>
+#include <stdxlib.h>
+
+#include "exitcodes.h"
+#include "setuid.h"
+
+/*#undef DEBUG*/
+/*#define DEBUG*/
+
+/* True at return from initsecurity */
+static uid_t real_uid = (uid_t) (-1);
+static uid_t effective_uid = (uid_t) (-1);
+static gid_t real_gid = (gid_t) (-1);
+static gid_t effective_gid = (gid_t) (-1);
+
+/* Run this at the beginning of the program to initialize this code and
+   to drop privileges before someone uses them to shoot us in the foot.
+   Do not pass(go), do not dollars += 200. */
+
+void initsecurity()
+{
+    int leffective_uid;
+
+    alarm(0);                  /* can be inherited from parent process */
+    real_uid = getuid();
+    leffective_uid = geteuid();
+    if ((int) real_uid != leffective_uid && leffective_uid != 0) { /* sanity check */
+        fprintf(stderr, "Warning: setuid but not to root (uid=%ld, euid=%d)\n", (long) real_uid, leffective_uid);
+        fprintf(stderr, "Dropping setuid privileges now.\n");
+        neverneedroot();
+    } else {
+        effective_uid = leffective_uid;
+    }
+    real_gid = getgid();
+    effective_gid = getegid();
+    dontneedroot();
+    dontneedgroup();
+}
+
+/* Temporarily gain root privileges. */
+
+#if defined _POSIX_SAVED_IDS && defined (HAVE_SETEUID) && defined SCO
+/* SCO seems to lack the prototypes... */
+int    seteuid(uid_t euid);
+int    setegid(gid_t guid);
+#endif
+
+void needroot(int necessary)
+{
+#ifdef DEBUG
+    fprintf(stderr, "call to     needroot (_euid_=%d, uid=%d), current=%d/%d, pid=%d\n",
+                       effective_uid, real_uid, geteuid(), getuid(), getpid());
+#endif
+    if (effective_uid) {
+        if (necessary) {
+         fprintf(stderr, "Fatal error:  require root privilege but not setuid root.\n");
+         exit(PERM_ERROR);
+       } else
+         return;
+    }
+    if (real_uid == (uid_t) (-1)) {
+       fprintf(stderr, "Fatal error:  initsecurity() not called.\n");
+       exit(INTERNAL_ERROR);
+    }
+
+    if (geteuid() == 0) return; /* nothing to do */
+
+#if defined _POSIX_SAVED_IDS && defined (HAVE_SETEUID)
+    if (seteuid(effective_uid)) {
+       perror("seteuid in needroot()");
+       exit(PERM_ERROR);
+    }
+#else
+#if defined (HAVE_SETREUID)
+    if (setreuid(real_uid, effective_uid)) {
+       perror("setreuid in needroot()");
+       exit(PERM_ERROR);
+    }
+#endif
+#endif
+    if (geteuid() != 0 && necessary) {
+       fprintf(stderr, "Fatal error:  did not get root privilege.\n");
+       exit(PERM_ERROR);
+    }
+#ifdef DEBUG
+    fprintf(stderr, "exit of     needroot (_euid_=%d, uid=%d), current=%d/%d, pid=%d\n",
+                       effective_uid, real_uid, geteuid(), getuid(), getpid());
+#endif
+}
+
+/* Temporarily drop root privileges.  */
+
+void dontneedroot()
+{
+#ifdef DEBUG
+    fprintf(stderr, "call to dontneedroot (_euid_=%d, uid=%d), current=%d/%d, pid=%d\n",
+                       effective_uid, real_uid, geteuid(), getuid(), getpid());
+#endif
+    if (real_uid == (uid_t) (-1)) {
+       fprintf(stderr, "Fatal error:  initsecurity() not called.\n");
+       exit(INTERNAL_ERROR);
+    }
+    if (effective_uid)
+       return;
+    if (geteuid() != 0) return; /* nothing to do */
+
+#if defined _POSIX_SAVED_IDS && defined (HAVE_SETEUID)
+    if (seteuid(real_uid)) {
+       perror("seteuid in dontneedroot()");
+       exit(PERM_ERROR);
+    }
+#else
+#if defined (HAVE_SETREUID)
+    if (setreuid(effective_uid, real_uid)) {
+       perror("setreuid in dontneedroot()");
+       exit(PERM_ERROR);
+    }
+#endif
+#endif
+    if (geteuid() != real_uid) {
+       fprintf(stderr, "Fatal error:  did not drop root privilege.\n");
+#ifdef DEBUG
+    fprintf(stderr, "in   to dontneedroot (_euid_=%d, uid=%d), current=%d/%d, pid=%d\n",
+                       effective_uid, real_uid, geteuid(), getuid(), getpid());
+#endif
+       exit(PERM_ERROR);
+    }
+}
+
+/* Permanently drop root privileges.  */
+
+void neverneedroot()
+{
+#ifdef DEBUG
+    fprintf(stderr, "call to neverneedroot (_euid_=%d, uid=%d), current=%d/%d, pid=%d\n",
+                       effective_uid, real_uid, geteuid(), getuid(), getpid());
+#endif
+    if (real_uid == (uid_t) (-1)) {
+       fprintf(stderr, "Fatal error:  initsecurity() not called.\n");
+       exit(INTERNAL_ERROR);
+    }
+    if (geteuid() == effective_uid) {
+#if defined (HAVE_SETUID)
+      if (setuid(real_uid)) {
+       perror("setuid in neverneedroot()");
+       exit(PERM_ERROR);
+      }
+#endif
+    }
+#if    defined(__FreeBSD__) || defined(__DragonFly__)  /* XXX this is a big hack and and not a permanent solution */
+    else {
+#if defined (HAVE_SETUID)
+       if (setuid(real_uid)) {
+               perror("setuid in neverneedroot()");
+               exit(PERM_ERROR);
+       }
+#endif
+    }
+#endif
+    if (geteuid() != real_uid || getuid() != real_uid) {
+       fprintf(stderr, "Fatal error:  did not drop root privilege.\n");
+#ifdef DEBUG
+    fprintf(stderr, "in  to neverneedroot (_euid_=%d, uid=%d), current=%d/%d, pid=%d\n",
+                       effective_uid, real_uid, geteuid(), getuid(), getpid());
+#endif
+       exit(PERM_ERROR);
+    }
+    effective_uid = real_uid;
+#ifdef DEBUG
+    fprintf(stderr, "exit of neverneedroot (_euid_=%d, uid=%d), current=%d/%d, pid=%d\n",
+                       effective_uid, real_uid, geteuid(), getuid(), getpid());
+#endif
+}
+
+/* Temporarily gain group privileges. */
+
+void needgroup(int necessary)
+{
+#ifdef DEBUG
+    fprintf(stderr, "call to     needgroup (egid=%d, gid=%d), current=%d/%d, pid=%d\n",
+                       effective_gid, real_gid, getegid(), getgid(), getpid());
+#endif
+    if (real_gid == (gid_t) (-1)) {
+       fprintf(stderr, "Fatal error:  initsecurity() not called.\n");
+       exit(INTERNAL_ERROR);
+    }
+
+    if (getegid() == effective_gid) return; /* nothing to do */
+
+#if defined _POSIX_SAVED_IDS && defined (HAVE_SETEGID)
+    if (setegid(effective_gid)) {
+       perror("setegid in needgroup()");
+       exit(PERM_ERROR);
+    }
+#else
+#if defined (HAVE_SETREGID)
+    if (setregid(real_gid, effective_gid)) {
+       perror("setregid in needgroup()");
+       exit(PERM_ERROR);
+    }
+#endif
+#endif
+    if (necessary && getegid() != effective_gid) {
+       fprintf(stderr, "Fatal error:  did not get group privilege.\n");
+       exit(PERM_ERROR);
+    }
+}
+
+/* Temporarily drop group privileges.  */
+
+void dontneedgroup()
+{
+#ifdef DEBUG
+    fprintf(stderr, "call to dontneedgroup (egid=%d, gid=%d), current=%d/%d, pid=%d\n",
+                       effective_gid, real_gid, getegid(), getgid(), getpid());
+#endif
+    if (real_gid == (gid_t) (-1)) {
+       fprintf(stderr, "Fatal error:  initsecurity() not called.\n");
+       exit(INTERNAL_ERROR);
+    }
+    if (getegid() != effective_gid) return; /* nothing to do */
+#if defined _POSIX_SAVED_IDS && defined (HAVE_SETEGID)
+    if (setegid(real_gid)) {
+       perror("setegid in dontneedgroup()");
+       exit(PERM_ERROR);
+    }
+#else
+#if defined (HAVE_SETREGID)
+    if (setregid(effective_gid, real_gid)) {
+       perror("setregid in dontneedgroup()");
+       exit(PERM_ERROR);
+    }
+#endif
+#endif
+    if (getegid() != real_gid) {
+       fprintf(stderr, "Fatal error:  did not drop group privilege.\n");
+       exit(PERM_ERROR);
+    }
+#ifdef DEBUG
+    fprintf(stderr, "exit if dontneedgroup (egid=%d, gid=%d), current=%d/%d, pid=%d\n",
+                       effective_gid, real_gid, getegid(), getgid(), getpid());
+#endif
+}
+
+/* Permanently drop group privileges.  */
+
+void neverneedgroup()
+{
+#ifdef DEBUG
+    fprintf(stderr, "call to neverneedgroup (egid=%d, gid=%d), current=%d/%d, pid=%d\n",
+                       effective_gid, real_gid, getegid(), getgid(), getpid());
+#endif
+    if (real_gid == (gid_t) (-1)) {
+       fprintf(stderr, "Fatal error:  initsecurity() not called.\n");
+       exit(INTERNAL_ERROR);
+    }
+    if (getegid() == effective_gid) {
+#if defined (HAVE_SETGID)
+      if (setgid(real_gid)) {
+         perror("setgid in neverneedgroup()");
+         exit(PERM_ERROR);
+      }
+#endif
+    }
+#if    defined(__FreeBSD__) || defined(__DragonFly__)  /* XXX this is a big hack and and not a permanent solution */
+    else {
+#if defined (HAVE_SETGID)
+       if (setgid(real_gid)) {
+               perror("setgid in neverneedgroup()");
+               exit(PERM_ERROR);
+       }
+#endif
+    }
+#endif
+    if (getegid() != real_gid || getgid() != real_gid) {
+       fprintf(stderr, "Fatal error:  did not drop group privilege.\n");
+       exit(PERM_ERROR);
+    }
+    effective_gid = real_gid;
+}
+
+#if defined (HPUX)
+int seteuid(uid_t uid)
+{
+  return setresuid(-1, uid, -1);
+}
+
+int setreuid(uid_t uid1, uid_t uid2)
+{
+  return setresuid(uid2, uid2, uid1 == uid2 ? uid2 : 0);
+}
+
+int setregid(gid_t gid1, gid_t gid2)
+{
+  return setresgid(gid2, gid2, gid1 == gid2 ? gid2 : 0);
+}
+#endif
diff --git a/icedax/setuid.h b/icedax/setuid.h
new file mode 100644 (file)
index 0000000..48a8ae0
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)setuid.h        1.2 99/12/19 Copyright 1998,1999 Heiko Eissfeldt */
+/* Security functions */
+void initsecurity(void);
+
+void needroot(int necessary);
+void dontneedroot(void);
+void neverneedroot(void);
+
+void needgroup(int necessary);
+void dontneedgroup(void);
+void neverneedgroup(void);
+
+#if defined (HPUX)
+#define HAVE_SETREUID
+#define HAVE_SETREGID
+int seteuid(uid_t uid);
+int setreuid(uid_t uid1, uid_t uid2);
+int setregid(gid_t gid1, gid_t gid2);
+#endif
diff --git a/icedax/sha.h b/icedax/sha.h
new file mode 100644 (file)
index 0000000..ca5e4a0
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)sha.h   1.4 03/06/28 Copyright 1998,1999 Heiko Eissfeldt */
+/*____________________________________________________________________________
+//
+//   CD Index - The Internet CD Index
+//
+//   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 of the License, 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.
+//
+//   $Id: sha.h,v 1.1.1.2 1999/04/29 00:53:34 marc Exp $
+//____________________________________________________________________________
+*/
+#ifndef SHA_H
+#define SHA_H
+
+/* NIST Secure Hash Algorithm */
+/* heavily modified by Uwe Hollerbach <uh@alumni.caltech edu> */
+/* from Peter C. Gutmann's implementation as found in */
+/* Applied Cryptography by Bruce Schneier */
+
+/* This code is in the public domain */
+
+/* Useful defines & typedefs */
+
+typedef unsigned char BYTE;    /* 8-bit quantity */
+typedef unsigned long ULONG;   /* 32-or-more-bit quantity */
+
+#define SHA_BLOCKSIZE          64
+#define SHA_DIGESTSIZE         20
+
+typedef struct {
+    ULONG digest[5];           /* message digest */
+    ULONG count_lo, count_hi;  /* 64-bit bit count */
+    BYTE data[SHA_BLOCKSIZE];  /* SHA data buffer */
+    int local;                 /* unprocessed amount in data */
+} SHA_INFO;
+
+void sha_init(SHA_INFO *);
+void sha_update(SHA_INFO *, BYTE *, int);
+void sha_final(unsigned char [20], SHA_INFO *);
+
+#ifdef SHA_FOR_C
+
+#include <mconfig.h>
+#include <stdxlib.h>
+#include <stdio.h>
+
+void sha_stream(unsigned char [20], SHA_INFO *, FILE *);
+void sha_print(unsigned char [20]);
+char *sha_version(void);
+#endif /* SHA_FOR_C */
+
+#define SHA_VERSION 1
+
+#ifndef WIN32 
+#ifdef WORDS_BIGENDIAN
+#  if SIZEOF_UNSIGNED_LONG_INT == 4
+#    define SHA_BYTE_ORDER  4321
+#  else
+#    if SIZEOF_UNSIGNED_LONG_INT == 8
+#      define SHA_BYTE_ORDER  87654321
+#    endif
+#  endif
+#else
+#  if SIZEOF_UNSIGNED_LONG_INT == 4
+#    define SHA_BYTE_ORDER  1234
+#  else
+#    if SIZEOF_UNSIGNED_LONG_INT == 8
+#      define SHA_BYTE_ORDER  12345678
+#    endif
+#  endif
+#endif
+
+#else
+
+#define SHA_BYTE_ORDER 1234
+
+#endif
+
+#endif /* SHA_H */
diff --git a/icedax/sha_func.c b/icedax/sha_func.c
new file mode 100644 (file)
index 0000000..06b55ac
--- /dev/null
@@ -0,0 +1,376 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)sha_func.c      1.3 01/10/27 Copyright 1998,1999 Heiko Eissfeldt */
+/*____________________________________________________________________________
+//
+//   CD Index - The Internet CD Index
+//
+//   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 of the License, 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.
+//
+//   $Id: sha_func.c,v 1.2 1999/06/04 14:10:07 marc Exp $
+//____________________________________________________________________________
+*/
+/* NIST Secure Hash Algorithm */
+
+/* heavily modified by Uwe Hollerbach <uh@alumni.caltech edu> */
+/* from Peter C. Gutmann's implementation as found in */
+/* Applied Cryptography by Bruce Schneier */
+/* Further modifications to include the "UNRAVEL" stuff, below */
+/* portability modifications Heiko Eissfeldt */
+
+/* This code is in the public domain */
+
+#include "config.h"
+#include <strdefs.h>
+#include "sha.h"
+
+/* UNRAVEL should be fastest & biggest */
+/* UNROLL_LOOPS should be just as big, but slightly slower */
+/* both undefined should be smallest and slowest */
+
+#define UNRAVEL
+/* #define UNROLL_LOOPS */
+
+/* SHA f()-functions */
+
+#define f1(x,y,z)      ((x & y) | (~x & z))
+#define f2(x,y,z)      (x ^ y ^ z)
+#define f3(x,y,z)      ((x & y) | (x & z) | (y & z))
+#define f4(x,y,z)      (x ^ y ^ z)
+
+/* SHA constants */
+
+#define CONST1         ULONG_C(0x5a827999)
+#define CONST2         ULONG_C(0x6ed9eba1)
+#define CONST3         ULONG_C(0x8f1bbcdc)
+#define CONST4         ULONG_C(0xca62c1d6)
+
+/* truncate to 32 bits -- should be a null op on 32-bit machines */
+
+#define T32(x) ((x) & ULONG_C(0xffffffff))
+
+/* 32-bit rotate */
+
+#define R32(x,n)       T32(((x << n) | (x >> (32 - n))))
+
+/* the generic case, for when the overall rotation is not unraveled */
+
+#define FG(n)  \
+    T = T32(R32(A,5) + CONCAT(f,n(B,C,D)) + E + *WP++ + CONCAT(CONST,n));      \
+    E = D; D = C; C = R32(B,30); B = A; A = T
+
+/* specific cases, for when the overall rotation is unraveled */
+
+#define FA(n)  \
+    T = T32(R32(A,5) + CONCAT(f,n(B,C,D)) + E + *WP++ + CONCAT(CONST,n)); B = R32(B,30)
+
+#define FB(n)  \
+    E = T32(R32(T,5) + CONCAT(f,n(A,B,C)) + D + *WP++ + CONCAT(CONST,n)); A = R32(A,30)
+
+#define FC(n)  \
+    D = T32(R32(E,5) + CONCAT(f,n(T,A,B)) + C + *WP++ + CONCAT(CONST,n)); T = R32(T,30)
+
+#define FD(n)  \
+    C = T32(R32(D,5) + CONCAT(f,n(E,T,A)) + B + *WP++ + CONCAT(CONST,n)); E = R32(E,30)
+
+#define FE(n)  \
+    B = T32(R32(C,5) + CONCAT(f,n(D,E,T)) + A + *WP++ + CONCAT(CONST,n)); D = R32(D,30)
+
+#define FT(n)  \
+    A = T32(R32(B,5) + CONCAT(f,n(C,D,E)) + T + *WP++ + CONCAT(CONST,n)); C = R32(C,30)
+
+/* do SHA transformation */
+
+static void sha_transform(SHA_INFO *sha_info);
+
+static void sha_transform(SHA_INFO *sha_info)
+{
+    int i;
+    BYTE *dp;
+    ULONG T, A, B, C, D, E, W[80], *WP;
+
+    dp = sha_info->data;
+
+/*
+the following makes sure that at least one code block below is
+traversed or an error is reported, without the necessity for nested
+preprocessor if/else/endif blocks, which are a great pain in the
+nether regions of the anatomy...
+*/
+#undef SWAP_DONE
+
+#if (SHA_BYTE_ORDER == 1234)
+#define SWAP_DONE
+    for (i = 0; i < 16; ++i) {
+       T = *((ULONG *) dp);
+       dp += 4;
+       W[i] =  ((T << 24) & ULONG_C(0xff000000)) | ((T <<  8) & ULONG_C(0x00ff0000)) |
+               ((T >>  8) & ULONG_C(0x0000ff00)) | ((T >> 24) & ULONG_C(0x000000ff));
+    }
+#endif /* SHA_BYTE_ORDER == 1234 */
+
+#if (SHA_BYTE_ORDER == 4321)
+#define SWAP_DONE
+    for (i = 0; i < 16; ++i) {
+       T = *((ULONG *) dp);
+       dp += 4;
+       W[i] = T32(T);
+    }
+#endif /* SHA_BYTE_ORDER == 4321 */
+
+#if (SHA_BYTE_ORDER == 12345678)
+#define SWAP_DONE
+    for (i = 0; i < 16; i += 2) {
+       T = *((ULONG *) dp);
+       dp += 8;
+       W[i] =  ((T << 24) & ULONG_C(0xff000000)) | ((T <<  8) & ULONG_C(0x00ff0000)) |
+               ((T >>  8) & ULONG_C(0x0000ff00)) | ((T >> 24) & ULONG_C(0x000000ff));
+       T >>= 32;
+       W[i+1] = ((T << 24) & ULONG_C(0xff000000)) | ((T <<  8) & ULONG_C(0x00ff0000)) |
+                ((T >>  8) & ULONG_C(0x0000ff00)) | ((T >> 24) & ULONG_C(0x000000ff));
+    }
+#endif /* SHA_BYTE_ORDER == 12345678 */
+
+#if (SHA_BYTE_ORDER == 87654321)
+#define SWAP_DONE
+    for (i = 0; i < 16; i += 2) {
+       T = *((ULONG *) dp);
+       dp += 8;
+       W[i] = T32(T >> 32);
+       W[i+1] = T32(T);
+    }
+#endif /* SHA_BYTE_ORDER == 87654321 */
+
+#ifndef SWAP_DONE
+error Unknown byte order -- you need to add code here
+#endif /* SWAP_DONE */
+
+    for (i = 16; i < 80; ++i) {
+       W[i] = W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16];
+#if (SHA_VERSION == 1)
+       W[i] = R32(W[i], 1);
+#endif /* SHA_VERSION */
+    }
+    A = sha_info->digest[0];
+    B = sha_info->digest[1];
+    C = sha_info->digest[2];
+    D = sha_info->digest[3];
+    E = sha_info->digest[4];
+    WP = W;
+#ifdef UNRAVEL
+    FA(1); FB(1); FC(1); FD(1); FE(1); FT(1); FA(1); FB(1); FC(1); FD(1);
+    FE(1); FT(1); FA(1); FB(1); FC(1); FD(1); FE(1); FT(1); FA(1); FB(1);
+    FC(2); FD(2); FE(2); FT(2); FA(2); FB(2); FC(2); FD(2); FE(2); FT(2);
+    FA(2); FB(2); FC(2); FD(2); FE(2); FT(2); FA(2); FB(2); FC(2); FD(2);
+    FE(3); FT(3); FA(3); FB(3); FC(3); FD(3); FE(3); FT(3); FA(3); FB(3);
+    FC(3); FD(3); FE(3); FT(3); FA(3); FB(3); FC(3); FD(3); FE(3); FT(3);
+    FA(4); FB(4); FC(4); FD(4); FE(4); FT(4); FA(4); FB(4); FC(4); FD(4);
+    FE(4); FT(4); FA(4); FB(4); FC(4); FD(4); FE(4); FT(4); FA(4); FB(4);
+    sha_info->digest[0] = T32(sha_info->digest[0] + E);
+    sha_info->digest[1] = T32(sha_info->digest[1] + T);
+    sha_info->digest[2] = T32(sha_info->digest[2] + A);
+    sha_info->digest[3] = T32(sha_info->digest[3] + B);
+    sha_info->digest[4] = T32(sha_info->digest[4] + C);
+#else /* !UNRAVEL */
+#ifdef UNROLL_LOOPS
+    FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1);
+    FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1);
+    FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2);
+    FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2);
+    FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3);
+    FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3);
+    FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4);
+    FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4);
+#else /* !UNROLL_LOOPS */
+    for (i =  0; i < 20; ++i) { FG(1); }
+    for (i = 20; i < 40; ++i) { FG(2); }
+    for (i = 40; i < 60; ++i) { FG(3); }
+    for (i = 60; i < 80; ++i) { FG(4); }
+#endif /* !UNROLL_LOOPS */
+    sha_info->digest[0] = T32(sha_info->digest[0] + A);
+    sha_info->digest[1] = T32(sha_info->digest[1] + B);
+    sha_info->digest[2] = T32(sha_info->digest[2] + C);
+    sha_info->digest[3] = T32(sha_info->digest[3] + D);
+    sha_info->digest[4] = T32(sha_info->digest[4] + E);
+#endif /* !UNRAVEL */
+}
+
+/* initialize the SHA digest */
+
+void sha_init(SHA_INFO *sha_info);
+
+void sha_init(SHA_INFO *sha_info)
+{
+    sha_info->digest[0] = ULONG_C(0x67452301);
+    sha_info->digest[1] = ULONG_C(0xefcdab89);
+    sha_info->digest[2] = ULONG_C(0x98badcfe);
+    sha_info->digest[3] = ULONG_C(0x10325476);
+    sha_info->digest[4] = ULONG_C(0xc3d2e1f0);
+    sha_info->count_lo = 0L;
+    sha_info->count_hi = 0L;
+    sha_info->local = 0;
+}
+
+/* update the SHA digest */
+
+void sha_update(SHA_INFO *sha_info, BYTE *buffer, int count);
+
+void sha_update(SHA_INFO *sha_info, BYTE *buffer, int count)
+{
+    int i;
+    ULONG clo;
+
+    clo = T32(sha_info->count_lo + ((ULONG) count << 3));
+    if (clo < sha_info->count_lo) {
+       ++sha_info->count_hi;
+    }
+    sha_info->count_lo = clo;
+    sha_info->count_hi += (ULONG) count >> 29;
+    if (sha_info->local) {
+       i = SHA_BLOCKSIZE - sha_info->local;
+       if (i > count) {
+           i = count;
+       }
+       memcpy(((BYTE *) sha_info->data) + sha_info->local, buffer, i);
+       count -= i;
+       buffer += i;
+       sha_info->local += i;
+       if (sha_info->local == SHA_BLOCKSIZE) {
+           sha_transform(sha_info);
+       } else {
+           return;
+       }
+    }
+    while (count >= SHA_BLOCKSIZE) {
+       memcpy(sha_info->data, buffer, SHA_BLOCKSIZE);
+       buffer += SHA_BLOCKSIZE;
+       count -= SHA_BLOCKSIZE;
+       sha_transform(sha_info);
+    }
+    memcpy(sha_info->data, buffer, count);
+    sha_info->local = count;
+}
+
+/* finish computing the SHA digest */
+
+void sha_final(unsigned char digest[20], SHA_INFO *sha_info);
+
+void sha_final(unsigned char digest[20], SHA_INFO *sha_info)
+{
+    int count;
+    ULONG lo_bit_count, hi_bit_count;
+
+    lo_bit_count = sha_info->count_lo;
+    hi_bit_count = sha_info->count_hi;
+    count = (int) ((lo_bit_count >> 3) & 0x3f);
+    ((BYTE *) sha_info->data)[count++] = 0x80;
+    if (count > SHA_BLOCKSIZE - 8) {
+       memset(((BYTE *) sha_info->data) + count, 0, SHA_BLOCKSIZE - count);
+       sha_transform(sha_info);
+       memset((BYTE *) sha_info->data, 0, SHA_BLOCKSIZE - 8);
+    } else {
+       memset(((BYTE *) sha_info->data) + count, 0,
+           SHA_BLOCKSIZE - 8 - count);
+    }
+    sha_info->data[56] = (unsigned char) ((hi_bit_count >> 24) & 0xff);
+    sha_info->data[57] = (unsigned char) ((hi_bit_count >> 16) & 0xff);
+    sha_info->data[58] = (unsigned char) ((hi_bit_count >>  8) & 0xff);
+    sha_info->data[59] = (unsigned char) ((hi_bit_count >>  0) & 0xff);
+    sha_info->data[60] = (unsigned char) ((lo_bit_count >> 24) & 0xff);
+    sha_info->data[61] = (unsigned char) ((lo_bit_count >> 16) & 0xff);
+    sha_info->data[62] = (unsigned char) ((lo_bit_count >>  8) & 0xff);
+    sha_info->data[63] = (unsigned char) ((lo_bit_count >>  0) & 0xff);
+    sha_transform(sha_info);
+    digest[ 0] = (unsigned char) ((sha_info->digest[0] >> 24) & 0xff);
+    digest[ 1] = (unsigned char) ((sha_info->digest[0] >> 16) & 0xff);
+    digest[ 2] = (unsigned char) ((sha_info->digest[0] >>  8) & 0xff);
+    digest[ 3] = (unsigned char) ((sha_info->digest[0]      ) & 0xff);
+    digest[ 4] = (unsigned char) ((sha_info->digest[1] >> 24) & 0xff);
+    digest[ 5] = (unsigned char) ((sha_info->digest[1] >> 16) & 0xff);
+    digest[ 6] = (unsigned char) ((sha_info->digest[1] >>  8) & 0xff);
+    digest[ 7] = (unsigned char) ((sha_info->digest[1]      ) & 0xff);
+    digest[ 8] = (unsigned char) ((sha_info->digest[2] >> 24) & 0xff);
+    digest[ 9] = (unsigned char) ((sha_info->digest[2] >> 16) & 0xff);
+    digest[10] = (unsigned char) ((sha_info->digest[2] >>  8) & 0xff);
+    digest[11] = (unsigned char) ((sha_info->digest[2]      ) & 0xff);
+    digest[12] = (unsigned char) ((sha_info->digest[3] >> 24) & 0xff);
+    digest[13] = (unsigned char) ((sha_info->digest[3] >> 16) & 0xff);
+    digest[14] = (unsigned char) ((sha_info->digest[3] >>  8) & 0xff);
+    digest[15] = (unsigned char) ((sha_info->digest[3]      ) & 0xff);
+    digest[16] = (unsigned char) ((sha_info->digest[4] >> 24) & 0xff);
+    digest[17] = (unsigned char) ((sha_info->digest[4] >> 16) & 0xff);
+    digest[18] = (unsigned char) ((sha_info->digest[4] >>  8) & 0xff);
+    digest[19] = (unsigned char) ((sha_info->digest[4]      ) & 0xff);
+}
+
+#ifdef SHA_FOR_C
+
+/* compute the SHA digest of a FILE stream */
+
+#define BLOCK_SIZE     8192
+
+void sha_stream(unsigned char digest[20], SHA_INFO *sha_info, FILE *fin);
+
+void sha_stream(unsigned char digest[20], SHA_INFO *sha_info, FILE *fin)
+{
+    int i;
+    BYTE data[BLOCK_SIZE];
+
+    sha_init(sha_info);
+    while ((i = fread(data, 1, BLOCK_SIZE, fin)) > 0) {
+       sha_update(sha_info, data, i);
+    }
+    sha_final(digest, sha_info);
+}
+
+/* print a SHA digest */
+
+void sha_print(unsigned char digest[20]);
+
+void sha_print(unsigned char digest[20])
+{
+    int i, j;
+
+    for (j = 0; j < 5; ++j) {
+       for (i = 0; i < 4; ++i) {
+           printf("%02x", *digest++);
+       }
+       printf("%c", (j < 4) ? ' ' : '\n');
+    }
+}
+
+char *sha_version(void);
+
+char *sha_version()
+{
+#if (SHA_VERSION == 1)
+    static char *version = "SHA-1";
+#else
+    static char *version = "SHA";
+#endif
+    return(version);
+}
+
+#endif /* SHA_FOR_C */
diff --git a/icedax/sndconfig.c b/icedax/sndconfig.c
new file mode 100644 (file)
index 0000000..ac446fc
--- /dev/null
@@ -0,0 +1,607 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)sndconfig.c     1.17 04/08/03 Copyright 1998-2004 Heiko Eissfeldt */
+/* os dependent functions */
+#include "config.h"
+#include <stdio.h>
+#include <stdxlib.h>
+#include <strdefs.h>
+#include <fctldefs.h>
+#include <unixstd.h>
+#include <sys/ioctl.h>
+
+#if    !defined __CYGWIN32__
+# include <timedefs.h>
+#endif
+#include <schily.h>
+
+
+/* soundcard setup */
+#if defined (HAVE_SOUNDCARD_H) || defined (HAVE_LINUX_SOUNDCARD_H) || defined (HAVE_SYS_SOUNDCARD_H) || defined (HAVE_MACHINE_SOUNDCARD_H)
+# if defined (HAVE_SOUNDCARD_H)
+#  include <soundcard.h>
+# else
+#  if defined (HAVE_MACHINE_SOUNDCARD_H)
+#   include <machine/soundcard.h>
+#  else
+#   if defined (HAVE_SYS_SOUNDCARD_H)
+#    include <sys/soundcard.h>
+#   else
+#    if defined (HAVE_LINUX_SOUNDCARD_H)
+#     include <linux/soundcard.h>
+#    endif
+#   endif
+#  endif
+# endif
+#endif
+
+#include "mytype.h"
+#include "byteorder.h"
+#include "lowlevel.h"
+#include "global.h"
+#include "sndconfig.h"
+
+#ifdef ECHO_TO_SOUNDCARD
+#   if defined(__CYGWIN32__)
+#      include <windows.h>
+#      include "mmsystem.h"
+#   endif
+
+#   if defined(__EMX__)
+#      define  INCL_DOS
+#      define  INCL_OS2MM
+#      include <os2.h>
+#      define  PPFN    _PPFN
+#      include <os2me.h>
+#      undef   PPFN
+static unsigned long   DeviceID;
+
+#      define  FRAGMENTS       2
+/* playlist-structure */
+typedef struct {
+        ULONG ulCommand;
+        ULONG ulOperand1, ulOperand2, ulOperand3;
+} PLAYLISTSTRUCTURE;
+
+static PLAYLISTSTRUCTURE PlayList[FRAGMENTS + 1];
+static unsigned BufferInd;
+#   endif /* defined __EMX__ */
+
+static char snd_device[200] = SOUND_DEV;
+
+int set_snd_device(const char *devicename)
+{
+       strncpy(snd_device, devicename, sizeof(snd_device));
+       return 0;
+}
+
+#   if defined __CYGWIN32__
+static HWAVEOUT        DeviceID;
+#      define WAVEHDRS 3
+static WAVEHDR wavehdr[WAVEHDRS];
+static unsigned lastwav = 0;
+
+static int check_winsound_caps(int bits, double rate, int channels);
+
+static int check_winsound_caps(int bits, double rate, int channels)
+{
+  int result = 0;
+
+  WAVEOUTCAPS caps;
+
+  /* get caps */
+  if (waveOutGetDevCaps(0, &caps, sizeof(caps))) {
+     fprintf(stderr, "cannot get soundcard capabilities!\n");
+     return 1;
+  }
+
+  /* check caps */
+  if ((bits == 8 && !(caps.dwFormats & 0x333)) ||
+      (bits == 16 && !(caps.dwFormats & 0xccc))) {
+      fprintf(stderr, "%d bits sound are not supported\n", bits);
+      result = 2;
+  }
+
+  if ((channels == 1 && !(caps.dwFormats & 0x555)) ||
+      (channels == 2 && !(caps.dwFormats & 0xaaa))) {
+      fprintf(stderr, "%d sound channels are not supported\n", channels);
+      result = 3;
+  }
+
+  if ((rate == 44100.0 && !(caps.dwFormats & 0xf00)) ||
+      (rate == 22050.0 && !(caps.dwFormats & 0xf0)) ||
+      (rate == 11025.0 && !(caps.dwFormats & 0xf))) {
+      fprintf(stderr, "%d sample rate is not supported\n", (int)rate);
+      result = 4;
+  }
+
+  return result;
+}
+#   endif /* defined CYGWIN */
+#endif /* defined ECHO_TO_SOUNDCARD */
+
+#ifdef HAVE_SUN_AUDIOIO_H
+# include <sun/audioio.h>
+#endif
+#ifdef HAVE_SYS_AUDIOIO_H
+# include <sys/audioio.h>
+#endif
+
+#ifdef HAVE_SYS_ASOUNDLIB_H
+# include <sys/asoundlib.h>
+snd_pcm_t      *pcm_handle;
+#endif
+
+#if    defined HAVE_OSS && defined SNDCTL_DSP_GETOSPACE
+audio_buf_info abinfo;
+#endif
+
+int init_soundcard(double rate, int bits)
+{
+#ifdef ECHO_TO_SOUNDCARD
+  if (global.echo) {
+# if   defined(HAVE_OSS) && HAVE_OSS == 1
+    if (open_snd_device() != 0) {
+        errmsg("Cannot open sound device '%s'\n", snd_device);
+        global.echo = 0;
+    } else { 
+       /* This the sound device initialisation for 4front Open sound drivers */
+
+       int dummy;
+       int garbled_rate = rate;
+       int stereo = (global.channels == 2);
+       int myformat = bits == 8 ? AFMT_U8 :
+               (MY_LITTLE_ENDIAN ? AFMT_S16_LE : AFMT_S16_BE);
+       int mask;
+
+       if (ioctl(global.soundcard_fd, (int)SNDCTL_DSP_GETBLKSIZE, &dummy) == -1) {
+           fprintf(stderr, "Cannot get blocksize for %s\n", snd_device);
+           global.echo = 0;
+       }
+       if (ioctl(global.soundcard_fd, (int)SNDCTL_DSP_SYNC, NULL) == -1) {
+           fprintf(stderr, "Cannot sync for %s\n", snd_device);
+           global.echo = 0;
+       }
+
+#if    defined SNDCTL_DSP_GETOSPACE
+       if (ioctl(global.soundcard_fd, SNDCTL_DSP_GETOSPACE, &abinfo) == -1) {
+               fprintf(stderr, "Cannot get input buffersize for %s\n", snd_device);
+               abinfo.fragments  = 0;
+       }
+#endif
+
+       /* check, if the sound device can do the requested format */
+       if (ioctl(global.soundcard_fd, (int)SNDCTL_DSP_GETFMTS, &mask) == -1) {
+               perror("fatal error:");
+               return -1;
+       }
+       if ((mask & myformat) == 0) {
+               fprintf(stderr, "sound format (%d bits signed) is not available\n", bits);
+               if ((mask & AFMT_U8) != 0) {
+                       bits = 8;
+                       myformat = AFMT_U8;
+               }
+       }
+       if (ioctl(global.soundcard_fd, (int)SNDCTL_DSP_SETFMT, &myformat) == -1) {
+           fprintf(stderr, "Cannot set %d bits/sample for %s\n",bits, snd_device);
+           global.echo = 0;
+       }
+
+       /* limited sound devices may not support stereo */
+       if (stereo
+           && ioctl(global.soundcard_fd, (int)SNDCTL_DSP_STEREO, &stereo) == -1) {
+           fprintf(stderr, "Cannot set stereo mode for %s\n", snd_device);
+           stereo = 0;
+       }
+       if (!stereo
+            && ioctl(global.soundcard_fd, (int)SNDCTL_DSP_STEREO, &stereo) == -1) {
+           fprintf(stderr, "Cannot set mono mode for %s\n", snd_device);
+           global.echo = 0;
+       }
+
+       /* set the sample rate */
+       if (ioctl(global.soundcard_fd, (int)SNDCTL_DSP_SPEED, &garbled_rate) == -1) {
+           fprintf(stderr, "Cannot set rate %d.%2d Hz for %s\n",
+               (int)rate, (int)(rate*100)%100, snd_device);
+           global.echo = 0;
+       }
+       if ( abs((long)rate - garbled_rate) > rate / 20) {
+           fprintf(stderr, "sound device: next best sample rate is %d\n",garbled_rate);
+       }
+    }
+
+# else /* HAVE_OSS */
+
+#  if defined  HAVE_SYS_AUDIOIO_H || defined HAVE_SUN_AUDIOIO_H
+       /* This is the SunOS / Solaris and compatibles sound initialisation */
+
+    if ((global.soundcard_fd = open(snd_device, O_WRONLY, 0)) == EOF) {
+       perror("");
+        fprintf(stderr, "Cannot open %s\n",snd_device);
+        global.echo = 0;
+    } else { 
+
+        audio_info_t            info;
+
+#   if defined (AUDIO_INITINFO) && defined (AUDIO_ENCODING_LINEAR)
+        AUDIO_INITINFO(&info);
+        info.play.sample_rate = rate;
+        info.play.channels = global.channels;
+        info.play.precision = bits;
+        info.play.encoding = AUDIO_ENCODING_LINEAR;
+        info.play.pause = 0;
+        info.record.pause = 0;
+        info.monitor_gain = 0;
+        if (ioctl(global.soundcard_fd, AUDIO_SETINFO, &info) < 0) {
+           fprintf(stderr, "Cannot init %s (sun)\n", snd_device);
+           global.echo = 0;
+       }
+#   else
+       fprintf(stderr, "Cannot init sound device with 44.1 KHz sample rate on %s (sun compatible)\n", snd_device);
+       global.echo = 0;
+#   endif
+    }
+#  else /* SUN audio */
+#   if defined(__CYGWIN32__)
+    /* Windows sound info */
+
+    MMRESULT mmres;
+    WAVEFORMATEX wavform;
+
+    if (waveOutGetNumDevs() < 1) {
+       fprintf( stderr, "no sound devices available!\n");
+       global.echo = 0;
+       return 1;
+    }
+
+    /* check capabilities */
+    if (check_winsound_caps(bits, rate, global.channels) != 0) {
+       fprintf( stderr, "soundcard capabilities are not sufficient!\n");
+       global.echo = 0;
+       return 1;
+    }
+
+    wavform.wFormatTag = WAVE_FORMAT_PCM;
+    wavform.nChannels = global.channels;
+    wavform.nSamplesPerSec = (int)rate;
+    wavform.wBitsPerSample = bits;
+    wavform.cbSize = sizeof(wavform);
+    wavform.nAvgBytesPerSec = (int)rate * global.channels *
+                               (wavform.wBitsPerSample / 8);
+    wavform.nBlockAlign = global.channels * (wavform.wBitsPerSample / 8);
+  
+    DeviceID = 0;
+    mmres = waveOutOpen(&DeviceID, WAVE_MAPPER, &wavform, (unsigned long)WIN_CallBack, 0, CALLBACK_FUNCTION);
+    if (mmres) {
+       char erstr[329];
+
+       waveOutGetErrorText(mmres, erstr, sizeof(erstr));
+       fprintf( stderr, "soundcard open error: %s!\n", erstr);
+       global.echo = 0;
+       return 1;
+    }
+
+    global.soundcard_fd = 0;
+
+    /* init all wavehdrs */
+    { int i;
+       for (i=0; i < WAVEHDRS; i++) {
+           wavehdr[i].dwBufferLength = (global.channels*(bits/ 8)*(int)rate*
+                               global.nsectors)/75;
+           wavehdr[i].lpData = malloc(wavehdr[i].dwBufferLength);
+           if (wavehdr[i].lpData == NULL) {
+                   fprintf(stderr, "no memory for sound buffers available\n");
+                   waveOutReset(0);
+                   waveOutClose(DeviceID);
+                   return 1;
+           }
+           
+           mmres = waveOutPrepareHeader(DeviceID, &wavehdr[i], sizeof(WAVEHDR));
+           if (mmres) {
+               char erstr[129];
+
+               waveOutGetErrorText(mmres, erstr, sizeof(erstr));
+               fprintf( stderr, "soundcard prepare error: %s!\n", erstr);
+               return 1;
+           }
+
+           wavehdr[i].dwLoops = 0;
+           wavehdr[i].dwFlags = WHDR_DONE;
+           wavehdr[i].dwBufferLength = 0;
+       }
+    }
+
+#   else
+#    if defined(__EMX__)
+#      if defined (HAVE_MMPM)
+    /* OS/2 MMPM/2 MCI sound info */
+
+    MCI_OPEN_PARMS mciOpenParms;
+    int i;
+
+    /* create playlist */
+    for (i = 0; i < FRAGMENTS; i++) {
+        PlayList[i].ulCommand = DATA_OPERATION; /* play data */
+        PlayList[i].ulOperand1 = 0;    /* address */
+        PlayList[i].ulOperand2 = 0;    /* size */
+        PlayList[i].ulOperand3 = 0;     /* offset */
+    }
+    PlayList[FRAGMENTS].ulCommand = BRANCH_OPERATION;       /* jump */
+    PlayList[FRAGMENTS].ulOperand1 = 0;
+    PlayList[FRAGMENTS].ulOperand2 = 0;     /* destination */
+    PlayList[FRAGMENTS].ulOperand3 = 0;
+
+    memset(&mciOpenParms, 0, sizeof(mciOpenParms));
+    mciOpenParms.pszDeviceType = (PSZ) (((unsigned long) MCI_DEVTYPE_WAVEFORM_AUDIO << 16) | (unsigned short) DeviceIndex);
+    mciOpenParms.pszElementName = (PSZ) & PlayList;
+
+    /* try to open the sound device */
+    if (mciSendCommand(0, MCI_OPEN,
+        MCI_WAIT | MCI_OPEN_SHAREABLE | MCIOPEN_Type_ID, &mciOpenParms, 0)
+        != MCIERR_SUCCESS) {
+       /* no sound */
+       fprintf( stderr, "no sound devices available!\n");
+       global.echo = 0;
+       return 1;
+    }
+    /* try to set the parameters */
+    DeviceID = mciOpenParms.usDeviceID;
+
+    {
+       MCI_WAVE_SET_PARMS mciWaveSetParms;
+
+       memset(&mciWaveSetParms, 0, sizeof(mciWaveSetParms));
+       mciWaveSetParms.ulSamplesPerSec = rate;
+       mciWaveSetParms.usBitsPerSample = bits;
+       mciWaveSetParms.usChannels = global.channels;
+       mciWaveSetParms.ulAudio = MCI_SET_AUDIO_ALL;
+
+       /* set play-parameters */
+       if (mciSendCommand(DeviceID, MCI_SET,
+                       MCI_WAIT | MCI_WAVE_SET_SAMPLESPERSEC |
+                       MCI_WAVE_SET_BITSPERSAMPLE | MCI_WAVE_SET_CHANNELS,
+                       (PVOID) & mciWaveSetParms, 0)) {
+               MCI_GENERIC_PARMS mciGenericParms;
+               fprintf( stderr, "soundcard capabilities are not sufficient!\n");
+               global.echo = 0;
+               /* close */
+               mciSendCommand(DeviceID, MCI_CLOSE, MCI_WAIT, &mciGenericParms, 0);
+               return 1;
+       }
+    }
+
+#       endif /* EMX MMPM OS2 sound */
+#    else
+#      if defined(__QNX__)
+
+       int     card = -1;
+       int     dev = 0;
+       int     rtn;
+       snd_pcm_channel_info_t  pi;
+       snd_pcm_channel_params_t        pp;
+
+       if (card == -1) {
+               rtn = snd_pcm_open_preferred(&pcm_handle, 
+                       &card, &dev, SND_PCM_OPEN_PLAYBACK);
+               if (rtn < 0) {
+                       perror("sound device open");
+                       return 1;
+               }
+       } else {
+               rtn = snd_pcm_open(&pcm_handle, 
+                       card, dev, SND_PCM_OPEN_PLAYBACK);
+               if (rtn < 0) {
+                       perror("sound device open");
+                       return 1;
+               }
+       }
+
+       memset(&pi, 0, sizeof(pi));
+       pi.channel = SND_PCM_CHANNEL_PLAYBACK;
+       rtn = snd_pcm_plugin_info(pcm_handle, &pi);
+       if (rtn < 0) {
+               fprintf(stderr, "snd_pcm_plugin_info failed: %s\n", snd_strerror(rtn));
+               return 1;
+       }
+
+       memset(&pp, 0, sizeof(pp));
+       pp.mode = SND_PCM_MODE_BLOCK;
+       pp.channel = SND_PCM_CHANNEL_PLAYBACK;
+       pp.start_mode = SND_PCM_START_FULL;
+       pp.stop_mode = SND_PCM_STOP_STOP;
+
+       pp.buf.block.frag_size = pi.max_fragment_size;
+       pp.buf.block.frags_max = 1;
+       pp.buf.block.frags_min = 1;
+
+       pp.format.interleave = 1;
+       pp.format.rate = rate;
+       pp.format.voices = global.channels;
+       if (bits == 8) {
+               pp.format.format = SND_PCM_SFMT_U8;
+       } else {
+               pp.format.format = SND_PCM_SFMT_S16_LE;
+       }
+
+       rtn = snd_pcm_plugin_params(pcm_handle, &pp);
+       if (rtn < 0) {
+               fprintf(stderr, "snd_pcm_plugin_params failed: %s\n", snd_strerror(rtn));
+               return 1;
+       }
+
+       rtn = snd_pcm_plugin_prepare(pcm_handle, SND_PCM_CHANNEL_PLAYBACK);
+       if (rtn < 0) {
+               fprintf(stderr, "snd_pcm_plugin_prepare failed: %s\n", snd_strerror(rtn));
+               return 1;
+       }
+
+       global.soundcard_fd = snd_pcm_file_descriptor(pcm_handle, SND_PCM_CHANNEL_PLAYBACK);
+
+#      endif /* QNX sound */
+#    endif /* EMX OS2 sound */
+#   endif /* CYGWIN Windows sound */
+#  endif /* else SUN audio */
+# endif /* else HAVE_OSS */
+  }
+#endif /* ifdef ECHO_TO_SOUNDCARD */
+  return 0;
+}
+
+int open_snd_device()
+{
+#if    defined(F_GETFL) && defined(F_SETFL) && defined(O_NONBLOCK)
+       int     fl;
+#endif
+
+#if    defined ECHO_TO_SOUNDCARD && !defined __CYGWIN32__ && !defined __EMX__
+       global.soundcard_fd = open(snd_device, O_WRONLY
+#ifdef linux
+               /* Linux BUG: the sound driver open() blocks, if the device is in use. */
+                | O_NONBLOCK
+#endif
+               , 0);
+
+#if    defined(F_GETFL) && defined(F_SETFL) && defined(O_NONBLOCK)
+       fl = fcntl(global.soundcard_fd, F_GETFL, 0);
+       fl &= ~O_NONBLOCK;
+       fcntl(global.soundcard_fd, F_SETFL, fl);
+#endif
+
+       return (global.soundcard_fd < 0);
+#else
+       return 0;
+#endif
+}
+
+int close_snd_device ()
+{
+#if    !defined ECHO_TO_SOUNDCARD
+       return 0;
+#else
+
+# if   defined __CYGWIN32__
+       waveOutReset(0);
+       return waveOutClose(DeviceID);
+# else /* !Cygwin32 */
+
+#  if  defined __EMX__
+#   if defined HAVE_MMPM
+       /* close the sound device */
+       MCI_GENERIC_PARMS mciGenericParms;
+       mciSendCommand(DeviceID, MCI_CLOSE, MCI_WAIT, &mciGenericParms, 0);
+#   else /* HAVE_MMPM */
+       return 0;
+#   endif /* HAVE_MMPM */
+#  else /* !EMX */
+#   if defined __QNX__
+       snd_pcm_plugin_flush(pcm_handle, SND_PCM_CHANNEL_PLAYBACK);
+       return snd_pcm_close(pcm_handle);
+#   else /* !QNX */
+       return close(global.soundcard_fd);
+#   endif /* !QNX */
+#  endif /* !EMX */
+# endif /* !Cygwin32 */
+#endif /* ifdef ECHO_TO_SOUNDCARD */
+}
+
+int write_snd_device(char *buffer, unsigned todo)
+{
+       int result = 0;
+#ifdef ECHO_TO_SOUNDCARD
+#if    defined __CYGWIN32__
+       MMRESULT mmres;
+
+       wavehdr[lastwav].dwBufferLength = todo;
+       memcpy(wavehdr[lastwav].lpData, buffer, todo);
+
+       mmres = waveOutWrite(DeviceID, &wavehdr[lastwav], sizeof(WAVEHDR));
+       if (mmres) {
+               char erstr[129];
+
+               waveOutGetErrorText(mmres, erstr, sizeof(erstr));
+               fprintf( stderr, "soundcard write error: %s!\n", erstr);
+               return 1;
+       }
+       if (++lastwav >= WAVEHDRS)
+                lastwav -= WAVEHDRS;
+       result = mmres;
+#else
+#if    defined __EMX__
+       Playlist[BufferInd].ulOperand1 = buffer;
+       Playlist[BufferInd].ulOperand2 = todo;
+       Playlist[BufferInd].ulOperand3 = 0;
+       if (++BufferInd >= FRAGMENTS)
+               BufferInd -= FRAGMENTS;
+
+       /* no MCI_WAIT here, because application program has to continue */
+       memset(&mciPlayParms, 0, sizeof(mciPlayParms));
+       if (mciSendCommand(DeviceID, MCI_PLAY, MCI_FROM, &mciPlayParms, 0)) {
+               fprintf( stderr, "soundcard write error: %s!\n", erstr);
+               return 1;
+       }
+       result = 0;
+#else
+       int retval2;
+       int towrite;
+
+#if    defined HAVE_OSS && defined SNDCTL_DSP_GETOSPACE
+       towrite = abinfo.fragments * abinfo.fragsize;
+       if (towrite == 0)
+#endif
+       towrite = todo;
+       do {
+               fd_set writefds[1];
+               struct timeval timeout2;
+               int wrote;
+
+               timeout2.tv_sec = 0;
+               timeout2.tv_usec = 4*120000;
+
+               FD_ZERO(writefds);
+               FD_SET(global.soundcard_fd, writefds);
+               retval2 = select(global.soundcard_fd + 1,
+                                NULL, writefds, NULL, &timeout2);
+               switch (retval2) {
+                       default:
+                       case -1: perror ("select failed");
+                       /* fall through */
+                       case 0: /* timeout */
+                               result = 2;
+                               goto outside_loop;
+                       case 1: break;
+               }
+               if (towrite > todo) {
+                       towrite = todo;
+               }
+#if            defined __QNX__ && defined HAVE_SYS_ASOUNDLIB_H
+               wrote = snd_pcm_plugin_write(pcm_handle, buffer, towrite);
+#else
+               wrote = write(global.soundcard_fd, buffer, towrite);
+#endif
+               if (wrote <= 0) {
+                       perror( "cant write audio");
+                       result = 1;
+                       goto outside_loop;
+               } else {
+                       todo -= wrote;
+                       buffer += wrote;
+               }
+       } while (todo > 0);
+outside_loop:
+       ;
+#endif /* !defined __EMX__ */
+#endif /* !defined __CYGWIN32__ */
+#endif /* ECHO_TO_SOUNDCARD */
+       return result;
+}
+
diff --git a/icedax/sndconfig.h b/icedax/sndconfig.h
new file mode 100644 (file)
index 0000000..1a2e18d
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)sndconfig.h     1.2 99/12/19 Copyright 1998,1999 Heiko Eissfeldt */
+#define NONBLOCKING_AUDIO
+int set_snd_device(const char *devicename);
+int init_soundcard(double rate, int bits);
+
+int open_snd_device(void);
+int close_snd_device(void);
+int write_snd_device(char *buffer, unsigned length);
diff --git a/icedax/sndfile.h b/icedax/sndfile.h
new file mode 100644 (file)
index 0000000..73ef9ff
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)sndfile.h       1.4 06/02/19 Copyright 1998,1999 Heiko Eissfeldt, Copyright 2006 J. Schilling */
+
+/*
+ * generic soundfile structure
+ */
+
+#ifndef        _SNDFILE_H
+#define        _SNDFILE_H
+
+#include <utypes.h>
+
+struct soundfile {
+       int     (* InitSound)(int audio, long channels, Ulong rate,
+                                                         long nBitsPerSample,
+                                                         Ulong expected_bytes);
+       int     (* ExitSound)(int audio, Ulong nBytesDone);
+       Ulong   (* GetHdrSize)(void);
+       int     (* WriteSound)(int audio, unsigned char *buf, Ulong BytesToDo);
+       Ulong   (* InSizeToOutSize)(Ulong BytesToDo);
+
+       int     need_big_endian;
+};
+
+#endif /* _SNDFILE_H */
diff --git a/icedax/sun.c b/icedax/sun.c
new file mode 100644 (file)
index 0000000..99ff443
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)sun.c   1.4 01/10/27 Copyright 1998,1999 Heiko Eissfeldt */
+/***
+ * CopyPolicy: GNU Public License 2 applies
+ * Copyright (C) by Heiko Eissfeldt
+ *
+ *
+ * ---------------------------------------------------------------------
+ *  definitions for sun pcm output
+ * ---------------------------------------------------------------------
+ */
+
+#include "config.h"
+#include "mytype.h"
+#include <stdio.h>
+#include <unixstd.h>
+#include "byteorder.h"
+#include "sndfile.h"
+
+typedef struct SUNHDR {
+  unsigned int magic;                  /* dns. a la .snd */
+  unsigned int data_location;          /* offset to data */
+  unsigned int size;                   /* # of data bytes */
+  unsigned int format;                 /* format code */
+  unsigned int sample_rate;            /* in Hertz */
+  unsigned int channelcount;           /* 1 for mono, 2 for stereo */
+  char info[8];                                /* comments */
+} SUNHDR;
+
+static SUNHDR sunHdr;
+
+static int InitSound(int audio, long channels, unsigned long rate, 
+                                                       long nBitsPerSample, unsigned long expected_bytes);
+
+static int InitSound(int audio, long channels, unsigned long rate, 
+                                                       long nBitsPerSample, unsigned long expected_bytes)
+{
+  unsigned long format = nBitsPerSample > 8 ? 0x03 : 0x02;
+
+  sunHdr.magic         = cpu_to_le32(UINT4_C(0x646e732e));
+  sunHdr.data_location = cpu_to_be32(0x20);
+  sunHdr.size          = cpu_to_be32(expected_bytes);
+  sunHdr.format        = cpu_to_be32(format);
+  sunHdr.sample_rate   = cpu_to_be32(rate);
+  sunHdr.channelcount  = cpu_to_be32(channels);
+
+  return write (audio, &sunHdr, sizeof (sunHdr));
+}
+
+static int ExitSound(int audio, unsigned long nBytesDone);
+
+static int ExitSound(int audio, unsigned long nBytesDone)
+{
+  sunHdr.size = cpu_to_be32(nBytesDone);
+
+  /* goto beginning */
+  if (lseek(audio, 0L, SEEK_SET) == -1) {
+    return 0;
+  }
+  return write (audio, &sunHdr, sizeof (sunHdr));
+}
+
+static unsigned long GetHdrSize(void);
+
+static unsigned long GetHdrSize()
+{
+  return sizeof( sunHdr );
+}
+
+static unsigned long InSizeToOutSize(unsigned long BytesToDo);
+
+static unsigned long InSizeToOutSize(unsigned long BytesToDo)
+{
+        return BytesToDo;
+}
+
+struct soundfile sunsound =
+{
+       InitSound,              /* init header method */
+       ExitSound,              /* exit header method */
+       GetHdrSize,             /* report header size method */
+       /* get sound samples out */
+       (int (*)(int audio, unsigned char *buf, unsigned long BytesToDo)) write,
+       InSizeToOutSize,        /* compressed? output file size */
+       1                       /* needs big endian samples */
+};
+
+
diff --git a/icedax/sun.h b/icedax/sun.h
new file mode 100644 (file)
index 0000000..400fc4a
--- /dev/null
@@ -0,0 +1,14 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)sun.h   1.2 99/12/19 Copyright 1998,1999 Heiko Eissfeldt */
+extern struct soundfile sunsound;
diff --git a/icedax/toc.c b/icedax/toc.c
new file mode 100644 (file)
index 0000000..e03c23d
--- /dev/null
@@ -0,0 +1,3841 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)toc.c   1.57 06/02/19 Copyright 1998-2003 Heiko Eissfeldt */
+/*
+ * Copyright: GNU Public License 2 applies
+ *
+ *   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.
+ *
+ * CDDA2WAV (C) Heiko Eissfeldt heiko@hexco.de
+ * CDDB routines (C) Ti Kan and Steve Scherf
+ */
+#include "config.h"
+#include <stdio.h>
+#include <standard.h>
+#include <stdxlib.h>
+#include <strdefs.h>
+#include <utypes.h>
+#include <intcvt.h>
+#include <unixstd.h>           /* sleep */
+#include <ctype.h>
+#include <errno.h>
+#include <fctldefs.h>
+#include <vadefs.h>
+#include <schily.h>
+#include <libport.h>
+#include <sys/ioctl.h>
+
+#define CD_TEXT
+#define CD_EXTRA
+#undef DEBUG_XTRA
+#undef DEBUG_CDTEXT
+#undef DEBUG_CDDBP
+
+
+#include <usal/scsitransp.h>
+
+#include "mytype.h"
+#include "byteorder.h"
+#include "interface.h"
+#include "icedax.h"
+#include "global.h"
+#include "sha.h"
+#include "base64.h"
+#include "toc.h"
+#include "exitcodes.h"
+#include "ringbuff.h"
+
+int Get_Mins(unsigned long p_track);
+int Get_Secs(unsigned long p_track);
+int Get_Frames(unsigned long p_track);
+int Get_Flags(unsigned long p_track);
+int Get_SCMS(unsigned long p_track);
+
+
+#if    defined USE_REMOTE
+/* tcp stuff */
+/* fix OS/2 compilation */
+#ifdef __EMX__
+#define        gethostid       nogethostid
+#endif
+#include <sys/socket.h>
+#undef gethostid
+#include <netinet/in.h>
+#if    defined(HAVE_NETDB_H) && !defined(HOST_NOT_FOUND) && \
+                               !defined(_INCL_NETDB_H)
+#include <netdb.h>
+#define        _INCL_NETDB_H
+#endif
+#endif
+
+int have_CD_text;
+int have_multisession;
+int have_CD_extra;
+int have_CDDB;
+
+struct iterator;
+
+static void                    UpdateTrackData(int p_num);
+static void                    UpdateIndexData(int p_num);
+static void                    UpdateTimeData(int p_min, int p_sec, int p_frm);
+static unsigned int    is_multisession(void);
+static unsigned int    get_end_of_last_audio_track(unsigned mult_off);
+static int                             cddb_sum(int n);
+static void                    dump_extra_info(unsigned from);
+static int                             GetIndexOfSector(unsigned sec, unsigned track);
+static int                             patch_cd_extra(unsigned track, unsigned long sector);
+static void                    patch_to_audio(unsigned long p_track);
+static int                             restrict_tracks_illleadout(void);
+static void                    Set_MCN(unsigned char *MCN_arg);
+static void                    Set_ISRC(int track, const unsigned char *ISRC_arg);
+static void                    InitIterator(struct iterator *iter, unsigned long p_track);
+
+static unsigned char g_track=0xff, g_index=0xff;       /* current track, index */
+
+/* Conversion function: from logical block adresses  to minute,second,frame
+ */
+int lba_2_msf(long lba, int *m, int *s, int *f)
+{
+#ifdef  __follow_redbook__
+       if (lba >= -150 && lba < 405000) {      /* lba <= 404849 */
+#else
+       if (lba >= -150) {
+#endif
+               lba += 150;
+       } else if (lba >= -45150 && lba <= -151) {
+               lba += 450150;
+       } else
+               return 1;
+
+       *m = lba / 60 / 75;
+       lba -= (*m)*60*75;
+       *s = lba / 75;
+       lba -= (*s)*75;
+       *f = lba;
+
+       return 0;
+}
+
+/* print the track currently read */
+static void UpdateTrackData(int p_num)
+{
+  if (global.quiet == 0) { 
+    fprintf (stderr, "\ntrack: %.2d, ", p_num); fflush(stderr);
+  }
+  g_track = (unsigned char) p_num;
+}
+
+
+/* print the index currently read */
+static void UpdateIndexData(int p_num)
+{
+  if (global.quiet == 0) { 
+    fprintf (stderr, "index: %.2d\n", p_num); fflush(stderr);
+  }
+  g_index = (unsigned char) p_num;
+}
+
+
+/* print the time of track currently read */
+static void UpdateTimeData(int p_min, int p_sec, int p_frm)
+{
+  if (global.quiet == 0) {
+    fprintf (stderr, "time: %.2d:%.2d.%.2d\r", p_min, p_sec, p_frm); 
+    fflush(stderr);
+  }
+}
+
+void AnalyzeQchannel(unsigned frame)
+{
+    subq_chnl *sub_ch;
+
+    if (trackindex_disp != 0) {
+       sub_ch = ReadSubQ(get_scsi_p(), GET_POSITIONDATA,0);
+       /* analyze sub Q-channel data */
+       if (sub_ch->track != g_track ||
+           sub_ch->index != g_index) {
+           UpdateTrackData (sub_ch->track);
+           UpdateIndexData (sub_ch->index);
+       }
+    }
+    frame += 150;
+    UpdateTimeData ((unsigned char) (frame / (60*75)), 
+                   (unsigned char) ((frame % (60*75)) / 75), 
+                   (unsigned char) (frame % 75));
+}
+
+unsigned cdtracks = 0;
+
+int no_disguised_audiotracks(void)
+{
+       /* we can assume no audio tracks according to toc here. */
+       /* read a data sector from the first data track */
+       unsigned char p[3000];
+       int retval;
+       get_scsi_p()->silent++;
+       retval = 1 == ReadCdRomData(get_scsi_p(), p, Get_StartSector(1), 1);
+       get_scsi_p()->silent--;
+       if (retval == 0) {
+               int i;
+fprintf(stderr, "Warning: wrong track types found: patching to audio...\n");
+               for (i = 0; i < cdtracks; i++)
+                       patch_to_audio(i);
+       }
+       return retval;
+}
+
+
+#undef SIM_ILLLEADOUT
+int ReadToc(void)
+{
+    int retval = (*doReadToc)( get_scsi_p() );
+#if    defined SIM_ILLLEADOUT
+    g_toc[cdtracks+1] = 20*75;
+#endif
+    return retval;
+}
+
+static int can_read_illleadout(void);
+
+static int can_read_illleadout(void)
+{
+       SCSI *usalp = get_scsi_p();
+
+       UINT4 buffer [CD_FRAMESIZE_RAW/4];
+       if (global.illleadout_cd == 0) return 0;
+
+       usalp->silent++;
+       global.reads_illleadout = 
+           ReadCdRom(usalp, buffer, Get_AudioStartSector(CDROM_LEADOUT), 1);
+       usalp->silent--;
+       return global.reads_illleadout;
+}
+
+
+unsigned find_an_off_sector(unsigned lSector, unsigned SectorBurstVal);
+
+unsigned find_an_off_sector(unsigned lSector, unsigned SectorBurstVal)
+{
+       long track_of_start = Get_Track(lSector);
+       long track_of_end = Get_Track(lSector + SectorBurstVal -1);
+       long start = Get_AudioStartSector(track_of_start);
+       long end = Get_EndSector(track_of_end);
+
+       if (lSector - start > end - lSector + SectorBurstVal -1)
+               return start;
+       else
+               return end;
+}
+
+#ifdef CD_TEXT
+#include "scsi_cmds.h"
+#endif
+
+
+int handle_cdtext(void)
+{
+#ifdef CD_TEXT
+       if (bufferTOC[0] == 0 && bufferTOC[1] == 0) {
+               have_CD_text = 0;
+               return have_CD_text;
+       }
+
+       /* do a quick scan over all pack type indicators */
+       {
+               int i;
+               int count_fails = 0;
+               int len = (bufferTOC[0] << 8) | bufferTOC[1];
+
+               len = min(len, 2048);
+               for (i = 0; i < len-4; i += 18) {
+                       if (bufferTOC[4+i] < 0x80 || bufferTOC[4+i] > 0x8f) {
+                               count_fails++;
+                       }
+               }
+               have_CD_text = len > 4 && count_fails < 3;
+       }
+
+#else
+       have_CD_text = 0;
+#endif
+       return have_CD_text;
+}
+
+
+#ifdef CD_TEXT
+#include "cd_text.c"
+#endif
+
+
+#if defined CDROMMULTISESSION
+static int tmp_fd;
+#endif
+
+#ifdef CD_EXTRA
+#include "cd_extra.c"
+#endif
+
+static unsigned session_start;
+/*
+   A Cd-Extra is detected, if it is a multisession CD with
+   only audio tracks in the first session and a data track
+   in the last session.
+ */
+static unsigned is_multisession(void)
+{
+  unsigned mult_off;
+#if defined CDROMMULTISESSION
+  /*
+   * FIXME: we would have to do a ioctl (CDROMMULTISESSION)
+   *        for the cdrom device associated with the generic device
+   *       not just AUX_DEVICE
+   */
+  struct cdrom_multisession ms_str;
+
+  if (interface == GENERIC_SCSI)
+    tmp_fd = open (global.aux_name, O_RDONLY);
+  else
+    tmp_fd = global.cooked_fd;
+
+  if (tmp_fd != -1) {
+    int result;
+
+    ms_str.addr_format = CDROM_LBA;
+    result = ioctl(tmp_fd, CDROMMULTISESSION, &ms_str);
+    if (result == -1) {
+      if (global.verbose != 0)
+        perror("multi session ioctl not supported: ");
+    } else {
+#ifdef DEBUG_XTRA
+  fprintf(stderr, "current ioctl multisession_offset = %u\n", ms_str.addr.lba);
+#endif
+       if (interface == GENERIC_SCSI)
+               close (tmp_fd);
+       if (ms_str.addr.lba > 0)
+         return ms_str.addr.lba;
+    }
+  }
+#endif
+  mult_off = 0;
+  if (LastAudioTrack() + 1 == FirstDataTrack()) {
+         mult_off = Get_StartSector(FirstDataTrack());
+  }
+
+#ifdef DEBUG_XTRA
+  fprintf(stderr, "current guessed multisession_offset = %u\n", mult_off);
+#endif
+  return mult_off;
+}
+
+#define SESSIONSECTORS (152*75)
+/*
+   The solution is to read the Table of Contents of the first
+   session only (if the drive permits that) and directly use
+   the start of the leadout. If this is not supported, we subtract
+   a constant of SESSIONSECTORS sectors (found heuristically).
+ */
+static unsigned get_end_of_last_audio_track(unsigned mult_off)
+{
+   unsigned retval;
+
+   /* Try to read the first session table of contents.
+      This works for Sony and mmc type drives. */
+   if (ReadLastAudio && (retval = ReadLastAudio(get_scsi_p())) != 0) {
+     return retval;
+   } else {
+     return mult_off - SESSIONSECTORS;
+   }
+}
+
+static void dump_cdtext_info(void);
+
+#if defined CDDB_SUPPORT
+static void emit_cddb_form(char *fname_baseval);
+#endif
+
+#if defined CDINDEX_SUPPORT
+static void emit_cdindex_form(char *fname_baseval);
+#endif
+
+
+typedef struct TOC {   /* structure of table of contents (cdrom) */
+       unsigned char reserved1;
+       unsigned char bFlags;
+       unsigned char bTrack;
+       unsigned char reserved2;
+       unsigned int dwStartSector;
+       int mins;
+       int secs;
+       int frms;
+       unsigned char ISRC[16];
+       int     SCMS;
+} TOC;
+
+
+/* Flags contains two fields:
+    bits 7-4 (ADR)
+       : 0 no sub-q-channel information
+       : 1 sub-q-channel contains current position
+       : 2 sub-q-channel contains media catalog number
+       : 3 sub-q-channel contains International Standard
+                                  Recording Code ISRC
+       : other values reserved
+    bits 3-0 (Control) :
+    bit 3 : when set indicates there are 4 audio channels else 2 channels
+    bit 2 : when set indicates this is a data track else an audio track
+    bit 1 : when set indicates digital copy is permitted else prohibited
+    bit 0 : when set indicates pre-emphasis is present else not present
+ */
+
+#define GETFLAGS(x) ((x)->bFlags)
+#define GETTRACK(x) ((x)->bTrack)
+#define GETSTART(x) ((x)->dwStartSector)
+#define GETMINS(x)  ((x)->mins)
+#define GETSECS(x)  ((x)->secs)
+#define GETFRAMES(x) ((x)->frms)
+#define GETISRC(x)  ((x)->ISRC)
+
+#define IS__PREEMPHASIZED(p) ( (GETFLAGS(p) & 0x10) != 0)
+#define IS__INCREMENTAL(p) ( (GETFLAGS(p) & 0x10) != 0)
+#define IS__COPYRESTRICTED(p) (!(GETFLAGS(p) & 0x20) != 0)
+#define IS__COPYRIGHTED(p) (!(GETFLAGS(p) & 0x20) != 0)
+#define IS__DATA(p)        ( (GETFLAGS(p) & 0x40) != 0)
+#define IS__AUDIO(p)       (!(GETFLAGS(p) & 0x40) != 0)
+#define IS__QUADRO(p)      ( (GETFLAGS(p) & 0x80) != 0)
+
+/*
+ * Iterator interface inspired from Java
+ */
+struct iterator {
+       int index;
+       int startindex;
+       void        (*reset)(struct iterator *this);
+       struct TOC *(*getNextTrack)(struct iterator *this);
+       int         (*hasNextTrack)(struct iterator *this);
+};
+
+
+
+
+/* The Table of Contents needs to be corrected if we
+   have a CD-Extra. In this case all audio tracks are
+   followed by a data track (in the second session).
+   Unlike for single session CDs the end of the last audio
+   track cannot be set to the start of the following
+   track, since the lead-out and lead-in would then
+   errenously be part of the audio track. This would
+   lead to read errors when trying to read into the
+   lead-out area.
+   So the length of the last track in case of Cd-Extra
+   has to be fixed.
+ */
+unsigned FixupTOC(unsigned no_tracks)
+{
+    unsigned mult_off;
+    unsigned offset = 0;
+    int j = -1;
+    unsigned real_end = 2000000;
+
+    /* get the multisession offset in sectors */
+    mult_off = is_multisession();
+
+    /* if the first track address had been the victim of an underflow,
+     * set it to zero.
+     */
+    if (Get_StartSector(1) > Get_StartSector(LastTrack())) {
+       fprintf(stderr, "Warning: first track has negative start sector! Setting to zero.\n");
+       toc_entry( 1, Get_Flags(1), Get_Tracknumber(1), Get_ISRC(1), 0, 0, 2, 0 );
+    }
+
+#ifdef DEBUG_XTRA
+    fprintf(stderr, "current multisession_offset = %u\n", mult_off);
+#endif
+    dump_cdtext_info();
+
+    if (mult_off > 100) { /* the offset has to have a minimum size */
+
+      /* believe the multisession offset :-) */
+      /* adjust end of last audio track to be in the first session */
+      real_end = get_end_of_last_audio_track(mult_off);
+#ifdef DEBUG_XTRA
+      fprintf(stderr, "current end = %u\n", real_end);
+#endif
+
+      j = FirstDataTrack();
+      if (LastAudioTrack() + 1 == j) {
+         long sj = Get_StartSector(j);
+         if (sj > (long)real_end) {
+           session_start = mult_off;
+               have_multisession = sj;
+
+#ifdef CD_EXTRA
+           offset = Read_CD_Extra_Info(sj);
+
+           if (offset != 0) {
+               have_CD_extra = sj;
+               dump_extra_info(offset);
+           }
+#endif
+         }
+      }
+    }
+    if (global.cddbp) {
+#if    defined USE_REMOTE
+        if (global.disctitle == NULL) {
+           have_CDDB = !request_titles();
+        }
+#else
+        fprintf(stderr, "Cannot lookup titles: no cddbp support included!\n");
+#endif
+    }
+#if defined CDINDEX_SUPPORT || defined CDDB_SUPPORT
+    if (have_CD_text || have_CD_extra || have_CDDB) {
+           unsigned long       count_audio_tracks = 0;
+           static struct iterator i;
+           if (i.reset == NULL)
+                   InitIterator(&i, 1);
+
+           while (i.hasNextTrack(&i)) {
+                   struct TOC *p = i.getNextTrack(&i);
+                   if (IS__AUDIO(p)) count_audio_tracks++;
+           }
+
+           if (count_audio_tracks > 0 && global.no_cddbfile == 0) {
+#if defined CDINDEX_SUPPORT
+                   emit_cdindex_form(global.fname_base);
+#endif
+#if defined CDDB_SUPPORT
+                   emit_cddb_form(global.fname_base);
+#endif
+           }
+    }
+#endif
+    if (have_multisession) {
+       /* set start of track to beginning of lead-out */
+       patch_cd_extra(j, real_end);
+#if    defined CD_EXTRA && defined DEBUG_XTRA
+       fprintf(stderr, "setting end of session (track %d) to %u\n", j, real_end);
+#endif
+    }
+    return offset;
+}
+
+static int cddb_sum(int n)
+{
+  int ret;
+
+  for (ret = 0; n > 0; n /= 10) {
+    ret += (n % 10);
+  }
+
+  return ret;
+}
+
+void calc_cddb_id(void)
+{
+  UINT4 i;
+  UINT4 t = 0;
+  UINT4 n = 0;
+
+  for (i = 1; i <= cdtracks; i++) {
+    n += cddb_sum(Get_StartSector(i)/75 + 2);
+  }
+
+  t = Get_StartSector(i)/75 - Get_StartSector(1)/75;
+
+  global.cddb_id = (n % 0xff) << 24 | (t << 8) | cdtracks;
+}
+
+
+#undef TESTCDINDEX
+#ifdef TESTCDINDEX
+void TestGenerateId(void)
+{
+   SHA_INFO       sha;
+   unsigned char  digest[20], *base64;
+   unsigned long  size;
+
+   sha_init(&sha);
+   sha_update(&sha, (unsigned char *)"0123456789", 10);
+   sha_final(digest, &sha);
+
+   base64 = rfc822_binary((char *)digest, 20, &size);
+   if (strncmp((char*) base64, "h6zsF82dzSCnFsws9nQXtxyKcBY-", size))
+   {
+       free(base64);
+
+       fprintf(stderr, "The SHA-1 hash function failed to properly generate the\n");
+       fprintf(stderr, "test key.\n");
+       exit(INTERNAL_ERROR);
+   }
+   free(base64);
+}
+#endif
+
+void calc_cdindex_id()
+{
+       SHA_INFO        sha;
+       unsigned char   digest[20], *base64;
+       unsigned long   size;
+       unsigned        i;
+       char            temp[9];
+
+#ifdef TESTCDINDEX
+       TestGenerateId();
+       g_toc[1].bTrack = 1;
+       cdtracks = 15;
+       g_toc[cdtracks].bTrack = 15;
+       i = 1;
+       g_toc[i++].dwStartSector = 0U;
+       g_toc[i++].dwStartSector = 18641U;
+       g_toc[i++].dwStartSector = 34667U;
+       g_toc[i++].dwStartSector = 56350U;
+       g_toc[i++].dwStartSector = 77006U;
+       g_toc[i++].dwStartSector = 106094U;
+       g_toc[i++].dwStartSector = 125729U;
+       g_toc[i++].dwStartSector = 149785U;
+       g_toc[i++].dwStartSector = 168885U;
+       g_toc[i++].dwStartSector = 185910U;
+       g_toc[i++].dwStartSector = 205829U;
+       g_toc[i++].dwStartSector = 230142U;
+       g_toc[i++].dwStartSector = 246659U;
+       g_toc[i++].dwStartSector = 265614U;
+       g_toc[i++].dwStartSector = 289479U;
+       g_toc[i++].dwStartSector = 325732U;
+#endif
+       sha_init(&sha);
+       sprintf(temp, "%02X", Get_Tracknumber(1));
+       sha_update(&sha, (unsigned char *)temp, 2);
+       sprintf(temp, "%02X", Get_Tracknumber(cdtracks));
+       sha_update(&sha, (unsigned char *)temp, 2);
+
+       /* the position of the leadout comes first. */
+       sprintf(temp, "%08lX", 150 + Get_StartSector(CDROM_LEADOUT));
+       sha_update(&sha, (unsigned char *)temp, 8);
+
+       /* now 99 tracks follow with their positions. */
+       for (i = 1; i <= cdtracks; i++) {
+               sprintf(temp, "%08lX", 150+Get_StartSector(i));
+               sha_update(&sha, (unsigned char *)temp, 8);
+       }
+       for (i++  ; i <= 100; i++) {
+               sha_update(&sha, (unsigned char *)"00000000", 8);
+       }
+       sha_final(digest, &sha);
+
+       base64 = rfc822_binary((char *)digest, 20, &size);
+       global.cdindex_id = base64;
+}
+
+
+#if defined CDDB_SUPPORT
+
+#ifdef PROTOTYPES
+static void escape_and_split(FILE *channel, const char *args, ...)
+#else
+/*VARARGS3*/
+static void escape_and_split(FILE *channel, const char *args, va_dcl va_alist)
+#endif
+{
+       va_list marker;
+
+       int prefixlen;
+       int len;
+       char    *q;
+
+#ifdef PROTOTYPES
+       va_start(marker, args);
+#else
+       va_start(marker);
+#endif
+
+       prefixlen = strlen(args);
+       len = prefixlen;
+       fputs(args, channel);
+
+       q = va_arg(marker, char *);
+       while (*q != '\0') {
+               while (*q != '\0') {
+                       len += 2;
+                       if (*q == '\\')
+                               fputs("\\\\", channel);
+                       else if (*q == '\t')
+                               fputs("\\t", channel);
+                       else if (*q == '\n')
+                               fputs("\\n", channel);
+                       else {
+                               fputc(*q, channel);
+                               len--;
+                       }
+                       if (len > 78) {
+                               fputc('\n', channel);
+                               fputs(args, channel);
+                               len = prefixlen;
+                       }
+                       q++;
+               }
+               q = va_arg(marker, char *);
+       }
+       fputc('\n', channel);
+
+       va_end(marker);
+}
+
+static void emit_cddb_form(char *fname_baseval)
+{
+  static struct iterator i;
+  unsigned first_audio;
+  FILE *cddb_form;
+  char fname[200];
+  char *pp;
+
+  if (fname_baseval == NULL || fname_baseval[0] == 0)
+       return;
+
+  if (!strcmp(fname_baseval,"standard_output")) return;
+  InitIterator(&i, 1);
+
+  strncpy(fname, fname_baseval, sizeof(fname) -1);
+  fname[sizeof(fname) -1] = 0;
+  pp = strrchr(fname, '.');
+  if (pp == NULL) {
+    pp = fname + strlen(fname);
+  }
+  strncpy(pp, ".cddb", sizeof(fname) - 1 - (pp - fname));
+
+  cddb_form = fopen(fname, "w");
+  if (cddb_form == NULL) return;
+
+  first_audio = FirstAudioTrack();
+  fprintf( cddb_form, "# xmcd\n#\n");
+  fprintf( cddb_form, "# Track frame offsets:\n#\n");
+
+  while (i.hasNextTrack(&i)) {
+         struct TOC *p = i.getNextTrack(&i);
+         if (GETTRACK(p) == CDROM_LEADOUT) break;
+         fprintf( cddb_form,
+                  "# %lu\n", 150 + Get_AudioStartSector(GETTRACK(p)));
+  }
+
+  fprintf( cddb_form, "#\n# Disc length: %lu seconds\n#\n", 
+           (150 + Get_StartSector(CDROM_LEADOUT)) / 75);
+  fprintf( cddb_form, "# Revision: %u\n", global.cddb_revision );
+  fprintf( cddb_form, "# Submitted via: icedax " VERSION "\n" );
+
+  fprintf( cddb_form, "DISCID=%08lx\n", (unsigned long)global.cddb_id);
+
+  if (global.disctitle == NULL && global.creator == NULL) {
+       fprintf( cddb_form, "DTITLE=\n");
+  } else {
+       if (global.creator == NULL) {
+               escape_and_split( cddb_form, "DTITLE=", global.disctitle, "");
+       } else if (global.disctitle == NULL) {
+               escape_and_split( cddb_form, "DTITLE=", global.creator, "");
+       } else {
+               escape_and_split( cddb_form, "DTITLE=", global.creator, " / ", global.disctitle, "");
+       }
+  }
+  if (global.cddb_year != 0)
+       fprintf( cddb_form, "DYEAR=%4u\n", global.cddb_year);
+  else
+       fprintf( cddb_form, "DYEAR=\n");
+  fprintf( cddb_form, "DGENRE=%s\n", global.cddb_genre);
+
+  i.reset(&i);
+  while (i.hasNextTrack(&i)) {
+         struct TOC *p = i.getNextTrack(&i);
+         int ii;
+
+         ii = GETTRACK(p);
+         if (ii == CDROM_LEADOUT) break;
+
+         if (global.tracktitle[ii] != NULL) {
+               char prefix[10];
+               sprintf(prefix, "TTITLE%d=", ii-1);
+                 escape_and_split( cddb_form, prefix, global.tracktitle[ii], "");
+         } else {
+                 fprintf( cddb_form, "TTITLE%d=\n", ii-1);
+         }
+  }
+
+  if (global.copyright_message == NULL) {
+       fprintf( cddb_form, "EXTD=\n");
+  } else {
+       escape_and_split( cddb_form, "EXTD=", "Copyright ", global.copyright_message, "");
+  }
+
+  i.reset(&i);
+  while (i.hasNextTrack(&i)) {
+         struct TOC *p = i.getNextTrack(&i);
+         int ii;
+
+         ii = GETTRACK(p);
+
+         if (ii == CDROM_LEADOUT) break;
+
+         fprintf( cddb_form, "EXTT%d=\n", ii-1);
+  }
+  fprintf( cddb_form, "PLAYORDER=\n");
+  fclose( cddb_form );
+}
+
+#if    defined USE_REMOTE
+#include <pwd.h>
+
+static int readn(register int fd, register char *ptr, register int nbytes)
+{
+       int     nread;
+
+       nread = read(fd, ptr, nbytes);
+#ifdef DEBUG_CDDBP
+       if (nread > 0) {
+               fprintf(stderr, "READ :(%d)", nread);
+               write(2, ptr, nread);
+       }
+#endif
+       if (nread < 0) {
+          perror("socket read error: ");
+          fprintf(stderr, "fd=%d, ptr=%p, nbytes=%d\n", fd, ptr, nbytes);
+       }
+
+       return nread;
+}
+
+static ssize_t writez(int fd, const char *ptr)
+{
+       size_t nleft, nbytes;
+
+       nleft = nbytes = strlen(ptr);
+
+       while (nleft > 0) {
+               ssize_t nwritten = write(fd, ptr, nleft);
+               if (nwritten <= 0) {
+                       return nwritten;        /* return error */
+               }
+#ifdef DEBUG_CDDBP
+               fprintf(stderr, "WRITE:%s\n", ptr);
+#endif
+
+               nleft -= nwritten;
+               ptr   += nwritten;
+       }
+
+       return nbytes - nleft;
+}
+
+#define        SOCKBUFF        2048
+  
+static void filter_nonprintable(char *c, size_t l)
+{
+       size_t i;
+       for(i = 0; i < l; ++i) {
+               if(!isprint(c[i]) && !isspace(c[i])) {
+                       c[i] = '_';
+               }
+       }
+}
+
+
+int process_cddb_titles(int sock_fd, char *inbuff, int readbytes);
+int process_cddb_titles(int sock_fd, char *inbuff, int readbytes)
+{
+       int     finished = 0;
+       char    *p = inbuff;
+       int     ind = 0;
+       unsigned char **        target = &global.creator;
+
+       do {
+               while (readbytes > 0) {
+                       /* do we have a complete line in the buffer? */
+                       p = (char *)memchr(inbuff+ind, '\n', readbytes);
+                       if (p == NULL) break;
+
+                       /* look for the terminator first */
+                       if (!strncmp(".\r\n", inbuff+ind, 3)) {
+                               finished = 1;
+                               break;
+                       }
+                       /* kill carriage return */
+                       if (p > inbuff+ind && *(p-1) == '\r') {
+                               *(p-1) = '\0';
+                       }
+                       /* kill line feed */
+                       *p = '\0';
+
+                       /* handle escaped characters */
+
+                       {
+                               char *q = inbuff+ind;
+                               while (*q) {
+                                       if (*q++ == '\\' && *q != '\0') {
+                                               if (*q == '\\') {
+                                                       readbytes--;
+                                                       p--;
+                                                       memmove(q, q+1, readbytes - (q-inbuff-ind));
+                                               } else if (*q == 'n') {
+                                                       *(q-1) = '\n';
+                                                       readbytes--;
+                                                       p--;
+                                                       memmove(q, q+1, readbytes - (q-inbuff-ind));
+                                               } else if (*q == 't') {
+                                                       *(q-1) = '\t';
+                                                       readbytes--;
+                                                       p--;
+                                                       memmove(q, q+1, readbytes - (q-inbuff-ind));
+                                               }
+                                       }
+                               }
+                                               
+                       }
+
+                       /* handle multi line entries concatenate fields */
+
+/* TODO if the delimiter is split into two lines, it is not recognized. */
+                       if (!strncmp(inbuff+ind, "DTITLE=", 7)) {
+                               char *res = strstr(inbuff+ind+7, " / ");
+                               int clen;
+                               char *q;
+
+                               if (res == NULL) {
+                                       /* no limiter found yet */
+                                       /* copy until the end */
+                                       q = p;
+                               } else {
+                                       /* limiter found */
+                                       /* copy until the limiter */
+                                       q = res;
+                                       *q = '\0';
+                               }
+
+                               clen = q - (inbuff+ind+7);
+                               if (*target == NULL) {
+                                       *target = malloc(clen+1);
+                                       if (*target != NULL)
+                                               **target = '\0';
+                               } else {
+                                       *target = realloc(*target, strlen((char *)*target) + clen - 1);
+                               }
+                               if (*target != NULL) {
+                                       strcat((char *)*target, inbuff+ind+7);
+                               }
+
+                               /* handle part after the delimiter, if present */
+                               if (res != NULL) {
+                                       target = (unsigned char **)&global.disctitle;
+                                       /* skip the delimiter */
+                                       q += 3;
+                                       clen = p - q;
+                                       if (*target == NULL) {
+                                               *target = malloc(clen+1);
+                                               if (*target != NULL)
+                                                       **target = '\0';
+                                       }
+                                       if (*target != NULL) {
+                                               strcat((char *)*target, q);
+                                       }
+                               }
+                       } else if (!strncmp(inbuff+ind, "TTITLE", 6)) {
+                               char    *q = (char *)memchr(inbuff+ind, '=', readbytes);
+                               unsigned tno;
+
+                               if (q != NULL) {
+                                       *q = '\0';
+                                       tno = (unsigned)atoi(inbuff+ind+6);
+                                       tno++;
+                                       if (tno < 100) {
+                                               if (global.tracktitle[tno] == NULL) {
+                                                       global.tracktitle[tno] = malloc( p - q + 1 );
+                                                       if (global.tracktitle[tno] != NULL)
+                                                               *(global.tracktitle[tno]) = '\0';
+                                               } else {
+                                                       global.tracktitle[tno] = realloc(global.tracktitle[tno], strlen((char *)global.tracktitle[tno]) + p - q + 1 );
+                                               }
+                                               if (global.tracktitle[tno] != NULL) {
+                                                       strcat((char *)global.tracktitle[tno], q+1);
+                                               }
+                                       }
+                               }
+                       } else if (!strncmp(inbuff+ind, "DYEAR", 5)) {
+                               char    *q = (char *)memchr(inbuff+ind, '=', readbytes);
+                               if (q++ != NULL) {
+                                       sscanf(q, "%d", &global.cddb_year);
+                               }
+                       } else if (!strncmp(inbuff+ind, "DGENRE", 6)) {
+                               char    *q = (char *)memchr(inbuff+ind, '=', readbytes);
+                               if (q++ != NULL) {
+                                       /* patch from Joe Nuzman, thanks */
+                                       /* might have significant whitespace */
+                                       strncpy(global.cddb_genre, q, sizeof(global.cddb_genre)-1);
+                                       /* always have a terminator */
+                                       global.cddb_genre[sizeof(global.cddb_genre)-1] = '\0';
+                               }
+                       } else if (!strncmp(inbuff+ind, "# Revision: ", 12)) {
+                               char    *q = inbuff+ind+11;
+                               sscanf(q, "%d", &global.cddb_revision);
+                               global.cddb_revision++;
+                       }
+                       readbytes -= (p - inbuff -ind) + 1;
+                       ind = (p - inbuff) + 1;
+               }
+               if (!finished) {
+                       int     newbytes;
+                       memmove(inbuff, inbuff+ind, readbytes);
+                       newbytes = readn(sock_fd, inbuff+readbytes, SOCKBUFF-readbytes);
+                       if (newbytes < 0) {
+                               fprintf(stderr, "Could not read from socket.\n");
+                               return 0; /* Caller checks for != 1 */
+                       }
+                       filter_nonprintable(inbuff+readbytes, newbytes);
+                       if (newbytes <= 0)
+                               break;
+                       readbytes += newbytes;
+                       ind = 0;
+               }
+       } while (!(finished || readbytes == 0));
+       return finished;
+}
+
+static int handle_userchoice(char *p, unsigned size);
+
+static int handle_userchoice(char *p, unsigned size)
+{
+       unsigned        nr = 0;
+       unsigned        user_choice;
+       int             i;
+       char            *q;
+       char            *o;
+
+       /* count lines. */
+       q = p;
+       while ((q = (char *)memchr(q, '\n', size - (q-p))) != NULL) {
+               nr++;
+               q++;
+       }
+       if (nr > 1) nr--;
+
+       /* handle escaped characters */
+
+       {
+               char *r = p;
+               while (*r) {
+                       if (*r++ == '\\' && *r != '\0') {
+                               if (*r == '\\') {
+                                       size--;
+                                       memmove(r, r+1, size - (r-p));
+                               } else if (*r == 'n') {
+                                       *(r-1) = '\n';
+                                       size--;
+                                       memmove(r, r+1, size - (r-p));
+                               } else if (*r == 't') {
+                                       *(r-1) = '\t';
+                                       size--;
+                                       memmove(r, r+1, size - (r-p));
+                               }
+                       }
+               }
+       }
+
+       /* list entries. */
+       q = p;
+       fprintf(stderr, "%u entries found:\n", nr);
+       for (q = (char *)memchr(q, '\n', size - (q-p)), o = p, i = 0; i < nr; i++) {
+               *q = '\0';
+               fprintf(stderr, "%02u: %s\n", i, o);
+               o = q+1;
+               q = (char *)memchr(q, '\n', size - (q-p));
+       }
+       fprintf(stderr, "%02u: ignore\n", i);
+
+       /* get user response. */
+       do {
+               fprintf(stderr, "please choose one (0-%u): ", nr);
+               scanf("%u", &user_choice); /* FIXME: check return value */
+       } while (user_choice > nr);
+
+       if (user_choice == nr)
+               return -1;
+
+       /* skip to choice. */
+       q = p;
+       for (i = 0; i <= (int)user_choice - 1; i++) {
+               q = (char *)memchr(q, '\0', size - (q-p)) + 1;
+       }
+       return  q-p;
+}
+
+/* request disc and track titles from a cddbp server.
+ *
+ * return values:
+ *     0       titles have been found exactly (success)
+ *     -1      some communication error happened.
+ *     1       titles have not been found.
+ *     2       multiple fuzzy matches have been found.
+ */
+int
+request_titles(void)
+{
+       int             retval = 0;
+       int             sock_fd;
+       struct sockaddr_in sa;
+       struct hostent *he;
+       struct servent *se;
+       struct passwd *pw = getpwuid(getuid());
+       char            hostname[HOST_NAME_MAX];
+       char            inbuff[SOCKBUFF];
+       char            outbuff[SOCKBUFF];
+       int             i;
+       char            category[64];
+       unsigned        cat_offset;
+       unsigned        disc_id;
+       ssize_t         readbytes;
+
+       sock_fd = socket(AF_INET, SOCK_STREAM, 0);
+       if (sock_fd < 0) {
+               perror("cddb socket failed: ");
+               retval = -1;
+               goto errout;
+       }
+
+       /* TODO fallbacks
+        * freedb.freedb.org
+        * de.freedb.org
+        * at.freedb.org
+        */
+       if (global.cddbp_server != NULL)
+               he = gethostbyname(global.cddbp_server);
+       else
+               he = gethostbyname(CDDBHOST /*"freedb.freedb.org"*/);
+
+       if (he == NULL) {
+               perror("cddb cannot resolve freedb host: ");
+               he = malloc(sizeof(struct hostent));
+               memset(he, 0 , sizeof(struct hostent));
+               he->h_length = 4;
+               he->h_addrtype = AF_INET;
+               he->h_addr_list = malloc(4);
+               he->h_addr_list[0] = malloc(4);
+               ((struct in_addr *)(he->h_addr_list[0]))->s_addr =
+                       /* kingfisher.berlios.de          freedb.freedb.de */
+                        htonl(UINT_C(0xc3254d85));     /*0xc2610412*/
+               he->h_name = "freedb.freedb.org";
+#if    0
+               retval = -1;
+               goto errout;
+#endif
+       }
+
+       /* save result data IMMEDIATELY!! */
+       memset(&sa, 0 , sizeof(struct sockaddr_in));
+       sa.sin_family      = he->h_addrtype;    /* AF_INET; */
+       sa.sin_addr.s_addr = ((struct in_addr *)((he->h_addr_list)[0]))->s_addr;
+
+       se = NULL;
+       if (global.cddbp_port == NULL)
+               se = getservbyname("cddbp-alt", "tcp");
+
+       if (se == NULL) {
+               if (global.cddbp_port == NULL) {
+                       se = getservbyname("cddbp", "tcp");
+               }
+               if (se == NULL) {
+                       se = malloc(sizeof(struct servent));
+                       memset(se, 0 , sizeof(struct servent));
+                       se->s_port = htons(CDDBPORT /*8880*/);
+#if    0       
+                       perror("cddb cannot resolve cddbp or cddbp-alt port:\n "); 
+                       retval = -1;
+                       goto errout;
+#endif
+               }
+       }
+       if (global.cddbp_port != NULL) {
+               se->s_port = htons(atoi(global.cddbp_port));
+       }
+
+       sa.sin_port        = se->s_port;
+
+/* TODO timeout */
+       if (0 > connect(sock_fd, (struct sockaddr *)&sa, 
+                       sizeof(struct sockaddr_in))) {
+               perror("cddb connect failed: ");
+               retval = -1;
+               goto errout;
+       }
+
+       /* read banner */
+       readbytes = readn(sock_fd, inbuff, sizeof(inbuff));
+       if (readbytes < 0) {
+               fprintf(stderr, "Could not read from socket\n");
+               retval = -1;
+               goto errout;
+       }
+
+       if (strncmp(inbuff, "200 ", 4) && strncmp(inbuff, "201 ", 4)) {
+               if(readbytes == sizeof(inbuff))
+                       --readbytes;
+               inbuff[readbytes] = '\0';
+               filter_nonprintable(inbuff, readbytes);
+               fprintf(stderr, "bad status from freedb server during sign-on banner: %s\n", inbuff);
+               retval = -1;
+               goto errout;
+       }
+
+       /* say hello */
+       hostname[0] = '\0'; 
+       if (0 > gethostname(hostname, sizeof(hostname)))
+               strcpy(hostname, "unknown_host"); 
+       hostname[sizeof(hostname)-1] = '\0';
+       writez(sock_fd, "cddb hello ");
+       if (pw != NULL) {
+               BOOL    space_err = FALSE;
+               BOOL    ascii_err = FALSE;
+               /* change spaces to underscores */
+               char *q = pw->pw_name;
+               while (*q != '\0') {
+                       if (*q == ' ') {
+                               if (!space_err) {
+                                       space_err = TRUE;
+                                       errmsgno(EX_BAD,
+                                       "Warning: Space in user name '%s'.\n",
+                                       pw->pw_name);
+                               }
+                               *q = '_';
+                       }
+                       if (*q < ' ' || *q > '~') {
+                               if (!ascii_err) {
+                                       ascii_err = TRUE;
+                                       errmsgno(EX_BAD,
+                                       "Warning: Nonascii character in user name '%s'.\n",
+                                       pw->pw_name);
+                               }
+                               *q = '_';
+                       }
+                       q++;
+               }
+               writez(sock_fd, pw->pw_name);
+               writez(sock_fd, " ");
+       } else {
+               writez(sock_fd, "unknown ");
+       }
+
+       /* change spaces to underscores */
+       {
+               char *q = hostname;
+               BOOL    space_err = FALSE;
+               BOOL    ascii_err = FALSE;
+
+               while (*q != '\0') {
+                       if (*q == ' ') {
+                               if (!space_err) {
+                                       space_err = TRUE;
+                                       errmsgno(EX_BAD,
+                                       "Warning: Space in hostname '%s'.\n",
+                                       hostname);
+                               }
+                               *q = '_';
+                       }
+                       if (*q < ' ' || *q > '~') {
+                               if (!ascii_err) {
+                                       ascii_err = TRUE;
+                                       errmsgno(EX_BAD,
+                                       "Warning: Nonascii character in hostname '%s'.\n",
+                                       hostname);
+                               }
+                               *q = '_';
+                       }
+                       q++;
+               }
+       }
+
+       writez(sock_fd, hostname);
+       writez(sock_fd, " icedax " VERSION "\n");
+
+       readbytes = readn(sock_fd, inbuff, sizeof(inbuff));
+       if (readbytes < 0) {
+               fprintf(stderr, "Could not read from socket\n");
+               retval = -1;
+               goto errout;
+       }
+       if (strncmp(inbuff, "200 ", 4)) {
+               if(readbytes == sizeof(inbuff))
+                       --readbytes;
+               inbuff[readbytes] = '\0';
+               filter_nonprintable(inbuff, readbytes);
+               fprintf(stderr, "bad status from freedb server during hello: %s\n", inbuff);
+               retval = -1;
+               goto signoff;
+       }
+
+       /* enable new protocol variant. Weird command here, no cddb prefix ?!?! */
+       writez(sock_fd, "proto\n");
+       readbytes = readn(sock_fd, inbuff, sizeof(inbuff));
+       if (readbytes < 0) {
+               fprintf(stderr, "Could not read from socket\n");
+               retval = -1;
+               goto errout;
+       }
+       /* check for errors and maximum supported protocol level */
+       if (strncmp(inbuff, "201 ", 4) > 0) {
+               if(readbytes == sizeof(inbuff))
+                       --readbytes;
+               inbuff[readbytes] = '\0';
+               filter_nonprintable(inbuff, readbytes);
+               fprintf(stderr, "bad status from freedb server during proto command: %s\n", inbuff);
+               retval = -1;
+               goto signoff;
+       }
+       
+       /* check the supported protocol level */
+       if (!memcmp(inbuff, "200 CDDB protocol level: current 1, supported ", 46)) {
+               char *q = strstr(inbuff, " supported ");
+               unsigned        pr_level;
+
+               if (q != NULL) {
+                       q += 11;
+                       sscanf(q, "%u\n", &pr_level);
+                       if (pr_level > 1) {
+                               if (pr_level > 5)
+                                       pr_level = 5;
+                               sprintf(inbuff, "proto %1u\n", pr_level);
+                               writez(sock_fd, inbuff);
+                               readbytes = readn(sock_fd, inbuff, sizeof(inbuff));
+                               if (readbytes < 0) {
+                                       fprintf(stderr, "Could not read from socket\n");
+                                       retval = -1;
+                                       goto errout;
+                               }
+                               /* check for errors and maximum supported protocol level */
+                               if (strncmp(inbuff, "201 ", 4) > 0) {
+                                       if(readbytes == sizeof(inbuff))
+                                               --readbytes;
+                                       inbuff[readbytes] = '\0';
+                                       filter_nonprintable(inbuff,
+                                         readbytes);
+                                       fprintf(stderr, "bad status from freedb server during proto x: %s\n", inbuff);
+                                       retval = -1;
+                                       goto signoff;
+                               }
+                       }
+               }
+       }
+
+       /* format query string */
+       /* query */
+#define        CDDPB_INCLUDING_DATATRACKS
+#ifdef CDDPB_INCLUDING_DATATRACKS
+       sprintf(outbuff, "cddb query %08lx %ld ", (unsigned long)global.cddb_id, LastTrack() - FirstTrack() + 1);
+       /* first all leading datatracks */
+       {
+               int j = FirstAudioTrack();
+               if (j < 0)
+                       j = LastTrack() +1;
+               for (i = FirstTrack(); i < j; i++) {
+                       sprintf(outbuff + strlen(outbuff), "%ld ", 150 + Get_StartSector(i));
+               }
+       }
+#else
+       sprintf(outbuff, "cddb query %08lx %ld ", global.cddb_id, LastAudioTrack() - FirstAudioTrack() + 1);
+#endif
+       /* all audio tracks */
+       for (i = FirstAudioTrack(); i != -1 && i <= LastAudioTrack(); i++) {
+               sprintf(outbuff + strlen(outbuff), "%ld ", 150 + Get_AudioStartSector(i));
+       }
+#ifdef CDDPB_INCLUDING_DATATRACKS
+       /* now all trailing datatracks */
+       for (; i != -1 && i <= LastTrack(); i++) {
+               sprintf(outbuff + strlen(outbuff), "%ld ", 150 + Get_StartSector(i));
+       }
+       sprintf(outbuff + strlen(outbuff), "%lu\n",
+           (150 + Get_StartSector(CDROM_LEADOUT)) / 75);
+#else
+       sprintf(outbuff + strlen(outbuff), "%lu\n",
+           (150 + Get_LastSectorOnCd(FirstAudioTrack())) / 75);
+#endif
+/*     strcpy(outbuff, "cddb query 9709210c 12 150 12010 33557 50765 65380 81467 93235 109115 124135 137732 152575 166742 2339\n"); */
+/*     strcpy(outbuff, "cddb query 03015501 1 296 344\n"); */
+       writez(sock_fd, outbuff);
+
+       readbytes = readn(sock_fd, inbuff, sizeof(inbuff) - 1);
+       if (readbytes < 0) {
+               fprintf(stderr, "Could not read from socket\n");
+               retval = -1;
+               goto errout;
+       }
+       inbuff[readbytes] = '\0';
+       filter_nonprintable(inbuff, readbytes);
+       cat_offset = 4;
+       if (!strncmp(inbuff, "210 ", 4)
+          || !strncmp(inbuff, "211 ", 4)) {
+               /* Check if there are really multiple entries. */
+               char *p = (char *)memchr(inbuff, '\n', readbytes-1);
+
+               if (p != NULL) cat_offset = p+1 - inbuff;
+               /* first entry */
+               if (p) p = (char *)memchr(p+1, '\n', inbuff+readbytes - p);
+               /* second entry */
+               if (p) p = (char *)memchr(p+1, '\n', inbuff+readbytes - p);
+               /* . */
+               if (p) p = (char *)memchr(p+1, '\n', inbuff+readbytes - p);
+               if (p) {
+                       /* multiple entries */
+                       switch (global.cddbp) {
+                               case    2:      /* take the first entry */
+                               break;
+                               case    1:      /* ask user */
+                                       if (!global.gui) {
+                                               int userret = handle_userchoice(inbuff+cat_offset, readbytes - cat_offset);
+                                               if (userret == -1) {
+                                                       /* ignore any selection */
+                                                       retval = -1;
+                                                       goto signoff;
+                                               }
+                                               cat_offset += userret;
+                                       }
+                               break;
+                               default:
+                                       fprintf(stderr, "multiple entries found: %s\n", inbuff);
+                                       retval = 2;
+                                       goto signoff;
+                       }
+               }
+
+       } else if (strncmp(inbuff, "200 ", 4)) {
+               if (!strncmp(inbuff, "202 ", 4)) {
+                       fprintf(stderr, "no cddb entry found: %s\n", inbuff);
+                       retval = 1;
+               } else {
+                       fprintf(stderr, "bad status from freedb server during query: %s\n%s", inbuff, outbuff);
+                       retval = -1;
+               }
+               goto signoff;
+       }
+       sscanf(inbuff + cat_offset, "%s %x", category, &disc_id );
+
+
+       /* read */
+       sprintf(inbuff, "cddb read %s %08x\n", category, disc_id);
+       writez(sock_fd, inbuff);
+
+       /* read status and first buffer size. */
+       readbytes = readn(sock_fd, inbuff, sizeof(inbuff));
+       if (readbytes < 0) {
+               fprintf(stderr, "Could not read from socket\n");
+               retval = -1;
+               goto errout;
+       }
+       filter_nonprintable(inbuff, readbytes);
+       if (strncmp(inbuff, "210 ", 4)) {
+               if(readbytes == sizeof(inbuff))
+                       --readbytes;
+               inbuff[readbytes] = '\0';
+               fprintf(stderr, "bad status from freedb server during read: %s\n", inbuff);
+               retval = -1;
+               goto signoff;
+       }
+
+       if (1 != process_cddb_titles(sock_fd, inbuff, readbytes)) {
+               fprintf(stderr, "cddb read finished not correctly!\n");
+       }
+
+signoff:
+       /* sign-off */
+       writez(sock_fd, "quit\n");
+       readbytes = readn(sock_fd, inbuff, sizeof(inbuff));
+       if (readbytes < 0) {
+               fprintf(stderr, "Could not read from socket\n");
+               retval = -1;
+               goto errout;
+       }
+       if (strncmp(inbuff, "230 ", 4)) {
+               if(readbytes == sizeof(inbuff))
+                       --readbytes;
+               inbuff[readbytes] = '\0';
+               filter_nonprintable(inbuff, readbytes);
+               fprintf(stderr, "bad status from freedb server during quit: %s\n", inbuff);
+               goto errout;
+       }
+
+errout:
+       close(sock_fd);
+       return retval;
+}
+#endif
+#endif
+
+#if    defined CDINDEX_SUPPORT
+
+static int IsSingleArtist(void);
+
+/* check, if there are more than one track creators */
+static int IsSingleArtist(void)
+{
+       static struct iterator i;
+       InitIterator(&i, 1);
+
+       while (i.hasNextTrack(&i)) {
+               struct TOC *p = i.getNextTrack(&i);
+               int ii;
+
+               if (IS__DATA(p) || GETTRACK(p) == CDROM_LEADOUT) continue;
+
+               ii = GETTRACK(p);
+               if (global.creator && global.trackcreator[ii]
+                       && strcmp((char *) global.creator,
+                                 (char *) global.trackcreator[ii]) != 0)
+                       return 0;
+       }
+       return 1;
+}
+
+static const char *a2h[255-191] = {
+"&Agrave;",
+"&Aacute;",
+"&Acirc;",
+"&Atilde;",
+"&Auml;",
+"&Aring;",
+"&AElig;",
+"&Ccedil;",
+"&Egrave;",
+"&Eacute;",
+"&Ecirc;",
+"&Euml;",
+"&Igrave;",
+"&Iacute;",
+"&Icirc;",
+"&Iuml;",
+"&ETH;",
+"&Ntilde;",
+"&Ograve;",
+"&Oacute;",
+"&Ocirc;",
+"&Otilde;",
+"&Ouml;",
+"&times;",
+"&Oslash;",
+"&Ugrave;",
+"&Uacute;",
+"&Ucirc;",
+"&Uuml;",
+"&Yacute;",
+"&THORN;",
+"&szlig;",
+"&agrave;",
+"&aacute;",
+"&acirc;",
+"&atilde;",
+"&auml;",
+"&aring;",
+"&aelig;",
+"&ccedil;",
+"&egrave;",
+"&eacute;",
+"&ecirc;",
+"&euml;",
+"&igrave;",
+"&iacute;",
+"&icirc;",
+"&iuml;",
+"&eth;",
+"&ntilde;",
+"&ograve;",
+"&oacute;",
+"&ocirc;",
+"&otilde;",
+"&ouml;",
+"&divide;",
+"&oslash;",
+"&ugrave;",
+"&uacute;",
+"&ucirc;",
+"&uuml;",
+"&yacute;",
+"&thorn;",
+"&yuml;",
+};
+
+static char *ascii2html(unsigned char *inp)
+{
+       static size_t buflen = 256;
+       static char *outline = 0;
+       size_t pos = 0;
+    size_t l=0;
+
+       /* init */
+       if(!outline) {
+               outline = malloc(buflen);
+               if(outline == 0) {
+                       fprintf(stderr, "error: memory exhausted\n");
+                       _exit(EXIT_FAILURE);
+               }
+       }
+
+       outline[pos] = '\0';
+
+       while (*inp != '\0') {
+
+               /* Pick the sequence to insert */
+               const char *insert;
+               char b[2];
+               const int c = (unsigned char)*inp;
+               switch(c) {
+                       case '"':       insert = "&quot;";      break;
+                       case '&':       insert = "&amp;";       break;
+                       case '<':       insert = "&lt;";        break;
+                       case '>':       insert = "&gt;";        break;
+                       case 160:       insert = "&nbsp;";      break;
+                       default: {
+                                        if(c < 192) {
+                                                b[0] = c;
+                                                b[1] = '\0';
+                                                insert = b;
+                                        } else {
+                                                insert = a2h[c - 192];
+                                        }
+                                }
+               };
+
+               /* Resize buffer */
+               l = strlen(insert);
+               while(pos + l + 1 >= buflen) {
+                       outline = realloc(outline, buflen *= 2);
+                       if(outline == 0) {
+                               fprintf(stderr, "error: memory exhausted\n");
+                               _exit(EXIT_FAILURE);
+                       }
+               }
+
+               /* Copy in */
+               strcpy(&outline[pos], insert);
+               pos += l;
+
+               ++inp;
+       }
+
+       return outline;
+}
+
+static void emit_cdindex_form(char *fname_baseval)
+{
+  FILE *cdindex_form;
+  char fname[200];
+  char *pp;
+
+  if (fname_baseval == NULL || fname_baseval[0] == 0)
+       return;
+
+  strncpy(fname, fname_baseval, sizeof(fname) -1);
+  fname[sizeof(fname) -1] = 0;
+  pp = strrchr(fname, '.');
+  if (pp == NULL) {
+    pp = fname + strlen(fname);
+  }
+  strncpy(pp, ".cdindex", sizeof(fname) - 1 - (pp - fname));
+
+  cdindex_form = fopen(fname, "w");
+  if (cdindex_form == NULL) return;
+
+#define        CDINDEX_URL     "http://www.musicbrainz.org/dtd/CDInfo.dtd"
+
+  /* format XML page according to cdindex DTD (see www.musicbrainz.org) */
+  fprintf( cdindex_form, "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n<!DOCTYPE CDInfo SYSTEM \"%s\">\n\n<CDInfo>\n",
+                 CDINDEX_URL);
+
+  fprintf( cdindex_form, "   <Title>%s</Title>\n",
+        global.disctitle ? ascii2html(global.disctitle) : "");
+  /* 
+   * In case of mixed mode and Extra-CD, nonaudio tracks are included!
+   */
+  fprintf( cdindex_form, "   <NumTracks>%d</NumTracks>\n\n", cdtracks);
+  fprintf( cdindex_form, "   <IdInfo>\n      <DiskId>\n         <Id>%s</Id>\n      </DiskId>\n", global.cdindex_id); 
+
+  fprintf( cdindex_form, "   </IdInfo>\n\n");
+
+  if (IsSingleArtist()) {
+    static struct iterator i;
+    InitIterator(&i, 1);
+
+    fprintf( cdindex_form, "   <SingleArtistCD>\n      <Artist>%s</Artist>\n",
+        global.creator ? ascii2html(global.creator) : "");
+
+    while (i.hasNextTrack(&i)) {
+           struct TOC *p = i.getNextTrack(&i);
+           int ii = GETTRACK(p);
+
+           if (ii == CDROM_LEADOUT) break;
+           if (IS__AUDIO(p)) {
+                   fprintf( cdindex_form,
+                            "      <Track Num=\"%d\">\n         <Name>%s</Name>\n      </Track>\n",
+                            ii, global.tracktitle[ii] ? ascii2html(global.tracktitle[ii]) : "");
+           } else {
+                   fprintf( cdindex_form,
+                            "      <Track Num=\"%d\">\n         <Name>data track</Name>\n      </Track>\n",
+                            ii );
+           }
+    }
+    fprintf( cdindex_form, "   </SingleArtistCD>\n");
+  } else {
+    static struct iterator i;
+    InitIterator(&i, 1);
+
+    fprintf( cdindex_form, "   <MultipleArtistCD>\n");
+
+    while (i.hasNextTrack(&i)) {
+           struct TOC *p = i.getNextTrack(&i);
+           int ii = GETTRACK(p);
+
+           if (ii == CDROM_LEADOUT) break;
+           if (IS__AUDIO(p)) {
+                   fprintf( cdindex_form, "         <Artist>%s</Artist>\n",
+                            global.trackcreator[ii] ? ascii2html(global.trackcreator[ii]) : "");
+                   fprintf( cdindex_form, "         <Name>%s</Name>\n      </Track>\n",
+                 global.tracktitle[ii] ? ascii2html(global.tracktitle[ii]) : "");
+           } else {
+                   fprintf( cdindex_form,
+                            "         <Artist>data track</Artist>\n         <Name>data track</Name>\n      </Track>\n");
+           }
+    }
+    fprintf( cdindex_form, "   </MultipleArtistCD>\n");
+  }
+  fprintf( cdindex_form, "</CDInfo>\n");
+
+  fclose( cdindex_form );
+}
+#endif
+
+static void dump_cdtext_info(void)
+{
+#ifdef CD_TEXT
+  /* interpret the contents of CD Text information based on an early draft
+     of SCSI-3 mmc version 2 from jan 2, 1998
+     CD Text information consists of a text group containing up to
+     8 language blocks containing up to
+     255 Pack data chunks of
+     18 bytes each.
+     So we have at most 36720 bytes to cope with.
+   */
+  {
+    short int datalength;
+    unsigned char *p = bufferTOC;
+    unsigned char lastline[255*12];
+    int                lastitem = -1;
+    int                itemcount = 0;
+    int                inlinecount = 0;
+    int                outlinecount = 0;
+
+    lastline[0] = '\0';
+    datalength = ((p[0] << 8) + p[1]) - 2;
+    datalength = min(datalength, 2048-4);
+    p += 4;
+    for (;datalength > 0;
+       datalength -= sizeof (cdtextpackdata),
+       p += sizeof (cdtextpackdata)) {
+      unsigned char *zeroposition;
+
+      /* handle one packet of CD Text Information Descriptor Pack Data */
+      /* this is raw R-W subchannel data converted to 8 bit values. */
+      cdtextpackdata *c = (cdtextpackdata *)p;
+      int dbcc;
+      int crc_error;
+      unsigned tracknr;
+
+#ifdef DEBUG_CDTEXT
+      fprintf(stderr, "datalength =%d\n", datalength);
+#endif
+      crc_error = !cdtext_crc_ok(c);
+
+      if (lastitem != c->headerfield[0]) {
+       itemcount = 0;
+       lastitem = c->headerfield[0];
+      }
+
+      tracknr = c->headerfield[1] & 0x7f;
+      dbcc = ((unsigned)(c->headerfield[3] & 0x80)) >> 7; /* double byte character code */
+
+#if defined DEBUG_CDTEXT
+       {
+      int extension_flag;
+      int sequence_number;
+      int block_number;
+      int character_position;
+
+      extension_flag = ((unsigned)(c->headerfield[1] & 0x80)) >> 7;
+      sequence_number = c->headerfield[2];
+      block_number = ((unsigned)(c->headerfield[3] & 0x30)) >> 4; /* language */
+      character_position = c->headerfield[3] & 0x0f;
+
+      fprintf(stderr, "CDText: ext_fl=%d, trnr=%u, seq_nr=%d, dbcc=%d, block_nr=%d, char_pos=%d\n",
+             extension_flag, tracknr, sequence_number, dbcc, block_number, character_position);
+       }
+#endif
+
+      /* print ASCII information */
+      memcpy(lastline+inlinecount, c->textdatafield, 12);
+      inlinecount += 12;
+      zeroposition = (unsigned char *)memchr(lastline+outlinecount, '\0', inlinecount-outlinecount);
+      while (zeroposition != NULL) {
+         process_header(c, tracknr, dbcc, lastline+outlinecount);
+         outlinecount += zeroposition - (lastline+outlinecount) + 1;
+
+#if defined DEBUG_CDTEXT
+         fprintf(stderr, "\tin=%d, out=%d, items=%d, trcknum=%u\n", inlinecount, outlinecount, itemcount, tracknr);
+{ int q; for (q= outlinecount; q < inlinecount; q++) fprintf (stderr, "%c", lastline[q] ? lastline[q] : 'ß'); fputs("\n", stderr); }
+#else
+         if (DETAILED) {
+           if (crc_error) fputs(" ! uncorr. CRC-Error", stderr);
+           fputs("\n", stderr);
+         }
+#endif
+
+         itemcount++;
+         if (itemcount > (int)cdtracks
+               || (c->headerfield[0] == 0x8f
+               || (c->headerfield[0] <= 0x8d && c->headerfield[0] >= 0x86))) {
+           outlinecount = inlinecount;
+           break;
+         }
+         tracknr++;
+         zeroposition = (unsigned char *)memchr(lastline+outlinecount, '\0', inlinecount-outlinecount);
+      }
+    }
+  }
+#endif
+}
+
+
+
+static void dump_extra_info(unsigned int from)
+{
+#ifdef CD_EXTRA
+  unsigned char *p;
+  unsigned pos, length;
+
+  if (from == 0) return;
+
+  p = Extra_buffer + 48;
+  while (*p != '\0') {
+    pos    = GET_BE_UINT_FROM_CHARP(p+2);
+    length = GET_BE_UINT_FROM_CHARP(p+6);
+    if (pos == (unsigned)-1) {
+      pos = from+1;
+    } else {
+      pos += session_start;
+    }
+
+#ifdef DEBUG_XTRA
+    if (global.gui == 0 && global.verbose != 0) {
+       fprintf(stderr, "Language: %c%c (as defined by ISO 639)", *p, *(p+1));
+       fprintf(stderr, " at sector %u, len=%u (sessionstart=%u)", pos, length, session_start);
+       fputs("\n", stderr);
+    }
+#endif
+    /* dump this entry */
+    Read_Subinfo(pos, length);
+    p += 10;
+
+    if (p + 9 > (Extra_buffer + CD_FRAMESIZE))
+      break;
+  }
+#endif
+}
+
+static char *quote(unsigned char *string);
+
+static char *quote(unsigned char *string)
+{
+  static char result[200];
+  unsigned char *p = (unsigned char *)result;
+
+  while (*string) {
+    if (*string == '\'' || *string == '\\') {
+       *p++ = '\\';
+    }
+    *p++ = *string++;
+  }
+  *p = '\0';
+
+  return result;
+}
+
+
+
+static void DisplayToc_with_gui(unsigned long dw);
+
+static void DisplayToc_with_gui(unsigned long dw)
+{
+       unsigned mins;
+       unsigned secnds;
+       unsigned frames;
+       int count_audio_trks;
+       static struct iterator i;
+       if (i.reset == NULL) InitIterator(&i, 1);
+       else i.reset(&i);
+
+       mins    =   dw / ( 60*75 );
+       secnds  = ( dw % ( 60*75 ) ) / 75;
+       frames  = ( dw %      75   );
+
+       /* summary */
+       count_audio_trks = 0;
+
+       if ((global.verbose & SHOW_STARTPOSITIONS) != 0) {
+               if (global.illleadout_cd != 0 && have_CD_extra == 0) {
+                       fprintf( stderr, "Tracks:%u > %u:%02u.%02u\n", cdtracks, mins, secnds, frames );
+               } else {
+                       fprintf( stderr, "Tracks:%u %u:%02u.%02u\n", cdtracks, mins, secnds, frames );
+               }
+       }
+
+       if (global.quiet == 0) {
+               fprintf( stderr, "CDINDEX discid: %s\n", global.cdindex_id);
+               fprintf( stderr, "CDDB discid: 0x%08lx", (unsigned long) global.cddb_id);
+
+               if (have_CDDB != 0) {
+                       fprintf(stderr, " CDDBP titles: resolved\n");
+               } else {
+                       fprintf(stderr, "\n");
+               }
+               if (have_CD_text != 0) {
+                       fprintf(stderr, "CD-Text: detected\n");
+                       dump_cdtext_info();
+               } else {
+                       fprintf(stderr, "CD-Text: not detected\n");
+               }
+               if (have_CD_extra != 0) {
+                       fprintf(stderr, "CD-Extra: detected\n");
+                       dump_extra_info(have_CD_extra);
+               } else {
+                       fprintf(stderr, "CD-Extra: not detected\n");
+               }
+               fprintf( stderr, 
+                        "Album title: '%s'", (void *)global.disctitle != NULL
+                        ? quote(global.disctitle) : "");
+
+               fprintf( stderr, " from '%s'\n", (void *)global.creator != NULL 
+                        ? quote(global.creator) : "");
+       }
+       count_audio_trks = 0;
+
+
+       if ((global.verbose & (SHOW_TOC | SHOW_STARTPOSITIONS | SHOW_SUMMARY | SHOW_TITLES)) != 0
+           && i.hasNextTrack(&i)) {
+               TOC *o = i.getNextTrack(&i);
+               while (i.hasNextTrack(&i)) {
+                       TOC *p = i.getNextTrack(&i);
+                       int from;
+                       from = GETTRACK(o);
+
+                       fprintf(stderr, "T%02d:", from);
+
+                       if (IS__DATA(o)) {
+                               /*
+                                * Special case of cd extra
+                                */
+                               unsigned int real_start = have_CD_extra
+                                       ? have_CD_extra : GETSTART(o);
+
+
+                               dw = (unsigned long) (GETSTART(p) - real_start);
+
+                               mins   =   dw / ( 60*75 );
+                               secnds = ( dw % ( 60*75 )) / 75;
+                               frames = ( dw %      75   );
+
+                               if ( global.verbose & SHOW_STARTPOSITIONS )
+                                       fprintf(stderr,
+                                               " %7u",
+                                               real_start
+                                       );
+
+                               if ( global.verbose & SHOW_TOC )
+                                       fprintf(stderr,
+                                               " %2u:%02u.%02u",
+                                               mins, secnds, frames
+                                       );
+
+                               if ( global.verbose & SHOW_SUMMARY )
+                                       fprintf(stderr,
+                                               " data %s %s N/A",
+                                               
+                                               /* how recorded */
+                                               IS__INCREMENTAL(o)
+                                               ? "incremental" : "uninterrupted",
+
+                                               /* copy-permission */
+                                               IS__COPYRIGHTED(o)
+                                               ? "copydenied" : "copyallowed"
+                                       );
+                               fputs("\n", stderr);
+                       } else {
+                               dw = (unsigned long) (GETSTART(p) - GETSTART(o));
+                               mins   =   dw / ( 60*75 );
+                               secnds = ( dw % ( 60*75 )) / 75;
+                               frames = ( dw %      75   );
+                                       
+                               if ( global.verbose & SHOW_STARTPOSITIONS )
+                                       fprintf(stderr,
+                                               " %7u",
+                                               GETSTART(o)
+                                       );
+
+                               if ( global.verbose & SHOW_TOC )
+                                       fprintf(stderr,
+                                               " %2u:%02u.%02u",
+                                               mins, secnds, frames
+                                       );
+
+                               if ( global.verbose & SHOW_SUMMARY )
+                                       fprintf(stderr,
+                                               " audio %s %s %s",
+
+                                       /* how recorded */
+                                       IS__PREEMPHASIZED(o)
+                                       ? "pre-emphasized" : "linear",
+                                               
+                                       /* copy-permission */
+                                       IS__COPYRIGHTED(o)
+                                       ? "copydenied" : "copyallowed",
+
+                                       /* channels */
+                                       IS__QUADRO(o)
+                                               ? "quadro" : "stereo");
+
+                               /* Title */
+                               if ( global.verbose & SHOW_TITLES ) {
+                                       fprintf(stderr,
+                                               " title '%s' from ",
+
+                                               (void *) global.tracktitle[GETTRACK(o)] != NULL
+                                               ? quote(global.tracktitle[GETTRACK(o)]) : ""
+                                       );
+                                       
+                                       fprintf(stderr,
+                                               "'%s'",
+
+                                               (void *) global.trackcreator[GETTRACK(o)] != NULL
+                                               ? quote(global.trackcreator[GETTRACK(o)]) : ""
+                                       );
+                               }
+                               fputs("\n", stderr);
+                               count_audio_trks++;
+                       }
+                       o = p;
+               } /* while */
+               if ( global.verbose & SHOW_STARTPOSITIONS )
+                       if (GETTRACK(o) == CDROM_LEADOUT) {
+                               fprintf(stderr, "Leadout: %7u\n", GETSTART(o));
+                       }
+       } /* if */
+}
+
+static void DisplayToc_no_gui(unsigned long dw);
+
+static void DisplayToc_no_gui(unsigned long dw)
+{
+       unsigned mins;
+       unsigned secnds;
+       unsigned frames;
+       int count_audio_trks;
+       unsigned ii = 0;
+       static struct iterator i;
+       if (i.reset == NULL) InitIterator(&i, 1);
+       else i.reset(&i);
+
+       mins    =   dw / ( 60*75 );
+       secnds  = ( dw % ( 60*75 ) ) / 75;
+       frames  = ( dw %      75   );
+
+       /* summary */
+       count_audio_trks = 0;
+
+       if (i.hasNextTrack(&i)) {
+               TOC *o = i.getNextTrack(&i);
+               while (i.hasNextTrack(&i)) {
+                       TOC *p = i.getNextTrack(&i);
+                       int from;
+                       from = GETTRACK(o);
+
+
+                       while ( p != NULL && GETTRACK(p) != CDROM_LEADOUT
+                               && GETFLAGS(o) == GETFLAGS(p) ) {
+                               o = p;
+                               p = i.getNextTrack(&i);
+                       }
+                       if ((global.verbose & SHOW_SUMMARY) == 0) continue;
+
+                       if (IS__DATA(o)) {
+                               fputs( " DATAtrack recorded      copy-permitted tracktype\n" , stderr);
+                               fprintf(stderr,
+                                       "     %2d-%2d %13.13s %14.14s      data\n",
+                                       from,
+                                       GETTRACK(o),
+                                       /* how recorded */
+                                       IS__INCREMENTAL(o) 
+                                        ? "incremental" : "uninterrupted",
+
+                                       /* copy-perm */
+                                       IS__COPYRIGHTED(o) ? "no" : "yes"
+                                       );
+                       } else { 
+                               fputs( "AUDIOtrack pre-emphasis  copy-permitted tracktype channels\n" , stderr);
+                               fprintf(stderr,
+                                       "     %2d-%2d %12.12s  %14.14s     audio    %1c\n",
+                                       from,
+                                       GETTRACK(o),
+                                       IS__PREEMPHASIZED(o) 
+                                        ? "yes" : "no",
+                                       IS__COPYRIGHTED(o) ? "no" : "yes",
+                                       IS__QUADRO(o) ? '4' : '2'
+                                       );
+                               count_audio_trks++;
+                       }
+                       o = p;
+               }
+       }
+       if ((global.verbose & SHOW_STARTPOSITIONS) != 0) {
+               if (global.illleadout_cd != 0 && have_multisession == 0) {
+
+                       fprintf ( stderr, 
+                                 "Table of Contents: total tracks:%u, (total time more than %u:%02u.%02u)\n",
+                                 cdtracks, mins, secnds, frames );
+               } else {
+                       fprintf ( stderr, 
+                                 "Table of Contents: total tracks:%u, (total time %u:%02u.%02u)\n",
+                                 cdtracks, mins, secnds, frames );
+               }
+       }
+
+       i.reset(&i);
+       if ((global.verbose & SHOW_TOC) != 0 &&
+               i.hasNextTrack(&i)) {
+               TOC *o = i.getNextTrack(&i);
+
+               for (; i.hasNextTrack(&i);) {
+                       TOC *p = i.getNextTrack(&i);
+
+                       if ( GETTRACK(o) <= MAXTRK ) {
+                               unsigned char brace1, brace2;
+                               unsigned trackbeg;
+                               trackbeg = have_multisession && IS__DATA(o) ? have_multisession : GETSTART(o);
+                       
+                               dw = (unsigned long) (GETSTART(p) - trackbeg);
+                               mins   =   dw / ( 60*75 );
+                               secnds = ( dw % ( 60*75 )) / 75;
+                               frames = ( dw %      75   );
+
+                               if ( IS__DATA(o) ) {
+                                       /* data track display */
+                                       brace1 = '[';
+                                       brace2 = ']';
+                               } else if (have_multisession
+                                          && GETTRACK(o) == LastAudioTrack()) {
+                                       /* corrected length of
+                                        * last audio track in cd extra
+                                        */
+                                       brace1 = '|';
+                                       brace2 = '|';
+                               } else {
+                                       /* audio track display */
+                                       brace1 = '(';
+                                       brace2 = ')';
+                               }
+                               fprintf ( stderr,
+                                         " %2u.%c%2u:%02u.%02u%c",
+                                         GETTRACK(o),
+                                         brace1,
+                                         mins, secnds, frames,
+                                         brace2
+                                       );
+                               ii++;
+                       
+                               if ( ii % 5 == 0 )
+                                       fputs( ",\n", stderr );
+                               else if (ii != cdtracks)
+                                       fputc ( ',', stderr );
+                       }
+                       o = p;
+               } /* for */
+               if ( (ii % 5) != 0 )
+                       fputs( "\n", stderr );
+       
+       } /* if */
+
+       if ((global.verbose & SHOW_STARTPOSITIONS) != 0) {
+               fputs ("\nTable of Contents: starting sectors\n", stderr);
+
+               ii = 0;
+               i.reset(&i);
+               if (i.hasNextTrack(&i)) {
+                       TOC *o = i.getNextTrack(&i);
+                       for ( ; i.hasNextTrack(&i);) {
+                               TOC *p = i.getNextTrack(&i);
+                               fprintf ( stderr,
+                                         " %2u.(%8u)",
+                                         GETTRACK(o),
+                                         have_multisession
+                                          && GETTRACK(o) == FirstDataTrack()
+                                           ? have_multisession
+                                           : GETSTART(o)
+#ifdef DEBUG_CDDB
+                                         +150
+#endif
+                                       );
+
+                               ii++;
+                               if ( (ii) % 5 == 0 )
+                                       fputs( ",\n", stderr );
+                               else
+                                       fputc ( ',', stderr );
+                               o = p;
+                       }
+                       fprintf ( stderr, " lead-out(%8u)", GETSTART(o));
+                       fputs ("\n", stderr);
+               }
+       }
+       if (global.quiet == 0) {
+               fprintf(stderr, "CDINDEX discid: %s\n", global.cdindex_id);
+               fprintf( stderr, "CDDB discid: 0x%08lx", (unsigned long) global.cddb_id);
+
+               if (have_CDDB != 0) {
+                       fprintf(stderr, " CDDBP titles: resolved\n");
+               } else {
+                       fprintf(stderr, "\n");
+               }
+               if (have_CD_text != 0) {
+                       fprintf(stderr, "CD-Text: detected\n");
+               } else {
+                       fprintf(stderr, "CD-Text: not detected\n");
+               }
+               if (have_CD_extra != 0) {
+                       fprintf(stderr, "CD-Extra: detected\n");
+               } else {
+                       fprintf(stderr, "CD-Extra: not detected\n");
+               }
+       }
+       if ((global.verbose & SHOW_TITLES) != 0) {
+               int maxlen = 0;
+               
+               if ( global.disctitle != NULL ) {
+                       fprintf( stderr, "Album title: '%s'", global.disctitle);
+                       if ( global.creator != NULL ) {
+                               fprintf( stderr, "\t[from %s]", global.creator);
+                       }
+                       fputs("\n", stderr);
+               }
+
+               i.reset(&i);
+               for ( ; i.hasNextTrack(&i);) {
+                       TOC *p = i.getNextTrack(&i);
+                       int jj = GETTRACK(p);
+
+                       if ( global.tracktitle[jj] != NULL ) {
+                               int len = strlen((char *)global.tracktitle[jj]);
+                               maxlen = max(maxlen, len);
+                       }
+               }
+               maxlen = (maxlen + 12 + 8 + 7)/8;
+               
+               i.reset(&i);
+               for ( ; i.hasNextTrack(&i); ) {
+                       TOC *p = i.getNextTrack(&i);
+                       int jj;
+
+                       if (IS__DATA(p))
+                               continue;
+
+                       jj = GETTRACK(p);
+
+                       if (jj == CDROM_LEADOUT)
+                               break;
+                       
+                       if ( maxlen != 3 ) {
+                               if ( global.tracktitle[jj] != NULL ) {
+                                       fprintf( stderr, "Track %2u: '%s'", jj, global.tracktitle[jj]);
+                               } else {
+                                       fprintf( stderr, "Track %2u: '%s'", jj, "");
+                               }
+                               if ( global.trackcreator[jj] != NULL
+                                    && global.trackcreator[jj][0] != '\0'
+#if 1
+                                    && (global.creator == NULL
+                                        || 0 != strcmp((char *)global.creator,(char *)global.trackcreator[jj]))
+#endif
+                                       ) {
+                                       int j;
+                                       char *o = global.tracktitle[jj] != NULL
+                                               ? (char *)global.tracktitle[jj]
+                                               : "";
+                                       for ( j = 0;
+                                             j < (maxlen - ((int)strlen(o) + 12)/8);
+                                             j++)
+                                               fprintf(stderr, "\t");
+                                       fprintf( stderr, "[from %s]", global.trackcreator[jj]);
+                               }
+                               fputs("\n", stderr);
+                       }
+               }
+       }
+}
+
+void DisplayToc(void)
+{
+       unsigned long dw;
+
+       /* special handling of pseudo-red-book-audio cds */
+       if (cdtracks > 1
+           && Get_StartSector(CDROM_LEADOUT) < Get_StartSector(cdtracks)) {
+               global.illleadout_cd = 1;
+               can_read_illleadout();
+       }
+
+
+       /* get total time */
+       if (global.illleadout_cd == 0)
+               dw = (unsigned long) Get_StartSector(CDROM_LEADOUT) - Get_StartSector(1);
+       else
+               dw = (unsigned long) Get_StartSector(cdtracks     ) - Get_StartSector(1);
+
+       if ( global.gui == 0 ) {
+               /* table formatting when in cmdline mode */
+               DisplayToc_no_gui( dw );
+       } else if (global.gui == 1) {
+               /* line formatting when in gui mode */
+               DisplayToc_with_gui( dw );
+       }
+
+       if (global.illleadout_cd != 0) {
+               if (global.quiet == 0) {
+                       fprintf(stderr, "CD with illegal leadout position detected!\n");
+               }
+
+               if (global.reads_illleadout == 0) {
+                       /* limit accessible tracks 
+                        * to lowered leadout position
+                        */
+                       restrict_tracks_illleadout();
+
+                       if (global.quiet == 0) {
+                               fprintf(stderr,
+                                       "The cdrom drive firmware does not permit access beyond the leadout position!\n");
+                       }
+                       if (global.verbose & (SHOW_ISRC | SHOW_INDICES)) {
+                               global.verbose &= ~(SHOW_ISRC | SHOW_INDICES);
+                               fprintf(stderr, "Switching index scan and ISRC scan off!\n");
+                       }
+
+                       if (global.quiet == 0) {
+                               fprintf(stderr,
+                                       "Audio extraction will be limited to track %ld with maximal %ld sectors...\n",
+                                       LastTrack(),
+                                       Get_EndSector(LastTrack())+1
+                                       );
+                       }
+               } else {
+                       /* The cdrom drive can read beyond the
+                        * indicated leadout. We patch a new leadout
+                        * position to the maximum:
+                        *   99 minutes, 59 seconds, 74 frames
+                        */
+                       patch_real_end(150 + (99*60+59)*75 + 74);
+                       if (global.quiet == 0) {
+                               fprintf(stderr,
+                                       "Restrictions apply, since the size of the last track is unknown!\n");
+                       }
+               }
+       }
+}
+
+static void Read_MCN_toshiba(subq_chnl **sub_ch);
+
+static void Read_MCN_toshiba(subq_chnl **sub_ch)
+{
+       if (Toshiba3401() != 0 && global.quiet == 0
+           && ((*sub_ch) != 0
+               || (((subq_catalog *)(*sub_ch)->data)->mc_valid & 0x80))) {
+               /* no valid MCN yet. do more searching */
+               long h = Get_AudioStartSector(1);
+               
+               while (h <= Get_AudioStartSector(1) + 100) {
+                       if (Toshiba3401())
+                               ReadCdRom(get_scsi_p(), RB_BASE->data, h, global.nsectors);
+                       (*sub_ch) = ReadSubQ(get_scsi_p(), GET_CATALOGNUMBER,0);
+                       if ((*sub_ch) != NULL) {
+                               subq_catalog *subq_cat;
+
+                               subq_cat = (subq_catalog *) (*sub_ch)->data;
+                               if ((subq_cat->mc_valid & 0x80) != 0) {
+                                       break;
+                               }
+                       }
+                       h += global.nsectors;
+               }
+       }
+}
+
+static void Get_Set_MCN(void);
+
+static void Get_Set_MCN(void)
+{
+       subq_chnl *sub_ch;
+       subq_catalog *subq_cat = NULL;
+       fprintf(stderr, "scanning for MCN...");
+    
+       sub_ch = ReadSubQ(get_scsi_p(), GET_CATALOGNUMBER,0);
+
+#define EXPLICIT_READ_MCN_ISRC 1
+#if EXPLICIT_READ_MCN_ISRC == 1 /* TOSHIBA HACK */
+       Read_MCN_toshiba( &sub_ch );
+#endif
+
+       if (sub_ch != NULL)
+               subq_cat = (subq_catalog *)sub_ch->data;
+                       
+       if (sub_ch != NULL
+           && (subq_cat->mc_valid & 0x80) != 0
+           && global.quiet == 0) {
+
+               /* unified format guesser:
+                * format MCN all digits in bcd
+                *     1                                  13
+                * A: ab cd ef gh ij kl m0  0  0  0  0  0  0  Plextor 6x Rel. 1.02
+                * B: 0a 0b 0c 0d 0e 0f 0g 0h 0i 0j 0k 0l 0m  Toshiba 3401
+                * C: AS AS AS AS AS AS AS AS AS AS AS AS AS  ASCII SCSI-2 Plextor 4.5x and 6x Rel. 1.06
+                */
+               unsigned char *cp = subq_cat->media_catalog_number;
+               if (!(cp[8] | cp[9] | cp[10] | cp[11] | cp[12])
+                   && ((cp[0] & 0xf0) | (cp[1] & 0xf0)
+                       | (cp[2] & 0xf0) | (cp[3] & 0xf0)
+                       | (cp[4] & 0xf0) | (cp[5] & 0xf0)
+                       | (cp[6] & 0xf0))) {
+                       /* reformat A: to B: */
+                       cp[12] = cp[6] >> 4; cp[11] = cp[5] & 0xf;
+                       cp[10] = cp[5] >> 4; cp[ 9] = cp[4] & 0xf;
+                       cp[ 8] = cp[4] >> 4; cp[ 7] = cp[3] & 0xf;
+                       cp[ 6] = cp[3] >> 4; cp[ 5] = cp[2] & 0xf;
+                       cp[ 4] = cp[2] >> 4; cp[ 3] = cp[1] & 0xf;
+                       cp[ 2] = cp[1] >> 4; cp[ 1] = cp[0] & 0xf;
+                       cp[ 0] = cp[0] >> 4;
+               }
+
+               if (!isdigit(cp[0])
+                   && (memcmp(subq_cat->media_catalog_number,
+                              "\0\0\0\0\0\0\0\0\0\0\0\0\0", 13) != 0)) {
+                       sprintf((char *)
+                               subq_cat->media_catalog_number, 
+                               "%1.1X%1.1X%1.1X%1.1X%1.1X%1.1X%1.1X%1.1X%1.1X%1.1X%1.1X%1.1X%1.1X", 
+                               subq_cat->media_catalog_number [0],
+                               subq_cat->media_catalog_number [1],
+                               subq_cat->media_catalog_number [2],
+                               subq_cat->media_catalog_number [3],
+                               subq_cat->media_catalog_number [4],
+                               subq_cat->media_catalog_number [5],
+                               subq_cat->media_catalog_number [6],
+                               subq_cat->media_catalog_number [7],
+                               subq_cat->media_catalog_number [8],
+                               subq_cat->media_catalog_number [9],
+                               subq_cat->media_catalog_number [10],
+                               subq_cat->media_catalog_number [11],
+                               subq_cat->media_catalog_number [12]
+                               );
+               }
+
+               if (memcmp(subq_cat->media_catalog_number,"0000000000000",13)
+                   != 0) {
+                       Set_MCN(subq_cat->media_catalog_number);
+               }
+       }
+}
+
+
+static void Read_ISRC_toshiba(subq_chnl **sub_ch, unsigned tr);
+
+static void Read_ISRC_toshiba(subq_chnl **sub_ch, unsigned tr)
+{
+       if (Toshiba3401() != 0) {
+               int j;
+               j = (Get_AudioStartSector(tr)/100 + 1) * 100;
+               do {
+                       ReadCdRom(get_scsi_p(), RB_BASE->data, j, global.nsectors);
+                       *sub_ch = ReadSubQ(get_scsi_p(), GET_TRACK_ISRC, Get_Tracknumber(tr));
+                       if (*sub_ch != NULL) {
+                               subq_track_isrc * subq_tr;
+
+                               subq_tr = (subq_track_isrc *) (*sub_ch)->data;
+                               if (subq_tr != NULL && (subq_tr->tc_valid & 0x80) != 0)
+                                       break;
+                       }
+                       j += global.nsectors;
+               } while (j < (Get_AudioStartSector(tr)/100 + 1) * 100 + 100);
+       }
+}
+
+
+static void Get_Set_ISRC(unsigned tr);
+
+static void Get_Set_ISRC(unsigned tr)
+{
+       subq_chnl *sub_ch;
+       subq_track_isrc * subq_tr;
+
+       fprintf(stderr, "\rscanning for ISRCs: %d ...", tr);
+
+       subq_tr = NULL;
+       sub_ch = ReadSubQ(get_scsi_p(), GET_TRACK_ISRC, tr);
+
+#if EXPLICIT_READ_MCN_ISRC == 1 /* TOSHIBA HACK */
+       Read_ISRC_toshiba( &sub_ch, tr );
+#endif
+    
+       if (sub_ch != NULL)
+               subq_tr = (subq_track_isrc *)sub_ch->data;
+       
+       if (sub_ch != NULL && (subq_tr->tc_valid & 0x80)
+           && global.quiet == 0) {
+               unsigned char p_start[16];
+               unsigned char *p = p_start;
+               unsigned char *cp = subq_tr->track_isrc;
+
+               /* unified format guesser:
+                * there are 60 bits and 15 bytes available.
+                * 5 * 6bit-items + two zero fill bits + 7 * 4bit-items
+                *
+                * A: ab cd ef gh ij kl mn o0 0  0  0  0  0  0  0  Plextor 6x Rel. 1.02
+                * B: 0a 0b 0c 0d 0e 0f 0g 0h 0i 0j 0k 0l 0m 0n 0o Toshiba 3401
+                * C: AS AS AS AS AS AS AS AS AS AS AS AS AS AS AS ASCII SCSI-2
+                * eg 'G''B''-''A''0''7''-''6''8''-''0''0''2''7''0' makes most sense
+                * D: 'G''B''A''0''7''6''8''0''0''2''7''0'0  0  0  Plextor 6x Rel. 1.06 and 4.5x R. 1.01 and 1.04
+                */
+
+               /* Check for format A: */
+               if (!(cp[8] | cp[9] | cp[10] | cp[11] | cp[12] | cp[13] | cp[14]) &&
+                   ((cp[0] & 0xf0) | (cp[1] & 0xf0) | (cp[2] & 0xf0) | 
+                    (cp[3] & 0xf0) | (cp[4] & 0xf0) | (cp[5] & 0xf0) | 
+                    (cp[6] & 0xf0) | (cp[7] & 0xf0))) {
+#if DEBUG_ISRC
+       fprintf(stderr, "a!\t");
+#endif
+                       /* reformat A: to B: */
+                       cp[14] = cp[7] >> 4; cp[13] = cp[6] & 0xf;
+                       cp[12] = cp[6] >> 4; cp[11] = cp[5] & 0xf;
+                       cp[10] = cp[5] >> 4; cp[ 9] = cp[4] & 0xf;
+                       cp[ 8] = cp[4] >> 4; cp[ 7] = cp[3] & 0xf;
+                       cp[ 6] = cp[3] >> 4; cp[ 5] = cp[2] & 0xf;
+                       cp[ 4] = cp[2] >> 4; cp[ 3] = cp[1] & 0xf;
+                       cp[ 2] = cp[1] >> 4; cp[ 1] = cp[0] & 0xf;
+                       cp[ 0] = cp[0] >> 4;
+#if DEBUG_ISRC
+       fprintf(stderr, "a->b: %15.15s\n", cp);
+#endif
+               }
+      
+               /* Check for format B:
+                * If not yet in ASCII format, do the conversion
+                */
+               if (cp[0] < '0' && cp[1] < '0') {
+                       /* coding table for International Standard Recording Code */
+                       static char bin2ISRC[] = {
+                        '0','1','2','3','4','5','6','7','8','9',      /* 10 */
+                        ':',';','<','=','>','?','@',                  /* 17 */
+                        'A','B','C','D','E','F','G','H','I','J','K',  /* 28 */
+                        'L','M','N','O','P','Q','R','S','T','U','V',  /* 39 */
+                        'W','X','Y','Z',                              /* 43 */
+#if 1
+                        '[','\\',']','^','_','`',                     /* 49 */
+                        'a','b','c','d','e','f','g','h','i','j','k',  /* 60 */
+                        'l','m','n','o'                               /* 64 */
+#endif
+                       };
+       
+                       /* build 6-bit vector of coded values */
+                       unsigned ind;
+                       int bits;
+       
+#if DEBUG_ISRC
+       fprintf(stderr, "b!\n");
+#endif
+                       ind =   (cp[0] << 26) +
+                               (cp[1] << 22) +
+                               (cp[2] << 18) + 
+                               (cp[3] << 14) +
+                               (cp[4] << 10) +
+                               (cp[5] << 6) +
+                               (cp[6] << 2) +
+                               (cp[7] >> 2);
+
+                       if ((cp[7] & 3) == 3) {
+                               if (global.verbose) {
+                                       fprintf(stderr,
+                                               "Recorder-ID encountered: ");
+                                       for (bits = 0; bits < 30; bits +=6) {
+                                               unsigned binval = (ind & (ULONG_C(0x3f) << (24-bits)))
+                                                                                       >> (24-bits);
+                                               if ((binval < sizeof(bin2ISRC)) &&
+                                                   (binval <= 9 || binval >= 16)) {
+                                                       fprintf(stderr, "%X", bin2ISRC[binval]);
+                                               }
+                                       }
+
+                                       fprintf(stderr, "%.1X%.1X%.1X%.1X%.1X%.1X%.1X",
+                                           subq_tr->track_isrc [8] & 0x0f,
+                                           subq_tr->track_isrc [9] & 0x0f,
+                                           subq_tr->track_isrc [10] & 0x0f,
+                                           subq_tr->track_isrc [11] & 0x0f,
+                                           subq_tr->track_isrc [12] & 0x0f,
+                                           subq_tr->track_isrc [13] & 0x0f,
+                                           subq_tr->track_isrc [14] & 0x0f
+                                           );
+                                       fprintf(stderr, "\n");
+                               }
+                               return;
+                       }
+                       if ((cp[7] & 3) != 0) {
+                               fprintf(stderr, "unknown mode 3 entry C1=0x%02x, C2=0x%02x\n",
+                                       (cp[7] >> 1) & 1, cp[7] & 1);
+                               return;
+                       }
+         
+                       /* decode ISRC due to IEC 908 */
+                       for (bits = 0; bits < 30; bits +=6) {
+                               unsigned binval = (ind & ((unsigned long) 0x3fL << (24L-bits))) >> (24L-bits);
+                               if ((binval >= sizeof(bin2ISRC)) ||
+                                   (binval > 9 && binval < 16)) {
+                                       /* Illegal ISRC, dump and skip */
+                                       int y;
+                                                   
+                                       Get_ISRC(tr)[0] = '\0';
+                                       fprintf(stderr, "\nIllegal ISRC for track %d, skipped: ", tr);
+                                       for (y = 0; y < 15; y++) {
+                                               fprintf(stderr, "%02x ", cp[y]);
+                                       }
+                                       fputs("\n", stderr);
+                                       return;
+                               }
+                               *p++ = bin2ISRC[binval];
+                               
+                               /* insert a dash after two country characters for legibility */
+                               if (bits == 6)
+                                       *p++ = '-';
+                       }
+                       
+                       /* format year and serial number */
+                       sprintf ((char *)p, "-%.1X%.1X-%.1X%.1X%.1X%.1X%.1X",
+                                subq_tr->track_isrc [8] & 0x0f,
+                                subq_tr->track_isrc [9] & 0x0f,
+                                subq_tr->track_isrc [10] & 0x0f,
+                                subq_tr->track_isrc [11] & 0x0f,
+                                subq_tr->track_isrc [12] & 0x0f,
+                                subq_tr->track_isrc [13] & 0x0f,
+                                subq_tr->track_isrc [14] & 0x0f
+                               ); 
+#if DEBUG_ISRC
+       fprintf(stderr, "b: %15.15s!\n", p_start);
+#endif
+               } else {
+                       /* It might be in ASCII, surprise */
+                       int ii;
+                       for (ii = 0; ii < 12; ii++) {
+                               if (cp[ii] < '0' || cp[ii] > 'Z') {
+                                       break;
+                               }
+                       }
+                       if (ii != 12) {
+                               int y;
+                               
+                               Get_ISRC(ii)[0] = '\0';
+                               fprintf(stderr, "\nIllegal ISRC for track %d, skipped: ", ii+1);
+                               for (y = 0; y < 15; y++) {
+                                       fprintf(stderr, "%02x ", cp[y]);
+                               }
+                               fputs("\n", stderr);
+                               return;
+                       }
+                       
+#if DEBUG_ISRC
+       fprintf(stderr, "ascii: %15.15s!\n", cp);
+#endif
+                       for (ii = 0; ii < 12; ii++) {
+#if 1
+                               if ((ii == 2 || ii == 5 || ii == 7) && cp[ii] != ' ')
+                                       *p++ = '-';
+#endif
+                               *p++ = cp[ii];
+                       }
+                       if (p - p_start >= 16)
+                               *(p_start + 15) = '\0';
+                       else
+                               *p = '\0';
+               }
+
+               if (memcmp(p_start,"00-000-00-00000",15) != 0) {
+                       Set_ISRC(tr, p_start);
+               }
+       }
+}
+
+/* get and display Media Catalog Number ( one per disc )
+ *  and Track International Standard Recording Codes (for each track)
+ */
+void Read_MCN_ISRC(void)
+{
+       if ((global.verbose & SHOW_MCN) != 0) {
+
+               if (Get_MCN()[0] == '\0') {
+                       Get_Set_MCN();
+               }
+
+               if (Get_MCN()[0] != '\0')
+                       fprintf(stderr, "\rMedia catalog number: %13.13s\n", Get_MCN());
+               else
+                       fprintf(stderr, "\rNo media catalog number present.\n");
+       }
+
+
+
+       if ((global.verbose & SHOW_ISRC) != 0) {
+               static struct iterator i;
+
+               InitIterator(&i, 1);
+
+               while (i.hasNextTrack(&i)) {
+                       struct TOC *p = i.getNextTrack(&i);
+                       unsigned ii = GETTRACK(p);
+                       
+                       if (ii == CDROM_LEADOUT) break;
+                       
+                       if (!IS__AUDIO(p))
+                               continue;
+
+                       if (GETISRC(p)[0] == '\0') {
+                               Get_Set_ISRC(ii);
+                       }
+
+                       if (GETISRC(p)[0] != '\0') {
+                               fprintf (stderr, "\rT: %2d ISRC: %15.15s\n", ii, GETISRC(p));
+                               fflush(stderr); 
+                       }
+               } /* for all tracks */
+
+               fputs("\n", stderr);
+       } /* if SHOW_ISRC */
+}
+
+static int playing = 0;
+
+static subq_chnl *ReadSubChannel(unsigned sec);
+
+static subq_chnl *ReadSubChannel(unsigned sec)
+{
+       subq_chnl *sub_ch;
+
+       /*
+        * For modern drives implement a direct method. If the drive supports
+        * reading of subchannel data, do direct reads.
+        */
+       if (ReadSubChannels != NULL) {
+               get_scsi_p()->silent++;
+               sub_ch = ReadSubChannels(get_scsi_p(), sec);
+               get_scsi_p()->silent--;
+               if (sub_ch == NULL /*&& (usal_sense_key(get_scsi_p()) == 5)*/) {
+                       /* command is not implemented */
+                       ReadSubChannels = NULL;
+#if    defined DEBUG_SUB
+fprintf(stderr, "\nCommand not implemented: switching ReadSubChannels off !\n");
+#endif
+                       goto fallback;
+               }
+
+               /* check the adress mode field */
+               if ((sub_ch->control_adr & 0x0f) == 0) {
+                       /* no Q mode information present at all, weird */
+                       sub_ch->control_adr = 0xAA;
+               }
+
+               if ((int)(sub_ch->control_adr & 0x0f) > 0x01) {
+                       /* this sector just has no position information.
+                        * we try the one before and then the one after.
+                        */
+                       if (sec > 1) {
+                               sec -= 1;
+                               sub_ch = ReadSubChannels(get_scsi_p(), sec);
+                               if (sub_ch == NULL) return NULL;
+                               sec += 1;
+                       }
+                       if ((sub_ch->control_adr & 0x0f) != 0x01) {
+                               sec += 2;
+                               sub_ch = ReadSubChannels(get_scsi_p(), sec);
+                               if (sub_ch == NULL) return NULL;
+                               sec -= 2;
+                       }
+               }
+
+               /* check adress mode field for position information */
+               if ((sub_ch->control_adr & 0x0f) == 0x01) {
+                       return sub_ch;
+               }
+               ReadSubChannels = NULL;
+fprintf(stderr, "\nCould not get position information (%02x) for sectors %d, %d, %d: switching ReadSubChannels off !\n", sub_ch->control_adr &0x0f, sec-1, sec, sec+2);
+       }
+
+       /*
+        * We rely on audio sectors here!!!
+        * The only method that worked even with my antique Toshiba 3401,
+        * is playing the sector and then request the subchannel afterwards.
+        */
+fallback:
+       /* We need a conformed audio track here! */
+
+       /* Fallback to ancient method */
+       if (-1 == Play_at(get_scsi_p(), sec, 1)) {
+               return NULL;
+       }
+       playing = 1;
+       sub_ch = ReadSubQ(get_scsi_p(), GET_POSITIONDATA,0);
+       return sub_ch;
+}
+
+static int ReadSubControl(unsigned sec);
+static int ReadSubControl(unsigned sec)
+{
+       subq_chnl *sub_ch = ReadSubChannel(sec);
+       if (sub_ch == NULL) return -1;
+
+       return  sub_ch->control_adr & 0xf0;
+}
+
+static int HaveSCMS(unsigned StartSector);
+static int HaveSCMS(unsigned StartSector)
+{
+       int i;
+       int     cr;
+       int     copy_bits_set = 0;
+
+       for (i = 0; i < 8; i++) {
+               cr = ReadSubControl(StartSector + i);
+               if (cr == -1) continue;
+               (cr & 0x20) ? copy_bits_set++ : 0;
+       }
+       return (copy_bits_set >= 1 && copy_bits_set < 8);
+}
+
+void Check_Toc(void)
+{
+       /* detect layout */
+       
+       /* detect tracks */
+}
+
+static int GetIndexOfSector(unsigned sec, unsigned track)
+{
+       subq_chnl *sub_ch = ReadSubChannel(sec);
+       if (sub_ch == NULL) {
+               if ((long)sec == Get_EndSector(track)) {
+                       fprintf(stderr, "Driver and/or firmware bug detected! Drive cannot play the very last sector (%u)!\n", sec);
+               }
+               return -1;
+       }
+
+       /* can we trust that these values are hex and NOT bcd? */
+       if ((sub_ch->track >= 0x10) && (sub_ch->track - track > 5)) {
+               /* change all values from bcd to hex */
+               sub_ch->track = (sub_ch->track >> 4)*10 + (sub_ch->track & 0x0f);
+               sub_ch->index = (sub_ch->index >> 4)*10 + (sub_ch->index & 0x0f);
+       }
+
+#if 1
+    /* compare tracks */
+    if (sub_ch->index != 0 && track != sub_ch->track) {
+       if (global.verbose) fprintf(stderr, "\ntrack mismatch: %1d, in-track subchannel: %1d (index %1d, sector %1d)\n",
+               track, sub_ch->track, sub_ch->index, sec);
+    }
+#endif
+
+    /* compare control field with the one from the TOC */
+    if ((Get_Flags(track) & 0xf0) != (sub_ch->control_adr & 0xf0)) {
+       int     diffbits = (Get_Flags(track) & 0xf0) ^ (sub_ch->control_adr & 0xf0);
+       if ((diffbits & 0x80) == 0x80) {
+               /* broadcast difference */
+               if (global.verbose) fprintf(stderr, "broadcast type conflict detected -> TOC:%s, subchannel:%s\n",
+               (sub_ch->control_adr & 0x80) == 0 ? "broadcast" : "nonbroadcast"
+               ,(sub_ch->control_adr & 0x80) != 0 ? "broadcast" : "nonbroadcast"
+               );
+       }
+       if ((diffbits & 0x40) == 0x40) {
+               /* track type difference */
+               if (global.verbose) fprintf(stderr, "track type conflict detected -> TOC:%s, subchannel:%s\n",
+               (sub_ch->control_adr & 0x40) == 0 ? "data" : "audio"
+               ,(sub_ch->control_adr & 0x40) != 0 ? "data" : "audio"
+               );
+       }
+       if ((diffbits & 0x20) == 0x20 && !Get_SCMS(track)) {
+               /* copy permission difference is a sign for SCMS
+                * and is treated elsewhere. */
+               if (global.verbose) fprintf(stderr, "difference: TOC:%s, subchannel:%s\ncorrecting TOC...\n",
+               (sub_ch->control_adr & 0x20) == 0 ? "unprotected" : "copyright protected",
+               (sub_ch->control_adr & 0x20) != 0 ? "unprotected" : "copyright protected"
+               );
+               toc_entry(track, 
+                 (Get_Flags(track) & 0xDF) | (sub_ch->control_adr & 0x20),
+                 Get_Tracknumber(track),
+                 Get_ISRC(track),
+                 Get_AudioStartSector(track),
+                 Get_Mins(track),
+                 Get_Secs(track),
+                 Get_Frames(track)
+                 );
+       }
+       if ((diffbits & 0x10) == 0x10) {
+               /* preemphasis difference */
+               if (global.verbose) fprintf(stderr, "difference: TOC:%s, subchannel:%s preemphasis\ncorrecting TOC...\n",
+               (sub_ch->control_adr & 0x10) == 0 ? "with" : "without",
+               (sub_ch->control_adr & 0x10) != 0 ? "with" : "without"
+               );
+               toc_entry(track, 
+                 (Get_Flags(track) & 0xEF) | (sub_ch->control_adr & 0x10),
+                 Get_Tracknumber(track),
+                 Get_ISRC(track),
+                 Get_AudioStartSector(track),
+                 Get_Mins(track),
+                 Get_Secs(track),
+                 Get_Frames(track)
+                 );
+       }
+
+    }
+
+    return sub_ch ? sub_ch->index == 244 ? 1 : sub_ch->index : -1;
+}
+
+static int ScanBackwardFrom(unsigned sec, unsigned limit, int *where, 
+                                                                        unsigned track);
+
+static int ScanBackwardFrom(unsigned sec, unsigned limit, int *where, 
+                                                                        unsigned track)
+{
+       unsigned lastindex = 0;
+       unsigned mysec = sec;
+
+       /* try to find the transition of index n to index 0,
+        * if the track ends with an index 0.
+        */
+       while ((lastindex = GetIndexOfSector(mysec, track)) == 0) {
+               if (mysec < limit+75) {
+                       break;
+               }
+               mysec -= 75;
+       }
+       if (mysec == sec) {
+               /* there is no pre-gap in this track */
+               if (where != NULL) *where = -1;
+       } else {
+               /* we have a pre-gap in this track */
+
+               if (lastindex == 0) {
+                       /* we did not cross the transition yet -> search backward */
+                       do {
+                               if (mysec < limit+1) {
+                                       break;
+                               }
+                               mysec --;
+                       } while ((lastindex = GetIndexOfSector(mysec,track)) == 0);
+                       if (lastindex != 0) {
+                               /* successful */
+                               mysec ++;
+                               /* register mysec as transition */
+                               if (where != NULL) *where = (int) mysec;
+                       } else {
+                               /* could not find transition */
+                               if (!global.quiet)
+                                       fprintf(stderr,
+                                        "Could not find index transition for pre-gap.\n");
+                               if (where != NULL) *where = -1;
+                       }
+               } else {
+                       int myindex = -1;
+                       /* we have crossed the transition -> search forward */
+                       do {
+                               if (mysec >= sec) {
+                                       break;
+                               }
+                               mysec ++;
+                       } while ((myindex = GetIndexOfSector(mysec,track)) != 0);
+                       if (myindex == 0) {
+                               /* successful */
+                               /* register mysec as transition */
+                               if (where != NULL) *where = (int) mysec;
+                       } else {
+                               /* could not find transition */
+                               if (!global.quiet)
+                                       fprintf(stderr,
+                                        "Could not find index transition for pre-gap.\n");
+                               if (where != NULL) *where = -1;
+                       }
+               }
+       }
+       return lastindex;
+}
+
+#ifdef USE_LINEAR_SEARCH
+static int linear_search(int searchInd, unsigned int Start, unsigned int End, 
+                                                                unsigned track);
+
+static int linear_search(int searchInd, unsigned int Start, unsigned int End, 
+                                                                unsigned track)
+{
+      int l = Start;
+      int r = End;
+
+      for (; l <= r; l++ ) {
+          int ind;
+
+         ind = GetIndexOfSector(l, track);
+         if ( searchInd == ind ) {
+             break;
+         }
+      }
+      if ( l <= r ) {
+        /* Index found. */
+       return l;
+      }
+
+      return -1;
+}
+#endif
+
+#ifndef        USE_LINEAR_SEARCH
+#undef DEBUG_BINSEARCH
+static int binary_search(int searchInd, unsigned int Start, unsigned int End, 
+                                                                unsigned track);
+
+static int binary_search(int searchInd, unsigned Start, unsigned End, 
+                                                                unsigned track)
+{
+      int l = Start;
+      int r = End;
+      int x = 0;
+      int ind;
+
+      while ( l <= r ) {
+         x = ( l + r ) / 2;
+         /* try to avoid seeking */
+         ind = GetIndexOfSector(x, track);
+         if ( searchInd == ind ) {
+             break;
+         } else {
+             if ( searchInd < ind ) r = x - 1;
+             else                   l = x + 1;
+         }
+      }
+#ifdef DEBUG_BINSEARCH
+fprintf(stderr, "(%d,%d,%d > ",l,x,r);
+#endif
+      if ( l <= r ) {
+        /* Index found. Now find the first position of this index */
+       /* l=LastPos    x=found         r=NextPos */
+        r = x;
+       while ( l < r-1 ) {
+         x = ( l + r ) / 2;
+         /* try to avoid seeking */
+         ind = GetIndexOfSector(x, track);
+         if ( searchInd == ind ) {
+             r = x;
+         } else {
+             l = x;
+         }
+#ifdef DEBUG_BINSEARCH
+fprintf(stderr, "%d -> ",x);
+#endif
+        }
+#ifdef DEBUG_BINSEARCH
+fprintf(stderr, "%d,%d)\n",l,r);
+#endif
+       if (searchInd == GetIndexOfSector(l, track))
+         return l;
+       else
+         return r;
+      }
+
+      return -1;
+}
+#endif
+
+
+static void register_index_position(int IndexOffset, 
+                                                                                               index_list **last_index_entry);
+
+static void register_index_position(int IndexOffset, 
+                                                                                               index_list **last_index_entry)
+{
+      index_list *indexentry;
+
+      /* register higher index entries */
+      if (*last_index_entry != NULL) {
+        indexentry = (index_list *) malloc( sizeof(index_list) );
+      } else {
+        indexentry = NULL;
+      }
+      if (indexentry != NULL) {
+        indexentry->next = NULL;
+        (*last_index_entry)->next = indexentry;
+        *last_index_entry = indexentry;
+        indexentry->frameoffset = IndexOffset;
+#if defined INFOFILES
+      } else {
+        fprintf( stderr, "No memory for index lists. Index positions\nwill not be written in info file!\n");
+#endif
+      }
+}
+
+static void Set_SCMS(unsigned long p_track);
+
+#undef DEBUG_INDLIST
+/* experimental code */
+/* search for indices (audio mode required) */
+unsigned ScanIndices(unsigned track, unsigned cd_index, int bulk)
+{
+  /* scan for indices. */
+  /* look at last sector of track. */
+  /* when the index is not equal 1 scan by bipartition 
+   * for offsets of all indices */
+
+  unsigned starttrack, endtrack;
+  unsigned startindex, endindex;
+
+  unsigned j;
+  int LastIndex=0;
+  int n_0_transition;
+  unsigned StartSector;
+  unsigned retval = 0;
+
+  index_list *baseindex_pool;
+  index_list *last_index_entry;
+
+  SCSI *usalp = get_scsi_p();
+
+  static struct iterator i;
+  InitIterator(&i, 1);
+  
+  EnableCdda(usalp, 0, 0);
+  EnableCdda(usalp, 1, CD_FRAMESIZE_RAW + 16);
+
+  if (!global.quiet && !(global.verbose & SHOW_INDICES))
+    fprintf(stderr, "seeking index start ...");
+
+  if (bulk != 1) {
+    starttrack = track; endtrack = track;
+  } else {
+    starttrack = 1; endtrack = cdtracks;
+  }
+  baseindex_pool = (index_list *) malloc( sizeof(index_list) * (endtrack - starttrack + 1));
+#ifdef DEBUG_INDLIST
+  fprintf(stderr, "index0-mem-pool %p\n", baseindex_pool);
+#endif
+
+
+  while (i.hasNextTrack(&i)) {
+         struct TOC *p = i.getNextTrack(&i);
+         unsigned ii = GETTRACK(p);
+
+         if ( ii < starttrack || IS__DATA(p) )
+                 continue;     /* skip nonaudio tracks */
+
+         if ( ii > endtrack )
+                 break;
+
+         if ( global.verbose & SHOW_INDICES ) { 
+                 if (global.illleadout_cd && global.reads_illleadout && ii == endtrack) {
+                         fprintf(stderr, "Analysis of track %d skipped due to unknown length\n", ii);
+                 }
+         }
+         if (global.illleadout_cd && global.reads_illleadout 
+             && ii == endtrack) continue;
+
+         StartSector = Get_AudioStartSector(ii);
+         if (HaveSCMS(StartSector)) {
+               Set_SCMS(ii);
+         }
+         if ( global.verbose & SHOW_INDICES ) { 
+                 fprintf( stderr, "\rindex scan: %d...", ii ); 
+                 fflush (stderr);
+         }
+         LastIndex = ScanBackwardFrom(Get_EndSector(ii), StartSector, &n_0_transition, ii);
+         if (LastIndex > 99) continue;
+
+         if (baseindex_pool != NULL) {
+#ifdef DEBUG_INDLIST
+#endif
+                 /* register first index entry for this track */
+                 baseindex_pool[ii - starttrack].next = NULL;
+                 baseindex_pool[ii - starttrack].frameoffset = StartSector;
+                 global.trackindexlist[ii] = &baseindex_pool[ii - starttrack];
+#ifdef DEBUG_INDLIST
+#endif
+         } else {
+                 global.trackindexlist[ii] = NULL;
+         }
+         last_index_entry = global.trackindexlist[ii];
+
+         if (LastIndex < 2) {
+                 register_index_position(n_0_transition, &last_index_entry);
+                 continue;
+         }
+
+         if ((global.verbose & SHOW_INDICES) && LastIndex > 1)
+                 fprintf(stderr, "\rtrack %2d has %d indices, index table (pairs of 'index: frame offset')\n", ii, LastIndex);
+         
+         startindex = 0;
+         endindex = LastIndex;
+
+         for (j = startindex; j <= endindex; j++) {
+                 int IndexOffset;
+                 
+                 /* this track has indices */
+
+#ifdef USE_LINEAR_SEARCH
+                 /* do a linear search */
+                 IndexOffset = linear_search(j, StartSector, Get_EndSector(ii), ii);
+#else
+                 /* do a binary search */
+                 IndexOffset = binary_search(j, StartSector, Get_EndSector(ii), ii);
+#endif
+
+                 if (IndexOffset != -1) {
+                         StartSector = IndexOffset;
+                 }
+
+                 if (j == 1)
+                         last_index_entry->frameoffset = IndexOffset;
+                 else if (j > 1)
+                         register_index_position(IndexOffset, &last_index_entry);
+
+                 if ( IndexOffset == -1 ) {
+                         if (global.verbose & SHOW_INDICES) {
+                                 if (global.gui == 0) {
+                                         fprintf(stderr, "%2u: N/A   ",j);
+                                         if (((j + 1) % 8) == 0) fputs("\n", stderr);
+                                 } else {
+                                         fprintf(stderr, "\rT%02d I%02u N/A\n",ii,j);
+                                 }
+                         }
+                 } else {
+                         if (global.verbose & SHOW_INDICES) {
+                                 if (global.gui == 0) {
+                                         fprintf(stderr, 
+                                               "%2u:%6lu ",
+                                               j,
+                                               IndexOffset-Get_AudioStartSector(ii)
+                                                );
+                                         if (((j + 1) % 8) == 0) fputs("\n", stderr);
+                                 } else {
+                                         fprintf(stderr,
+                                               "\rT%02d I%02u %06lu\n",
+                                               ii,
+                                               j,
+                                               IndexOffset-Get_AudioStartSector(ii)
+                                                );
+                                 }
+                         }
+
+                         if (track == ii && cd_index == j) {
+                                 retval = IndexOffset-Get_AudioStartSector(ii);
+                         }
+                 } /* if IndexOffset */
+         } /* for index */
+         register_index_position(n_0_transition, &last_index_entry);
+
+         /* sanity check. clear all consecutive nonindex entries (frameoffset -1) from the end. */
+         {
+               index_list *ip = global.trackindexlist[ii];
+               index_list *iq = NULL;
+               index_list *lastgood = iq;
+
+               while (ip != NULL)
+               {
+                       if (ip->frameoffset == -1)
+                       {
+                               /* no index available */
+                               if (lastgood == NULL)
+                               {
+                                       /* if this is the first one in a sequence, store predecessor */
+                                       lastgood = iq;
+                               }
+                       } else {
+                               /* this is a valid index, reset marker */
+                               lastgood = NULL;
+                       }
+
+                       iq = ip;
+                       ip = ip->next;
+               }
+               /* terminate chain at the last well defined entry. */
+               if (lastgood != NULL)
+                       lastgood->next = NULL;
+         }
+
+         if (global.gui == 0 && (global.verbose & SHOW_INDICES)
+             && ii != endtrack)
+                 fputs("\n", stderr);
+  } /* for tracks */
+  if (global.gui == 0 && (global.verbose & SHOW_INDICES))
+         fputs("\n", stderr);
+  if (playing != 0) StopPlay(get_scsi_p());
+
+  EnableCdda(usalp, 0, 0);
+  EnableCdda(usalp, 1, CD_FRAMESIZE_RAW);
+
+  return retval;
+}
+
+static unsigned char MCN[14];
+
+static void Set_MCN(unsigned char *MCN_arg)
+{
+       memcpy(MCN, MCN_arg, 14);
+       MCN[13] = '\0';
+}
+
+unsigned char *Get_MCN(void)
+{
+       return MCN;
+}
+
+
+static TOC g_toc [MAXTRK+1]; /* hidden track + 100 regular tracks */
+
+/*#define IS_AUDIO(i) (!(g_toc[i].bFlags & 0x40))*/
+
+int 
+TOC_entries(unsigned tracks, unsigned char *a, unsigned char *b, int binvalid)
+{
+       int i;
+       for (i = 1; i <= (int)tracks; i++) {
+               unsigned char *p;
+               unsigned long dwStartSector;
+
+               if (binvalid) {
+                       p = a + 8*(i-1);
+
+                       g_toc[i].bFlags = p[1];
+                       g_toc[i].bTrack = p[2];
+                       g_toc[i].ISRC[0] = 0;
+                       dwStartSector = a_to_u_4_byte(p+4);
+                       g_toc[i].dwStartSector = dwStartSector;
+                       lba_2_msf((long)dwStartSector,
+                                 &g_toc[i].mins,
+                                 &g_toc[i].secs,
+                                 &g_toc[i].frms);
+               } else {
+                       p = b + 8*(i-1);
+                       g_toc[i].bFlags = p[1];
+                       g_toc[i].bTrack = p[2];
+                       g_toc[i].ISRC[0] = 0;
+                       if ((int)((p[5]*60 + p[6])*75 + p[7]) >= 150) {
+                               g_toc[i].dwStartSector = (p[5]*60 + p[6])*75 + p[7] -150;
+                       } else {
+                               g_toc[i].dwStartSector = 0;
+                       }
+                       g_toc[i].mins = p[5];
+                       g_toc[i].secs = p[6];
+                       g_toc[i].frms = p[7];
+               }
+       }
+       return 0;
+}
+
+void toc_entry(unsigned nr, unsigned flag, unsigned tr, unsigned char *ISRC, 
+               unsigned long lba, int m, int s, int f)
+{
+       if (nr > MAXTRK) return;
+
+       g_toc[nr].bFlags = flag;
+       g_toc[nr].bTrack = tr;
+       if (ISRC) {
+               strncpy((char *)g_toc[nr].ISRC, (char *)ISRC,
+                       sizeof(g_toc[nr].ISRC) -1);
+               g_toc[nr].ISRC[sizeof(g_toc[nr].ISRC) -1] = '\0';
+       }
+       g_toc[nr].dwStartSector = lba;
+       g_toc[nr].mins = m;
+       g_toc[nr].secs = s;
+       g_toc[nr].frms = f;
+}
+
+int patch_real_end(unsigned long sector)
+{
+       g_toc[cdtracks+1].dwStartSector = sector;
+       return 0;
+}
+
+static int patch_cd_extra(unsigned track, unsigned long sector)
+{
+       if (track <= cdtracks)
+               g_toc[track].dwStartSector = sector;
+       return 0;
+}
+
+static int restrict_tracks_illleadout(void)
+{
+       struct TOC *o = &g_toc[cdtracks+1];
+       int i;
+       for (i = cdtracks; i >= 0; i--) {
+               struct TOC *p = &g_toc[i];
+               if (GETSTART(o) > GETSTART(p)) break;
+       }
+       patch_cd_extra(i+1, GETSTART(o));
+       cdtracks = i;
+
+       return 0;
+}
+
+static void Set_ISRC(int track, const unsigned char *ISRC_arg)
+{
+       if (track <= (int)cdtracks) {
+               memcpy(Get_ISRC(track), ISRC_arg, 16);
+       }
+}
+
+
+unsigned char *Get_ISRC(unsigned long p_track)
+{
+       if (p_track <= cdtracks)
+               return g_toc[p_track].ISRC;
+       return NULL;
+}
+
+static void patch_to_audio(unsigned long p_track)
+{
+       if (p_track <= cdtracks)
+               g_toc[p_track].bFlags &= ~0x40;
+}
+
+int Get_Flags(unsigned long p_track)
+{
+       if (p_track <= cdtracks)
+               return g_toc[p_track].bFlags;
+       return -1;
+}
+
+int Get_Mins(unsigned long p_track)
+{
+       if (p_track <= cdtracks)
+               return g_toc[p_track].mins;
+       return -1;
+}
+
+int Get_Secs(unsigned long p_track)
+{
+       if (p_track <= cdtracks)
+               return g_toc[p_track].secs;
+       return -1;
+}
+
+int Get_Frames(unsigned long p_track)
+{
+       if (p_track <= cdtracks)
+               return g_toc[p_track].frms;
+       return -1;
+}
+
+int Get_Preemphasis(unsigned long p_track)
+{
+       if (p_track <= cdtracks)
+               return g_toc[p_track].bFlags & 0x10;
+       return -1;
+}
+
+static void Set_SCMS(unsigned long p_track)
+{
+       g_toc[p_track].SCMS = 1;
+}
+
+int Get_SCMS(unsigned long p_track)
+{
+       if (p_track <= cdtracks)
+               return g_toc[p_track].SCMS;
+       return -1;
+}
+
+int Get_Copyright(unsigned long p_track)
+{
+       if (p_track <= cdtracks) {
+               if (g_toc[p_track].SCMS) return 1;
+               return ((int)g_toc[p_track].bFlags & 0x20) >> 4;
+       }
+       return -1;
+}
+
+int Get_Datatrack(unsigned long p_track)
+{
+       if (p_track <= cdtracks)
+               return g_toc[p_track].bFlags & 0x40;
+       return -1;
+}
+
+int Get_Channels(unsigned long p_track)
+{
+       if (p_track <= cdtracks)
+               return g_toc[p_track].bFlags & 0x80;
+       return -1;
+}
+
+int Get_Tracknumber(unsigned long p_track)
+{
+       if (p_track <= cdtracks)
+               return g_toc[p_track].bTrack;
+       return -1;
+}
+
+static int useHiddenTrack(void)
+{
+       return 0;
+}
+
+
+
+static void it_reset(struct iterator *this);
+
+static void it_reset(struct iterator *this)
+{
+       this->index = this->startindex;
+}
+
+
+static int it_hasNextTrack(struct iterator *this);
+static struct TOC *it_getNextTrack(struct iterator *this);
+
+static int it_hasNextTrack(struct iterator *this)
+{
+       return this->index <= (int)cdtracks+1;
+}
+
+
+
+static struct TOC *it_getNextTrack(struct iterator *this)
+{
+       /* if ( (*this->hasNextTrack)(this) == 0 ) return NULL; */
+       if ( this->index > (int)cdtracks+1 ) return NULL;
+
+       return &g_toc[ this->index++ ];
+}
+
+
+static void InitIterator(struct iterator *iter, unsigned long p_track)
+{
+       if (iter == NULL) return;
+
+       iter->index = iter->startindex = useHiddenTrack() ? 0 : p_track;
+       iter->reset = it_reset;
+       iter->getNextTrack = it_getNextTrack;
+       iter->hasNextTrack = it_hasNextTrack;
+}
+
+#if    0
+static struct iterator *NewIterator(void);
+
+static struct iterator *NewIterator ()
+{
+       struct iterator *retval;
+
+       retval = malloc (sizeof(struct iterator));
+       if (retval != NULL) {
+               InitIterator(retval, 1);
+       }
+       return retval;
+}
+#endif
+
+long Get_AudioStartSector(unsigned long p_track)
+{
+#if    1
+       if (p_track == CDROM_LEADOUT)
+               p_track = cdtracks + 1;
+
+       if (p_track <= cdtracks +1
+               && IS__AUDIO(&g_toc[p_track]))
+               return GETSTART(&g_toc[p_track]);
+#else
+       static struct iterator i;
+       if (i.reset == NULL) InitIterator(&i, p_track);
+       else i.reset(&i);
+
+       if (p_track == cdtracks + 1) p_track = CDROM_LEADOUT;
+
+       while (i.hasNextTrack(&i)) {
+               TOC *p = i.getNextTrack(&i);
+
+               if (GETTRACK(p) == p_track) {
+                       if (IS__DATA(p)) {
+                               return -1;
+                       }
+                       return GETSTART(p);
+               }
+       }
+#endif
+       return -1;
+}
+
+
+long Get_StartSector(unsigned long p_track)
+{
+#if    1
+       if (p_track == CDROM_LEADOUT)
+               p_track = cdtracks + 1;
+
+       if (p_track <= cdtracks +1)
+               return GETSTART(&g_toc[p_track]);
+#else
+       static struct iterator i;
+       if (i.reset == NULL) InitIterator(&i, p_track);
+       else i.reset(&i);
+
+       if (p_track == cdtracks + 1) p_track = CDROM_LEADOUT;
+
+       while (i.hasNextTrack(&i)) {
+               TOC *p = i.getNextTrack(&i);
+
+               if (GETTRACK(p) == p_track) {
+                       return GETSTART(p);
+               }
+       }
+#endif
+       return -1;
+}
+
+
+long Get_EndSector(unsigned long p_track)
+{
+#if    1
+       if (p_track <= cdtracks)
+               return GETSTART(&g_toc[p_track+1])-1;
+#else
+       static struct iterator i;
+       if (i.reset == NULL) InitIterator(&i, p_track);
+       else i.reset(&i);
+
+       if (p_track == cdtracks + 1) p_track = CDROM_LEADOUT;
+
+       while (i.hasNextTrack(&i)) {
+               TOC *p = i.getNextTrack(&i);
+               if (GETTRACK(p) == p_track) {
+                       p = i.getNextTrack(&i);
+                       if (p == NULL) {
+                               return -1;
+                       }
+                       return GETSTART(p)-1;
+               }
+       }
+#endif
+       return -1;
+}
+
+long FirstTrack(void)
+{
+       static struct iterator i;
+       if (i.reset == NULL) InitIterator(&i, 1);
+       else i.reset(&i);
+
+       if (i.hasNextTrack(&i)) {
+               return GETTRACK(i.getNextTrack(&i));
+       }
+       return -1;
+}
+
+long FirstAudioTrack(void)
+{
+       static struct iterator i;
+       if (i.reset == NULL) InitIterator(&i, 1);
+       else i.reset(&i);
+
+       while (i.hasNextTrack(&i)) {
+               TOC *p = i.getNextTrack(&i);
+               unsigned ii = GETTRACK(p);
+
+               if (ii == CDROM_LEADOUT) break;
+               if (IS__AUDIO(p)) {
+                       return ii;
+               }
+       }
+       return -1;
+}
+
+long FirstDataTrack(void)
+{
+       static struct iterator i;
+       if (i.reset == NULL) InitIterator(&i, 1);
+       else i.reset(&i);
+
+       while (i.hasNextTrack(&i)) {
+               TOC *p = i.getNextTrack(&i);
+               if (IS__DATA(p)) {
+                       return GETTRACK(p);
+               }
+       }
+       return -1;
+}
+
+long LastTrack(void)
+{
+       return g_toc[cdtracks].bTrack;
+}
+
+long LastAudioTrack(void)
+{
+       long j = -1;
+       static struct iterator i;
+       if (i.reset == NULL) InitIterator(&i, 1);
+       else i.reset(&i);
+
+       while (i.hasNextTrack(&i)) {
+               TOC *p = i.getNextTrack(&i);
+               if (IS__AUDIO(p) && (GETTRACK(p) != CDROM_LEADOUT)) {
+                       j = GETTRACK(p);
+               }
+       }
+       return j;
+}
+
+long Get_LastSectorOnCd(unsigned long p_track)
+{
+       long LastSec = 0;
+       static struct iterator i;
+
+       if (global.illleadout_cd && global.reads_illleadout)
+               return 150+(99*60+59)*75+74;
+
+       if (i.reset == NULL) InitIterator(&i, p_track);
+       else i.reset(&i);
+
+       if (p_track == cdtracks + 1) p_track = CDROM_LEADOUT;
+
+       while (i.hasNextTrack(&i)) {
+               TOC *p = i.getNextTrack(&i);
+
+               if (GETTRACK(p) < p_track)
+                       continue;
+
+               LastSec = GETSTART(p);
+
+               if (IS__DATA(p)) break;
+       }
+       return LastSec;
+}
+
+int Get_Track(unsigned long sector)
+{
+       static struct iterator i;
+       if (i.reset == NULL) InitIterator(&i, 1);
+       else i.reset(&i);
+
+       if (i.hasNextTrack(&i)) {
+               TOC *o = i.getNextTrack(&i);
+               while (i.hasNextTrack(&i)) {
+                       TOC *p = i.getNextTrack(&i);
+                       if ((GETSTART(o) <= sector) && (GETSTART(p) > sector)) {
+                               if (IS__DATA(o)) {
+                                       return -1;
+                               } else {
+                                       return GETTRACK(o);
+                               }
+                       }
+                       o = p;
+               }
+       }
+       return -1;
+}
+
+int CheckTrackrange(unsigned long from, unsigned long upto)
+{
+       static struct iterator i;
+       if (i.reset == NULL) InitIterator(&i, from);
+       else i.reset(&i);
+
+       while (i.hasNextTrack(&i)) {
+               TOC *p = i.getNextTrack(&i);
+
+               if (GETTRACK(p) < from)
+                       continue;
+
+               if (GETTRACK(p) == upto)
+                       return 1;
+
+               /* data tracks terminate the search */
+               if (IS__DATA(p))
+                       return 0;
+       }
+       /* track not found */
+       return 0;
+}
+
+#ifdef USE_PARANOIA
+long cdda_disc_firstsector(void *d);
+
+long cdda_disc_firstsector(void *d)
+{
+       return Get_StartSector(FirstAudioTrack());
+}
+
+int cdda_tracks(void *d);
+
+int cdda_tracks(void *d)
+{
+       return LastAudioTrack() - FirstAudioTrack() +1;
+}
+
+int cdda_track_audiop(void *d, int track);
+
+int cdda_track_audiop(void *d, int track)
+{
+       return Get_Datatrack(track) == 0;
+}
+
+long cdda_track_firstsector(void *d, int track);
+
+long cdda_track_firstsector(void *d, int track)
+{
+       return Get_AudioStartSector(track);
+}
+
+long cdda_track_lastsector(void *d, int track);
+
+long cdda_track_lastsector(void *d, int track)
+{
+       return Get_EndSector(track);
+}
+
+long cdda_disc_lastsector(void *d);
+
+long cdda_disc_lastsector(void *d)
+{
+       return Get_LastSectorOnCd(cdtracks) - 1;
+}
+
+int cdda_sector_gettrack(void *d,long sector);
+
+int cdda_sector_gettrack(void *d, long sector)
+{
+       return Get_Track(sector);
+}
+
+#endif
diff --git a/icedax/toc.h b/icedax/toc.h
new file mode 100644 (file)
index 0000000..84da13a
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)toc.h   1.9 06/02/19 Copyright 1998,1999 Heiko Eissfeldt, Copyright 2006 J. Schilling */
+
+#define        MAXTRK  100     /* maximum of audio tracks (without a hidden track) */
+
+extern unsigned cdtracks;
+extern int     have_multisession;
+extern int     have_CD_extra;
+extern int     have_CD_text;
+extern int     have_CDDB;
+
+#if    !defined(HAVE_NETDB_H)
+#undef USE_REMOTE
+#else
+#define        USE_REMOTE      1
+extern int             request_titles(void);
+#endif
+
+extern int             ReadToc(void);
+extern void            Check_Toc(void);
+extern int             TOC_entries(unsigned tracks, 
+                                                                               unsigned char *a, unsigned char *b,
+                                                                               int bvalid);
+extern void            toc_entry(unsigned nr, unsigned flag, unsigned tr,
+                                                                        unsigned char *ISRC,
+                                                                        unsigned long lba, int m, int s, int f);
+extern int             patch_real_end(unsigned long sector);
+extern int             no_disguised_audiotracks(void);
+
+extern int             Get_Track(unsigned long sector);
+extern long            FirstTrack(void);
+extern long            LastTrack(void);
+extern long            FirstAudioTrack(void);
+extern long            FirstDataTrack(void);
+extern long            LastAudioTrack(void);
+extern long            Get_EndSector(unsigned long p_track);
+extern long            Get_StartSector(unsigned long p_track);
+extern long            Get_AudioStartSector(unsigned long p_track);
+extern long            Get_LastSectorOnCd(unsigned long p_track);
+extern int             CheckTrackrange(unsigned long from, unsigned long upto);
+
+extern int             Get_Preemphasis(unsigned long p_track);
+extern int             Get_Channels(unsigned long p_track);
+extern int             Get_Copyright(unsigned long p_track);
+extern int             Get_Datatrack(unsigned long p_track);
+extern int             Get_Tracknumber(unsigned long p_track);
+extern unsigned char *Get_MCN(void);
+extern unsigned char *Get_ISRC(unsigned long p_track);
+
+extern unsigned        find_an_off_sector(unsigned lSector, unsigned SectorBurstVal);
+extern void            DisplayToc(void);
+extern unsigned        FixupTOC(unsigned no_tracks);
+extern void            calc_cddb_id(void);
+extern void            calc_cdindex_id(void);
+extern void            Read_MCN_ISRC(void);
+extern unsigned        ScanIndices(unsigned trackval, unsigned indexval, int bulk);
+extern int             handle_cdtext(void);
+extern int             lba_2_msf(long lba, int *m, int *s, int *f);
diff --git a/icedax/version.sed b/icedax/version.sed
new file mode 100644 (file)
index 0000000..d0752df
--- /dev/null
@@ -0,0 +1,4 @@
+/cdr_version\[\] = /{
+  s/.*"\(.*\)";/\1/
+  p
+}
diff --git a/icedax/wav.c b/icedax/wav.c
new file mode 100644 (file)
index 0000000..b30ed9b
--- /dev/null
@@ -0,0 +1,157 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)wav.c   1.4 01/10/27 Copyright 1998,1999 Heiko Eissfeldt */
+/***
+ * CopyPolicy: GNU Public License 2 applies
+ * Copyright (C) by Heiko Eissfeldt
+ *
+ *
+ */
+#include "config.h"
+#include <stdio.h>
+#include <unixstd.h>
+#include "byteorder.h"
+#include "sndfile.h"
+
+/***
+ * ---------------------------------------------------------------------
+ *  definitions for RIFF-output (from windows MMSYSTEM)
+ * ---------------------------------------------------------------------
+ */
+
+typedef unsigned int FOURCC;   /* a four character code */
+
+typedef struct CHUNKHDR {
+  FOURCC ckid;         /* chunk ID */
+  unsigned int dwSize;         /* chunk size */
+} CHUNKHDR;
+
+/* flags for 'wFormatTag' field of WAVEFORMAT */
+#define WAVE_FORMAT_PCM 1
+
+/* specific waveform format structure for PCM data */
+typedef struct pcmwaveformat_tag {
+  unsigned short wFormatTag;   /* format type */
+  unsigned short nChannels;    /* number of channels (i.e. mono, stereo, etc.) */
+  unsigned int nSamplesPerSec; /* sample rate */
+  unsigned int nAvgBytesPerSec;/* for buffer size estimate */
+  unsigned short nBlockAlign;  /* block size of data */
+  unsigned short wBitsPerSample;
+} PCMWAVEFORMAT;
+typedef PCMWAVEFORMAT *PPCMWAVEFORMAT;
+
+
+/* MMIO macros */
+#define mmioFOURCC(ch0, ch1, ch2, ch3) \
+  ((unsigned int)(unsigned char)(ch0) | ((unsigned int)(unsigned char)(ch1) << 8) | \
+  ((unsigned int)(unsigned char)(ch2) << 16) | ((unsigned int)(unsigned char)(ch3) << 24))
+
+#define FOURCC_RIFF    mmioFOURCC ('R', 'I', 'F', 'F')
+#define FOURCC_LIST    mmioFOURCC ('L', 'I', 'S', 'T')
+#define FOURCC_WAVE    mmioFOURCC ('W', 'A', 'V', 'E')
+#define FOURCC_FMT     mmioFOURCC ('f', 'm', 't', ' ')
+#define FOURCC_DATA    mmioFOURCC ('d', 'a', 't', 'a')
+
+
+/* simplified Header for standard WAV files */
+typedef struct WAVEHDR {
+  CHUNKHDR chkRiff;
+  FOURCC fccWave;
+  CHUNKHDR chkFmt;
+  unsigned short wFormatTag;   /* format type */
+  unsigned short nChannels;    /* number of channels (i.e. mono, stereo, etc.) */
+  unsigned int nSamplesPerSec; /* sample rate */
+  unsigned int nAvgBytesPerSec;/* for buffer estimation */
+  unsigned short nBlockAlign;  /* block size of data */
+  unsigned short wBitsPerSample;
+  CHUNKHDR chkData;
+} WAVEHDR;
+
+#define IS_STD_WAV_HEADER(waveHdr) ( \
+  waveHdr.chkRiff.ckid == FOURCC_RIFF && \
+  waveHdr.fccWave == FOURCC_WAVE && \
+  waveHdr.chkFmt.ckid == FOURCC_FMT && \
+  waveHdr.chkData.ckid == FOURCC_DATA && \
+  waveHdr.wFormatTag == WAVE_FORMAT_PCM)
+
+static WAVEHDR waveHdr;
+
+static int _InitSound(int audio, long channels, unsigned long rate, 
+                                                        long nBitsPerSample, unsigned long expected_bytes);
+
+static int _InitSound(int audio, long channels, unsigned long rate, 
+                      long nBitsPerSample, unsigned long expected_bytes)
+{
+  unsigned long nBlockAlign = channels * ((nBitsPerSample + 7) / 8);
+  unsigned long nAvgBytesPerSec = nBlockAlign * rate;
+  unsigned long temp = expected_bytes + sizeof(WAVEHDR) - sizeof(CHUNKHDR);
+
+  waveHdr.chkRiff.ckid    = cpu_to_le32(FOURCC_RIFF);
+  waveHdr.fccWave         = cpu_to_le32(FOURCC_WAVE);
+  waveHdr.chkFmt.ckid     = cpu_to_le32(FOURCC_FMT);
+  waveHdr.chkFmt.dwSize   = cpu_to_le32(sizeof (PCMWAVEFORMAT));
+  waveHdr.wFormatTag      = cpu_to_le16(WAVE_FORMAT_PCM);
+  waveHdr.nChannels       = cpu_to_le16(channels);
+  waveHdr.nSamplesPerSec  = cpu_to_le32(rate);
+  waveHdr.nBlockAlign     = cpu_to_le16(nBlockAlign);
+  waveHdr.nAvgBytesPerSec = cpu_to_le32(nAvgBytesPerSec);
+  waveHdr.wBitsPerSample  = cpu_to_le16(nBitsPerSample);
+  waveHdr.chkData.ckid    = cpu_to_le32(FOURCC_DATA);
+  waveHdr.chkRiff.dwSize  = cpu_to_le32(temp);
+  waveHdr.chkData.dwSize  = cpu_to_le32(expected_bytes);
+
+  return write (audio, &waveHdr, sizeof (waveHdr));
+}
+
+static int _ExitSound(int audio, unsigned long nBytesDone);
+
+static int _ExitSound(int audio, unsigned long nBytesDone)
+{
+  unsigned long temp = nBytesDone + sizeof(WAVEHDR) - sizeof(CHUNKHDR);
+
+  waveHdr.chkRiff.dwSize = cpu_to_le32(temp);
+  waveHdr.chkData.dwSize = cpu_to_le32(nBytesDone);
+
+  /* goto beginning */
+  if (lseek(audio, 0L, SEEK_SET) == -1) {
+    return 0;
+  }
+  return write (audio, &waveHdr, sizeof (waveHdr));
+}
+
+static unsigned long _GetHdrSize(void);
+
+static unsigned long _GetHdrSize(void)
+{
+  return sizeof( waveHdr );
+}
+
+static unsigned long InSizeToOutSize(unsigned long BytesToDo);
+
+static unsigned long InSizeToOutSize(unsigned long BytesToDo)
+{
+       return BytesToDo;
+}
+
+struct soundfile wavsound =
+{
+       _InitSound,             /* init header method */
+       _ExitSound,             /* exit header method */
+       _GetHdrSize,            /* report header size method */
+       /* get sound samples out */
+       (int (*)(int audio, unsigned char *buf, unsigned long BytesToDo)) write,
+       InSizeToOutSize,        /* compressed? output file size */
+       0                       /* needs big endian samples */
+};
+
+
diff --git a/icedax/wav.h b/icedax/wav.h
new file mode 100644 (file)
index 0000000..e1a90d1
--- /dev/null
@@ -0,0 +1,14 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)wav.h   1.2 99/12/19 Copyright 1998,1999 Heiko Eissfeldt */
+extern struct soundfile wavsound;
diff --git a/include/AddNetworkBits.cmake b/include/AddNetworkBits.cmake
new file mode 100644 (file)
index 0000000..56643b3
--- /dev/null
@@ -0,0 +1,60 @@
+
+# various checks add additional of extra libs, most likely for SunOS
+# using own checks and not CHECK_SYMBOLE because of spurios problems seen with
+# it
+
+INCLUDE(CheckCSourceCompiles)
+
+SET(TESTSRC "
+#include <sys/types.h>
+#include <sys/socket.h>
+
+int main(int argc, char **argv) {
+return socket(AF_INET, SOCK_STREAM, 0);
+}
+")
+
+SET(CMAKE_REQUIRED_LIBRARIES )
+CHECK_C_SOURCE_COMPILES("${TESTSRC}" USE_LIBC_SOCKET)
+
+IF(NOT USE_LIBC_SOCKET)
+
+   LIST(APPEND EXTRA_LIBS socket)
+
+   SET(CMAKE_REQUIRED_LIBRARIES socket)
+   CHECK_C_SOURCE_COMPILES("${TESTSRC}" USE_LIBSOCKET)
+   IF(NOT USE_LIBSOCKET)
+      MESSAGE(FATAL_ERROR "No working socket(...) found in libc or libsocket")
+   ENDIF(NOT USE_LIBSOCKET)
+
+ENDIF(NOT USE_LIBC_SOCKET)
+
+SET(TESTSRC "
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+
+int main(int argc, char **argv) {
+struct hostent *h = gethostbyname(argv[0]);
+return sizeof(h);
+}
+")
+
+CHECK_C_SOURCE_COMPILES("${TESTSRC}" USE_LIBC_NLS)
+IF(NOT USE_LIBC_NLS)
+   SET(CMAKE_REQUIRED_LIBRARIES nls)
+   CHECK_C_SOURCE_COMPILES("${TESTSRC}" USE_LIBNLS)
+   IF(USE_LIBNLS)
+      LIST(APPEND EXTRA_LIBS nls)
+   ELSE(USE_LIBNLS)
+      SET(CMAKE_REQUIRED_LIBRARIES xnet)
+      CHECK_C_SOURCE_COMPILES("${TESTSRC}" USE_LIBXNET)
+      IF(NOT USE_LIBXNET)
+         MESSAGE(FATAL_ERROR "Error: Could not find a system library providing gethostbyname.")
+      ELSE(NOT USE_LIBXNET)
+         LIST(APPEND EXTRA_LIBS xnet)
+      ENDIF(NOT USE_LIBXNET)
+   ENDIF(USE_LIBNLS)
+ENDIF(NOT USE_LIBC_NLS)
+SET(CMAKE_REQUIRED_LIBRARIES )
+
diff --git a/include/AddScgBits.cmake b/include/AddScgBits.cmake
new file mode 100644 (file)
index 0000000..6aaff73
--- /dev/null
@@ -0,0 +1,65 @@
+
+IF(NOT GUARD_SCGCONFIG)
+   SET(GUARD_SCGCONFIG 1)
+
+
+LIST(APPEND EXTRA_LIBS "usal")
+
+INCLUDE(CheckIncludeFiles)
+CHECK_INCLUDE_FILES("stdio.h;camlib.h" HAVE_CAMLIB_H)
+
+IF(HAVE_CAMLIB_H)
+
+   # quick an dirty, should better become a variable used by libusal only,
+   # analogous to SCG_SELF_LIBS
+   ADD_DEFINITIONS(-DHAVE_CAMLIB_H)
+
+   LIST(APPEND EXTRA_LIBS "cam")
+   LIST(APPEND SCG_SELF_LIBS "cam")
+
+ENDIF(HAVE_CAMLIB_H)
+
+FIND_LIBRARY(HAVE_LIBVOLMGT "volmgt")
+IF(HAVE_LIBVOLMGT)
+   LIST(APPEND EXTRA_LIBS "volmgt")
+   LIST(APPEND SCG_SELF_LIBS "volmgt")
+ENDIF(HAVE_LIBVOLMGT)
+
+   INCLUDE(CheckCSourceCompiles)
+
+   SET(TESTSRC "
+#include <sys/types.h>
+#include <sys/socket.h>
+
+int main(int argc, char **argv) {
+   return socket(AF_INET, SOCK_STREAM, 0);
+}
+")
+
+SET(CMAKE_REQUIRED_LIBRARIES )
+   CHECK_C_SOURCE_COMPILES("${TESTSRC}" LIBC_SOCKET)
+
+IF(NOT LIBC_SOCKET)
+   LIST(APPEND EXTRA_LIBS -lsocket)
+   #MESSAGE("Using libsocket for socket functions")
+ENDIF(NOT LIBC_SOCKET)
+
+
+   SET(TESTSRC "
+#include <sched.h>
+struct sched_param scp;
+         int main(int argc, char **argv) {
+         return sched_setscheduler(0, SCHED_RR, &scp);
+         }
+")
+
+
+SET(CMAKE_REQUIRED_LIBRARIES )
+   CHECK_C_SOURCE_COMPILES("${TESTSRC}" LIBC_SCHED)
+
+IF(NOT LIBC_SCHED)
+   LIST(APPEND EXTRA_LIBS -lrt)
+   #MESSAGE("Using librt for realtime functions")
+ENDIF(NOT LIBC_SCHED)
+
+ENDIF(NOT GUARD_SCGCONFIG)
diff --git a/include/AddSchilyBits.cmake b/include/AddSchilyBits.cmake
new file mode 100644 (file)
index 0000000..475e5cd
--- /dev/null
@@ -0,0 +1,13 @@
+IF(NOT CHECKED_rols)
+   SET(CHECKED_rols 1)
+
+   LIST(APPEND EXTRA_LIBS "rols")
+
+# abuse this include file to make sure the target is set
+
+   IF(NOT MANSUBDIR)
+      SET(MANSUBDIR "share/man")
+   ENDIF(NOT MANSUBDIR)
+
+ENDIF(NOT CHECKED_rols)
+
diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt
new file mode 100644 (file)
index 0000000..99a69fd
--- /dev/null
@@ -0,0 +1,170 @@
+PROJECT (INCLUDES C)
+
+FILE(READ "${CMAKE_SOURCE_DIR}/VERSION" CDRKIT_VERSION)
+STRING(REPLACE "\n" "" CDRKIT_VERSION "${CDRKIT_VERSION}")
+MESSAGE("Configuring Cdrkit, version ${CDRKIT_VERSION}")
+
+# auto-generated header with sizeof magic
+INCLUDE(CheckTypeSize)
+CHECK_TYPE_SIZE(short SIZE_SHORT)
+MATH(EXPR SHORTLESS ${SIZE_SHORT}-1)
+CHECK_TYPE_SIZE(int SIZE_INT)
+MATH(EXPR INTLESS ${SIZE_INT}-1)
+CHECK_TYPE_SIZE(long SIZE_LONG)
+MATH(EXPR LONGLESS ${SIZE_LONG}-1)
+CHECK_TYPE_SIZE("long long" SIZE_LLONG)
+MATH(EXPR LLONGLESS ${SIZE_LLONG}-1)
+CHECK_TYPE_SIZE(float SIZE_FLOAT)
+MATH(EXPR FLOATLESS ${SIZE_FLOAT}-1)
+CHECK_TYPE_SIZE(double SIZE_DOUBLE)
+MATH(EXPR DOUBLELESS ${SIZE_DOUBLE}-1)
+CHECK_TYPE_SIZE("char*" SIZE_PTR)
+MATH(EXPR PTRLESS ${SIZE_PTR}-1)
+CONFIGURE_FILE( align.h.in align.h)
+#SET_SOURCE_FILES_PROPERTIES(align.h PROPERTIES GENERATED 1)
+
+TRY_COMPILE(VA_LIST_IS_ARRAY ${CMAKE_BINARY_DIR}  ${CMAKE_CURRENT_SOURCE_DIR}/test_VA_LIST_IS_ARRAY.c)
+# invert the result, has the condition IFF compiler fails. There must be a simple way to say a=!b... but how?
+IF(VA_LIST_IS_ARRAY) 
+   SET(VA_LIST_IS_ARRAY FALSE)
+else(VA_LIST_IS_ARRAY) 
+   SET(VA_LIST_IS_ARRAY TRUE)
+endif(VA_LIST_IS_ARRAY)
+
+
+INCLUDE(TestBigEndian)
+TEST_BIG_ENDIAN(WORDS_BIGENDIAN)
+
+TRY_RUN(BITFIELDS_HTOL TEST_DUMMY ${CMAKE_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/test_BITFIELDS_HTOL.c)
+
+INCLUDE(CheckIncludeFiles)
+
+#SET(CMAKE_REQUIRED_INCLUDES "/usr/include;/usr/local/include")
+CHECK_INCLUDE_FILES("stdarg.h" HAVE_STDARG_H)
+CHECK_INCLUDE_FILES("stdlib.h" HAVE_STDLIB_H)
+CHECK_INCLUDE_FILES("string.h" HAVE_STRING_H)
+CHECK_INCLUDE_FILES("strings.h" HAVE_STRINGS_H)
+CHECK_INCLUDE_FILES("unistd.h" HAVE_UNISTD_H)
+CHECK_INCLUDE_FILES("getopt.h" HAVE_GETOPT_H)
+CHECK_INCLUDE_FILES("limits.h" HAVE_LIMITS_H)
+CHECK_INCLUDE_FILES("fcntl.h" HAVE_FCNTL_H)
+CHECK_INCLUDE_FILES("sys/file.h" HAVE_SYS_FILE_H)
+CHECK_INCLUDE_FILES("inttypes.h" HAVE_INTTYPES_H)
+CHECK_INCLUDE_FILES("dirent.h" HAVE_DIRENT_H)
+CHECK_INCLUDE_FILES("alloca.h" HAVE_ALLOCA_H)
+CHECK_INCLUDE_FILES("termios.h" HAVE_TERMIOS_H)
+CHECK_INCLUDE_FILES("termio.h" HAVE_TERMIO_H)
+CHECK_INCLUDE_FILES("pwd.h" HAVE_PWD_H)
+CHECK_INCLUDE_FILES("sys/time.h" HAVE_SYS_TIME_H)
+CHECK_INCLUDE_FILES("utime.h" HAVE_UTIME_H)
+CHECK_INCLUDE_FILES("sys/ioctl.h" HAVE_SYS_IOCTL_H)
+CHECK_INCLUDE_FILES("sys/param.h" HAVE_SYS_PARAM_H)
+CHECK_INCLUDE_FILES("wait.h" HAVE_WAIT_H)
+CHECK_INCLUDE_FILES("sys/wait.h" HAVE_SYS_WAIT_H)
+CHECK_INCLUDE_FILES("sys/resource.h" HAVE_SYS_RESOURCE_H)
+CHECK_INCLUDE_FILES("sys/utsname.h" HAVE_SYS_UTSNAME_H)
+CHECK_INCLUDE_FILES("poll.h" HAVE_POLL_H)
+CHECK_INCLUDE_FILES("sys/poll.h" HAVE_SYS_POLL_H)
+CHECK_INCLUDE_FILES("netdb.h" HAVE_NETDB_H)
+CHECK_INCLUDE_FILES("sys/socket.h" HAVE_SYS_SOCKET_H)
+CHECK_INCLUDE_FILES("linux/pg.h" HAVE_LINUX_PG_H)
+CHECK_INCLUDE_FILES("arpa/inet.h" HAVE_ARPA_INET_H)
+CHECK_INCLUDE_FILES("sys/ipc.h" HAVE_SYS_IPC_H)
+CHECK_INCLUDE_FILES("sys/types.h;sys/mman.h" HAVE_SYS_MMAN_H)
+CHECK_INCLUDE_FILES("sys/types.h;sys/dkio.h" HAVE_SYS_DKIO_H)
+CHECK_INCLUDE_FILES("sys/types.h;sun/dkio.h" HAVE_SUN_DKIO_H)
+CHECK_INCLUDE_FILES("iconv.h" HAVE_ICONV_H)
+
+
+INCLUDE(CheckCSourceCompiles)
+INCLUDE(CheckFunctionExists)
+
+#SET(CMAKE_REQUIRED_LIBRARIES iconv)
+SET(TESTSRC " 
+#include <iconv.h>
+int main(int a, char **b) { iconv_t foo = iconv_open(b[0], b[0]); return(0); }
+")
+
+CHECK_C_SOURCE_COMPILES("${TESTSRC}" USE_LIBC_ICONV)
+IF(NOT USE_LIBC_ICONV)
+SET(CMAKE_REQUIRED_LIBRARIES iconv)
+CHECK_C_SOURCE_COMPILES("${TESTSRC}" USE_LIBICONV)
+IF(NOT USE_LIBICONV)
+   message("ERROR: no library providing iconv found")
+ENDIF(NOT USE_LIBICONV)
+ENDIF(NOT USE_LIBC_ICONV)
+SET(CMAKE_REQUIRED_INCLUDES )
+
+
+
+#CHECK_C_SOURCE_COMPILES("${TESTSRC}" USE_LIBICONV)
+#IF(NOT USE_LIBICONV)
+#   FIND_FILE(ICONV_H_LOCATION "iconv.h")
+#   IF(NOT "${ICONV_H_LOCATION}" EQUAL "/usr/include/iconv.h")
+#      MESSAGE("WARNING: iconv.h found in non-standard location (${ICONV_H_LOCATION}) but")
+#      MESSAGE("GNU libiconv is not available. See INSTALL for details. Sleeping 10 seconds.")
+#      EXECUTE_PROCESS(COMMAND "sleep" "10")
+#   ENDIF(NOT "${ICONV_H_LOCATION}" EQUAL "/usr/include/iconv.h")
+#ENDIF(NOT USE_LIBICONV)
+
+SET(CMAKE_REQUIRED_LIBRARIES )
+SET(TESTSRC " 
+#include <stdlib.h>
+int main() { return ( (int) drand48()  )  ; }
+")
+CHECK_C_SOURCE_COMPILES("${TESTSRC}" HAVE_DRAND48)
+SET(TESTSRC " 
+#include <stdlib.h>
+int main() { return ( (int) drand()  )  ; }
+")
+CHECK_C_SOURCE_COMPILES("${TESTSRC}" HAVE_DRAND)
+SET(TESTSRC " 
+#include <sys/socket.h>
+#include <netdb.h>
+int main(int argc, char **argv) {
+struct sockaddr sa;
+return getnameinfo(&sa, 1, argv[0], 1, argv[1], 1, 0);
+}
+")
+CHECK_C_SOURCE_COMPILES("${TESTSRC}" HAVE_GETNAMEINFO)
+SET(TESTSRC " 
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+int main(int a, char **b) {
+struct in_addr in;
+inet_ntoa(in);
+return 0;
+}
+")
+CHECK_C_SOURCE_COMPILES("${TESTSRC}" HAVE_INET_NTOA)
+
+SET(TESTSRC "
+#include <sys/types.h>
+#include <wait.h>
+int main() {
+union wait w;
+return 0; 
+}
+")
+# FIXME: try the same with #include <sys/wait.h>... may work, if yes, integrate properly
+CHECK_C_SOURCE_COMPILES("${TESTSRC}" HAVE_UNION_WAIT)
+SET(TESTSRC "
+#include <sys/types.h>
+#include <sys/mman.h>
+int main() {
+if (mlockall(MCL_CURRENT|MCL_FUTURE) < 0)  
+   return(0);
+   }
+")
+CHECK_C_SOURCE_COMPILES("${TESTSRC}" HAVE_MLOCKALL)
+SET(TESTSRC "
+int main(int argc, char **argv) {
+   int a[argc];
+   return 0;
+}
+")
+CHECK_C_SOURCE_COMPILES("${TESTSRC}" HAVE_DYN_ARRAYS)
+
+CONFIGURE_FILE( xconfig.h.in xconfig.h)
+
diff --git a/include/align.h.in b/include/align.h.in
new file mode 100644 (file)
index 0000000..411fec1
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * This file has been generated automatically
+ * by CMake commands. Do not edit.
+ *
+ * Original contents from @(#)align_test.c     1.19 03/11/25 Copyright 1995 J. Schilling
+ *
+ */
+
+#ifndef        _UTYPES_H
+#include <utypes.h>
+#endif
+
+#define ALIGN_SHORT @SIZE_SHORT@
+#define ALIGN_INT @SIZE_INT@
+#define ALIGN_LONG @SIZE_LONG@
+#define ALIGN_LLONG @SIZE_LLONG@
+#define ALIGN_FLOAT @SIZE_FLOAT@
+#define ALIGN_DOUBLE @SIZE_DOUBLE@
+#define ALIGN_PTR @SIZE_PTR@
+
+#define SIZE_SHORT @SIZE_SHORT@
+#define SIZE_INT @SIZE_INT@
+#define SIZE_LONG @SIZE_LONG@
+#define SIZE_LLONG @SIZE_LLONG@
+#define SIZE_FLOAT @SIZE_FLOAT@
+#define SIZE_DOUBLE @SIZE_DOUBLE@
+#define SIZE_PTR @SIZE_PTR@
+
+
+#define ALIGN_SMASK @SHORTLESS@
+#define ALIGN_IMASK @INTLESS@
+#define ALIGN_LMASK @LONGLESS@
+#define ALIGN_LLMASK @LLONGLESS@
+#define ALIGN_FMASK @FLOATLESS@
+#define ALIGN_DMASK @DOUBLELESS@
+#define ALIGN_PMASK @PTRLESS@
+
+
+/*
+ * There used to be a cast to an int but we get a warning from GCC.
+ * This warning message from GCC is wrong.
+ * Believe me that this macro would even be usable if I would cast to short.
+ * In order to avoid this warning, we are now using UIntptr_t
+ */
+#define        xaligned(a, s)          ((((UIntptr_t)(a)) & (s)) == 0 )
+#define        x2aligned(a, b, s)      (((((UIntptr_t)(a)) | ((UIntptr_t)(b))) & (s)) == 0 )
+
+#define        saligned(a)             xaligned(a, ALIGN_SMASK)
+#define        s2aligned(a, b)         x2aligned(a, b, ALIGN_SMASK)
+
+#define        ialigned(a)             xaligned(a, ALIGN_IMASK)
+#define        i2aligned(a, b)         x2aligned(a, b, ALIGN_IMASK)
+
+#define        laligned(a)             xaligned(a, ALIGN_LMASK)
+#define        l2aligned(a, b)         x2aligned(a, b, ALIGN_LMASK)
+
+#define        llaligned(a)            xaligned(a, ALIGN_LLMASK)
+#define        ll2aligned(a, b)        x2aligned(a, b, ALIGN_LLMASK)
+
+#define        faligned(a)             xaligned(a, ALIGN_FMASK)
+#define        f2aligned(a, b)         x2aligned(a, b, ALIGN_FMASK)
+
+#define        daligned(a)             xaligned(a, ALIGN_DMASK)
+#define        d2aligned(a, b)         x2aligned(a, b, ALIGN_DMASK)
+
+#define        paligned(a)             xaligned(a, ALIGN_PMASK)
+#define        p2aligned(a, b)         x2aligned(a, b, ALIGN_PMASK)
+
+
+/*
+ * There used to be a cast to an int but we get a warning from GCC.
+ * This warning message from GCC is wrong.
+ * Believe me that this macro would even be usable if I would cast to short.
+ * In order to avoid this warning, we are now using UIntptr_t
+ */
+#define        xalign(x, a, m)         ( ((char *)(x)) + ( (a) - 1 - ((((UIntptr_t)(x))-1)&(m))) )
+
+#define        salign(x)               xalign((x), ALIGN_SHORT, ALIGN_SMASK)
+#define        ialign(x)               xalign((x), ALIGN_INT, ALIGN_IMASK)
+#define        lalign(x)               xalign((x), ALIGN_LONG, ALIGN_LMASK)
+#define        llalign(x)              xalign((x), ALIGN_LLONG, ALIGN_LLMASK)
+#define        falign(x)               xalign((x), ALIGN_FLOAT, ALIGN_FMASK)
+#define        dalign(x)               xalign((x), ALIGN_DOUBLE, ALIGN_DMASK)
+#define        palign(x)               xalign((x), ALIGN_PTR, ALIGN_PMASK)
diff --git a/include/allocax.h b/include/allocax.h
new file mode 100644 (file)
index 0000000..11431de
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)allocax.h       1.3 03/07/15 Copyright 2002 J. Schilling */
+/*
+ *     Definitions for users of alloca()
+ *
+ *     Important: #include this directly after <mconfig.h>
+ *     and before any other include file.
+ *     See comment in _AIX part below.
+ *
+ *     Copyright (c) 2002 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef        _ALLOCAX_H
+#define        _ALLOCAX_H
+
+#ifdef __GNUC__
+#      ifndef  alloca
+#              define  alloca(s)       __builtin_alloca(s)
+#      endif
+#else
+#      ifdef _MSC_VER
+#              include <malloc.h>
+#              define alloca _alloca
+#      else
+#              ifdef HAVE_ALLOCA_H
+#                      include <alloca.h>
+#              else
+#                      ifdef _AIX
+                               /*
+                                * Indent so pre-ANSI compilers will ignore it
+                                *
+                                * Some versions of AIX may require this to be
+                                * first in the file and only preceded by
+                                * comments and preprocessor directives/
+                                */
+                               #pragma alloca
+#                      else
+#                              ifndef alloca
+                                       /*
+                                        * predefined by HP cc +Olibcalls
+                                        */
+#                                      ifdef   PROTOTYPES
+                                               extern void *alloca();
+#                                      else
+                                               extern char *alloca();
+#                                      endif
+#                              endif
+#                      endif
+#              endif
+#      endif
+#endif
+
+
+#endif /* _ALLOCAX_H */
diff --git a/include/avoffset.h b/include/avoffset.h
new file mode 100644 (file)
index 0000000..aa0fdaa
--- /dev/null
@@ -0,0 +1,13 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* Dummy */
diff --git a/include/btorder.h b/include/btorder.h
new file mode 100644 (file)
index 0000000..a76a239
--- /dev/null
@@ -0,0 +1,130 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)btorder.h       1.16 03/06/15 Copyright 1996 J. Schilling */
+/*
+ *     Definitions for Bit and Byte ordering
+ *
+ *     Copyright (c) 1996 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef        _BTORDER_H
+#define        _BTORDER_H
+
+#ifndef        _INCL_SYS_TYPES_H
+#include <sys/types.h>                 /* try to load isa_defs.h on Solaris */
+#define        _INCL_SYS_TYPES_H
+#endif
+
+#ifndef _MCONFIG_H
+#include <mconfig.h>                   /* load bit/byte-oder from xmconfig.h*/
+#endif
+
+/*
+ * Convert bit-order definitions from xconfig.h into our values
+ * and verify them.
+ */
+#if defined(HAVE_C_BITFIELDS)  && \
+    defined(BITFIELDS_LTOH)
+#define        _BIT_FIELDS_LTOH
+#endif
+
+#if defined(HAVE_C_BITFIELDS)  && \
+    defined(BITFIELDS_HTOL)
+#define        _BIT_FIELDS_HTOL
+#endif
+
+#if defined(HAVE_C_BITFIELDS) && \
+       !defined(BITFIELDS_HTOL)
+#define        BITFIELDS_LTOH
+#define        _BIT_FIELDS_LTOH
+#endif
+
+#if    defined(_BIT_FIELDS_LTOH) && defined(_BIT_FIELDS_HTOL)
+/*
+ * #error will not work for all compilers (e.g. sunos4)
+ * The following line will abort compilation on all compilers
+ * if none of the above is defines. And that's  what we want.
+ */
+error  Only one of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL may be defined
+#endif
+
+
+/*
+ * Convert byte-order definitions from xconfig.h into our values
+ * and verify them.
+ * Note that we cannot use the definitions _LITTLE_ENDIAN and _BIG_ENDIAN
+ * because they are used on IRIX-6.5 with different meaning.
+ */
+#if defined(HAVE_C_BIGENDIAN) && \
+       !defined(WORDS_BIGENDIAN)
+#define        WORDS_LITTLEENDIAN
+/*#define      _LITTLE_ENDIAN*/
+#endif
+
+#if defined(HAVE_C_BIGENDIAN)  && \
+    defined(WORDS_BIGENDIAN)
+#undef WORDS_LITTLEENDIAN
+/*#define      _BIG_ENDIAN*/
+#endif
+
+#if    defined(_BIT_FIELDS_LTOH) || defined(_BIT_FIELDS_HTOL)
+/*
+ * Bitorder is already known.
+ */
+#else
+/*
+ * Bitorder not yet known.
+ */
+#      if defined(sun3) || defined(mc68000) || \
+           defined(sun4) || defined(__sparc) || defined(sparc) || \
+           defined(__hppa) || defined(_ARCH_PPC) || defined(_IBMR2)
+#              define _BIT_FIELDS_HTOL
+#      endif
+
+#      if defined(__sgi) && defined(__mips)
+#              define _BIT_FIELDS_HTOL
+#      endif
+
+#      if defined(__i386__) || defined(__i386) || defined(i386) || \
+           defined(__alpha__) || defined(__alpha) || defined(alpha) || \
+           defined(__arm__) || defined(__arm) || defined(arm)
+#              define _BIT_FIELDS_LTOH
+#      endif
+
+#      if defined(__ppc__) || defined(ppc) || defined(__ppc) || \
+           defined(__PPC) || defined(powerpc) || defined(__powerpc__)
+
+#              if      defined(__BIG_ENDIAN__)
+#                      define _BIT_FIELDS_HTOL
+#              else
+#                      define _BIT_FIELDS_LTOH
+#              endif
+#      endif
+#endif
+
+#endif /* _BTORDER_H */
diff --git a/include/ccomdefs.h b/include/ccomdefs.h
new file mode 100644 (file)
index 0000000..6667501
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)ccomdefs.h      1.3 03/06/15 Copyright 2000 J. Schilling */
+/*
+ *     Various compiler dependant macros.
+ *
+ *     Copyright (c) 2000 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _CCOMDEFS_H
+#define        _CCOMDEFS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Compiler-dependent macros to declare that functions take printf-like
+ * or scanf-like arguments. They are defined to nothing for versions of gcc
+ * that are not known to support the features properly (old versions of gcc-2
+ * didn't permit keeping the keywords out of the application namespace).
+ */
+#if __GNUC__ < 2 || __GNUC__ == 2 && __GNUC_MINOR__ < 7
+
+#define        __printflike__(fmtarg, firstvararg)
+#define        __printf0like__(fmtarg, firstvararg)
+#define        __scanflike__(fmtarg, firstvararg)
+
+#else /* We found GCC that supports __attribute__ */
+
+#define        __printflike__(fmtarg, firstvararg) \
+               __attribute__((__format__(__printf__, fmtarg, firstvararg)))
+#define        __printf0like__(fmtarg, firstvararg) \
+               __attribute__((__format__(__printf0__, fmtarg, firstvararg)))
+
+/*
+ * FreeBSD GCC implements printf0 that allows the format string to
+ * be a NULL pointer.
+ */
+#if    __FreeBSD_cc_version < 300001
+#undef __printf0like__
+#define        __printf0like__ __printflike__
+#endif
+
+#define        __scanflike__(fmtarg, firstvararg) \
+               __attribute__((__format__(__scanf__, fmtarg, firstvararg)))
+
+#endif /* GNUC */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _CCOMDEFS_H */
diff --git a/include/deflts.h b/include/deflts.h
new file mode 100644 (file)
index 0000000..097047b
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ *     Copyright (c) 2006 Eduard Bloch
+ *
+ *     Config parsing code, with interface similar to basic libdeflt interface
+ *     from J.  Schilling but with different semantics
+ *
+ *     get_value uses a static buffer (warning, non-reentrant)
+ *     cfg_open and cfg_close maintain a static FILE pointer (warning, non-reentrant)
+ *
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef        _DEFLTS_H
+#define        _DEFLTS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* FIXME: use inline trough an INLINE macro wrapper */
+extern int     cfg_open        (const char *name);
+extern int     cfg_close       (void);
+
+/* reset the position in FILE */
+extern void    cfg_restart     (void);
+/* returns the next value found after the current position */
+extern char    *cfg_get_next   (const char *name);
+/* equivalent to cfg_restart(); cfg_get_next(...) */
+extern char *cfg_get(const char *key);
+/* function wrapped by those above */
+extern char *get_value(FILE *srcfile, const char *key, int dorewind);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/device.h b/include/device.h
new file mode 100644 (file)
index 0000000..a3c8c92
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)device.h        1.13 05/01/24 Copyright 1995 J. Schilling */
+/*
+ *     Generic header for users of major(), minor() and makedev()
+ *
+ *     Copyright (c) 1995 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef        _DEVICE_H
+#define        _DEVICE_H
+
+#ifndef _MCONFIG_H
+#include <mconfig.h>
+#endif
+#ifndef _PROTOTYP_H
+#include <prototyp.h>
+#endif
+
+/*
+ * On generic SVR4, major is a function (defined in sys/mkdev.h).
+ * On Solaris it is defined ...
+ * As we cannot just test if major is #define'd, we have to
+ * define _FOUND_MAJOR_ instead.
+ *
+ * WARNING: Do never include <sys/sysmacros.h> in SVR4, it contains
+ * an old definition for major()/minor() defining 8 minorbits.
+ * Use <sys/mkdev.h> instead.
+ */
+#ifndef        _INCL_SYS_TYPES_H
+#include <sys/types.h>
+#define        _INCL_SYS_TYPES_H
+#endif
+/*
+ * Some systems define major in <sys/types.h>.
+ * We are ready...
+ */
+#ifdef major
+#      define _FOUND_MAJOR_
+#endif
+
+#ifdef MAJOR_IN_MKDEV
+#      ifndef  _INCL_SYS_MKDEV_H
+#      include <sys/mkdev.h>
+#      define  _INCL_SYS_MKDEV_H
+#      endif
+       /*
+        * Interix doesn't use makedev(); it uses mkdev()
+        */
+#      if !defined(makedev) && defined(mkdev)
+#              define makedev(a,b)     mkdev((a),(b))
+#      endif
+#      define _FOUND_MAJOR_
+#endif
+
+#ifndef _FOUND_MAJOR_
+#      ifdef MAJOR_IN_SYSMACROS
+#              ifndef  _INCL_SYS_SYSMACROS_H
+#              include <sys/sysmacros.h>
+#              define  _INCL_SYS_SYSMACROS_H
+#              endif
+#              define _FOUND_MAJOR_
+#      endif
+#endif
+
+/*
+ * If we are on HP/UX before HP/UX 8,
+ * major/minor are not in <sys/sysmacros.h>.
+ */
+#ifndef _FOUND_MAJOR_
+#      if defined(hpux) || defined(__hpux__) || defined(__hpux)
+#              ifndef  _INCL_SYS_MKOD_H
+#              include <sys/mknod.h>
+#              define  _INCL_SYS_MKOD_H
+#              endif
+#              define _FOUND_MAJOR_
+#      endif
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * For all other systems define major()/minor() here.
+ * XXX Check if this definition will be usefull for ms dos too.
+ */
+#ifndef _FOUND_MAJOR_
+#      define major(dev)               (((dev) >> 8) & 0xFF)
+#      define minor(dev)               ((dev) & 0xFF)
+#      define makedev(majo, mino)      (((majo) << 8) | (mino))
+#endif
+
+/*
+ * Don't pollute namespace...
+ */
+#undef _FOUND_MAJOR_
+
+#ifdef __XDEV__
+/*
+ * The following defines are currently only needed for 'star'.
+ * We make it conditional code to avoid to pollute the namespace.
+ */
+#define        XDEV_T  unsigned long
+
+extern int     minorbits;
+extern XDEV_T  minormask;
+extern XDEV_T  _dev_mask[];
+
+#define        dev_major(dev)                  (((XDEV_T)(dev)) >> minorbits)
+#define        _dev_major(mbits, dev)          (((XDEV_T)(dev)) >> (mbits))
+
+#define        dev_minor(dev)                  (((XDEV_T)(dev)) & minormask)
+#define        _dev_minor(mbits, dev)          (((XDEV_T)(dev)) & _dev_mask[(mbits)])
+
+
+#define        dev_make(majo, mino)            ((((XDEV_T)(majo)) << minorbits) | \
+                                                       ((XDEV_T)(mino)))
+#define        _dev_make(mbits, majo, mino)    ((((XDEV_T)(majo)) << (mbits) | \
+                                                       ((XDEV_T)(mino)))
+
+extern void    dev_init(BOOL debug);
+#ifndef        dev_major
+extern XDEV_T  dev_major(XDEV_T dev);
+extern XDEV_T  _dev_major(int mbits, XDEV_T dev);
+extern XDEV_T  dev_minor(XDEV_T dev);
+extern XDEV_T  _dev_minor(int mbits, XDEV_T dev);
+extern XDEV_T  dev_make(XDEV_T majo, XDEV_T mino);
+extern XDEV_T  _dev_make(int mbits, XDEV_T majo, XDEV_T mino);
+#endif
+
+#endif /* __XDEV__ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _DEVICE_H */
diff --git a/include/dirdefs.h b/include/dirdefs.h
new file mode 100644 (file)
index 0000000..fa966ab
--- /dev/null
@@ -0,0 +1,188 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)dirdefs.h       1.15 04/06/16 Copyright 1987, 1998 J. Schilling */
+/*
+ *     Copyright (c) 1987, 1998 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef        _DIRDEFS_H
+#define        _DIRDEFS_H
+
+#ifndef _MCONFIG_H
+#include <mconfig.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef JOS
+#      ifndef  _INCL_SYS_STYPES_H
+#      include <sys/stypes.h>
+#      define  _INCL_SYS_STYPES_H
+#      endif
+#      ifndef  _INCL_SYS_FILEDESC_H
+#      include <sys/filedesc.h>
+#      define  _INCL_SYS_FILEDESC_H
+#      endif
+#      define  NEED_READDIR
+#      define  dirent                  _direct
+#      define  DIR_NAMELEN(dirent)     strlen((dirent)->d_name)
+#      define  DIRSIZE 30
+#      define  FOUND_DIRSIZE
+       typedef struct _dirent {
+               char    name[DIRSIZE];
+               short   ino;
+       } dirent;
+
+#else  /* !JOS */
+
+#      ifndef  _INCL_SYS_TYPES_H
+#      include <sys/types.h>
+#      define  _INCL_SYS_TYPES_H
+#      endif
+#      ifndef  _INCL_SYS_STAT_H
+#      include <sys/stat.h>
+#      define  _INCL_SYS_STAT_H
+#      endif
+#      ifdef   HAVE_LIMITS_H
+#              ifndef  _INCL_LIMITS_H
+#              include <limits.h>
+#              define  _INCL_LIMITS_H
+#              endif
+#      endif
+#      ifdef   HAVE_SYS_PARAM_H
+#              ifndef  _INCL_SYS_PARAM_H
+#              include <sys/param.h>
+#              define  _INCL_SYS_PARAM_H
+#              endif
+#      endif
+
+#      ifdef   HAVE_DIRENT_H           /* This a POSIX compliant system */
+#              ifndef  _INCL_DIRENT_H
+#              include <dirent.h>
+#              define  _INCL_DIRENT_H
+#              endif
+#              define  DIR_NAMELEN(dirent)     strlen((dirent)->d_name)
+#              define  _FOUND_DIR_
+#      else                            /* This is a Pre POSIX system    */
+
+#      define  dirent  direct
+#      define  DIR_NAMELEN(dirent)     (dirent)->d_namlen
+
+#      if      defined(HAVE_SYS_DIR_H)
+#              ifndef  _INCL_SYS_DIR_H
+#              include <sys/dir.h>
+#              define  _INCL_SYS_DIR_H
+#              endif
+#              define  _FOUND_DIR_
+#      endif
+
+#      if      defined(HAVE_NDIR_H) && !defined(_FOUND_DIR_)
+#              ifndef  _INCL_NDIR_H
+#              include <ndir.h>
+#              define  _INCL_NDIR_H
+#              endif
+#              define  _FOUND_DIR_
+#      endif
+
+#      if      defined(HAVE_SYS_NDIR_H) && !defined(_FOUND_DIR_)
+#              ifndef  _INCL_SYS_NDIR_H
+#              include <sys/ndir.h>
+#              define  _INCL_SYS_NDIR_H
+#              endif
+#              define  _FOUND_DIR_
+#      endif
+#      endif   /* HAVE_DIRENT_H */
+
+#      if      defined(_FOUND_DIR_)
+/*
+ * Don't use defaults here to allow recognition of problems.
+ */
+#      ifdef   MAXNAMELEN
+#              define  DIRSIZE         MAXNAMELEN      /* From sys/param.h */
+#              define  FOUND_DIRSIZE
+#      else
+#      ifdef   MAXNAMLEN
+#              define  DIRSIZE         MAXNAMLEN       /* From dirent.h    */
+#              define  FOUND_DIRSIZE
+#      else
+#      ifdef   DIRSIZ
+#              define  DIRSIZE         DIRSIZ          /* From sys/dir.h   */
+#              define  FOUND_DIRSIZE
+#      endif
+#      endif
+#      endif
+#      else    /* !_FOUND_DIR_ */
+
+#              define  NEED_DIRENT
+#              define  NEED_READDIR
+#              define  dirent                  _direct
+#              define  DIR_NAMELEN(dirent)     strlen((dirent)->d_name)
+
+#      endif   /* _FOUND_DIR_ */
+
+
+#ifdef NEED_DIRENT
+
+#ifndef        FOUND_DIRSIZE
+#define        DIRSIZE         14      /* The old UNIX standard value */
+#define        FOUND_DIRSIZE
+#endif
+
+typedef struct _dirent {
+       short   ino;
+       char    name[DIRSIZE];
+} dirent;
+
+#endif /* NEED_DIRENT */
+
+#endif /* !JOS */
+
+#ifdef NEED_READDIR
+       typedef struct __dirdesc {
+               FILE    *dd_fd;
+       } DIR;
+
+       struct _direct {
+               unsigned long   d_ino;
+               unsigned short  d_reclen;
+               unsigned short  d_namlen;
+               char            d_name[DIRSIZE +1];
+       };
+
+extern DIR             *opendir();
+extern                 closedir();
+extern struct dirent   *readdir();
+
+#endif /* NEED_READDIR */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _DIRDEFS_H */
diff --git a/include/fctldefs.h b/include/fctldefs.h
new file mode 100644 (file)
index 0000000..d382e68
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)fctldefs.h      1.13 03/02/23 Copyright 1996 J. Schilling */
+/*
+ *     Generic header for users of open(), creat() and chmod()
+ *
+ *     Copyright (c) 1996 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _FCTLDEFS_H
+#define        _FCTLDEFS_H
+
+#ifndef        _MCONFIG_H
+#include <mconfig.h>
+#endif
+
+#ifndef        _STATDEFS_H
+#include <statdefs.h>          /* For 3rd arg of open() and chmod()    */
+#endif
+
+#ifndef        _INCL_SYS_TYPES_H
+#include <sys/types.h>         /* Needed for fcntl.h                   */
+#define        _INCL_SYS_TYPES_H
+#endif
+
+#ifdef HAVE_SYS_FILE_H
+/*
+ * Historical systems with flock() only need sys/file.h
+ */
+#      ifndef  _INCL_SYS_FILE_H
+#      include <sys/file.h>
+#      define  _INCL_SYS_FILE_H
+#      endif
+#endif
+#ifdef HAVE_FCNTL_H
+#      ifndef  _INCL_FCNTL_H
+#      include <fcntl.h>
+#      define  _INCL_FCNTL_H
+#endif
+#endif
+
+/*
+ * Do not define more than O_RDONLY / O_WRONLY / O_RDWR / O_BINARY
+ * The values may differ.
+ *
+ * O_BINARY is defined here to allow all applications to compile on a non DOS
+ * environment without repeating this definition.
+ */
+#ifndef        O_RDONLY
+#      define  O_RDONLY        0
+#endif
+#ifndef        O_WRONLY
+#      define  O_WRONLY        1
+#endif
+#ifndef        O_RDWR
+#      define  O_RDWR          2
+#endif
+#ifndef        O_BINARY                        /* Only present on DOS or similar */
+#      define  O_BINARY        0
+#endif
+#ifndef        O_NDELAY                        /* This is undefined on BeOS :-( */
+#      define  O_NDELAY        0
+#endif
+
+#ifndef        O_ACCMODE
+#define        O_ACCMODE               (O_RDONLY|O_WRONLY|O_RDWR)
+#endif
+
+#endif /* _FCTLDEFS_H */
diff --git a/include/getargs.h b/include/getargs.h
new file mode 100644 (file)
index 0000000..6aa36b0
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)getargs.h       1.10 04/09/25 Copyright 1985 J. Schilling */
+/*
+ *     Definitions for getargs()/getallargs()/getfiles()
+ *
+ *     Copyright (c) 1985 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef        _GETARGS_H
+#define        _GETARGS_H
+
+#ifndef _MCONFIG_H
+#include <mconfig.h>
+#endif
+#ifndef _PROTOTYP_H
+#include <prototyp.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define        NOARGS            0     /* No more args                 */
+#define        NOTAFLAG          1     /* Not a flag type argument     */
+#define        BADFLAG         (-1)    /* Not a valid flag argument    */
+#define        BADFMT          (-2)    /* Error in format string       */
+#define        NOTAFILE        (-3)    /* Seems to be a flag type      */
+
+typedef        int     (*getargfun)(const void *, void *);
+
+/*
+ * Keep in sync with schily.h
+ */
+extern int     getallargs(int *, char * const**, const char *, ...);
+extern int     getargs(int *, char * const**, const char *, ...);
+extern int     getfiles(int *, char * const**, const char *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _GETARGS_H */
diff --git a/include/getcwd.h b/include/getcwd.h
new file mode 100644 (file)
index 0000000..462a43c
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)getcwd.h        1.3 01/07/15 Copyright 1998 J. Schilling */
+/*
+ *     Definitions for getcwd()
+ *
+ *     Copyright (c) 1998 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef        _GETCWD_H
+#define        _GETCWD_H
+
+#ifndef _MCONFIG_H
+#include <mconfig.h>
+#endif
+
+#ifdef JOS
+#      ifndef  _INCL_SYS_STYPES_H
+#      include <sys/stypes.h>
+#      define  _INCL_SYS_STYPES_H
+#      endif
+       extern char     *gwd();
+#      define          getcwd(b, len)  gwd(b)
+#else
+#      ifndef  HAVE_GETCWD
+#              define  getcwd(b, len)  getwd(b)
+#      endif
+#endif
+
+#endif /* _GETCWD_H */
diff --git a/include/glibc_elf.h b/include/glibc_elf.h
new file mode 100644 (file)
index 0000000..ae640d5
--- /dev/null
@@ -0,0 +1,2558 @@
+/*
+ * This file has been modified for inclusion into the cdrkit package.
+ */
+
+/* This file defines standard ELF types, structures, and macros.
+   Copyright (C) 1995-2003, 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#ifndef _ELF_H
+#define        _ELF_H 1
+
+/* Standard ELF types.  */
+
+#include <inttypes.h>
+#include <sys/types.h>
+
+/* Type for a 16-bit quantity.  */
+typedef uint16_t Elf32_Half;
+typedef uint16_t Elf64_Half;
+
+/* Types for signed and unsigned 32-bit quantities.  */
+typedef uint32_t Elf32_Word;
+typedef        int32_t  Elf32_Sword;
+typedef uint32_t Elf64_Word;
+typedef        int32_t  Elf64_Sword;
+
+/* Types for signed and unsigned 64-bit quantities.  */
+typedef uint64_t Elf32_Xword;
+typedef        int64_t  Elf32_Sxword;
+typedef uint64_t Elf64_Xword;
+typedef        int64_t  Elf64_Sxword;
+
+/* Type of addresses.  */
+typedef uint32_t Elf32_Addr;
+typedef uint64_t Elf64_Addr;
+
+/* Type of file offsets.  */
+typedef uint32_t Elf32_Off;
+typedef uint64_t Elf64_Off;
+
+/* Type for section indices, which are 16-bit quantities.  */
+typedef uint16_t Elf32_Section;
+typedef uint16_t Elf64_Section;
+
+/* Type for version symbol information.  */
+typedef Elf32_Half Elf32_Versym;
+typedef Elf64_Half Elf64_Versym;
+
+
+/* The ELF file header.  This appears at the start of every ELF file.  */
+
+#define EI_NIDENT (16)
+
+typedef struct
+{
+  unsigned char        e_ident[EI_NIDENT];     /* Magic number and other info */
+  Elf32_Half   e_type;                 /* Object file type */
+  Elf32_Half   e_machine;              /* Architecture */
+  Elf32_Word   e_version;              /* Object file version */
+  Elf32_Addr   e_entry;                /* Entry point virtual address */
+  Elf32_Off    e_phoff;                /* Program header table file offset */
+  Elf32_Off    e_shoff;                /* Section header table file offset */
+  Elf32_Word   e_flags;                /* Processor-specific flags */
+  Elf32_Half   e_ehsize;               /* ELF header size in bytes */
+  Elf32_Half   e_phentsize;            /* Program header table entry size */
+  Elf32_Half   e_phnum;                /* Program header table entry count */
+  Elf32_Half   e_shentsize;            /* Section header table entry size */
+  Elf32_Half   e_shnum;                /* Section header table entry count */
+  Elf32_Half   e_shstrndx;             /* Section header string table index */
+} Elf32_Ehdr;
+
+typedef struct
+{
+  unsigned char        e_ident[EI_NIDENT];     /* Magic number and other info */
+  Elf64_Half   e_type;                 /* Object file type */
+  Elf64_Half   e_machine;              /* Architecture */
+  Elf64_Word   e_version;              /* Object file version */
+  Elf64_Addr   e_entry;                /* Entry point virtual address */
+  Elf64_Off    e_phoff;                /* Program header table file offset */
+  Elf64_Off    e_shoff;                /* Section header table file offset */
+  Elf64_Word   e_flags;                /* Processor-specific flags */
+  Elf64_Half   e_ehsize;               /* ELF header size in bytes */
+  Elf64_Half   e_phentsize;            /* Program header table entry size */
+  Elf64_Half   e_phnum;                /* Program header table entry count */
+  Elf64_Half   e_shentsize;            /* Section header table entry size */
+  Elf64_Half   e_shnum;                /* Section header table entry count */
+  Elf64_Half   e_shstrndx;             /* Section header string table index */
+} Elf64_Ehdr;
+
+/* Fields in the e_ident array.  The EI_* macros are indices into the
+   array.  The macros under each EI_* macro are the values the byte
+   may have.  */
+
+#define EI_MAG0                0               /* File identification byte 0 index */
+#define ELFMAG0                0x7f            /* Magic number byte 0 */
+
+#define EI_MAG1                1               /* File identification byte 1 index */
+#define ELFMAG1                'E'             /* Magic number byte 1 */
+
+#define EI_MAG2                2               /* File identification byte 2 index */
+#define ELFMAG2                'L'             /* Magic number byte 2 */
+
+#define EI_MAG3                3               /* File identification byte 3 index */
+#define ELFMAG3                'F'             /* Magic number byte 3 */
+
+/* Conglomeration of the identification bytes, for easy testing as a word.  */
+#define        ELFMAG          "\177ELF"
+#define        SELFMAG         4
+
+#define EI_CLASS       4               /* File class byte index */
+#define ELFCLASSNONE   0               /* Invalid class */
+#define ELFCLASS32     1               /* 32-bit objects */
+#define ELFCLASS64     2               /* 64-bit objects */
+#define ELFCLASSNUM    3
+
+#define EI_DATA                5               /* Data encoding byte index */
+#define ELFDATANONE    0               /* Invalid data encoding */
+#define ELFDATA2LSB    1               /* 2's complement, little endian */
+#define ELFDATA2MSB    2               /* 2's complement, big endian */
+#define ELFDATANUM     3
+
+#define EI_VERSION     6               /* File version byte index */
+                                       /* Value must be EV_CURRENT */
+
+#define EI_OSABI       7               /* OS ABI identification */
+#define ELFOSABI_NONE          0       /* UNIX System V ABI */
+#define ELFOSABI_SYSV          0       /* Alias.  */
+#define ELFOSABI_HPUX          1       /* HP-UX */
+#define ELFOSABI_NETBSD                2       /* NetBSD.  */
+#define ELFOSABI_LINUX         3       /* Linux.  */
+#define ELFOSABI_SOLARIS       6       /* Sun Solaris.  */
+#define ELFOSABI_AIX           7       /* IBM AIX.  */
+#define ELFOSABI_IRIX          8       /* SGI Irix.  */
+#define ELFOSABI_FREEBSD       9       /* FreeBSD.  */
+#define ELFOSABI_TRU64         10      /* Compaq TRU64 UNIX.  */
+#define ELFOSABI_MODESTO       11      /* Novell Modesto.  */
+#define ELFOSABI_OPENBSD       12      /* OpenBSD.  */
+#define ELFOSABI_ARM           97      /* ARM */
+#define ELFOSABI_STANDALONE    255     /* Standalone (embedded) application */
+
+#define EI_ABIVERSION  8               /* ABI version */
+
+#define EI_PAD         9               /* Byte index of padding bytes */
+
+/* Legal values for e_type (object file type).  */
+
+#define ET_NONE                0               /* No file type */
+#define ET_REL         1               /* Relocatable file */
+#define ET_EXEC                2               /* Executable file */
+#define ET_DYN         3               /* Shared object file */
+#define ET_CORE                4               /* Core file */
+#define        ET_NUM          5               /* Number of defined types */
+#define ET_LOOS                0xfe00          /* OS-specific range start */
+#define ET_HIOS                0xfeff          /* OS-specific range end */
+#define ET_LOPROC      0xff00          /* Processor-specific range start */
+#define ET_HIPROC      0xffff          /* Processor-specific range end */
+
+/* Legal values for e_machine (architecture).  */
+
+#define EM_NONE                 0              /* No machine */
+#define EM_M32          1              /* AT&T WE 32100 */
+#define EM_SPARC        2              /* SUN SPARC */
+#define EM_386          3              /* Intel 80386 */
+#define EM_68K          4              /* Motorola m68k family */
+#define EM_88K          5              /* Motorola m88k family */
+#define EM_860          7              /* Intel 80860 */
+#define EM_MIPS                 8              /* MIPS R3000 big-endian */
+#define EM_S370                 9              /* IBM System/370 */
+#define EM_MIPS_RS3_LE 10              /* MIPS R3000 little-endian */
+
+#define EM_PARISC      15              /* HPPA */
+#define EM_VPP500      17              /* Fujitsu VPP500 */
+#define EM_SPARC32PLUS 18              /* Sun's "v8plus" */
+#define EM_960         19              /* Intel 80960 */
+#define EM_PPC         20              /* PowerPC */
+#define EM_PPC64       21              /* PowerPC 64-bit */
+#define EM_S390                22              /* IBM S390 */
+
+#define EM_V800                36              /* NEC V800 series */
+#define EM_FR20                37              /* Fujitsu FR20 */
+#define EM_RH32                38              /* TRW RH-32 */
+#define EM_RCE         39              /* Motorola RCE */
+#define EM_ARM         40              /* ARM */
+#define EM_FAKE_ALPHA  41              /* Digital Alpha */
+#define EM_SH          42              /* Hitachi SH */
+#define EM_SPARCV9     43              /* SPARC v9 64-bit */
+#define EM_TRICORE     44              /* Siemens Tricore */
+#define EM_ARC         45              /* Argonaut RISC Core */
+#define EM_H8_300      46              /* Hitachi H8/300 */
+#define EM_H8_300H     47              /* Hitachi H8/300H */
+#define EM_H8S         48              /* Hitachi H8S */
+#define EM_H8_500      49              /* Hitachi H8/500 */
+#define EM_IA_64       50              /* Intel Merced */
+#define EM_MIPS_X      51              /* Stanford MIPS-X */
+#define EM_COLDFIRE    52              /* Motorola Coldfire */
+#define EM_68HC12      53              /* Motorola M68HC12 */
+#define EM_MMA         54              /* Fujitsu MMA Multimedia Accelerator*/
+#define EM_PCP         55              /* Siemens PCP */
+#define EM_NCPU                56              /* Sony nCPU embeeded RISC */
+#define EM_NDR1                57              /* Denso NDR1 microprocessor */
+#define EM_STARCORE    58              /* Motorola Start*Core processor */
+#define EM_ME16                59              /* Toyota ME16 processor */
+#define EM_ST100       60              /* STMicroelectronic ST100 processor */
+#define EM_TINYJ       61              /* Advanced Logic Corp. Tinyj emb.fam*/
+#define EM_X86_64      62              /* AMD x86-64 architecture */
+#define EM_PDSP                63              /* Sony DSP Processor */
+
+#define EM_FX66                66              /* Siemens FX66 microcontroller */
+#define EM_ST9PLUS     67              /* STMicroelectronics ST9+ 8/16 mc */
+#define EM_ST7         68              /* STmicroelectronics ST7 8 bit mc */
+#define EM_68HC16      69              /* Motorola MC68HC16 microcontroller */
+#define EM_68HC11      70              /* Motorola MC68HC11 microcontroller */
+#define EM_68HC08      71              /* Motorola MC68HC08 microcontroller */
+#define EM_68HC05      72              /* Motorola MC68HC05 microcontroller */
+#define EM_SVX         73              /* Silicon Graphics SVx */
+#define EM_ST19                74              /* STMicroelectronics ST19 8 bit mc */
+#define EM_VAX         75              /* Digital VAX */
+#define EM_CRIS                76              /* Axis Communications 32-bit embedded processor */
+#define EM_JAVELIN     77              /* Infineon Technologies 32-bit embedded processor */
+#define EM_FIREPATH    78              /* Element 14 64-bit DSP Processor */
+#define EM_ZSP         79              /* LSI Logic 16-bit DSP Processor */
+#define EM_MMIX                80              /* Donald Knuth's educational 64-bit processor */
+#define EM_HUANY       81              /* Harvard University machine-independent object files */
+#define EM_PRISM       82              /* SiTera Prism */
+#define EM_AVR         83              /* Atmel AVR 8-bit microcontroller */
+#define EM_FR30                84              /* Fujitsu FR30 */
+#define EM_D10V                85              /* Mitsubishi D10V */
+#define EM_D30V                86              /* Mitsubishi D30V */
+#define EM_V850                87              /* NEC v850 */
+#define EM_M32R                88              /* Mitsubishi M32R */
+#define EM_MN10300     89              /* Matsushita MN10300 */
+#define EM_MN10200     90              /* Matsushita MN10200 */
+#define EM_PJ          91              /* picoJava */
+#define EM_OPENRISC    92              /* OpenRISC 32-bit embedded processor */
+#define EM_ARC_A5      93              /* ARC Cores Tangent-A5 */
+#define EM_XTENSA      94              /* Tensilica Xtensa Architecture */
+#define EM_NUM         95
+
+/* If it is necessary to assign new unofficial EM_* values, please
+   pick large random numbers (0x8523, 0xa7f2, etc.) to minimize the
+   chances of collision with official or non-GNU unofficial values.  */
+
+#define EM_ALPHA       0x9026
+
+/* Legal values for e_version (version).  */
+
+#define EV_NONE                0               /* Invalid ELF version */
+#define EV_CURRENT     1               /* Current version */
+#define EV_NUM         2
+
+/* Section header.  */
+
+typedef struct
+{
+  Elf32_Word   sh_name;                /* Section name (string tbl index) */
+  Elf32_Word   sh_type;                /* Section type */
+  Elf32_Word   sh_flags;               /* Section flags */
+  Elf32_Addr   sh_addr;                /* Section virtual addr at execution */
+  Elf32_Off    sh_offset;              /* Section file offset */
+  Elf32_Word   sh_size;                /* Section size in bytes */
+  Elf32_Word   sh_link;                /* Link to another section */
+  Elf32_Word   sh_info;                /* Additional section information */
+  Elf32_Word   sh_addralign;           /* Section alignment */
+  Elf32_Word   sh_entsize;             /* Entry size if section holds table */
+} Elf32_Shdr;
+
+typedef struct
+{
+  Elf64_Word   sh_name;                /* Section name (string tbl index) */
+  Elf64_Word   sh_type;                /* Section type */
+  Elf64_Xword  sh_flags;               /* Section flags */
+  Elf64_Addr   sh_addr;                /* Section virtual addr at execution */
+  Elf64_Off    sh_offset;              /* Section file offset */
+  Elf64_Xword  sh_size;                /* Section size in bytes */
+  Elf64_Word   sh_link;                /* Link to another section */
+  Elf64_Word   sh_info;                /* Additional section information */
+  Elf64_Xword  sh_addralign;           /* Section alignment */
+  Elf64_Xword  sh_entsize;             /* Entry size if section holds table */
+} Elf64_Shdr;
+
+/* Special section indices.  */
+
+#define SHN_UNDEF      0               /* Undefined section */
+#define SHN_LORESERVE  0xff00          /* Start of reserved indices */
+#define SHN_LOPROC     0xff00          /* Start of processor-specific */
+#define SHN_BEFORE     0xff00          /* Order section before all others
+                                          (Solaris).  */
+#define SHN_AFTER      0xff01          /* Order section after all others
+                                          (Solaris).  */
+#define SHN_HIPROC     0xff1f          /* End of processor-specific */
+#define SHN_LOOS       0xff20          /* Start of OS-specific */
+#define SHN_HIOS       0xff3f          /* End of OS-specific */
+#define SHN_ABS                0xfff1          /* Associated symbol is absolute */
+#define SHN_COMMON     0xfff2          /* Associated symbol is common */
+#define SHN_XINDEX     0xffff          /* Index is in extra table.  */
+#define SHN_HIRESERVE  0xffff          /* End of reserved indices */
+
+/* Legal values for sh_type (section type).  */
+
+#define SHT_NULL         0             /* Section header table entry unused */
+#define SHT_PROGBITS     1             /* Program data */
+#define SHT_SYMTAB       2             /* Symbol table */
+#define SHT_STRTAB       3             /* String table */
+#define SHT_RELA         4             /* Relocation entries with addends */
+#define SHT_HASH         5             /* Symbol hash table */
+#define SHT_DYNAMIC      6             /* Dynamic linking information */
+#define SHT_NOTE         7             /* Notes */
+#define SHT_NOBITS       8             /* Program space with no data (bss) */
+#define SHT_REL                  9             /* Relocation entries, no addends */
+#define SHT_SHLIB        10            /* Reserved */
+#define SHT_DYNSYM       11            /* Dynamic linker symbol table */
+#define SHT_INIT_ARRAY   14            /* Array of constructors */
+#define SHT_FINI_ARRAY   15            /* Array of destructors */
+#define SHT_PREINIT_ARRAY 16           /* Array of pre-constructors */
+#define SHT_GROUP        17            /* Section group */
+#define SHT_SYMTAB_SHNDX  18           /* Extended section indeces */
+#define        SHT_NUM           19            /* Number of defined types.  */
+#define SHT_LOOS         0x60000000    /* Start OS-specific */
+#define SHT_GNU_LIBLIST          0x6ffffff7    /* Prelink library list */
+#define SHT_CHECKSUM     0x6ffffff8    /* Checksum for DSO content.  */
+#define SHT_LOSUNW       0x6ffffffa    /* Sun-specific low bound.  */
+#define SHT_SUNW_move    0x6ffffffa
+#define SHT_SUNW_COMDAT   0x6ffffffb
+#define SHT_SUNW_syminfo  0x6ffffffc
+#define SHT_GNU_verdef   0x6ffffffd    /* Version definition section.  */
+#define SHT_GNU_verneed          0x6ffffffe    /* Version needs section.  */
+#define SHT_GNU_versym   0x6fffffff    /* Version symbol table.  */
+#define SHT_HISUNW       0x6fffffff    /* Sun-specific high bound.  */
+#define SHT_HIOS         0x6fffffff    /* End OS-specific type */
+#define SHT_LOPROC       0x70000000    /* Start of processor-specific */
+#define SHT_HIPROC       0x7fffffff    /* End of processor-specific */
+#define SHT_LOUSER       0x80000000    /* Start of application-specific */
+#define SHT_HIUSER       0x8fffffff    /* End of application-specific */
+
+/* Legal values for sh_flags (section flags).  */
+
+#define SHF_WRITE           (1 << 0)   /* Writable */
+#define SHF_ALLOC           (1 << 1)   /* Occupies memory during execution */
+#define SHF_EXECINSTR       (1 << 2)   /* Executable */
+#define SHF_MERGE           (1 << 4)   /* Might be merged */
+#define SHF_STRINGS         (1 << 5)   /* Contains nul-terminated strings */
+#define SHF_INFO_LINK       (1 << 6)   /* `sh_info' contains SHT index */
+#define SHF_LINK_ORDER      (1 << 7)   /* Preserve order after combining */
+#define SHF_OS_NONCONFORMING (1 << 8)  /* Non-standard OS specific handling
+                                          required */
+#define SHF_GROUP           (1 << 9)   /* Section is member of a group.  */
+#define SHF_TLS                     (1 << 10)  /* Section hold thread-local data.  */
+#define SHF_MASKOS          0x0ff00000 /* OS-specific.  */
+#define SHF_MASKPROC        0xf0000000 /* Processor-specific */
+#define SHF_ORDERED         (1 << 30)  /* Special ordering requirement
+                                          (Solaris).  */
+#define SHF_EXCLUDE         (1 << 31)  /* Section is excluded unless
+                                          referenced or allocated (Solaris).*/
+
+/* Section group handling.  */
+#define GRP_COMDAT     0x1             /* Mark group as COMDAT.  */
+
+/* Symbol table entry.  */
+
+typedef struct
+{
+  Elf32_Word   st_name;                /* Symbol name (string tbl index) */
+  Elf32_Addr   st_value;               /* Symbol value */
+  Elf32_Word   st_size;                /* Symbol size */
+  unsigned char        st_info;                /* Symbol type and binding */
+  unsigned char        st_other;               /* Symbol visibility */
+  Elf32_Section        st_shndx;               /* Section index */
+} Elf32_Sym;
+
+typedef struct
+{
+  Elf64_Word   st_name;                /* Symbol name (string tbl index) */
+  unsigned char        st_info;                /* Symbol type and binding */
+  unsigned char st_other;              /* Symbol visibility */
+  Elf64_Section        st_shndx;               /* Section index */
+  Elf64_Addr   st_value;               /* Symbol value */
+  Elf64_Xword  st_size;                /* Symbol size */
+} Elf64_Sym;
+
+/* The syminfo section if available contains additional information about
+   every dynamic symbol.  */
+
+typedef struct
+{
+  Elf32_Half si_boundto;               /* Direct bindings, symbol bound to */
+  Elf32_Half si_flags;                 /* Per symbol flags */
+} Elf32_Syminfo;
+
+typedef struct
+{
+  Elf64_Half si_boundto;               /* Direct bindings, symbol bound to */
+  Elf64_Half si_flags;                 /* Per symbol flags */
+} Elf64_Syminfo;
+
+/* Possible values for si_boundto.  */
+#define SYMINFO_BT_SELF                0xffff  /* Symbol bound to self */
+#define SYMINFO_BT_PARENT      0xfffe  /* Symbol bound to parent */
+#define SYMINFO_BT_LOWRESERVE  0xff00  /* Beginning of reserved entries */
+
+/* Possible bitmasks for si_flags.  */
+#define SYMINFO_FLG_DIRECT     0x0001  /* Direct bound symbol */
+#define SYMINFO_FLG_PASSTHRU   0x0002  /* Pass-thru symbol for translator */
+#define SYMINFO_FLG_COPY       0x0004  /* Symbol is a copy-reloc */
+#define SYMINFO_FLG_LAZYLOAD   0x0008  /* Symbol bound to object to be lazy
+                                          loaded */
+/* Syminfo version values.  */
+#define SYMINFO_NONE           0
+#define SYMINFO_CURRENT                1
+#define SYMINFO_NUM            2
+
+
+/* How to extract and insert information held in the st_info field.  */
+
+#define ELF32_ST_BIND(val)             (((unsigned char) (val)) >> 4)
+#define ELF32_ST_TYPE(val)             ((val) & 0xf)
+#define ELF32_ST_INFO(bind, type)      (((bind) << 4) + ((type) & 0xf))
+
+/* Both Elf32_Sym and Elf64_Sym use the same one-byte st_info field.  */
+#define ELF64_ST_BIND(val)             ELF32_ST_BIND (val)
+#define ELF64_ST_TYPE(val)             ELF32_ST_TYPE (val)
+#define ELF64_ST_INFO(bind, type)      ELF32_ST_INFO ((bind), (type))
+
+/* Legal values for ST_BIND subfield of st_info (symbol binding).  */
+
+#define STB_LOCAL      0               /* Local symbol */
+#define STB_GLOBAL     1               /* Global symbol */
+#define STB_WEAK       2               /* Weak symbol */
+#define        STB_NUM         3               /* Number of defined types.  */
+#define STB_LOOS       10              /* Start of OS-specific */
+#define STB_HIOS       12              /* End of OS-specific */
+#define STB_LOPROC     13              /* Start of processor-specific */
+#define STB_HIPROC     15              /* End of processor-specific */
+
+/* Legal values for ST_TYPE subfield of st_info (symbol type).  */
+
+#define STT_NOTYPE     0               /* Symbol type is unspecified */
+#define STT_OBJECT     1               /* Symbol is a data object */
+#define STT_FUNC       2               /* Symbol is a code object */
+#define STT_SECTION    3               /* Symbol associated with a section */
+#define STT_FILE       4               /* Symbol's name is file name */
+#define STT_COMMON     5               /* Symbol is a common data object */
+#define STT_TLS                6               /* Symbol is thread-local data object*/
+#define        STT_NUM         7               /* Number of defined types.  */
+#define STT_LOOS       10              /* Start of OS-specific */
+#define STT_HIOS       12              /* End of OS-specific */
+#define STT_LOPROC     13              /* Start of processor-specific */
+#define STT_HIPROC     15              /* End of processor-specific */
+
+
+/* Symbol table indices are found in the hash buckets and chain table
+   of a symbol hash table section.  This special index value indicates
+   the end of a chain, meaning no further symbols are found in that bucket.  */
+
+#define STN_UNDEF      0               /* End of a chain.  */
+
+
+/* How to extract and insert information held in the st_other field.  */
+
+#define ELF32_ST_VISIBILITY(o) ((o) & 0x03)
+
+/* For ELF64 the definitions are the same.  */
+#define ELF64_ST_VISIBILITY(o) ELF32_ST_VISIBILITY (o)
+
+/* Symbol visibility specification encoded in the st_other field.  */
+#define STV_DEFAULT    0               /* Default symbol visibility rules */
+#define STV_INTERNAL   1               /* Processor specific hidden class */
+#define STV_HIDDEN     2               /* Sym unavailable in other modules */
+#define STV_PROTECTED  3               /* Not preemptible, not exported */
+
+
+/* Relocation table entry without addend (in section of type SHT_REL).  */
+
+typedef struct
+{
+  Elf32_Addr   r_offset;               /* Address */
+  Elf32_Word   r_info;                 /* Relocation type and symbol index */
+} Elf32_Rel;
+
+/* I have seen two different definitions of the Elf64_Rel and
+   Elf64_Rela structures, so we'll leave them out until Novell (or
+   whoever) gets their act together.  */
+/* The following, at least, is used on Sparc v9, MIPS, and Alpha.  */
+
+typedef struct
+{
+  Elf64_Addr   r_offset;               /* Address */
+  Elf64_Xword  r_info;                 /* Relocation type and symbol index */
+} Elf64_Rel;
+
+/* Relocation table entry with addend (in section of type SHT_RELA).  */
+
+typedef struct
+{
+  Elf32_Addr   r_offset;               /* Address */
+  Elf32_Word   r_info;                 /* Relocation type and symbol index */
+  Elf32_Sword  r_addend;               /* Addend */
+} Elf32_Rela;
+
+typedef struct
+{
+  Elf64_Addr   r_offset;               /* Address */
+  Elf64_Xword  r_info;                 /* Relocation type and symbol index */
+  Elf64_Sxword r_addend;               /* Addend */
+} Elf64_Rela;
+
+/* How to extract and insert information held in the r_info field.  */
+
+#define ELF32_R_SYM(val)               ((val) >> 8)
+#define ELF32_R_TYPE(val)              ((val) & 0xff)
+#define ELF32_R_INFO(sym, type)                (((sym) << 8) + ((type) & 0xff))
+
+#define ELF64_R_SYM(i)                 ((i) >> 32)
+#define ELF64_R_TYPE(i)                        ((i) & 0xffffffff)
+#define ELF64_R_INFO(sym,type)         ((((Elf64_Xword) (sym)) << 32) + (type))
+
+/* Program segment header.  */
+
+typedef struct
+{
+  Elf32_Word   p_type;                 /* Segment type */
+  Elf32_Off    p_offset;               /* Segment file offset */
+  Elf32_Addr   p_vaddr;                /* Segment virtual address */
+  Elf32_Addr   p_paddr;                /* Segment physical address */
+  Elf32_Word   p_filesz;               /* Segment size in file */
+  Elf32_Word   p_memsz;                /* Segment size in memory */
+  Elf32_Word   p_flags;                /* Segment flags */
+  Elf32_Word   p_align;                /* Segment alignment */
+} Elf32_Phdr;
+
+typedef struct
+{
+  Elf64_Word   p_type;                 /* Segment type */
+  Elf64_Word   p_flags;                /* Segment flags */
+  Elf64_Off    p_offset;               /* Segment file offset */
+  Elf64_Addr   p_vaddr;                /* Segment virtual address */
+  Elf64_Addr   p_paddr;                /* Segment physical address */
+  Elf64_Xword  p_filesz;               /* Segment size in file */
+  Elf64_Xword  p_memsz;                /* Segment size in memory */
+  Elf64_Xword  p_align;                /* Segment alignment */
+} Elf64_Phdr;
+
+/* Legal values for p_type (segment type).  */
+
+#define        PT_NULL         0               /* Program header table entry unused */
+#define PT_LOAD                1               /* Loadable program segment */
+#define PT_DYNAMIC     2               /* Dynamic linking information */
+#define PT_INTERP      3               /* Program interpreter */
+#define PT_NOTE                4               /* Auxiliary information */
+#define PT_SHLIB       5               /* Reserved */
+#define PT_PHDR                6               /* Entry for header table itself */
+#define PT_TLS         7               /* Thread-local storage segment */
+#define        PT_NUM          8               /* Number of defined types */
+#define PT_LOOS                0x60000000      /* Start of OS-specific */
+#define PT_GNU_EH_FRAME        0x6474e550      /* GCC .eh_frame_hdr segment */
+#define PT_GNU_STACK   0x6474e551      /* Indicates stack executability */
+#define PT_GNU_RELRO   0x6474e552      /* Read-only after relocation */
+#define PT_LOSUNW      0x6ffffffa
+#define PT_SUNWBSS     0x6ffffffa      /* Sun Specific segment */
+#define PT_SUNWSTACK   0x6ffffffb      /* Stack segment */
+#define PT_HISUNW      0x6fffffff
+#define PT_HIOS                0x6fffffff      /* End of OS-specific */
+#define PT_LOPROC      0x70000000      /* Start of processor-specific */
+#define PT_HIPROC      0x7fffffff      /* End of processor-specific */
+
+/* Legal values for p_flags (segment flags).  */
+
+#define PF_X           (1 << 0)        /* Segment is executable */
+#define PF_W           (1 << 1)        /* Segment is writable */
+#define PF_R           (1 << 2)        /* Segment is readable */
+#define PF_MASKOS      0x0ff00000      /* OS-specific */
+#define PF_MASKPROC    0xf0000000      /* Processor-specific */
+
+/* Legal values for note segment descriptor types for core files. */
+
+#define NT_PRSTATUS    1               /* Contains copy of prstatus struct */
+#define NT_FPREGSET    2               /* Contains copy of fpregset struct */
+#define NT_PRPSINFO    3               /* Contains copy of prpsinfo struct */
+#define NT_PRXREG      4               /* Contains copy of prxregset struct */
+#define NT_TASKSTRUCT  4               /* Contains copy of task structure */
+#define NT_PLATFORM    5               /* String from sysinfo(SI_PLATFORM) */
+#define NT_AUXV                6               /* Contains copy of auxv array */
+#define NT_GWINDOWS    7               /* Contains copy of gwindows struct */
+#define NT_ASRS                8               /* Contains copy of asrset struct */
+#define NT_PSTATUS     10              /* Contains copy of pstatus struct */
+#define NT_PSINFO      13              /* Contains copy of psinfo struct */
+#define NT_PRCRED      14              /* Contains copy of prcred struct */
+#define NT_UTSNAME     15              /* Contains copy of utsname struct */
+#define NT_LWPSTATUS   16              /* Contains copy of lwpstatus struct */
+#define NT_LWPSINFO    17              /* Contains copy of lwpinfo struct */
+#define NT_PRFPXREG    20              /* Contains copy of fprxregset struct*/
+
+/* Legal values for the note segment descriptor types for object files.  */
+
+#define NT_VERSION     1               /* Contains a version string.  */
+
+
+/* Dynamic section entry.  */
+
+typedef struct
+{
+  Elf32_Sword  d_tag;                  /* Dynamic entry type */
+  union
+    {
+      Elf32_Word d_val;                        /* Integer value */
+      Elf32_Addr d_ptr;                        /* Address value */
+    } d_un;
+} Elf32_Dyn;
+
+typedef struct
+{
+  Elf64_Sxword d_tag;                  /* Dynamic entry type */
+  union
+    {
+      Elf64_Xword d_val;               /* Integer value */
+      Elf64_Addr d_ptr;                        /* Address value */
+    } d_un;
+} Elf64_Dyn;
+
+/* Legal values for d_tag (dynamic entry type).  */
+
+#define DT_NULL                0               /* Marks end of dynamic section */
+#define DT_NEEDED      1               /* Name of needed library */
+#define DT_PLTRELSZ    2               /* Size in bytes of PLT relocs */
+#define DT_PLTGOT      3               /* Processor defined value */
+#define DT_HASH                4               /* Address of symbol hash table */
+#define DT_STRTAB      5               /* Address of string table */
+#define DT_SYMTAB      6               /* Address of symbol table */
+#define DT_RELA                7               /* Address of Rela relocs */
+#define DT_RELASZ      8               /* Total size of Rela relocs */
+#define DT_RELAENT     9               /* Size of one Rela reloc */
+#define DT_STRSZ       10              /* Size of string table */
+#define DT_SYMENT      11              /* Size of one symbol table entry */
+#define DT_INIT                12              /* Address of init function */
+#define DT_FINI                13              /* Address of termination function */
+#define DT_SONAME      14              /* Name of shared object */
+#define DT_RPATH       15              /* Library search path (deprecated) */
+#define DT_SYMBOLIC    16              /* Start symbol search here */
+#define DT_REL         17              /* Address of Rel relocs */
+#define DT_RELSZ       18              /* Total size of Rel relocs */
+#define DT_RELENT      19              /* Size of one Rel reloc */
+#define DT_PLTREL      20              /* Type of reloc in PLT */
+#define DT_DEBUG       21              /* For debugging; unspecified */
+#define DT_TEXTREL     22              /* Reloc might modify .text */
+#define DT_JMPREL      23              /* Address of PLT relocs */
+#define        DT_BIND_NOW     24              /* Process relocations of object */
+#define        DT_INIT_ARRAY   25              /* Array with addresses of init fct */
+#define        DT_FINI_ARRAY   26              /* Array with addresses of fini fct */
+#define        DT_INIT_ARRAYSZ 27              /* Size in bytes of DT_INIT_ARRAY */
+#define        DT_FINI_ARRAYSZ 28              /* Size in bytes of DT_FINI_ARRAY */
+#define DT_RUNPATH     29              /* Library search path */
+#define DT_FLAGS       30              /* Flags for the object being loaded */
+#define DT_ENCODING    32              /* Start of encoded range */
+#define DT_PREINIT_ARRAY 32            /* Array with addresses of preinit fct*/
+#define DT_PREINIT_ARRAYSZ 33          /* size in bytes of DT_PREINIT_ARRAY */
+#define        DT_NUM          34              /* Number used */
+#define DT_LOOS                0x6000000d      /* Start of OS-specific */
+#define DT_HIOS                0x6ffff000      /* End of OS-specific */
+#define DT_LOPROC      0x70000000      /* Start of processor-specific */
+#define DT_HIPROC      0x7fffffff      /* End of processor-specific */
+#define        DT_PROCNUM      DT_MIPS_NUM     /* Most used by any processor */
+
+/* DT_* entries which fall between DT_VALRNGHI & DT_VALRNGLO use the
+   Dyn.d_un.d_val field of the Elf*_Dyn structure.  This follows Sun's
+   approach.  */
+#define DT_VALRNGLO    0x6ffffd00
+#define DT_GNU_PRELINKED 0x6ffffdf5    /* Prelinking timestamp */
+#define DT_GNU_CONFLICTSZ 0x6ffffdf6   /* Size of conflict section */
+#define DT_GNU_LIBLISTSZ 0x6ffffdf7    /* Size of library list */
+#define DT_CHECKSUM    0x6ffffdf8
+#define DT_PLTPADSZ    0x6ffffdf9
+#define DT_MOVEENT     0x6ffffdfa
+#define DT_MOVESZ      0x6ffffdfb
+#define DT_FEATURE_1   0x6ffffdfc      /* Feature selection (DTF_*).  */
+#define DT_POSFLAG_1   0x6ffffdfd      /* Flags for DT_* entries, effecting
+                                          the following DT_* entry.  */
+#define DT_SYMINSZ     0x6ffffdfe      /* Size of syminfo table (in bytes) */
+#define DT_SYMINENT    0x6ffffdff      /* Entry size of syminfo */
+#define DT_VALRNGHI    0x6ffffdff
+#define DT_VALTAGIDX(tag)      (DT_VALRNGHI - (tag))   /* Reverse order! */
+#define DT_VALNUM 12
+
+/* DT_* entries which fall between DT_ADDRRNGHI & DT_ADDRRNGLO use the
+   Dyn.d_un.d_ptr field of the Elf*_Dyn structure.
+
+   If any adjustment is made to the ELF object after it has been
+   built these entries will need to be adjusted.  */
+#define DT_ADDRRNGLO   0x6ffffe00
+#define DT_GNU_CONFLICT        0x6ffffef8      /* Start of conflict section */
+#define DT_GNU_LIBLIST 0x6ffffef9      /* Library list */
+#define DT_CONFIG      0x6ffffefa      /* Configuration information.  */
+#define DT_DEPAUDIT    0x6ffffefb      /* Dependency auditing.  */
+#define DT_AUDIT       0x6ffffefc      /* Object auditing.  */
+#define        DT_PLTPAD       0x6ffffefd      /* PLT padding.  */
+#define        DT_MOVETAB      0x6ffffefe      /* Move table.  */
+#define DT_SYMINFO     0x6ffffeff      /* Syminfo table.  */
+#define DT_ADDRRNGHI   0x6ffffeff
+#define DT_ADDRTAGIDX(tag)     (DT_ADDRRNGHI - (tag))  /* Reverse order! */
+#define DT_ADDRNUM 10
+
+/* The versioning entry types.  The next are defined as part of the
+   GNU extension.  */
+#define DT_VERSYM      0x6ffffff0
+
+#define DT_RELACOUNT   0x6ffffff9
+#define DT_RELCOUNT    0x6ffffffa
+
+/* These were chosen by Sun.  */
+#define DT_FLAGS_1     0x6ffffffb      /* State flags, see DF_1_* below.  */
+#define        DT_VERDEF       0x6ffffffc      /* Address of version definition
+                                          table */
+#define        DT_VERDEFNUM    0x6ffffffd      /* Number of version definitions */
+#define        DT_VERNEED      0x6ffffffe      /* Address of table with needed
+                                          versions */
+#define        DT_VERNEEDNUM   0x6fffffff      /* Number of needed versions */
+#define DT_VERSIONTAGIDX(tag)  (DT_VERNEEDNUM - (tag)) /* Reverse order! */
+#define DT_VERSIONTAGNUM 16
+
+/* Sun added these machine-independent extensions in the "processor-specific"
+   range.  Be compatible.  */
+#define DT_AUXILIARY    0x7ffffffd      /* Shared object to load before self */
+#define DT_FILTER       0x7fffffff      /* Shared object to get values from */
+#define DT_EXTRATAGIDX(tag)    ((Elf32_Word)-((Elf32_Sword) (tag) <<1>>1)-1)
+#define DT_EXTRANUM    3
+
+/* Values of `d_un.d_val' in the DT_FLAGS entry.  */
+#define DF_ORIGIN      0x00000001      /* Object may use DF_ORIGIN */
+#define DF_SYMBOLIC    0x00000002      /* Symbol resolutions starts here */
+#define DF_TEXTREL     0x00000004      /* Object contains text relocations */
+#define DF_BIND_NOW    0x00000008      /* No lazy binding for this object */
+#define DF_STATIC_TLS  0x00000010      /* Module uses the static TLS model */
+
+/* State flags selectable in the `d_un.d_val' element of the DT_FLAGS_1
+   entry in the dynamic section.  */
+#define DF_1_NOW       0x00000001      /* Set RTLD_NOW for this object.  */
+#define DF_1_GLOBAL    0x00000002      /* Set RTLD_GLOBAL for this object.  */
+#define DF_1_GROUP     0x00000004      /* Set RTLD_GROUP for this object.  */
+#define DF_1_NODELETE  0x00000008      /* Set RTLD_NODELETE for this object.*/
+#define DF_1_LOADFLTR  0x00000010      /* Trigger filtee loading at runtime.*/
+#define DF_1_INITFIRST 0x00000020      /* Set RTLD_INITFIRST for this object*/
+#define DF_1_NOOPEN    0x00000040      /* Set RTLD_NOOPEN for this object.  */
+#define DF_1_ORIGIN    0x00000080      /* $ORIGIN must be handled.  */
+#define DF_1_DIRECT    0x00000100      /* Direct binding enabled.  */
+#define DF_1_TRANS     0x00000200
+#define DF_1_INTERPOSE 0x00000400      /* Object is used to interpose.  */
+#define DF_1_NODEFLIB  0x00000800      /* Ignore default lib search path.  */
+#define DF_1_NODUMP    0x00001000      /* Object can't be dldump'ed.  */
+#define DF_1_CONFALT   0x00002000      /* Configuration alternative created.*/
+#define DF_1_ENDFILTEE 0x00004000      /* Filtee terminates filters search. */
+#define        DF_1_DISPRELDNE 0x00008000      /* Disp reloc applied at build time. */
+#define        DF_1_DISPRELPND 0x00010000      /* Disp reloc applied at run-time.  */
+
+/* Flags for the feature selection in DT_FEATURE_1.  */
+#define DTF_1_PARINIT  0x00000001
+#define DTF_1_CONFEXP  0x00000002
+
+/* Flags in the DT_POSFLAG_1 entry effecting only the next DT_* entry.  */
+#define DF_P1_LAZYLOAD 0x00000001      /* Lazyload following object.  */
+#define DF_P1_GROUPPERM        0x00000002      /* Symbols from next object are not
+                                          generally available.  */
+
+/* Version definition sections.  */
+
+typedef struct
+{
+  Elf32_Half   vd_version;             /* Version revision */
+  Elf32_Half   vd_flags;               /* Version information */
+  Elf32_Half   vd_ndx;                 /* Version Index */
+  Elf32_Half   vd_cnt;                 /* Number of associated aux entries */
+  Elf32_Word   vd_hash;                /* Version name hash value */
+  Elf32_Word   vd_aux;                 /* Offset in bytes to verdaux array */
+  Elf32_Word   vd_next;                /* Offset in bytes to next verdef
+                                          entry */
+} Elf32_Verdef;
+
+typedef struct
+{
+  Elf64_Half   vd_version;             /* Version revision */
+  Elf64_Half   vd_flags;               /* Version information */
+  Elf64_Half   vd_ndx;                 /* Version Index */
+  Elf64_Half   vd_cnt;                 /* Number of associated aux entries */
+  Elf64_Word   vd_hash;                /* Version name hash value */
+  Elf64_Word   vd_aux;                 /* Offset in bytes to verdaux array */
+  Elf64_Word   vd_next;                /* Offset in bytes to next verdef
+                                          entry */
+} Elf64_Verdef;
+
+
+/* Legal values for vd_version (version revision).  */
+#define VER_DEF_NONE   0               /* No version */
+#define VER_DEF_CURRENT        1               /* Current version */
+#define VER_DEF_NUM    2               /* Given version number */
+
+/* Legal values for vd_flags (version information flags).  */
+#define VER_FLG_BASE   0x1             /* Version definition of file itself */
+#define VER_FLG_WEAK   0x2             /* Weak version identifier */
+
+/* Versym symbol index values.  */
+#define        VER_NDX_LOCAL           0       /* Symbol is local.  */
+#define        VER_NDX_GLOBAL          1       /* Symbol is global.  */
+#define        VER_NDX_LORESERVE       0xff00  /* Beginning of reserved entries.  */
+#define        VER_NDX_ELIMINATE       0xff01  /* Symbol is to be eliminated.  */
+
+/* Auxialiary version information.  */
+
+typedef struct
+{
+  Elf32_Word   vda_name;               /* Version or dependency names */
+  Elf32_Word   vda_next;               /* Offset in bytes to next verdaux
+                                          entry */
+} Elf32_Verdaux;
+
+typedef struct
+{
+  Elf64_Word   vda_name;               /* Version or dependency names */
+  Elf64_Word   vda_next;               /* Offset in bytes to next verdaux
+                                          entry */
+} Elf64_Verdaux;
+
+
+/* Version dependency section.  */
+
+typedef struct
+{
+  Elf32_Half   vn_version;             /* Version of structure */
+  Elf32_Half   vn_cnt;                 /* Number of associated aux entries */
+  Elf32_Word   vn_file;                /* Offset of filename for this
+                                          dependency */
+  Elf32_Word   vn_aux;                 /* Offset in bytes to vernaux array */
+  Elf32_Word   vn_next;                /* Offset in bytes to next verneed
+                                          entry */
+} Elf32_Verneed;
+
+typedef struct
+{
+  Elf64_Half   vn_version;             /* Version of structure */
+  Elf64_Half   vn_cnt;                 /* Number of associated aux entries */
+  Elf64_Word   vn_file;                /* Offset of filename for this
+                                          dependency */
+  Elf64_Word   vn_aux;                 /* Offset in bytes to vernaux array */
+  Elf64_Word   vn_next;                /* Offset in bytes to next verneed
+                                          entry */
+} Elf64_Verneed;
+
+
+/* Legal values for vn_version (version revision).  */
+#define VER_NEED_NONE   0              /* No version */
+#define VER_NEED_CURRENT 1             /* Current version */
+#define VER_NEED_NUM    2              /* Given version number */
+
+/* Auxiliary needed version information.  */
+
+typedef struct
+{
+  Elf32_Word   vna_hash;               /* Hash value of dependency name */
+  Elf32_Half   vna_flags;              /* Dependency specific information */
+  Elf32_Half   vna_other;              /* Unused */
+  Elf32_Word   vna_name;               /* Dependency name string offset */
+  Elf32_Word   vna_next;               /* Offset in bytes to next vernaux
+                                          entry */
+} Elf32_Vernaux;
+
+typedef struct
+{
+  Elf64_Word   vna_hash;               /* Hash value of dependency name */
+  Elf64_Half   vna_flags;              /* Dependency specific information */
+  Elf64_Half   vna_other;              /* Unused */
+  Elf64_Word   vna_name;               /* Dependency name string offset */
+  Elf64_Word   vna_next;               /* Offset in bytes to next vernaux
+                                          entry */
+} Elf64_Vernaux;
+
+
+/* Legal values for vna_flags.  */
+#define VER_FLG_WEAK   0x2             /* Weak version identifier */
+
+
+/* Auxiliary vector.  */
+
+/* This vector is normally only used by the program interpreter.  The
+   usual definition in an ABI supplement uses the name auxv_t.  The
+   vector is not usually defined in a standard <elf.h> file, but it
+   can't hurt.  We rename it to avoid conflicts.  The sizes of these
+   types are an arrangement between the exec server and the program
+   interpreter, so we don't fully specify them here.  */
+
+typedef struct
+{
+  int a_type;                  /* Entry type */
+  union
+    {
+      long int a_val;          /* Integer value */
+      void *a_ptr;             /* Pointer value */
+      void (*a_fcn) (void);    /* Function pointer value */
+    } a_un;
+} Elf32_auxv_t;
+
+typedef struct
+{
+  long int a_type;             /* Entry type */
+  union
+    {
+      long int a_val;          /* Integer value */
+      void *a_ptr;             /* Pointer value */
+      void (*a_fcn) (void);    /* Function pointer value */
+    } a_un;
+} Elf64_auxv_t;
+
+/* Legal values for a_type (entry type).  */
+
+#define AT_NULL                0               /* End of vector */
+#define AT_IGNORE      1               /* Entry should be ignored */
+#define AT_EXECFD      2               /* File descriptor of program */
+#define AT_PHDR                3               /* Program headers for program */
+#define AT_PHENT       4               /* Size of program header entry */
+#define AT_PHNUM       5               /* Number of program headers */
+#define AT_PAGESZ      6               /* System page size */
+#define AT_BASE                7               /* Base address of interpreter */
+#define AT_FLAGS       8               /* Flags */
+#define AT_ENTRY       9               /* Entry point of program */
+#define AT_NOTELF      10              /* Program is not ELF */
+#define AT_UID         11              /* Real uid */
+#define AT_EUID                12              /* Effective uid */
+#define AT_GID         13              /* Real gid */
+#define AT_EGID                14              /* Effective gid */
+#define AT_CLKTCK      17              /* Frequency of times() */
+
+/* Some more special a_type values describing the hardware.  */
+#define AT_PLATFORM    15              /* String identifying platform.  */
+#define AT_HWCAP       16              /* Machine dependent hints about
+                                          processor capabilities.  */
+
+/* This entry gives some information about the FPU initialization
+   performed by the kernel.  */
+#define AT_FPUCW       18              /* Used FPU control word.  */
+
+/* Cache block sizes.  */
+#define AT_DCACHEBSIZE 19              /* Data cache block size.  */
+#define AT_ICACHEBSIZE 20              /* Instruction cache block size.  */
+#define AT_UCACHEBSIZE 21              /* Unified cache block size.  */
+
+/* A special ignored value for PPC, used by the kernel to control the
+   interpretation of the AUXV. Must be > 16.  */
+#define AT_IGNOREPPC   22              /* Entry should be ignored.  */
+
+#define        AT_SECURE       23              /* Boolean, was exec setuid-like?  */
+
+/* Pointer to the global system page used for system calls and other
+   nice things.  */
+#define AT_SYSINFO     32
+#define AT_SYSINFO_EHDR        33
+
+/* Shapes of the caches.  Bits 0-3 contains associativity; bits 4-7 contains
+   log2 of line size; mask those to get cache size.  */
+#define AT_L1I_CACHESHAPE      34
+#define AT_L1D_CACHESHAPE      35
+#define AT_L2_CACHESHAPE       36
+#define AT_L3_CACHESHAPE       37
+
+/* Note section contents.  Each entry in the note section begins with
+   a header of a fixed form.  */
+
+typedef struct
+{
+  Elf32_Word n_namesz;                 /* Length of the note's name.  */
+  Elf32_Word n_descsz;                 /* Length of the note's descriptor.  */
+  Elf32_Word n_type;                   /* Type of the note.  */
+} Elf32_Nhdr;
+
+typedef struct
+{
+  Elf64_Word n_namesz;                 /* Length of the note's name.  */
+  Elf64_Word n_descsz;                 /* Length of the note's descriptor.  */
+  Elf64_Word n_type;                   /* Type of the note.  */
+} Elf64_Nhdr;
+
+/* Known names of notes.  */
+
+/* Solaris entries in the note section have this name.  */
+#define ELF_NOTE_SOLARIS       "SUNW Solaris"
+
+/* Note entries for GNU systems have this name.  */
+#define ELF_NOTE_GNU           "GNU"
+
+
+/* Defined types of notes for Solaris.  */
+
+/* Value of descriptor (one word) is desired pagesize for the binary.  */
+#define ELF_NOTE_PAGESIZE_HINT 1
+
+
+/* Defined note types for GNU systems.  */
+
+/* ABI information.  The descriptor consists of words:
+   word 0: OS descriptor
+   word 1: major version of the ABI
+   word 2: minor version of the ABI
+   word 3: subminor version of the ABI
+*/
+#define ELF_NOTE_ABI           1
+
+/* Known OSes.  These value can appear in word 0 of an ELF_NOTE_ABI
+   note section entry.  */
+#define ELF_NOTE_OS_LINUX      0
+#define ELF_NOTE_OS_GNU                1
+#define ELF_NOTE_OS_SOLARIS2   2
+#define ELF_NOTE_OS_FREEBSD    3
+
+
+/* Move records.  */
+typedef struct
+{
+  Elf32_Xword m_value;         /* Symbol value.  */
+  Elf32_Word m_info;           /* Size and index.  */
+  Elf32_Word m_poffset;                /* Symbol offset.  */
+  Elf32_Half m_repeat;         /* Repeat count.  */
+  Elf32_Half m_stride;         /* Stride info.  */
+} Elf32_Move;
+
+typedef struct
+{
+  Elf64_Xword m_value;         /* Symbol value.  */
+  Elf64_Xword m_info;          /* Size and index.  */
+  Elf64_Xword m_poffset;       /* Symbol offset.  */
+  Elf64_Half m_repeat;         /* Repeat count.  */
+  Elf64_Half m_stride;         /* Stride info.  */
+} Elf64_Move;
+
+/* Macro to construct move records.  */
+#define ELF32_M_SYM(info)      ((info) >> 8)
+#define ELF32_M_SIZE(info)     ((unsigned char) (info))
+#define ELF32_M_INFO(sym, size)        (((sym) << 8) + (unsigned char) (size))
+
+#define ELF64_M_SYM(info)      ELF32_M_SYM (info)
+#define ELF64_M_SIZE(info)     ELF32_M_SIZE (info)
+#define ELF64_M_INFO(sym, size)        ELF32_M_INFO (sym, size)
+
+
+/* Motorola 68k specific definitions.  */
+
+/* Values for Elf32_Ehdr.e_flags.  */
+#define EF_CPU32       0x00810000
+
+/* m68k relocs.  */
+
+#define R_68K_NONE     0               /* No reloc */
+#define R_68K_32       1               /* Direct 32 bit  */
+#define R_68K_16       2               /* Direct 16 bit  */
+#define R_68K_8                3               /* Direct 8 bit  */
+#define R_68K_PC32     4               /* PC relative 32 bit */
+#define R_68K_PC16     5               /* PC relative 16 bit */
+#define R_68K_PC8      6               /* PC relative 8 bit */
+#define R_68K_GOT32    7               /* 32 bit PC relative GOT entry */
+#define R_68K_GOT16    8               /* 16 bit PC relative GOT entry */
+#define R_68K_GOT8     9               /* 8 bit PC relative GOT entry */
+#define R_68K_GOT32O   10              /* 32 bit GOT offset */
+#define R_68K_GOT16O   11              /* 16 bit GOT offset */
+#define R_68K_GOT8O    12              /* 8 bit GOT offset */
+#define R_68K_PLT32    13              /* 32 bit PC relative PLT address */
+#define R_68K_PLT16    14              /* 16 bit PC relative PLT address */
+#define R_68K_PLT8     15              /* 8 bit PC relative PLT address */
+#define R_68K_PLT32O   16              /* 32 bit PLT offset */
+#define R_68K_PLT16O   17              /* 16 bit PLT offset */
+#define R_68K_PLT8O    18              /* 8 bit PLT offset */
+#define R_68K_COPY     19              /* Copy symbol at runtime */
+#define R_68K_GLOB_DAT 20              /* Create GOT entry */
+#define R_68K_JMP_SLOT 21              /* Create PLT entry */
+#define R_68K_RELATIVE 22              /* Adjust by program base */
+/* Keep this the last entry.  */
+#define R_68K_NUM      23
+
+/* Intel 80386 specific definitions.  */
+
+/* i386 relocs.  */
+
+#define R_386_NONE        0            /* No reloc */
+#define R_386_32          1            /* Direct 32 bit  */
+#define R_386_PC32        2            /* PC relative 32 bit */
+#define R_386_GOT32       3            /* 32 bit GOT entry */
+#define R_386_PLT32       4            /* 32 bit PLT address */
+#define R_386_COPY        5            /* Copy symbol at runtime */
+#define R_386_GLOB_DAT    6            /* Create GOT entry */
+#define R_386_JMP_SLOT    7            /* Create PLT entry */
+#define R_386_RELATIVE    8            /* Adjust by program base */
+#define R_386_GOTOFF      9            /* 32 bit offset to GOT */
+#define R_386_GOTPC       10           /* 32 bit PC relative offset to GOT */
+#define R_386_32PLT       11
+#define R_386_TLS_TPOFF           14           /* Offset in static TLS block */
+#define R_386_TLS_IE      15           /* Address of GOT entry for static TLS
+                                          block offset */
+#define R_386_TLS_GOTIE           16           /* GOT entry for static TLS block
+                                          offset */
+#define R_386_TLS_LE      17           /* Offset relative to static TLS
+                                          block */
+#define R_386_TLS_GD      18           /* Direct 32 bit for GNU version of
+                                          general dynamic thread local data */
+#define R_386_TLS_LDM     19           /* Direct 32 bit for GNU version of
+                                          local dynamic thread local data
+                                          in LE code */
+#define R_386_16          20
+#define R_386_PC16        21
+#define R_386_8                   22
+#define R_386_PC8         23
+#define R_386_TLS_GD_32           24           /* Direct 32 bit for general dynamic
+                                          thread local data */
+#define R_386_TLS_GD_PUSH  25          /* Tag for pushl in GD TLS code */
+#define R_386_TLS_GD_CALL  26          /* Relocation for call to
+                                          __tls_get_addr() */
+#define R_386_TLS_GD_POP   27          /* Tag for popl in GD TLS code */
+#define R_386_TLS_LDM_32   28          /* Direct 32 bit for local dynamic
+                                          thread local data in LE code */
+#define R_386_TLS_LDM_PUSH 29          /* Tag for pushl in LDM TLS code */
+#define R_386_TLS_LDM_CALL 30          /* Relocation for call to
+                                          __tls_get_addr() in LDM code */
+#define R_386_TLS_LDM_POP  31          /* Tag for popl in LDM TLS code */
+#define R_386_TLS_LDO_32   32          /* Offset relative to TLS block */
+#define R_386_TLS_IE_32           33           /* GOT entry for negated static TLS
+                                          block offset */
+#define R_386_TLS_LE_32           34           /* Negated offset relative to static
+                                          TLS block */
+#define R_386_TLS_DTPMOD32 35          /* ID of module containing symbol */
+#define R_386_TLS_DTPOFF32 36          /* Offset in TLS block */
+#define R_386_TLS_TPOFF32  37          /* Negated offset in static TLS block */
+/* Keep this the last entry.  */
+#define R_386_NUM         38
+
+/* SUN SPARC specific definitions.  */
+
+/* Legal values for ST_TYPE subfield of st_info (symbol type).  */
+
+#define STT_SPARC_REGISTER     13      /* Global register reserved to app. */
+
+/* Values for Elf64_Ehdr.e_flags.  */
+
+#define EF_SPARCV9_MM          3
+#define EF_SPARCV9_TSO         0
+#define EF_SPARCV9_PSO         1
+#define EF_SPARCV9_RMO         2
+#define EF_SPARC_LEDATA                0x800000 /* little endian data */
+#define EF_SPARC_EXT_MASK      0xFFFF00
+#define EF_SPARC_32PLUS                0x000100 /* generic V8+ features */
+#define EF_SPARC_SUN_US1       0x000200 /* Sun UltraSPARC1 extensions */
+#define EF_SPARC_HAL_R1                0x000400 /* HAL R1 extensions */
+#define EF_SPARC_SUN_US3       0x000800 /* Sun UltraSPARCIII extensions */
+
+/* SPARC relocs.  */
+
+#define R_SPARC_NONE           0       /* No reloc */
+#define R_SPARC_8              1       /* Direct 8 bit */
+#define R_SPARC_16             2       /* Direct 16 bit */
+#define R_SPARC_32             3       /* Direct 32 bit */
+#define R_SPARC_DISP8          4       /* PC relative 8 bit */
+#define R_SPARC_DISP16         5       /* PC relative 16 bit */
+#define R_SPARC_DISP32         6       /* PC relative 32 bit */
+#define R_SPARC_WDISP30                7       /* PC relative 30 bit shifted */
+#define R_SPARC_WDISP22                8       /* PC relative 22 bit shifted */
+#define R_SPARC_HI22           9       /* High 22 bit */
+#define R_SPARC_22             10      /* Direct 22 bit */
+#define R_SPARC_13             11      /* Direct 13 bit */
+#define R_SPARC_LO10           12      /* Truncated 10 bit */
+#define R_SPARC_GOT10          13      /* Truncated 10 bit GOT entry */
+#define R_SPARC_GOT13          14      /* 13 bit GOT entry */
+#define R_SPARC_GOT22          15      /* 22 bit GOT entry shifted */
+#define R_SPARC_PC10           16      /* PC relative 10 bit truncated */
+#define R_SPARC_PC22           17      /* PC relative 22 bit shifted */
+#define R_SPARC_WPLT30         18      /* 30 bit PC relative PLT address */
+#define R_SPARC_COPY           19      /* Copy symbol at runtime */
+#define R_SPARC_GLOB_DAT       20      /* Create GOT entry */
+#define R_SPARC_JMP_SLOT       21      /* Create PLT entry */
+#define R_SPARC_RELATIVE       22      /* Adjust by program base */
+#define R_SPARC_UA32           23      /* Direct 32 bit unaligned */
+
+/* Additional Sparc64 relocs.  */
+
+#define R_SPARC_PLT32          24      /* Direct 32 bit ref to PLT entry */
+#define R_SPARC_HIPLT22                25      /* High 22 bit PLT entry */
+#define R_SPARC_LOPLT10                26      /* Truncated 10 bit PLT entry */
+#define R_SPARC_PCPLT32                27      /* PC rel 32 bit ref to PLT entry */
+#define R_SPARC_PCPLT22                28      /* PC rel high 22 bit PLT entry */
+#define R_SPARC_PCPLT10                29      /* PC rel trunc 10 bit PLT entry */
+#define R_SPARC_10             30      /* Direct 10 bit */
+#define R_SPARC_11             31      /* Direct 11 bit */
+#define R_SPARC_64             32      /* Direct 64 bit */
+#define R_SPARC_OLO10          33      /* 10bit with secondary 13bit addend */
+#define R_SPARC_HH22           34      /* Top 22 bits of direct 64 bit */
+#define R_SPARC_HM10           35      /* High middle 10 bits of ... */
+#define R_SPARC_LM22           36      /* Low middle 22 bits of ... */
+#define R_SPARC_PC_HH22                37      /* Top 22 bits of pc rel 64 bit */
+#define R_SPARC_PC_HM10                38      /* High middle 10 bit of ... */
+#define R_SPARC_PC_LM22                39      /* Low miggle 22 bits of ... */
+#define R_SPARC_WDISP16                40      /* PC relative 16 bit shifted */
+#define R_SPARC_WDISP19                41      /* PC relative 19 bit shifted */
+#define R_SPARC_7              43      /* Direct 7 bit */
+#define R_SPARC_5              44      /* Direct 5 bit */
+#define R_SPARC_6              45      /* Direct 6 bit */
+#define R_SPARC_DISP64         46      /* PC relative 64 bit */
+#define R_SPARC_PLT64          47      /* Direct 64 bit ref to PLT entry */
+#define R_SPARC_HIX22          48      /* High 22 bit complemented */
+#define R_SPARC_LOX10          49      /* Truncated 11 bit complemented */
+#define R_SPARC_H44            50      /* Direct high 12 of 44 bit */
+#define R_SPARC_M44            51      /* Direct mid 22 of 44 bit */
+#define R_SPARC_L44            52      /* Direct low 10 of 44 bit */
+#define R_SPARC_REGISTER       53      /* Global register usage */
+#define R_SPARC_UA64           54      /* Direct 64 bit unaligned */
+#define R_SPARC_UA16           55      /* Direct 16 bit unaligned */
+#define R_SPARC_TLS_GD_HI22    56
+#define R_SPARC_TLS_GD_LO10    57
+#define R_SPARC_TLS_GD_ADD     58
+#define R_SPARC_TLS_GD_CALL    59
+#define R_SPARC_TLS_LDM_HI22   60
+#define R_SPARC_TLS_LDM_LO10   61
+#define R_SPARC_TLS_LDM_ADD    62
+#define R_SPARC_TLS_LDM_CALL   63
+#define R_SPARC_TLS_LDO_HIX22  64
+#define R_SPARC_TLS_LDO_LOX10  65
+#define R_SPARC_TLS_LDO_ADD    66
+#define R_SPARC_TLS_IE_HI22    67
+#define R_SPARC_TLS_IE_LO10    68
+#define R_SPARC_TLS_IE_LD      69
+#define R_SPARC_TLS_IE_LDX     70
+#define R_SPARC_TLS_IE_ADD     71
+#define R_SPARC_TLS_LE_HIX22   72
+#define R_SPARC_TLS_LE_LOX10   73
+#define R_SPARC_TLS_DTPMOD32   74
+#define R_SPARC_TLS_DTPMOD64   75
+#define R_SPARC_TLS_DTPOFF32   76
+#define R_SPARC_TLS_DTPOFF64   77
+#define R_SPARC_TLS_TPOFF32    78
+#define R_SPARC_TLS_TPOFF64    79
+/* Keep this the last entry.  */
+#define R_SPARC_NUM            80
+
+/* For Sparc64, legal values for d_tag of Elf64_Dyn.  */
+
+#define DT_SPARC_REGISTER 0x70000001
+#define DT_SPARC_NUM   2
+
+/* Bits present in AT_HWCAP, primarily for Sparc32.  */
+
+#define HWCAP_SPARC_FLUSH      1       /* The cpu supports flush insn.  */
+#define HWCAP_SPARC_STBAR      2
+#define HWCAP_SPARC_SWAP       4
+#define HWCAP_SPARC_MULDIV     8
+#define HWCAP_SPARC_V9         16      /* The cpu is v9, so v8plus is ok.  */
+#define HWCAP_SPARC_ULTRA3     32
+#define HWCAP_SPARC_BLKINIT    64      /* Sun4v with block-init/load-twin. */
+
+/* MIPS R3000 specific definitions.  */
+
+/* Legal values for e_flags field of Elf32_Ehdr.  */
+
+#define EF_MIPS_NOREORDER   1          /* A .noreorder directive was used */
+#define EF_MIPS_PIC        2           /* Contains PIC code */
+#define EF_MIPS_CPIC       4           /* Uses PIC calling sequence */
+#define EF_MIPS_XGOT       8
+#define EF_MIPS_64BIT_WHIRL 16
+#define EF_MIPS_ABI2       32
+#define EF_MIPS_ABI_ON32    64
+#define EF_MIPS_ARCH       0xf0000000  /* MIPS architecture level */
+
+/* Legal values for MIPS architecture level.  */
+
+#define EF_MIPS_ARCH_1     0x00000000  /* -mips1 code.  */
+#define EF_MIPS_ARCH_2     0x10000000  /* -mips2 code.  */
+#define EF_MIPS_ARCH_3     0x20000000  /* -mips3 code.  */
+#define EF_MIPS_ARCH_4     0x30000000  /* -mips4 code.  */
+#define EF_MIPS_ARCH_5     0x40000000  /* -mips5 code.  */
+#define EF_MIPS_ARCH_32            0x60000000  /* MIPS32 code.  */
+#define EF_MIPS_ARCH_64            0x70000000  /* MIPS64 code.  */
+
+/* The following are non-official names and should not be used.  */
+
+#define E_MIPS_ARCH_1    0x00000000    /* -mips1 code.  */
+#define E_MIPS_ARCH_2    0x10000000    /* -mips2 code.  */
+#define E_MIPS_ARCH_3    0x20000000    /* -mips3 code.  */
+#define E_MIPS_ARCH_4    0x30000000    /* -mips4 code.  */
+#define E_MIPS_ARCH_5    0x40000000    /* -mips5 code.  */
+#define E_MIPS_ARCH_32   0x60000000    /* MIPS32 code.  */
+#define E_MIPS_ARCH_64   0x70000000    /* MIPS64 code.  */
+
+/* Special section indices.  */
+
+#define SHN_MIPS_ACOMMON    0xff00     /* Allocated common symbols */
+#define SHN_MIPS_TEXT      0xff01      /* Allocated test symbols.  */
+#define SHN_MIPS_DATA      0xff02      /* Allocated data symbols.  */
+#define SHN_MIPS_SCOMMON    0xff03     /* Small common symbols */
+#define SHN_MIPS_SUNDEFINED 0xff04     /* Small undefined symbols */
+
+/* Legal values for sh_type field of Elf32_Shdr.  */
+
+#define SHT_MIPS_LIBLIST       0x70000000 /* Shared objects used in link */
+#define SHT_MIPS_MSYM         0x70000001
+#define SHT_MIPS_CONFLICT      0x70000002 /* Conflicting symbols */
+#define SHT_MIPS_GPTAB        0x70000003 /* Global data area sizes */
+#define SHT_MIPS_UCODE        0x70000004 /* Reserved for SGI/MIPS compilers */
+#define SHT_MIPS_DEBUG        0x70000005 /* MIPS ECOFF debugging information*/
+#define SHT_MIPS_REGINFO       0x70000006 /* Register usage information */
+#define SHT_MIPS_PACKAGE       0x70000007
+#define SHT_MIPS_PACKSYM       0x70000008
+#define SHT_MIPS_RELD         0x70000009
+#define SHT_MIPS_IFACE         0x7000000b
+#define SHT_MIPS_CONTENT       0x7000000c
+#define SHT_MIPS_OPTIONS       0x7000000d /* Miscellaneous options.  */
+#define SHT_MIPS_SHDR         0x70000010
+#define SHT_MIPS_FDESC        0x70000011
+#define SHT_MIPS_EXTSYM               0x70000012
+#define SHT_MIPS_DENSE        0x70000013
+#define SHT_MIPS_PDESC        0x70000014
+#define SHT_MIPS_LOCSYM               0x70000015
+#define SHT_MIPS_AUXSYM               0x70000016
+#define SHT_MIPS_OPTSYM               0x70000017
+#define SHT_MIPS_LOCSTR               0x70000018
+#define SHT_MIPS_LINE         0x70000019
+#define SHT_MIPS_RFDESC               0x7000001a
+#define SHT_MIPS_DELTASYM      0x7000001b
+#define SHT_MIPS_DELTAINST     0x7000001c
+#define SHT_MIPS_DELTACLASS    0x7000001d
+#define SHT_MIPS_DWARF         0x7000001e /* DWARF debugging information.  */
+#define SHT_MIPS_DELTADECL     0x7000001f
+#define SHT_MIPS_SYMBOL_LIB    0x70000020
+#define SHT_MIPS_EVENTS               0x70000021 /* Event section.  */
+#define SHT_MIPS_TRANSLATE     0x70000022
+#define SHT_MIPS_PIXIE        0x70000023
+#define SHT_MIPS_XLATE        0x70000024
+#define SHT_MIPS_XLATE_DEBUG   0x70000025
+#define SHT_MIPS_WHIRL        0x70000026
+#define SHT_MIPS_EH_REGION     0x70000027
+#define SHT_MIPS_XLATE_OLD     0x70000028
+#define SHT_MIPS_PDR_EXCEPTION 0x70000029
+
+/* Legal values for sh_flags field of Elf32_Shdr.  */
+
+#define SHF_MIPS_GPREL  0x10000000     /* Must be part of global data area */
+#define SHF_MIPS_MERGE  0x20000000
+#define SHF_MIPS_ADDR   0x40000000
+#define SHF_MIPS_STRINGS 0x80000000
+#define SHF_MIPS_NOSTRIP 0x08000000
+#define SHF_MIPS_LOCAL  0x04000000
+#define SHF_MIPS_NAMES  0x02000000
+#define SHF_MIPS_NODUPE         0x01000000
+
+
+/* Symbol tables.  */
+
+/* MIPS specific values for `st_other'.  */
+#define STO_MIPS_DEFAULT               0x0
+#define STO_MIPS_INTERNAL              0x1
+#define STO_MIPS_HIDDEN                        0x2
+#define STO_MIPS_PROTECTED             0x3
+#define STO_MIPS_SC_ALIGN_UNUSED       0xff
+
+/* MIPS specific values for `st_info'.  */
+#define STB_MIPS_SPLIT_COMMON          13
+
+/* Entries found in sections of type SHT_MIPS_GPTAB.  */
+
+typedef union
+{
+  struct
+    {
+      Elf32_Word gt_current_g_value;   /* -G value used for compilation */
+      Elf32_Word gt_unused;            /* Not used */
+    } gt_header;                       /* First entry in section */
+  struct
+    {
+      Elf32_Word gt_g_value;           /* If this value were used for -G */
+      Elf32_Word gt_bytes;             /* This many bytes would be used */
+    } gt_entry;                                /* Subsequent entries in section */
+} Elf32_gptab;
+
+/* Entry found in sections of type SHT_MIPS_REGINFO.  */
+
+typedef struct
+{
+  Elf32_Word   ri_gprmask;             /* General registers used */
+  Elf32_Word   ri_cprmask[4];          /* Coprocessor registers used */
+  Elf32_Sword  ri_gp_value;            /* $gp register value */
+} Elf32_RegInfo;
+
+/* Entries found in sections of type SHT_MIPS_OPTIONS.  */
+
+typedef struct
+{
+  unsigned char kind;          /* Determines interpretation of the
+                                  variable part of descriptor.  */
+  unsigned char size;          /* Size of descriptor, including header.  */
+  Elf32_Section section;       /* Section header index of section affected,
+                                  0 for global options.  */
+  Elf32_Word info;             /* Kind-specific information.  */
+} Elf_Options;
+
+/* Values for `kind' field in Elf_Options.  */
+
+#define ODK_NULL       0       /* Undefined.  */
+#define ODK_REGINFO    1       /* Register usage information.  */
+#define ODK_EXCEPTIONS 2       /* Exception processing options.  */
+#define ODK_PAD                3       /* Section padding options.  */
+#define ODK_HWPATCH    4       /* Hardware workarounds performed */
+#define ODK_FILL       5       /* record the fill value used by the linker. */
+#define ODK_TAGS       6       /* reserve space for desktop tools to write. */
+#define ODK_HWAND      7       /* HW workarounds.  'AND' bits when merging. */
+#define ODK_HWOR       8       /* HW workarounds.  'OR' bits when merging.  */
+
+/* Values for `info' in Elf_Options for ODK_EXCEPTIONS entries.  */
+
+#define OEX_FPU_MIN    0x1f    /* FPE's which MUST be enabled.  */
+#define OEX_FPU_MAX    0x1f00  /* FPE's which MAY be enabled.  */
+#define OEX_PAGE0      0x10000 /* page zero must be mapped.  */
+#define OEX_SMM                0x20000 /* Force sequential memory mode?  */
+#define OEX_FPDBUG     0x40000 /* Force floating point debug mode?  */
+#define OEX_PRECISEFP  OEX_FPDBUG
+#define OEX_DISMISS    0x80000 /* Dismiss invalid address faults?  */
+
+#define OEX_FPU_INVAL  0x10
+#define OEX_FPU_DIV0   0x08
+#define OEX_FPU_OFLO   0x04
+#define OEX_FPU_UFLO   0x02
+#define OEX_FPU_INEX   0x01
+
+/* Masks for `info' in Elf_Options for an ODK_HWPATCH entry.  */
+
+#define OHW_R4KEOP     0x1     /* R4000 end-of-page patch.  */
+#define OHW_R8KPFETCH  0x2     /* may need R8000 prefetch patch.  */
+#define OHW_R5KEOP     0x4     /* R5000 end-of-page patch.  */
+#define OHW_R5KCVTL    0x8     /* R5000 cvt.[ds].l bug.  clean=1.  */
+
+#define OPAD_PREFIX    0x1
+#define OPAD_POSTFIX   0x2
+#define OPAD_SYMBOL    0x4
+
+/* Entry found in `.options' section.  */
+
+typedef struct
+{
+  Elf32_Word hwp_flags1;       /* Extra flags.  */
+  Elf32_Word hwp_flags2;       /* Extra flags.  */
+} Elf_Options_Hw;
+
+/* Masks for `info' in ElfOptions for ODK_HWAND and ODK_HWOR entries.  */
+
+#define OHWA0_R4KEOP_CHECKED   0x00000001
+#define OHWA1_R4KEOP_CLEAN     0x00000002
+
+/* MIPS relocs.  */
+
+#define R_MIPS_NONE            0       /* No reloc */
+#define R_MIPS_16              1       /* Direct 16 bit */
+#define R_MIPS_32              2       /* Direct 32 bit */
+#define R_MIPS_REL32           3       /* PC relative 32 bit */
+#define R_MIPS_26              4       /* Direct 26 bit shifted */
+#define R_MIPS_HI16            5       /* High 16 bit */
+#define R_MIPS_LO16            6       /* Low 16 bit */
+#define R_MIPS_GPREL16         7       /* GP relative 16 bit */
+#define R_MIPS_LITERAL         8       /* 16 bit literal entry */
+#define R_MIPS_GOT16           9       /* 16 bit GOT entry */
+#define R_MIPS_PC16            10      /* PC relative 16 bit */
+#define R_MIPS_CALL16          11      /* 16 bit GOT entry for function */
+#define R_MIPS_GPREL32         12      /* GP relative 32 bit */
+
+#define R_MIPS_SHIFT5          16
+#define R_MIPS_SHIFT6          17
+#define R_MIPS_64              18
+#define R_MIPS_GOT_DISP                19
+#define R_MIPS_GOT_PAGE                20
+#define R_MIPS_GOT_OFST                21
+#define R_MIPS_GOT_HI16                22
+#define R_MIPS_GOT_LO16                23
+#define R_MIPS_SUB             24
+#define R_MIPS_INSERT_A                25
+#define R_MIPS_INSERT_B                26
+#define R_MIPS_DELETE          27
+#define R_MIPS_HIGHER          28
+#define R_MIPS_HIGHEST         29
+#define R_MIPS_CALL_HI16       30
+#define R_MIPS_CALL_LO16       31
+#define R_MIPS_SCN_DISP                32
+#define R_MIPS_REL16           33
+#define R_MIPS_ADD_IMMEDIATE   34
+#define R_MIPS_PJUMP           35
+#define R_MIPS_RELGOT          36
+#define R_MIPS_JALR            37
+/* Keep this the last entry.  */
+#define R_MIPS_NUM             38
+
+/* Legal values for p_type field of Elf32_Phdr.  */
+
+#define PT_MIPS_REGINFO        0x70000000      /* Register usage information */
+#define PT_MIPS_RTPROC  0x70000001     /* Runtime procedure table. */
+#define PT_MIPS_OPTIONS 0x70000002
+
+/* Special program header types.  */
+
+#define PF_MIPS_LOCAL  0x10000000
+
+/* Legal values for d_tag field of Elf32_Dyn.  */
+
+#define DT_MIPS_RLD_VERSION  0x70000001        /* Runtime linker interface version */
+#define DT_MIPS_TIME_STAMP   0x70000002        /* Timestamp */
+#define DT_MIPS_ICHECKSUM    0x70000003        /* Checksum */
+#define DT_MIPS_IVERSION     0x70000004        /* Version string (string tbl index) */
+#define DT_MIPS_FLAGS       0x70000005 /* Flags */
+#define DT_MIPS_BASE_ADDRESS 0x70000006        /* Base address */
+#define DT_MIPS_MSYM        0x70000007
+#define DT_MIPS_CONFLICT     0x70000008        /* Address of CONFLICT section */
+#define DT_MIPS_LIBLIST             0x70000009 /* Address of LIBLIST section */
+#define DT_MIPS_LOCAL_GOTNO  0x7000000a        /* Number of local GOT entries */
+#define DT_MIPS_CONFLICTNO   0x7000000b        /* Number of CONFLICT entries */
+#define DT_MIPS_LIBLISTNO    0x70000010        /* Number of LIBLIST entries */
+#define DT_MIPS_SYMTABNO     0x70000011        /* Number of DYNSYM entries */
+#define DT_MIPS_UNREFEXTNO   0x70000012        /* First external DYNSYM */
+#define DT_MIPS_GOTSYM      0x70000013 /* First GOT entry in DYNSYM */
+#define DT_MIPS_HIPAGENO     0x70000014        /* Number of GOT page table entries */
+#define DT_MIPS_RLD_MAP             0x70000016 /* Address of run time loader map.  */
+#define DT_MIPS_DELTA_CLASS  0x70000017        /* Delta C++ class definition.  */
+#define DT_MIPS_DELTA_CLASS_NO    0x70000018 /* Number of entries in
+                                               DT_MIPS_DELTA_CLASS.  */
+#define DT_MIPS_DELTA_INSTANCE    0x70000019 /* Delta C++ class instances.  */
+#define DT_MIPS_DELTA_INSTANCE_NO 0x7000001a /* Number of entries in
+                                               DT_MIPS_DELTA_INSTANCE.  */
+#define DT_MIPS_DELTA_RELOC  0x7000001b /* Delta relocations.  */
+#define DT_MIPS_DELTA_RELOC_NO 0x7000001c /* Number of entries in
+                                            DT_MIPS_DELTA_RELOC.  */
+#define DT_MIPS_DELTA_SYM    0x7000001d /* Delta symbols that Delta
+                                          relocations refer to.  */
+#define DT_MIPS_DELTA_SYM_NO 0x7000001e /* Number of entries in
+                                          DT_MIPS_DELTA_SYM.  */
+#define DT_MIPS_DELTA_CLASSSYM 0x70000020 /* Delta symbols that hold the
+                                            class declaration.  */
+#define DT_MIPS_DELTA_CLASSSYM_NO 0x70000021 /* Number of entries in
+                                               DT_MIPS_DELTA_CLASSSYM.  */
+#define DT_MIPS_CXX_FLAGS    0x70000022 /* Flags indicating for C++ flavor.  */
+#define DT_MIPS_PIXIE_INIT   0x70000023
+#define DT_MIPS_SYMBOL_LIB   0x70000024
+#define DT_MIPS_LOCALPAGE_GOTIDX 0x70000025
+#define DT_MIPS_LOCAL_GOTIDX 0x70000026
+#define DT_MIPS_HIDDEN_GOTIDX 0x70000027
+#define DT_MIPS_PROTECTED_GOTIDX 0x70000028
+#define DT_MIPS_OPTIONS             0x70000029 /* Address of .options.  */
+#define DT_MIPS_INTERFACE    0x7000002a /* Address of .interface.  */
+#define DT_MIPS_DYNSTR_ALIGN 0x7000002b
+#define DT_MIPS_INTERFACE_SIZE 0x7000002c /* Size of the .interface section. */
+#define DT_MIPS_RLD_TEXT_RESOLVE_ADDR 0x7000002d /* Address of rld_text_rsolve
+                                                   function stored in GOT.  */
+#define DT_MIPS_PERF_SUFFIX  0x7000002e /* Default suffix of dso to be added
+                                          by rld on dlopen() calls.  */
+#define DT_MIPS_COMPACT_SIZE 0x7000002f /* (O32)Size of compact rel section. */
+#define DT_MIPS_GP_VALUE     0x70000030 /* GP value for aux GOTs.  */
+#define DT_MIPS_AUX_DYNAMIC  0x70000031 /* Address of aux .dynamic.  */
+#define DT_MIPS_NUM         0x32
+
+/* Legal values for DT_MIPS_FLAGS Elf32_Dyn entry.  */
+
+#define RHF_NONE                  0            /* No flags */
+#define RHF_QUICKSTART            (1 << 0)     /* Use quickstart */
+#define RHF_NOTPOT                (1 << 1)     /* Hash size not power of 2 */
+#define RHF_NO_LIBRARY_REPLACEMENT (1 << 2)    /* Ignore LD_LIBRARY_PATH */
+#define RHF_NO_MOVE               (1 << 3)
+#define RHF_SGI_ONLY              (1 << 4)
+#define RHF_GUARANTEE_INIT        (1 << 5)
+#define RHF_DELTA_C_PLUS_PLUS     (1 << 6)
+#define RHF_GUARANTEE_START_INIT   (1 << 7)
+#define RHF_PIXIE                 (1 << 8)
+#define RHF_DEFAULT_DELAY_LOAD    (1 << 9)
+#define RHF_REQUICKSTART          (1 << 10)
+#define RHF_REQUICKSTARTED        (1 << 11)
+#define RHF_CORD                  (1 << 12)
+#define RHF_NO_UNRES_UNDEF        (1 << 13)
+#define RHF_RLD_ORDER_SAFE        (1 << 14)
+
+/* Entries found in sections of type SHT_MIPS_LIBLIST.  */
+
+typedef struct
+{
+  Elf32_Word l_name;           /* Name (string table index) */
+  Elf32_Word l_time_stamp;     /* Timestamp */
+  Elf32_Word l_checksum;       /* Checksum */
+  Elf32_Word l_version;                /* Interface version */
+  Elf32_Word l_flags;          /* Flags */
+} Elf32_Lib;
+
+typedef struct
+{
+  Elf64_Word l_name;           /* Name (string table index) */
+  Elf64_Word l_time_stamp;     /* Timestamp */
+  Elf64_Word l_checksum;       /* Checksum */
+  Elf64_Word l_version;                /* Interface version */
+  Elf64_Word l_flags;          /* Flags */
+} Elf64_Lib;
+
+
+/* Legal values for l_flags.  */
+
+#define LL_NONE                  0
+#define LL_EXACT_MATCH   (1 << 0)      /* Require exact match */
+#define LL_IGNORE_INT_VER (1 << 1)     /* Ignore interface version */
+#define LL_REQUIRE_MINOR  (1 << 2)
+#define LL_EXPORTS       (1 << 3)
+#define LL_DELAY_LOAD    (1 << 4)
+#define LL_DELTA         (1 << 5)
+
+/* Entries found in sections of type SHT_MIPS_CONFLICT.  */
+
+typedef Elf32_Addr Elf32_Conflict;
+
+
+/* HPPA specific definitions.  */
+
+/* Legal values for e_flags field of Elf32_Ehdr.  */
+
+#define EF_PARISC_TRAPNIL      0x00010000 /* Trap nil pointer dereference.  */
+#define EF_PARISC_EXT          0x00020000 /* Program uses arch. extensions. */
+#define EF_PARISC_LSB          0x00040000 /* Program expects little endian. */
+#define EF_PARISC_WIDE         0x00080000 /* Program expects wide mode.  */
+#define EF_PARISC_NO_KABP      0x00100000 /* No kernel assisted branch
+                                             prediction.  */
+#define EF_PARISC_LAZYSWAP     0x00400000 /* Allow lazy swapping.  */
+#define EF_PARISC_ARCH         0x0000ffff /* Architecture version.  */
+
+/* Defined values for `e_flags & EF_PARISC_ARCH' are:  */
+
+#define EFA_PARISC_1_0             0x020b /* PA-RISC 1.0 big-endian.  */
+#define EFA_PARISC_1_1             0x0210 /* PA-RISC 1.1 big-endian.  */
+#define EFA_PARISC_2_0             0x0214 /* PA-RISC 2.0 big-endian.  */
+
+/* Additional section indeces.  */
+
+#define SHN_PARISC_ANSI_COMMON 0xff00     /* Section for tenatively declared
+                                             symbols in ANSI C.  */
+#define SHN_PARISC_HUGE_COMMON 0xff01     /* Common blocks in huge model.  */
+
+/* Legal values for sh_type field of Elf32_Shdr.  */
+
+#define SHT_PARISC_EXT         0x70000000 /* Contains product specific ext. */
+#define SHT_PARISC_UNWIND      0x70000001 /* Unwind information.  */
+#define SHT_PARISC_DOC         0x70000002 /* Debug info for optimized code. */
+
+/* Legal values for sh_flags field of Elf32_Shdr.  */
+
+#define SHF_PARISC_SHORT       0x20000000 /* Section with short addressing. */
+#define SHF_PARISC_HUGE                0x40000000 /* Section far from gp.  */
+#define SHF_PARISC_SBP         0x80000000 /* Static branch prediction code. */
+
+/* Legal values for ST_TYPE subfield of st_info (symbol type).  */
+
+#define STT_PARISC_MILLICODE   13      /* Millicode function entry point.  */
+
+#define STT_HP_OPAQUE          (STT_LOOS + 0x1)
+#define STT_HP_STUB            (STT_LOOS + 0x2)
+
+/* HPPA relocs.  */
+
+#define R_PARISC_NONE          0       /* No reloc.  */
+#define R_PARISC_DIR32         1       /* Direct 32-bit reference.  */
+#define R_PARISC_DIR21L                2       /* Left 21 bits of eff. address.  */
+#define R_PARISC_DIR17R                3       /* Right 17 bits of eff. address.  */
+#define R_PARISC_DIR17F                4       /* 17 bits of eff. address.  */
+#define R_PARISC_DIR14R                6       /* Right 14 bits of eff. address.  */
+#define R_PARISC_PCREL32       9       /* 32-bit rel. address.  */
+#define R_PARISC_PCREL21L      10      /* Left 21 bits of rel. address.  */
+#define R_PARISC_PCREL17R      11      /* Right 17 bits of rel. address.  */
+#define R_PARISC_PCREL17F      12      /* 17 bits of rel. address.  */
+#define R_PARISC_PCREL14R      14      /* Right 14 bits of rel. address.  */
+#define R_PARISC_DPREL21L      18      /* Left 21 bits of rel. address.  */
+#define R_PARISC_DPREL14R      22      /* Right 14 bits of rel. address.  */
+#define R_PARISC_GPREL21L      26      /* GP-relative, left 21 bits.  */
+#define R_PARISC_GPREL14R      30      /* GP-relative, right 14 bits.  */
+#define R_PARISC_LTOFF21L      34      /* LT-relative, left 21 bits.  */
+#define R_PARISC_LTOFF14R      38      /* LT-relative, right 14 bits.  */
+#define R_PARISC_SECREL32      41      /* 32 bits section rel. address.  */
+#define R_PARISC_SEGBASE       48      /* No relocation, set segment base.  */
+#define R_PARISC_SEGREL32      49      /* 32 bits segment rel. address.  */
+#define R_PARISC_PLTOFF21L     50      /* PLT rel. address, left 21 bits.  */
+#define R_PARISC_PLTOFF14R     54      /* PLT rel. address, right 14 bits.  */
+#define R_PARISC_LTOFF_FPTR32  57      /* 32 bits LT-rel. function pointer. */
+#define R_PARISC_LTOFF_FPTR21L 58      /* LT-rel. fct ptr, left 21 bits. */
+#define R_PARISC_LTOFF_FPTR14R 62      /* LT-rel. fct ptr, right 14 bits. */
+#define R_PARISC_FPTR64                64      /* 64 bits function address.  */
+#define R_PARISC_PLABEL32      65      /* 32 bits function address.  */
+#define R_PARISC_PCREL64       72      /* 64 bits PC-rel. address.  */
+#define R_PARISC_PCREL22F      74      /* 22 bits PC-rel. address.  */
+#define R_PARISC_PCREL14WR     75      /* PC-rel. address, right 14 bits.  */
+#define R_PARISC_PCREL14DR     76      /* PC rel. address, right 14 bits.  */
+#define R_PARISC_PCREL16F      77      /* 16 bits PC-rel. address.  */
+#define R_PARISC_PCREL16WF     78      /* 16 bits PC-rel. address.  */
+#define R_PARISC_PCREL16DF     79      /* 16 bits PC-rel. address.  */
+#define R_PARISC_DIR64         80      /* 64 bits of eff. address.  */
+#define R_PARISC_DIR14WR       83      /* 14 bits of eff. address.  */
+#define R_PARISC_DIR14DR       84      /* 14 bits of eff. address.  */
+#define R_PARISC_DIR16F                85      /* 16 bits of eff. address.  */
+#define R_PARISC_DIR16WF       86      /* 16 bits of eff. address.  */
+#define R_PARISC_DIR16DF       87      /* 16 bits of eff. address.  */
+#define R_PARISC_GPREL64       88      /* 64 bits of GP-rel. address.  */
+#define R_PARISC_GPREL14WR     91      /* GP-rel. address, right 14 bits.  */
+#define R_PARISC_GPREL14DR     92      /* GP-rel. address, right 14 bits.  */
+#define R_PARISC_GPREL16F      93      /* 16 bits GP-rel. address.  */
+#define R_PARISC_GPREL16WF     94      /* 16 bits GP-rel. address.  */
+#define R_PARISC_GPREL16DF     95      /* 16 bits GP-rel. address.  */
+#define R_PARISC_LTOFF64       96      /* 64 bits LT-rel. address.  */
+#define R_PARISC_LTOFF14WR     99      /* LT-rel. address, right 14 bits.  */
+#define R_PARISC_LTOFF14DR     100     /* LT-rel. address, right 14 bits.  */
+#define R_PARISC_LTOFF16F      101     /* 16 bits LT-rel. address.  */
+#define R_PARISC_LTOFF16WF     102     /* 16 bits LT-rel. address.  */
+#define R_PARISC_LTOFF16DF     103     /* 16 bits LT-rel. address.  */
+#define R_PARISC_SECREL64      104     /* 64 bits section rel. address.  */
+#define R_PARISC_SEGREL64      112     /* 64 bits segment rel. address.  */
+#define R_PARISC_PLTOFF14WR    115     /* PLT-rel. address, right 14 bits.  */
+#define R_PARISC_PLTOFF14DR    116     /* PLT-rel. address, right 14 bits.  */
+#define R_PARISC_PLTOFF16F     117     /* 16 bits LT-rel. address.  */
+#define R_PARISC_PLTOFF16WF    118     /* 16 bits PLT-rel. address.  */
+#define R_PARISC_PLTOFF16DF    119     /* 16 bits PLT-rel. address.  */
+#define R_PARISC_LTOFF_FPTR64  120     /* 64 bits LT-rel. function ptr.  */
+#define R_PARISC_LTOFF_FPTR14WR        123     /* LT-rel. fct. ptr., right 14 bits. */
+#define R_PARISC_LTOFF_FPTR14DR        124     /* LT-rel. fct. ptr., right 14 bits. */
+#define R_PARISC_LTOFF_FPTR16F 125     /* 16 bits LT-rel. function ptr.  */
+#define R_PARISC_LTOFF_FPTR16WF        126     /* 16 bits LT-rel. function ptr.  */
+#define R_PARISC_LTOFF_FPTR16DF        127     /* 16 bits LT-rel. function ptr.  */
+#define R_PARISC_LORESERVE     128
+#define R_PARISC_COPY          128     /* Copy relocation.  */
+#define R_PARISC_IPLT          129     /* Dynamic reloc, imported PLT */
+#define R_PARISC_EPLT          130     /* Dynamic reloc, exported PLT */
+#define R_PARISC_TPREL32       153     /* 32 bits TP-rel. address.  */
+#define R_PARISC_TPREL21L      154     /* TP-rel. address, left 21 bits.  */
+#define R_PARISC_TPREL14R      158     /* TP-rel. address, right 14 bits.  */
+#define R_PARISC_LTOFF_TP21L   162     /* LT-TP-rel. address, left 21 bits. */
+#define R_PARISC_LTOFF_TP14R   166     /* LT-TP-rel. address, right 14 bits.*/
+#define R_PARISC_LTOFF_TP14F   167     /* 14 bits LT-TP-rel. address.  */
+#define R_PARISC_TPREL64       216     /* 64 bits TP-rel. address.  */
+#define R_PARISC_TPREL14WR     219     /* TP-rel. address, right 14 bits.  */
+#define R_PARISC_TPREL14DR     220     /* TP-rel. address, right 14 bits.  */
+#define R_PARISC_TPREL16F      221     /* 16 bits TP-rel. address.  */
+#define R_PARISC_TPREL16WF     222     /* 16 bits TP-rel. address.  */
+#define R_PARISC_TPREL16DF     223     /* 16 bits TP-rel. address.  */
+#define R_PARISC_LTOFF_TP64    224     /* 64 bits LT-TP-rel. address.  */
+#define R_PARISC_LTOFF_TP14WR  227     /* LT-TP-rel. address, right 14 bits.*/
+#define R_PARISC_LTOFF_TP14DR  228     /* LT-TP-rel. address, right 14 bits.*/
+#define R_PARISC_LTOFF_TP16F   229     /* 16 bits LT-TP-rel. address.  */
+#define R_PARISC_LTOFF_TP16WF  230     /* 16 bits LT-TP-rel. address.  */
+#define R_PARISC_LTOFF_TP16DF  231     /* 16 bits LT-TP-rel. address.  */
+#define R_PARISC_HIRESERVE     255
+
+/* Legal values for p_type field of Elf32_Phdr/Elf64_Phdr.  */
+
+#define PT_HP_TLS              (PT_LOOS + 0x0)
+#define PT_HP_CORE_NONE                (PT_LOOS + 0x1)
+#define PT_HP_CORE_VERSION     (PT_LOOS + 0x2)
+#define PT_HP_CORE_KERNEL      (PT_LOOS + 0x3)
+#define PT_HP_CORE_COMM                (PT_LOOS + 0x4)
+#define PT_HP_CORE_PROC                (PT_LOOS + 0x5)
+#define PT_HP_CORE_LOADABLE    (PT_LOOS + 0x6)
+#define PT_HP_CORE_STACK       (PT_LOOS + 0x7)
+#define PT_HP_CORE_SHM         (PT_LOOS + 0x8)
+#define PT_HP_CORE_MMF         (PT_LOOS + 0x9)
+#define PT_HP_PARALLEL         (PT_LOOS + 0x10)
+#define PT_HP_FASTBIND         (PT_LOOS + 0x11)
+#define PT_HP_OPT_ANNOT                (PT_LOOS + 0x12)
+#define PT_HP_HSL_ANNOT                (PT_LOOS + 0x13)
+#define PT_HP_STACK            (PT_LOOS + 0x14)
+
+#define PT_PARISC_ARCHEXT      0x70000000
+#define PT_PARISC_UNWIND       0x70000001
+
+/* Legal values for p_flags field of Elf32_Phdr/Elf64_Phdr.  */
+
+#define PF_PARISC_SBP          0x08000000
+
+#define PF_HP_PAGE_SIZE                0x00100000
+#define PF_HP_FAR_SHARED       0x00200000
+#define PF_HP_NEAR_SHARED      0x00400000
+#define PF_HP_CODE             0x01000000
+#define PF_HP_MODIFY           0x02000000
+#define PF_HP_LAZYSWAP         0x04000000
+#define PF_HP_SBP              0x08000000
+
+
+/* Alpha specific definitions.  */
+
+/* Legal values for e_flags field of Elf64_Ehdr.  */
+
+#define EF_ALPHA_32BIT         1       /* All addresses must be < 2GB.  */
+#define EF_ALPHA_CANRELAX      2       /* Relocations for relaxing exist.  */
+
+/* Legal values for sh_type field of Elf64_Shdr.  */
+
+/* These two are primerily concerned with ECOFF debugging info.  */
+#define SHT_ALPHA_DEBUG                0x70000001
+#define SHT_ALPHA_REGINFO      0x70000002
+
+/* Legal values for sh_flags field of Elf64_Shdr.  */
+
+#define SHF_ALPHA_GPREL                0x10000000
+
+/* Legal values for st_other field of Elf64_Sym.  */
+#define STO_ALPHA_NOPV         0x80    /* No PV required.  */
+#define STO_ALPHA_STD_GPLOAD   0x88    /* PV only used for initial ldgp.  */
+
+/* Alpha relocs.  */
+
+#define R_ALPHA_NONE           0       /* No reloc */
+#define R_ALPHA_REFLONG                1       /* Direct 32 bit */
+#define R_ALPHA_REFQUAD                2       /* Direct 64 bit */
+#define R_ALPHA_GPREL32                3       /* GP relative 32 bit */
+#define R_ALPHA_LITERAL                4       /* GP relative 16 bit w/optimization */
+#define R_ALPHA_LITUSE         5       /* Optimization hint for LITERAL */
+#define R_ALPHA_GPDISP         6       /* Add displacement to GP */
+#define R_ALPHA_BRADDR         7       /* PC+4 relative 23 bit shifted */
+#define R_ALPHA_HINT           8       /* PC+4 relative 16 bit shifted */
+#define R_ALPHA_SREL16         9       /* PC relative 16 bit */
+#define R_ALPHA_SREL32         10      /* PC relative 32 bit */
+#define R_ALPHA_SREL64         11      /* PC relative 64 bit */
+#define R_ALPHA_GPRELHIGH      17      /* GP relative 32 bit, high 16 bits */
+#define R_ALPHA_GPRELLOW       18      /* GP relative 32 bit, low 16 bits */
+#define R_ALPHA_GPREL16                19      /* GP relative 16 bit */
+#define R_ALPHA_COPY           24      /* Copy symbol at runtime */
+#define R_ALPHA_GLOB_DAT       25      /* Create GOT entry */
+#define R_ALPHA_JMP_SLOT       26      /* Create PLT entry */
+#define R_ALPHA_RELATIVE       27      /* Adjust by program base */
+#define R_ALPHA_TLS_GD_HI      28
+#define R_ALPHA_TLSGD          29
+#define R_ALPHA_TLS_LDM                30
+#define R_ALPHA_DTPMOD64       31
+#define R_ALPHA_GOTDTPREL      32
+#define R_ALPHA_DTPREL64       33
+#define R_ALPHA_DTPRELHI       34
+#define R_ALPHA_DTPRELLO       35
+#define R_ALPHA_DTPREL16       36
+#define R_ALPHA_GOTTPREL       37
+#define R_ALPHA_TPREL64                38
+#define R_ALPHA_TPRELHI                39
+#define R_ALPHA_TPRELLO                40
+#define R_ALPHA_TPREL16                41
+/* Keep this the last entry.  */
+#define R_ALPHA_NUM            46
+
+/* Magic values of the LITUSE relocation addend.  */
+#define LITUSE_ALPHA_ADDR      0
+#define LITUSE_ALPHA_BASE      1
+#define LITUSE_ALPHA_BYTOFF    2
+#define LITUSE_ALPHA_JSR       3
+#define LITUSE_ALPHA_TLS_GD    4
+#define LITUSE_ALPHA_TLS_LDM   5
+
+
+/* PowerPC specific declarations */
+
+/* Values for Elf32/64_Ehdr.e_flags.  */
+#define EF_PPC_EMB             0x80000000      /* PowerPC embedded flag */
+
+/* Cygnus local bits below */
+#define EF_PPC_RELOCATABLE     0x00010000      /* PowerPC -mrelocatable flag*/
+#define EF_PPC_RELOCATABLE_LIB 0x00008000      /* PowerPC -mrelocatable-lib
+                                                  flag */
+
+/* PowerPC relocations defined by the ABIs */
+#define R_PPC_NONE             0
+#define R_PPC_ADDR32           1       /* 32bit absolute address */
+#define R_PPC_ADDR24           2       /* 26bit address, 2 bits ignored.  */
+#define R_PPC_ADDR16           3       /* 16bit absolute address */
+#define R_PPC_ADDR16_LO                4       /* lower 16bit of absolute address */
+#define R_PPC_ADDR16_HI                5       /* high 16bit of absolute address */
+#define R_PPC_ADDR16_HA                6       /* adjusted high 16bit */
+#define R_PPC_ADDR14           7       /* 16bit address, 2 bits ignored */
+#define R_PPC_ADDR14_BRTAKEN   8
+#define R_PPC_ADDR14_BRNTAKEN  9
+#define R_PPC_REL24            10      /* PC relative 26 bit */
+#define R_PPC_REL14            11      /* PC relative 16 bit */
+#define R_PPC_REL14_BRTAKEN    12
+#define R_PPC_REL14_BRNTAKEN   13
+#define R_PPC_GOT16            14
+#define R_PPC_GOT16_LO         15
+#define R_PPC_GOT16_HI         16
+#define R_PPC_GOT16_HA         17
+#define R_PPC_PLTREL24         18
+#define R_PPC_COPY             19
+#define R_PPC_GLOB_DAT         20
+#define R_PPC_JMP_SLOT         21
+#define R_PPC_RELATIVE         22
+#define R_PPC_LOCAL24PC                23
+#define R_PPC_UADDR32          24
+#define R_PPC_UADDR16          25
+#define R_PPC_REL32            26
+#define R_PPC_PLT32            27
+#define R_PPC_PLTREL32         28
+#define R_PPC_PLT16_LO         29
+#define R_PPC_PLT16_HI         30
+#define R_PPC_PLT16_HA         31
+#define R_PPC_SDAREL16         32
+#define R_PPC_SECTOFF          33
+#define R_PPC_SECTOFF_LO       34
+#define R_PPC_SECTOFF_HI       35
+#define R_PPC_SECTOFF_HA       36
+
+/* PowerPC relocations defined for the TLS access ABI.  */
+#define R_PPC_TLS              67 /* none      (sym+add)@tls */
+#define R_PPC_DTPMOD32         68 /* word32    (sym+add)@dtpmod */
+#define R_PPC_TPREL16          69 /* half16*   (sym+add)@tprel */
+#define R_PPC_TPREL16_LO       70 /* half16    (sym+add)@tprel@l */
+#define R_PPC_TPREL16_HI       71 /* half16    (sym+add)@tprel@h */
+#define R_PPC_TPREL16_HA       72 /* half16    (sym+add)@tprel@ha */
+#define R_PPC_TPREL32          73 /* word32    (sym+add)@tprel */
+#define R_PPC_DTPREL16         74 /* half16*   (sym+add)@dtprel */
+#define R_PPC_DTPREL16_LO      75 /* half16    (sym+add)@dtprel@l */
+#define R_PPC_DTPREL16_HI      76 /* half16    (sym+add)@dtprel@h */
+#define R_PPC_DTPREL16_HA      77 /* half16    (sym+add)@dtprel@ha */
+#define R_PPC_DTPREL32         78 /* word32    (sym+add)@dtprel */
+#define R_PPC_GOT_TLSGD16      79 /* half16*   (sym+add)@got@tlsgd */
+#define R_PPC_GOT_TLSGD16_LO   80 /* half16    (sym+add)@got@tlsgd@l */
+#define R_PPC_GOT_TLSGD16_HI   81 /* half16    (sym+add)@got@tlsgd@h */
+#define R_PPC_GOT_TLSGD16_HA   82 /* half16    (sym+add)@got@tlsgd@ha */
+#define R_PPC_GOT_TLSLD16      83 /* half16*   (sym+add)@got@tlsld */
+#define R_PPC_GOT_TLSLD16_LO   84 /* half16    (sym+add)@got@tlsld@l */
+#define R_PPC_GOT_TLSLD16_HI   85 /* half16    (sym+add)@got@tlsld@h */
+#define R_PPC_GOT_TLSLD16_HA   86 /* half16    (sym+add)@got@tlsld@ha */
+#define R_PPC_GOT_TPREL16      87 /* half16*   (sym+add)@got@tprel */
+#define R_PPC_GOT_TPREL16_LO   88 /* half16    (sym+add)@got@tprel@l */
+#define R_PPC_GOT_TPREL16_HI   89 /* half16    (sym+add)@got@tprel@h */
+#define R_PPC_GOT_TPREL16_HA   90 /* half16    (sym+add)@got@tprel@ha */
+#define R_PPC_GOT_DTPREL16     91 /* half16*   (sym+add)@got@dtprel */
+#define R_PPC_GOT_DTPREL16_LO  92 /* half16*   (sym+add)@got@dtprel@l */
+#define R_PPC_GOT_DTPREL16_HI  93 /* half16*   (sym+add)@got@dtprel@h */
+#define R_PPC_GOT_DTPREL16_HA  94 /* half16*   (sym+add)@got@dtprel@ha */
+
+/* Keep this the last entry.  */
+#define R_PPC_NUM              95
+
+/* The remaining relocs are from the Embedded ELF ABI, and are not
+   in the SVR4 ELF ABI.  */
+#define R_PPC_EMB_NADDR32      101
+#define R_PPC_EMB_NADDR16      102
+#define R_PPC_EMB_NADDR16_LO   103
+#define R_PPC_EMB_NADDR16_HI   104
+#define R_PPC_EMB_NADDR16_HA   105
+#define R_PPC_EMB_SDAI16       106
+#define R_PPC_EMB_SDA2I16      107
+#define R_PPC_EMB_SDA2REL      108
+#define R_PPC_EMB_SDA21                109     /* 16 bit offset in SDA */
+#define R_PPC_EMB_MRKREF       110
+#define R_PPC_EMB_RELSEC16     111
+#define R_PPC_EMB_RELST_LO     112
+#define R_PPC_EMB_RELST_HI     113
+#define R_PPC_EMB_RELST_HA     114
+#define R_PPC_EMB_BIT_FLD      115
+#define R_PPC_EMB_RELSDA       116     /* 16 bit relative offset in SDA */
+
+/* Diab tool relocations.  */
+#define R_PPC_DIAB_SDA21_LO    180     /* like EMB_SDA21, but lower 16 bit */
+#define R_PPC_DIAB_SDA21_HI    181     /* like EMB_SDA21, but high 16 bit */
+#define R_PPC_DIAB_SDA21_HA    182     /* like EMB_SDA21, adjusted high 16 */
+#define R_PPC_DIAB_RELSDA_LO   183     /* like EMB_RELSDA, but lower 16 bit */
+#define R_PPC_DIAB_RELSDA_HI   184     /* like EMB_RELSDA, but high 16 bit */
+#define R_PPC_DIAB_RELSDA_HA   185     /* like EMB_RELSDA, adjusted high 16 */
+
+/* This is a phony reloc to handle any old fashioned TOC16 references
+   that may still be in object files.  */
+#define R_PPC_TOC16            255
+
+
+/* PowerPC64 relocations defined by the ABIs */
+#define R_PPC64_NONE           R_PPC_NONE
+#define R_PPC64_ADDR32         R_PPC_ADDR32 /* 32bit absolute address */
+#define R_PPC64_ADDR24         R_PPC_ADDR24 /* 26bit address, word aligned */
+#define R_PPC64_ADDR16         R_PPC_ADDR16 /* 16bit absolute address */
+#define R_PPC64_ADDR16_LO      R_PPC_ADDR16_LO /* lower 16bits of address */
+#define R_PPC64_ADDR16_HI      R_PPC_ADDR16_HI /* high 16bits of address. */
+#define R_PPC64_ADDR16_HA      R_PPC_ADDR16_HA /* adjusted high 16bits.  */
+#define R_PPC64_ADDR14         R_PPC_ADDR14 /* 16bit address, word aligned */
+#define R_PPC64_ADDR14_BRTAKEN R_PPC_ADDR14_BRTAKEN
+#define R_PPC64_ADDR14_BRNTAKEN        R_PPC_ADDR14_BRNTAKEN
+#define R_PPC64_REL24          R_PPC_REL24 /* PC-rel. 26 bit, word aligned */
+#define R_PPC64_REL14          R_PPC_REL14 /* PC relative 16 bit */
+#define R_PPC64_REL14_BRTAKEN  R_PPC_REL14_BRTAKEN
+#define R_PPC64_REL14_BRNTAKEN R_PPC_REL14_BRNTAKEN
+#define R_PPC64_GOT16          R_PPC_GOT16
+#define R_PPC64_GOT16_LO       R_PPC_GOT16_LO
+#define R_PPC64_GOT16_HI       R_PPC_GOT16_HI
+#define R_PPC64_GOT16_HA       R_PPC_GOT16_HA
+
+#define R_PPC64_COPY           R_PPC_COPY
+#define R_PPC64_GLOB_DAT       R_PPC_GLOB_DAT
+#define R_PPC64_JMP_SLOT       R_PPC_JMP_SLOT
+#define R_PPC64_RELATIVE       R_PPC_RELATIVE
+
+#define R_PPC64_UADDR32                R_PPC_UADDR32
+#define R_PPC64_UADDR16                R_PPC_UADDR16
+#define R_PPC64_REL32          R_PPC_REL32
+#define R_PPC64_PLT32          R_PPC_PLT32
+#define R_PPC64_PLTREL32       R_PPC_PLTREL32
+#define R_PPC64_PLT16_LO       R_PPC_PLT16_LO
+#define R_PPC64_PLT16_HI       R_PPC_PLT16_HI
+#define R_PPC64_PLT16_HA       R_PPC_PLT16_HA
+
+#define R_PPC64_SECTOFF                R_PPC_SECTOFF
+#define R_PPC64_SECTOFF_LO     R_PPC_SECTOFF_LO
+#define R_PPC64_SECTOFF_HI     R_PPC_SECTOFF_HI
+#define R_PPC64_SECTOFF_HA     R_PPC_SECTOFF_HA
+#define R_PPC64_ADDR30         37 /* word30 (S + A - P) >> 2 */
+#define R_PPC64_ADDR64         38 /* doubleword64 S + A */
+#define R_PPC64_ADDR16_HIGHER  39 /* half16 #higher(S + A) */
+#define R_PPC64_ADDR16_HIGHERA 40 /* half16 #highera(S + A) */
+#define R_PPC64_ADDR16_HIGHEST 41 /* half16 #highest(S + A) */
+#define R_PPC64_ADDR16_HIGHESTA        42 /* half16 #highesta(S + A) */
+#define R_PPC64_UADDR64                43 /* doubleword64 S + A */
+#define R_PPC64_REL64          44 /* doubleword64 S + A - P */
+#define R_PPC64_PLT64          45 /* doubleword64 L + A */
+#define R_PPC64_PLTREL64       46 /* doubleword64 L + A - P */
+#define R_PPC64_TOC16          47 /* half16* S + A - .TOC */
+#define R_PPC64_TOC16_LO       48 /* half16 #lo(S + A - .TOC.) */
+#define R_PPC64_TOC16_HI       49 /* half16 #hi(S + A - .TOC.) */
+#define R_PPC64_TOC16_HA       50 /* half16 #ha(S + A - .TOC.) */
+#define R_PPC64_TOC            51 /* doubleword64 .TOC */
+#define R_PPC64_PLTGOT16       52 /* half16* M + A */
+#define R_PPC64_PLTGOT16_LO    53 /* half16 #lo(M + A) */
+#define R_PPC64_PLTGOT16_HI    54 /* half16 #hi(M + A) */
+#define R_PPC64_PLTGOT16_HA    55 /* half16 #ha(M + A) */
+
+#define R_PPC64_ADDR16_DS      56 /* half16ds* (S + A) >> 2 */
+#define R_PPC64_ADDR16_LO_DS   57 /* half16ds  #lo(S + A) >> 2 */
+#define R_PPC64_GOT16_DS       58 /* half16ds* (G + A) >> 2 */
+#define R_PPC64_GOT16_LO_DS    59 /* half16ds  #lo(G + A) >> 2 */
+#define R_PPC64_PLT16_LO_DS    60 /* half16ds  #lo(L + A) >> 2 */
+#define R_PPC64_SECTOFF_DS     61 /* half16ds* (R + A) >> 2 */
+#define R_PPC64_SECTOFF_LO_DS  62 /* half16ds  #lo(R + A) >> 2 */
+#define R_PPC64_TOC16_DS       63 /* half16ds* (S + A - .TOC.) >> 2 */
+#define R_PPC64_TOC16_LO_DS    64 /* half16ds  #lo(S + A - .TOC.) >> 2 */
+#define R_PPC64_PLTGOT16_DS    65 /* half16ds* (M + A) >> 2 */
+#define R_PPC64_PLTGOT16_LO_DS 66 /* half16ds  #lo(M + A) >> 2 */
+
+/* PowerPC64 relocations defined for the TLS access ABI.  */
+#define R_PPC64_TLS            67 /* none      (sym+add)@tls */
+#define R_PPC64_DTPMOD64       68 /* doubleword64 (sym+add)@dtpmod */
+#define R_PPC64_TPREL16                69 /* half16*   (sym+add)@tprel */
+#define R_PPC64_TPREL16_LO     70 /* half16    (sym+add)@tprel@l */
+#define R_PPC64_TPREL16_HI     71 /* half16    (sym+add)@tprel@h */
+#define R_PPC64_TPREL16_HA     72 /* half16    (sym+add)@tprel@ha */
+#define R_PPC64_TPREL64                73 /* doubleword64 (sym+add)@tprel */
+#define R_PPC64_DTPREL16       74 /* half16*   (sym+add)@dtprel */
+#define R_PPC64_DTPREL16_LO    75 /* half16    (sym+add)@dtprel@l */
+#define R_PPC64_DTPREL16_HI    76 /* half16    (sym+add)@dtprel@h */
+#define R_PPC64_DTPREL16_HA    77 /* half16    (sym+add)@dtprel@ha */
+#define R_PPC64_DTPREL64       78 /* doubleword64 (sym+add)@dtprel */
+#define R_PPC64_GOT_TLSGD16    79 /* half16*   (sym+add)@got@tlsgd */
+#define R_PPC64_GOT_TLSGD16_LO 80 /* half16    (sym+add)@got@tlsgd@l */
+#define R_PPC64_GOT_TLSGD16_HI 81 /* half16    (sym+add)@got@tlsgd@h */
+#define R_PPC64_GOT_TLSGD16_HA 82 /* half16    (sym+add)@got@tlsgd@ha */
+#define R_PPC64_GOT_TLSLD16    83 /* half16*   (sym+add)@got@tlsld */
+#define R_PPC64_GOT_TLSLD16_LO 84 /* half16    (sym+add)@got@tlsld@l */
+#define R_PPC64_GOT_TLSLD16_HI 85 /* half16    (sym+add)@got@tlsld@h */
+#define R_PPC64_GOT_TLSLD16_HA 86 /* half16    (sym+add)@got@tlsld@ha */
+#define R_PPC64_GOT_TPREL16_DS 87 /* half16ds* (sym+add)@got@tprel */
+#define R_PPC64_GOT_TPREL16_LO_DS 88 /* half16ds (sym+add)@got@tprel@l */
+#define R_PPC64_GOT_TPREL16_HI 89 /* half16    (sym+add)@got@tprel@h */
+#define R_PPC64_GOT_TPREL16_HA 90 /* half16    (sym+add)@got@tprel@ha */
+#define R_PPC64_GOT_DTPREL16_DS        91 /* half16ds* (sym+add)@got@dtprel */
+#define R_PPC64_GOT_DTPREL16_LO_DS 92 /* half16ds (sym+add)@got@dtprel@l */
+#define R_PPC64_GOT_DTPREL16_HI        93 /* half16    (sym+add)@got@dtprel@h */
+#define R_PPC64_GOT_DTPREL16_HA        94 /* half16    (sym+add)@got@dtprel@ha */
+#define R_PPC64_TPREL16_DS     95 /* half16ds* (sym+add)@tprel */
+#define R_PPC64_TPREL16_LO_DS  96 /* half16ds  (sym+add)@tprel@l */
+#define R_PPC64_TPREL16_HIGHER 97 /* half16    (sym+add)@tprel@higher */
+#define R_PPC64_TPREL16_HIGHERA        98 /* half16    (sym+add)@tprel@highera */
+#define R_PPC64_TPREL16_HIGHEST        99 /* half16    (sym+add)@tprel@highest */
+#define R_PPC64_TPREL16_HIGHESTA 100 /* half16 (sym+add)@tprel@highesta */
+#define R_PPC64_DTPREL16_DS    101 /* half16ds* (sym+add)@dtprel */
+#define R_PPC64_DTPREL16_LO_DS 102 /* half16ds (sym+add)@dtprel@l */
+#define R_PPC64_DTPREL16_HIGHER        103 /* half16   (sym+add)@dtprel@higher */
+#define R_PPC64_DTPREL16_HIGHERA 104 /* half16 (sym+add)@dtprel@highera */
+#define R_PPC64_DTPREL16_HIGHEST 105 /* half16 (sym+add)@dtprel@highest */
+#define R_PPC64_DTPREL16_HIGHESTA 106 /* half16        (sym+add)@dtprel@highesta */
+
+/* Keep this the last entry.  */
+#define R_PPC64_NUM            107
+
+/* PowerPC64 specific values for the Dyn d_tag field.  */
+#define DT_PPC64_GLINK  (DT_LOPROC + 0)
+#define DT_PPC64_OPD   (DT_LOPROC + 1)
+#define DT_PPC64_OPDSZ (DT_LOPROC + 2)
+#define DT_PPC64_NUM    3
+
+
+/* ARM specific declarations */
+
+/* Processor specific flags for the ELF header e_flags field.  */
+#define EF_ARM_RELEXEC     0x01
+#define EF_ARM_HASENTRY    0x02
+#define EF_ARM_INTERWORK   0x04
+#define EF_ARM_APCS_26     0x08
+#define EF_ARM_APCS_FLOAT  0x10
+#define EF_ARM_PIC         0x20
+#define EF_ARM_ALIGN8      0x40                /* 8-bit structure alignment is in use */
+#define EF_ARM_NEW_ABI     0x80
+#define EF_ARM_OLD_ABI     0x100
+
+/* Other constants defined in the ARM ELF spec. version B-01.  */
+/* NB. These conflict with values defined above.  */
+#define EF_ARM_SYMSARESORTED   0x04
+#define EF_ARM_DYNSYMSUSESEGIDX 0x08
+#define EF_ARM_MAPSYMSFIRST    0x10
+#define EF_ARM_EABIMASK                0XFF000000
+
+#define EF_ARM_EABI_VERSION(flags) ((flags) & EF_ARM_EABIMASK)
+#define EF_ARM_EABI_UNKNOWN  0x00000000
+#define EF_ARM_EABI_VER1     0x01000000
+#define EF_ARM_EABI_VER2     0x02000000
+
+/* Additional symbol types for Thumb */
+#define STT_ARM_TFUNC      0xd
+
+/* ARM-specific values for sh_flags */
+#define SHF_ARM_ENTRYSECT  0x10000000   /* Section contains an entry point */
+#define SHF_ARM_COMDEF     0x80000000   /* Section may be multiply defined
+                                          in the input to a link step */
+
+/* ARM-specific program header flags */
+#define PF_ARM_SB          0x10000000   /* Segment contains the location
+                                          addressed by the static base */
+
+/* ARM relocs.  */
+#define R_ARM_NONE             0       /* No reloc */
+#define R_ARM_PC24             1       /* PC relative 26 bit branch */
+#define R_ARM_ABS32            2       /* Direct 32 bit  */
+#define R_ARM_REL32            3       /* PC relative 32 bit */
+#define R_ARM_PC13             4
+#define R_ARM_ABS16            5       /* Direct 16 bit */
+#define R_ARM_ABS12            6       /* Direct 12 bit */
+#define R_ARM_THM_ABS5         7
+#define R_ARM_ABS8             8       /* Direct 8 bit */
+#define R_ARM_SBREL32          9
+#define R_ARM_THM_PC22         10
+#define R_ARM_THM_PC8          11
+#define R_ARM_AMP_VCALL9       12
+#define R_ARM_SWI24            13
+#define R_ARM_THM_SWI8         14
+#define R_ARM_XPC25            15
+#define R_ARM_THM_XPC22                16
+#define R_ARM_COPY             20      /* Copy symbol at runtime */
+#define R_ARM_GLOB_DAT         21      /* Create GOT entry */
+#define R_ARM_JUMP_SLOT                22      /* Create PLT entry */
+#define R_ARM_RELATIVE         23      /* Adjust by program base */
+#define R_ARM_GOTOFF           24      /* 32 bit offset to GOT */
+#define R_ARM_GOTPC            25      /* 32 bit PC relative offset to GOT */
+#define R_ARM_GOT32            26      /* 32 bit GOT entry */
+#define R_ARM_PLT32            27      /* 32 bit PLT address */
+#define R_ARM_ALU_PCREL_7_0    32
+#define R_ARM_ALU_PCREL_15_8   33
+#define R_ARM_ALU_PCREL_23_15  34
+#define R_ARM_LDR_SBREL_11_0   35
+#define R_ARM_ALU_SBREL_19_12  36
+#define R_ARM_ALU_SBREL_27_20  37
+#define R_ARM_GNU_VTENTRY      100
+#define R_ARM_GNU_VTINHERIT    101
+#define R_ARM_THM_PC11         102     /* thumb unconditional branch */
+#define R_ARM_THM_PC9          103     /* thumb conditional branch */
+#define R_ARM_RXPC25           249
+#define R_ARM_RSBREL32         250
+#define R_ARM_THM_RPC22                251
+#define R_ARM_RREL32           252
+#define R_ARM_RABS22           253
+#define R_ARM_RPC24            254
+#define R_ARM_RBASE            255
+/* Keep this the last entry.  */
+#define R_ARM_NUM              256
+
+/* IA-64 specific declarations.  */
+
+/* Processor specific flags for the Ehdr e_flags field.  */
+#define EF_IA_64_MASKOS                0x0000000f      /* os-specific flags */
+#define EF_IA_64_ABI64         0x00000010      /* 64-bit ABI */
+#define EF_IA_64_ARCH          0xff000000      /* arch. version mask */
+
+/* Processor specific values for the Phdr p_type field.  */
+#define PT_IA_64_ARCHEXT       (PT_LOPROC + 0) /* arch extension bits */
+#define PT_IA_64_UNWIND                (PT_LOPROC + 1) /* ia64 unwind bits */
+#define PT_IA_64_HP_OPT_ANOT   (PT_LOOS + 0x12)
+#define PT_IA_64_HP_HSL_ANOT   (PT_LOOS + 0x13)
+#define PT_IA_64_HP_STACK      (PT_LOOS + 0x14)
+
+/* Processor specific flags for the Phdr p_flags field.  */
+#define PF_IA_64_NORECOV       0x80000000      /* spec insns w/o recovery */
+
+/* Processor specific values for the Shdr sh_type field.  */
+#define SHT_IA_64_EXT          (SHT_LOPROC + 0) /* extension bits */
+#define SHT_IA_64_UNWIND       (SHT_LOPROC + 1) /* unwind bits */
+
+/* Processor specific flags for the Shdr sh_flags field.  */
+#define SHF_IA_64_SHORT                0x10000000      /* section near gp */
+#define SHF_IA_64_NORECOV      0x20000000      /* spec insns w/o recovery */
+
+/* Processor specific values for the Dyn d_tag field.  */
+#define DT_IA_64_PLT_RESERVE   (DT_LOPROC + 0)
+#define DT_IA_64_NUM           1
+
+/* IA-64 relocations.  */
+#define R_IA64_NONE            0x00    /* none */
+#define R_IA64_IMM14           0x21    /* symbol + addend, add imm14 */
+#define R_IA64_IMM22           0x22    /* symbol + addend, add imm22 */
+#define R_IA64_IMM64           0x23    /* symbol + addend, mov imm64 */
+#define R_IA64_DIR32MSB                0x24    /* symbol + addend, data4 MSB */
+#define R_IA64_DIR32LSB                0x25    /* symbol + addend, data4 LSB */
+#define R_IA64_DIR64MSB                0x26    /* symbol + addend, data8 MSB */
+#define R_IA64_DIR64LSB                0x27    /* symbol + addend, data8 LSB */
+#define R_IA64_GPREL22         0x2a    /* @gprel(sym + add), add imm22 */
+#define R_IA64_GPREL64I                0x2b    /* @gprel(sym + add), mov imm64 */
+#define R_IA64_GPREL32MSB      0x2c    /* @gprel(sym + add), data4 MSB */
+#define R_IA64_GPREL32LSB      0x2d    /* @gprel(sym + add), data4 LSB */
+#define R_IA64_GPREL64MSB      0x2e    /* @gprel(sym + add), data8 MSB */
+#define R_IA64_GPREL64LSB      0x2f    /* @gprel(sym + add), data8 LSB */
+#define R_IA64_LTOFF22         0x32    /* @ltoff(sym + add), add imm22 */
+#define R_IA64_LTOFF64I                0x33    /* @ltoff(sym + add), mov imm64 */
+#define R_IA64_PLTOFF22                0x3a    /* @pltoff(sym + add), add imm22 */
+#define R_IA64_PLTOFF64I       0x3b    /* @pltoff(sym + add), mov imm64 */
+#define R_IA64_PLTOFF64MSB     0x3e    /* @pltoff(sym + add), data8 MSB */
+#define R_IA64_PLTOFF64LSB     0x3f    /* @pltoff(sym + add), data8 LSB */
+#define R_IA64_FPTR64I         0x43    /* @fptr(sym + add), mov imm64 */
+#define R_IA64_FPTR32MSB       0x44    /* @fptr(sym + add), data4 MSB */
+#define R_IA64_FPTR32LSB       0x45    /* @fptr(sym + add), data4 LSB */
+#define R_IA64_FPTR64MSB       0x46    /* @fptr(sym + add), data8 MSB */
+#define R_IA64_FPTR64LSB       0x47    /* @fptr(sym + add), data8 LSB */
+#define R_IA64_PCREL60B                0x48    /* @pcrel(sym + add), brl */
+#define R_IA64_PCREL21B                0x49    /* @pcrel(sym + add), ptb, call */
+#define R_IA64_PCREL21M                0x4a    /* @pcrel(sym + add), chk.s */
+#define R_IA64_PCREL21F                0x4b    /* @pcrel(sym + add), fchkf */
+#define R_IA64_PCREL32MSB      0x4c    /* @pcrel(sym + add), data4 MSB */
+#define R_IA64_PCREL32LSB      0x4d    /* @pcrel(sym + add), data4 LSB */
+#define R_IA64_PCREL64MSB      0x4e    /* @pcrel(sym + add), data8 MSB */
+#define R_IA64_PCREL64LSB      0x4f    /* @pcrel(sym + add), data8 LSB */
+#define R_IA64_LTOFF_FPTR22    0x52    /* @ltoff(@fptr(s+a)), imm22 */
+#define R_IA64_LTOFF_FPTR64I   0x53    /* @ltoff(@fptr(s+a)), imm64 */
+#define R_IA64_LTOFF_FPTR32MSB 0x54    /* @ltoff(@fptr(s+a)), data4 MSB */
+#define R_IA64_LTOFF_FPTR32LSB 0x55    /* @ltoff(@fptr(s+a)), data4 LSB */
+#define R_IA64_LTOFF_FPTR64MSB 0x56    /* @ltoff(@fptr(s+a)), data8 MSB */
+#define R_IA64_LTOFF_FPTR64LSB 0x57    /* @ltoff(@fptr(s+a)), data8 LSB */
+#define R_IA64_SEGREL32MSB     0x5c    /* @segrel(sym + add), data4 MSB */
+#define R_IA64_SEGREL32LSB     0x5d    /* @segrel(sym + add), data4 LSB */
+#define R_IA64_SEGREL64MSB     0x5e    /* @segrel(sym + add), data8 MSB */
+#define R_IA64_SEGREL64LSB     0x5f    /* @segrel(sym + add), data8 LSB */
+#define R_IA64_SECREL32MSB     0x64    /* @secrel(sym + add), data4 MSB */
+#define R_IA64_SECREL32LSB     0x65    /* @secrel(sym + add), data4 LSB */
+#define R_IA64_SECREL64MSB     0x66    /* @secrel(sym + add), data8 MSB */
+#define R_IA64_SECREL64LSB     0x67    /* @secrel(sym + add), data8 LSB */
+#define R_IA64_REL32MSB                0x6c    /* data 4 + REL */
+#define R_IA64_REL32LSB                0x6d    /* data 4 + REL */
+#define R_IA64_REL64MSB                0x6e    /* data 8 + REL */
+#define R_IA64_REL64LSB                0x6f    /* data 8 + REL */
+#define R_IA64_LTV32MSB                0x74    /* symbol + addend, data4 MSB */
+#define R_IA64_LTV32LSB                0x75    /* symbol + addend, data4 LSB */
+#define R_IA64_LTV64MSB                0x76    /* symbol + addend, data8 MSB */
+#define R_IA64_LTV64LSB                0x77    /* symbol + addend, data8 LSB */
+#define R_IA64_PCREL21BI       0x79    /* @pcrel(sym + add), 21bit inst */
+#define R_IA64_PCREL22         0x7a    /* @pcrel(sym + add), 22bit inst */
+#define R_IA64_PCREL64I                0x7b    /* @pcrel(sym + add), 64bit inst */
+#define R_IA64_IPLTMSB         0x80    /* dynamic reloc, imported PLT, MSB */
+#define R_IA64_IPLTLSB         0x81    /* dynamic reloc, imported PLT, LSB */
+#define R_IA64_COPY            0x84    /* copy relocation */
+#define R_IA64_SUB             0x85    /* Addend and symbol difference */
+#define R_IA64_LTOFF22X                0x86    /* LTOFF22, relaxable.  */
+#define R_IA64_LDXMOV          0x87    /* Use of LTOFF22X.  */
+#define R_IA64_TPREL14         0x91    /* @tprel(sym + add), imm14 */
+#define R_IA64_TPREL22         0x92    /* @tprel(sym + add), imm22 */
+#define R_IA64_TPREL64I                0x93    /* @tprel(sym + add), imm64 */
+#define R_IA64_TPREL64MSB      0x96    /* @tprel(sym + add), data8 MSB */
+#define R_IA64_TPREL64LSB      0x97    /* @tprel(sym + add), data8 LSB */
+#define R_IA64_LTOFF_TPREL22   0x9a    /* @ltoff(@tprel(s+a)), imm2 */
+#define R_IA64_DTPMOD64MSB     0xa6    /* @dtpmod(sym + add), data8 MSB */
+#define R_IA64_DTPMOD64LSB     0xa7    /* @dtpmod(sym + add), data8 LSB */
+#define R_IA64_LTOFF_DTPMOD22  0xaa    /* @ltoff(@dtpmod(sym + add)), imm22 */
+#define R_IA64_DTPREL14                0xb1    /* @dtprel(sym + add), imm14 */
+#define R_IA64_DTPREL22                0xb2    /* @dtprel(sym + add), imm22 */
+#define R_IA64_DTPREL64I       0xb3    /* @dtprel(sym + add), imm64 */
+#define R_IA64_DTPREL32MSB     0xb4    /* @dtprel(sym + add), data4 MSB */
+#define R_IA64_DTPREL32LSB     0xb5    /* @dtprel(sym + add), data4 LSB */
+#define R_IA64_DTPREL64MSB     0xb6    /* @dtprel(sym + add), data8 MSB */
+#define R_IA64_DTPREL64LSB     0xb7    /* @dtprel(sym + add), data8 LSB */
+#define R_IA64_LTOFF_DTPREL22  0xba    /* @ltoff(@dtprel(s+a)), imm22 */
+
+/* SH specific declarations */
+
+/* SH relocs.  */
+#define        R_SH_NONE               0
+#define        R_SH_DIR32              1
+#define        R_SH_REL32              2
+#define        R_SH_DIR8WPN            3
+#define        R_SH_IND12W             4
+#define        R_SH_DIR8WPL            5
+#define        R_SH_DIR8WPZ            6
+#define        R_SH_DIR8BP             7
+#define        R_SH_DIR8W              8
+#define        R_SH_DIR8L              9
+#define        R_SH_SWITCH16           25
+#define        R_SH_SWITCH32           26
+#define        R_SH_USES               27
+#define        R_SH_COUNT              28
+#define        R_SH_ALIGN              29
+#define        R_SH_CODE               30
+#define        R_SH_DATA               31
+#define        R_SH_LABEL              32
+#define        R_SH_SWITCH8            33
+#define        R_SH_GNU_VTINHERIT      34
+#define        R_SH_GNU_VTENTRY        35
+#define        R_SH_TLS_GD_32          144
+#define        R_SH_TLS_LD_32          145
+#define        R_SH_TLS_LDO_32         146
+#define        R_SH_TLS_IE_32          147
+#define        R_SH_TLS_LE_32          148
+#define        R_SH_TLS_DTPMOD32       149
+#define        R_SH_TLS_DTPOFF32       150
+#define        R_SH_TLS_TPOFF32        151
+#define        R_SH_GOT32              160
+#define        R_SH_PLT32              161
+#define        R_SH_COPY               162
+#define        R_SH_GLOB_DAT           163
+#define        R_SH_JMP_SLOT           164
+#define        R_SH_RELATIVE           165
+#define        R_SH_GOTOFF             166
+#define        R_SH_GOTPC              167
+/* Keep this the last entry.  */
+#define        R_SH_NUM                256
+
+/* Additional s390 relocs */
+
+#define R_390_NONE             0       /* No reloc.  */
+#define R_390_8                        1       /* Direct 8 bit.  */
+#define R_390_12               2       /* Direct 12 bit.  */
+#define R_390_16               3       /* Direct 16 bit.  */
+#define R_390_32               4       /* Direct 32 bit.  */
+#define R_390_PC32             5       /* PC relative 32 bit.  */
+#define R_390_GOT12            6       /* 12 bit GOT offset.  */
+#define R_390_GOT32            7       /* 32 bit GOT offset.  */
+#define R_390_PLT32            8       /* 32 bit PC relative PLT address.  */
+#define R_390_COPY             9       /* Copy symbol at runtime.  */
+#define R_390_GLOB_DAT         10      /* Create GOT entry.  */
+#define R_390_JMP_SLOT         11      /* Create PLT entry.  */
+#define R_390_RELATIVE         12      /* Adjust by program base.  */
+#define R_390_GOTOFF32         13      /* 32 bit offset to GOT.         */
+#define R_390_GOTPC            14      /* 32 bit PC relative offset to GOT.  */
+#define R_390_GOT16            15      /* 16 bit GOT offset.  */
+#define R_390_PC16             16      /* PC relative 16 bit.  */
+#define R_390_PC16DBL          17      /* PC relative 16 bit shifted by 1.  */
+#define R_390_PLT16DBL         18      /* 16 bit PC rel. PLT shifted by 1.  */
+#define R_390_PC32DBL          19      /* PC relative 32 bit shifted by 1.  */
+#define R_390_PLT32DBL         20      /* 32 bit PC rel. PLT shifted by 1.  */
+#define R_390_GOTPCDBL         21      /* 32 bit PC rel. GOT shifted by 1.  */
+#define R_390_64               22      /* Direct 64 bit.  */
+#define R_390_PC64             23      /* PC relative 64 bit.  */
+#define R_390_GOT64            24      /* 64 bit GOT offset.  */
+#define R_390_PLT64            25      /* 64 bit PC relative PLT address.  */
+#define R_390_GOTENT           26      /* 32 bit PC rel. to GOT entry >> 1. */
+#define R_390_GOTOFF16         27      /* 16 bit offset to GOT. */
+#define R_390_GOTOFF64         28      /* 64 bit offset to GOT. */
+#define R_390_GOTPLT12         29      /* 12 bit offset to jump slot.  */
+#define R_390_GOTPLT16         30      /* 16 bit offset to jump slot.  */
+#define R_390_GOTPLT32         31      /* 32 bit offset to jump slot.  */
+#define R_390_GOTPLT64         32      /* 64 bit offset to jump slot.  */
+#define R_390_GOTPLTENT                33      /* 32 bit rel. offset to jump slot.  */
+#define R_390_PLTOFF16         34      /* 16 bit offset from GOT to PLT. */
+#define R_390_PLTOFF32         35      /* 32 bit offset from GOT to PLT. */
+#define R_390_PLTOFF64         36      /* 16 bit offset from GOT to PLT. */
+#define R_390_TLS_LOAD         37      /* Tag for load insn in TLS code.  */
+#define R_390_TLS_GDCALL       38      /* Tag for function call in general
+                                          dynamic TLS code. */
+#define R_390_TLS_LDCALL       39      /* Tag for function call in local
+                                          dynamic TLS code. */
+#define R_390_TLS_GD32         40      /* Direct 32 bit for general dynamic
+                                          thread local data.  */
+#define R_390_TLS_GD64         41      /* Direct 64 bit for general dynamic
+                                         thread local data.  */
+#define R_390_TLS_GOTIE12      42      /* 12 bit GOT offset for static TLS
+                                          block offset.  */
+#define R_390_TLS_GOTIE32      43      /* 32 bit GOT offset for static TLS
+                                          block offset.  */
+#define R_390_TLS_GOTIE64      44      /* 64 bit GOT offset for static TLS
+                                          block offset. */
+#define R_390_TLS_LDM32                45      /* Direct 32 bit for local dynamic
+                                          thread local data in LE code.  */
+#define R_390_TLS_LDM64                46      /* Direct 64 bit for local dynamic
+                                          thread local data in LE code.  */
+#define R_390_TLS_IE32         47      /* 32 bit address of GOT entry for
+                                          negated static TLS block offset.  */
+#define R_390_TLS_IE64         48      /* 64 bit address of GOT entry for
+                                          negated static TLS block offset.  */
+#define R_390_TLS_IEENT                49      /* 32 bit rel. offset to GOT entry for
+                                          negated static TLS block offset.  */
+#define R_390_TLS_LE32         50      /* 32 bit negated offset relative to
+                                          static TLS block.  */
+#define R_390_TLS_LE64         51      /* 64 bit negated offset relative to
+                                          static TLS block.  */
+#define R_390_TLS_LDO32                52      /* 32 bit offset relative to TLS
+                                          block.  */
+#define R_390_TLS_LDO64                53      /* 64 bit offset relative to TLS
+                                          block.  */
+#define R_390_TLS_DTPMOD       54      /* ID of module containing symbol.  */
+#define R_390_TLS_DTPOFF       55      /* Offset in TLS block.  */
+#define R_390_TLS_TPOFF                56      /* Negated offset in static TLS
+                                          block.  */
+#define R_390_20               57      /* Direct 20 bit.  */
+#define R_390_GOT20            58      /* 20 bit GOT offset.  */
+#define R_390_GOTPLT20         59      /* 20 bit offset to jump slot.  */
+#define R_390_TLS_GOTIE20      60      /* 20 bit GOT offset for static TLS
+                                          block offset.  */
+/* Keep this the last entry.  */
+#define R_390_NUM              61
+
+
+/* CRIS relocations.  */
+#define R_CRIS_NONE            0
+#define R_CRIS_8               1
+#define R_CRIS_16              2
+#define R_CRIS_32              3
+#define R_CRIS_8_PCREL         4
+#define R_CRIS_16_PCREL                5
+#define R_CRIS_32_PCREL                6
+#define R_CRIS_GNU_VTINHERIT   7
+#define R_CRIS_GNU_VTENTRY     8
+#define R_CRIS_COPY            9
+#define R_CRIS_GLOB_DAT                10
+#define R_CRIS_JUMP_SLOT       11
+#define R_CRIS_RELATIVE                12
+#define R_CRIS_16_GOT          13
+#define R_CRIS_32_GOT          14
+#define R_CRIS_16_GOTPLT       15
+#define R_CRIS_32_GOTPLT       16
+#define R_CRIS_32_GOTREL       17
+#define R_CRIS_32_PLT_GOTREL   18
+#define R_CRIS_32_PLT_PCREL    19
+
+#define R_CRIS_NUM             20
+
+
+/* AMD x86-64 relocations.  */
+#define R_X86_64_NONE          0       /* No reloc */
+#define R_X86_64_64            1       /* Direct 64 bit  */
+#define R_X86_64_PC32          2       /* PC relative 32 bit signed */
+#define R_X86_64_GOT32         3       /* 32 bit GOT entry */
+#define R_X86_64_PLT32         4       /* 32 bit PLT address */
+#define R_X86_64_COPY          5       /* Copy symbol at runtime */
+#define R_X86_64_GLOB_DAT      6       /* Create GOT entry */
+#define R_X86_64_JUMP_SLOT     7       /* Create PLT entry */
+#define R_X86_64_RELATIVE      8       /* Adjust by program base */
+#define R_X86_64_GOTPCREL      9       /* 32 bit signed PC relative
+                                          offset to GOT */
+#define R_X86_64_32            10      /* Direct 32 bit zero extended */
+#define R_X86_64_32S           11      /* Direct 32 bit sign extended */
+#define R_X86_64_16            12      /* Direct 16 bit zero extended */
+#define R_X86_64_PC16          13      /* 16 bit sign extended pc relative */
+#define R_X86_64_8             14      /* Direct 8 bit sign extended  */
+#define R_X86_64_PC8           15      /* 8 bit sign extended pc relative */
+#define R_X86_64_DTPMOD64      16      /* ID of module containing symbol */
+#define R_X86_64_DTPOFF64      17      /* Offset in module's TLS block */
+#define R_X86_64_TPOFF64       18      /* Offset in initial TLS block */
+#define R_X86_64_TLSGD         19      /* 32 bit signed PC relative offset
+                                          to two GOT entries for GD symbol */
+#define R_X86_64_TLSLD         20      /* 32 bit signed PC relative offset
+                                          to two GOT entries for LD symbol */
+#define R_X86_64_DTPOFF32      21      /* Offset in TLS block */
+#define R_X86_64_GOTTPOFF      22      /* 32 bit signed PC relative offset
+                                          to GOT entry for IE symbol */
+#define R_X86_64_TPOFF32       23      /* Offset in initial TLS block */
+
+#define R_X86_64_NUM           24
+
+
+/* AM33 relocations.  */
+#define R_MN10300_NONE         0       /* No reloc.  */
+#define R_MN10300_32           1       /* Direct 32 bit.  */
+#define R_MN10300_16           2       /* Direct 16 bit.  */
+#define R_MN10300_8            3       /* Direct 8 bit.  */
+#define R_MN10300_PCREL32      4       /* PC-relative 32-bit.  */
+#define R_MN10300_PCREL16      5       /* PC-relative 16-bit signed.  */
+#define R_MN10300_PCREL8       6       /* PC-relative 8-bit signed.  */
+#define R_MN10300_GNU_VTINHERIT        7       /* Ancient C++ vtable garbage... */
+#define R_MN10300_GNU_VTENTRY  8       /* ... collection annotation.  */
+#define R_MN10300_24           9       /* Direct 24 bit.  */
+#define R_MN10300_GOTPC32      10      /* 32-bit PCrel offset to GOT.  */
+#define R_MN10300_GOTPC16      11      /* 16-bit PCrel offset to GOT.  */
+#define R_MN10300_GOTOFF32     12      /* 32-bit offset from GOT.  */
+#define R_MN10300_GOTOFF24     13      /* 24-bit offset from GOT.  */
+#define R_MN10300_GOTOFF16     14      /* 16-bit offset from GOT.  */
+#define R_MN10300_PLT32                15      /* 32-bit PCrel to PLT entry.  */
+#define R_MN10300_PLT16                16      /* 16-bit PCrel to PLT entry.  */
+#define R_MN10300_GOT32                17      /* 32-bit offset to GOT entry.  */
+#define R_MN10300_GOT24                18      /* 24-bit offset to GOT entry.  */
+#define R_MN10300_GOT16                19      /* 16-bit offset to GOT entry.  */
+#define R_MN10300_COPY         20      /* Copy symbol at runtime.  */
+#define R_MN10300_GLOB_DAT     21      /* Create GOT entry.  */
+#define R_MN10300_JMP_SLOT     22      /* Create PLT entry.  */
+#define R_MN10300_RELATIVE     23      /* Adjust by program base.  */
+
+#define R_MN10300_NUM          24
+
+
+/* M32R relocs.  */
+#define R_M32R_NONE            0       /* No reloc. */
+#define R_M32R_16              1       /* Direct 16 bit. */
+#define R_M32R_32              2       /* Direct 32 bit. */
+#define R_M32R_24              3       /* Direct 24 bit. */
+#define R_M32R_10_PCREL                4       /* PC relative 10 bit shifted. */
+#define R_M32R_18_PCREL                5       /* PC relative 18 bit shifted. */
+#define R_M32R_26_PCREL                6       /* PC relative 26 bit shifted. */
+#define R_M32R_HI16_ULO                7       /* High 16 bit with unsigned low. */
+#define R_M32R_HI16_SLO                8       /* High 16 bit with signed low. */
+#define R_M32R_LO16            9       /* Low 16 bit. */
+#define R_M32R_SDA16           10      /* 16 bit offset in SDA. */
+#define R_M32R_GNU_VTINHERIT   11
+#define R_M32R_GNU_VTENTRY     12
+/* M32R relocs use SHT_RELA.  */
+#define R_M32R_16_RELA         33      /* Direct 16 bit. */
+#define R_M32R_32_RELA         34      /* Direct 32 bit. */
+#define R_M32R_24_RELA         35      /* Direct 24 bit. */
+#define R_M32R_10_PCREL_RELA   36      /* PC relative 10 bit shifted. */
+#define R_M32R_18_PCREL_RELA   37      /* PC relative 18 bit shifted. */
+#define R_M32R_26_PCREL_RELA   38      /* PC relative 26 bit shifted. */
+#define R_M32R_HI16_ULO_RELA   39      /* High 16 bit with unsigned low */
+#define R_M32R_HI16_SLO_RELA   40      /* High 16 bit with signed low */
+#define R_M32R_LO16_RELA       41      /* Low 16 bit */
+#define R_M32R_SDA16_RELA      42      /* 16 bit offset in SDA */
+#define R_M32R_RELA_GNU_VTINHERIT      43
+#define R_M32R_RELA_GNU_VTENTRY        44
+
+#define R_M32R_GOT24           48      /* 24 bit GOT entry */
+#define R_M32R_26_PLTREL       49      /* 26 bit PC relative to PLT shifted */
+#define R_M32R_COPY            50      /* Copy symbol at runtime */
+#define R_M32R_GLOB_DAT                51      /* Create GOT entry */
+#define R_M32R_JMP_SLOT                52      /* Create PLT entry */
+#define R_M32R_RELATIVE                53      /* Adjust by program base */
+#define R_M32R_GOTOFF          54      /* 24 bit offset to GOT */
+#define R_M32R_GOTPC24         55      /* 24 bit PC relative offset to GOT */
+#define R_M32R_GOT16_HI_ULO    56      /* High 16 bit GOT entry with unsigned
+                                          low */
+#define R_M32R_GOT16_HI_SLO    57      /* High 16 bit GOT entry with signed
+                                          low */
+#define R_M32R_GOT16_LO                58      /* Low 16 bit GOT entry */
+#define R_M32R_GOTPC_HI_ULO    59      /* High 16 bit PC relative offset to
+                                          GOT with unsigned low */
+#define R_M32R_GOTPC_HI_SLO    60      /* High 16 bit PC relative offset to
+                                          GOT with signed low */
+#define R_M32R_GOTPC_LO                61      /* Low 16 bit PC relative offset to
+                                          GOT */
+#define R_M32R_GOTOFF_HI_ULO   62      /* High 16 bit offset to GOT
+                                          with unsigned low */
+#define R_M32R_GOTOFF_HI_SLO   63      /* High 16 bit offset to GOT
+                                          with signed low */
+#define R_M32R_GOTOFF_LO       64      /* Low 16 bit offset to GOT */
+#define R_M32R_NUM             256     /* Keep this the last entry. */
+
+
+#endif /* elf.h */
diff --git a/include/intcvt.h b/include/intcvt.h
new file mode 100644 (file)
index 0000000..12ef59a
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)intcvt.h        1.4 03/12/29 Copyright 1986-2003 J. Schilling */
+/*
+ *     Definitions for conversion to/from integer data types of various size.
+ *
+ *     Copyright (c) 1986-2003 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef        _INTCVT_H
+#define        _INTCVT_H
+
+#ifndef _MCONFIG_H
+#include <mconfig.h>
+#endif
+
+#define        i_to_2_byte(a, i)       (((Uchar *)(a))[0] = ((i) >> 8) & 0xFF,\
+                                   ((Uchar *)(a))[1] = (i) & 0xFF)
+
+#define        i_to_3_byte(a, i)       (((Uchar *)(a))[0] = ((i) >> 16)& 0xFF,\
+                                   ((Uchar *)(a))[1] = ((i) >> 8) & 0xFF,\
+                                   ((Uchar *)(a))[2] = (i) & 0xFF)
+
+#define        i_to_4_byte(a, i)       (((Uchar *)(a))[0] = ((i) >> 24)& 0xFF,\
+                                   ((Uchar *)(a))[1] = ((i) >> 16)& 0xFF,\
+                                   ((Uchar *)(a))[2] = ((i) >> 8) & 0xFF,\
+                                   ((Uchar *)(a))[3] = (i) & 0xFF)
+
+
+
+#define        a_to_byte(a)            (((Int8_t *) a)[0])
+
+#define        a_to_u_byte(a)          ((UInt8_t) \
+                               (((Uchar *) a)[0]               & 0xFF))
+
+#define        a_to_u_2_byte(a)        ((UInt16_t) \
+                               ((((Uchar *) a)[1]              & 0xFF) | \
+                                   (((Uchar *) a)[0] << 8      & 0xFF00)))
+
+#define        a_to_2_byte(a)          (int)(Int16_t)a_to_u_2_byte(a)
+
+#define        a_to_u_3_byte(a)        ((Ulong) \
+                               ((((Uchar *) a)[2]              & 0xFF) | \
+                                   (((Uchar *) a)[1] << 8      & 0xFF00) | \
+                                   (((Uchar *) a)[0] << 16     & 0xFF0000)))
+
+#define        a_to_3_byte(a)          a_to_u_3_byte(a)        /* XXX Is there a signed version ? */
+
+#ifdef __STDC__
+#      define  __TOP_4BYTE     0xFF000000UL
+#else
+#      define  __TOP_4BYTE     0xFF000000
+#endif
+
+#define        a_to_u_4_byte(a)        ((Ulong) \
+                               ((((Uchar*) a)[3]               & 0xFF) | \
+                                   (((Uchar*) a)[2] << 8       & 0xFF00) | \
+                                   (((Uchar*) a)[1] << 16      & 0xFF0000) | \
+                                   (((Uchar*) a)[0] << 24      & __TOP_4BYTE)))
+
+#define        a_to_4_byte(a)          (long)(Int32_t)a_to_u_4_byte(a)
+
+/*
+ * Little Endian versions of above macros
+ */
+#define        li_to_2_byte(a, i)      (((Uchar *)(a))[1] = ((i) >> 8) & 0xFF,\
+                                   ((Uchar *)(a))[0] = (i) & 0xFF)
+
+#define        li_to_3_byte(a, i)      (((Uchar *)(a))[2] = ((i) >> 16)& 0xFF,\
+                                   ((Uchar *)(a))[1] = ((i) >> 8) & 0xFF,\
+                                   ((Uchar *)(a))[0] = (i) & 0xFF)
+
+#define        li_to_4_byte(a, i)      (((Uchar *)(a))[3] = ((i) >> 24)& 0xFF,\
+                                   ((Uchar *)(a))[2] = ((i) >> 16)& 0xFF,\
+                                   ((Uchar *)(a))[1] = ((i) >> 8) & 0xFF,\
+                                   ((Uchar *)(a))[0] = (i) & 0xFF)
+
+
+#define        la_to_u_2_byte(a)       ((UInt16_t) \
+                               ((((Uchar*) a)[0]               & 0xFF) | \
+                                   (((Uchar*) a)[1] << 8       & 0xFF00)))
+
+#define        la_to_2_byte(a)         (int)(Int16_t)la_to_u_2_byte(a)
+
+#define        la_to_u_3_byte(a)       ((Ulong) \
+                               ((((Uchar*) a)[0]               & 0xFF) | \
+                                   (((Uchar*) a)[1] << 8       & 0xFF00) | \
+                                   (((Uchar*) a)[2] << 16      & 0xFF0000)))
+
+#define        la_to_3_byte(a)         la_to_u_3_byte(a)       /* XXX Is there a signed version ? */
+
+#define        la_to_u_4_byte(a)       ((Ulong) \
+                               ((((Uchar*) a)[0]               & 0xFF) | \
+                                   (((Uchar*) a)[1] << 8       & 0xFF00) | \
+                                   (((Uchar*) a)[2] << 16      & 0xFF0000) | \
+                                   (((Uchar*) a)[3] << 24      & __TOP_4BYTE)))
+
+#define        la_to_4_byte(a)         (long)(Int32_t)la_to_u_4_byte(a)
+
+#endif /* _INTCVT_H */
diff --git a/include/jmpdefs.h b/include/jmpdefs.h
new file mode 100644 (file)
index 0000000..d9d2db0
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)jmpdefs.h       1.2 00/11/08 Copyright 1999 J. Schilling */
+/*
+ *     Definitions that help to handle a jmp_buf
+ *
+ *     Copyright (c) 1998 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef        _JMPDEFS_H
+#define        _JMPDEFS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct {
+       jmp_buf jb;
+} jmps_t;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _JMPDEFS_H */
diff --git a/include/libport.h b/include/libport.h
new file mode 100644 (file)
index 0000000..2d5930f
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)libport.h       1.9 03/06/15 Copyright 1995 J. Schilling */
+/*
+ *     Copyright (c) 1995 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef _LIBPORT_H
+#define        _LIBPORT_H
+
+#ifndef        _MCONFIG_H
+#include <mconfig.h>
+#endif
+#ifndef        _PROTOTYP_H
+#include <prototyp.h>
+#endif
+#ifndef _STANDARD_H
+#include <standard.h>
+#endif
+
+/*
+ * Try to get HOST_NAME_MAX for gethostname()
+ */
+#ifndef _UNIXSTD_H
+#include <unixstd.h>
+#endif
+
+#ifndef HOST_NAME_MAX
+#if    defined(HAVE_NETDB_H) && !defined(HOST_NOT_FOUND) && \
+                               !defined(_INCL_NETDB_H)
+#include <netdb.h>
+#define        _INCL_NETDB_H
+#endif
+#ifdef MAXHOSTNAMELEN
+#define        HOST_NAME_MAX   MAXHOSTNAMELEN
+#endif
+#endif
+
+#ifndef HOST_NAME_MAX
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h> /* Include various defs needed with some OS */
+                       /* Linux MAXHOSTNAMELEN */
+#endif
+#ifdef MAXHOSTNAMELEN
+#ifndef HOST_NAME_MAX
+#define        HOST_NAME_MAX   MAXHOSTNAMELEN
+#endif
+#endif
+#endif
+
+#ifndef HOST_NAME_MAX
+#define        HOST_NAME_MAX   255
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef OPENSERVER
+/*
+ * Don't use the usleep() from libc on SCO's OPENSERVER.
+ * It will kill our processes with SIGALRM.
+ */
+/*
+ * Don't #undef HAVE_USLEEP in this file, SCO has a
+ * usleep() prototype in unistd.h
+ */
+/*#undef       HAVE_USLEEP*/
+#endif
+
+#ifndef        HAVE_GETHOSTID
+extern long            gethostid(void);
+#endif
+#ifndef        HAVE_GETHOSTNAME
+extern int             gethostname(char *name, int namelen);
+#endif
+#ifndef        HAVE_GETDOMAINNAME
+extern int             getdomainname(char *name, int namelen);
+#endif
+#ifndef        HAVE_GETPAGESIZE
+int            getpagesize(void);
+#endif
+#ifndef        HAVE_USLEEP
+extern int             usleep(int usec);
+#endif
+
+#if    !defined(HAVE_STRDUP) || defined(__SVR4)
+extern char            *strdup(const char *s);
+#endif
+
+#ifndef        HAVE_RENAME
+extern int             rename(const char *old, const char *new);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _LIBPORT_H */
diff --git a/include/librmt.h b/include/librmt.h
new file mode 100644 (file)
index 0000000..9264216
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)librmt.h        1.16 03/06/15 Copyright 1996 J. Schilling */
+/*
+ *     Prototypes for rmt client subroutines
+ *
+ *     Copyright (c) 1995,1996,2000-2002 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef        _LIBRMT_H
+#define        _LIBRMT_H
+
+#ifndef _MCONFIG_H
+#include <mconfig.h>
+#endif
+#ifndef _PROTOTYP_H
+#include <prototyp.h>
+#endif
+
+#ifndef        _INCL_SYS_TYPES_H
+#include <sys/types.h>
+#define        _INCL_SYS_TYPES_H
+#endif
+
+#include <rmtio.h>
+
+/*
+ * remote.c
+ */
+extern void            rmtinit(int (*errmsgn)(int, const char *, ...),
+                                                                 void (*eexit)(int));
+extern int             rmtdebug(int dlevel);
+extern char            *rmtfilename(char *name);
+extern char            *rmthostname(char *hostname, int hnsize, char *rmtspec);
+extern int             rmtgetconn(char *host, int trsize, int excode);
+extern int             rmtopen(int fd, char *fname, int fmode);
+extern int             rmtclose(int fd);
+extern int             rmtread(int fd, char *buf, int count);
+extern int             rmtwrite(int fd, char *buf, int count);
+extern off_t           rmtseek(int fd, off_t offset, int whence);
+extern int             rmtioctl(int fd, int cmd, int count);
+#ifdef MTWEOF
+extern int             rmtstatus(int fd, struct mtget *mtp);
+#endif
+extern int             rmtxstatus(int fd, struct rmtget *mtp);
+#ifdef MTWEOF
+extern void            _rmtg2mtg(struct mtget *mtp, struct rmtget *rmtp);
+extern int             _mtg2rmtg(struct rmtget *rmtp, struct mtget *mtp);
+#endif
+
+#endif /* _LIBRMT_H */
diff --git a/include/maxpath.h b/include/maxpath.h
new file mode 100644 (file)
index 0000000..a26cfe4
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)maxpath.h       1.6 03/08/23 Copyright 1985, 1995, 1998 J. Schilling */
+/*
+ *     Definitions for dealing with statically limitations on pathnames
+ *
+ *     Copyright (c) 1985, 1995, 1998 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef        _MAXPATH_H
+#define        _MAXPATH_H
+
+#ifndef        _DIRDEFS_H
+#include <dirdefs.h>                   /* Includes mconfig.h if needed     */
+#endif
+
+#ifdef JOS
+#ifndef        _JOS_MAXP_H
+#      include <jos_maxp.h>
+#endif
+#      define  FOUND_MAXPATHNAME
+#      define  FOUND_MAXFILENAME
+#else
+
+#      ifdef   MAXPATHLEN
+#              define  MAXPATHNAME     MAXPATHLEN      /* From sys/param.h */
+#              define  FOUND_MAXPATHNAME
+#      else
+#      ifdef   PATH_MAX
+#              define  MAXPATHNAME     PATH_MAX        /* From limits.h    */
+#              define  FOUND_MAXPATHNAME
+#      else
+#              define  MAXPATHNAME     256             /* Is there a limit? */
+#      endif
+#      endif
+
+/*
+ * Don't use defaults here to allow recognition of problems.
+ */
+#      ifdef   MAXNAMELEN
+#              define  MAXFILENAME     MAXNAMELEN      /* From sys/param.h */
+#              define  FOUND_MAXFILENAME
+#      else
+#      ifdef   MAXNAMLEN
+#              define  MAXFILENAME     MAXNAMLEN       /* From dirent.h    */
+#              define  FOUND_MAXFILENAME
+#      else
+#      ifdef   DIRSIZ
+#              define  MAXFILENAME     DIRSIZ          /* From sys/dir.h   */
+#              define  FOUND_MAXFILENAME
+#      endif
+#      endif
+#      endif
+
+#if    !defined(FOUND_MAXFILENAME) && defined(FOUND_DIRSIZE)
+#      define  MAXFILENAME             DIRSIZE         /* From dirdefs.h    */
+#      define  FOUND_MAXFILENAME
+#endif
+
+#endif /* JOS */
+
+#endif /* _MAXPATH_H */
diff --git a/include/mconfig.h b/include/mconfig.h
new file mode 100644 (file)
index 0000000..ee356ec
--- /dev/null
@@ -0,0 +1,487 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)mconfig.h       1.50 04/07/11 Copyright 1995 J. Schilling */
+/*
+ *     definitions for machine configuration
+ *
+ *     Copyright (c) 1995 J. Schilling
+ *
+ *     This file must be included before any other file.
+ *     If this file is not included before stdio.h you will not be
+ *     able to get LARGEFILE support
+ *
+ *     Use only cpp instructions.
+ *
+ *     NOTE: SING: (Schily Is Not Gnu)
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _MCONFIG_H
+#define        _MCONFIG_H
+
+/* whatever, just shut up */
+#define __sccsid "forked version from cdrkit"
+#define _sccsid "forked version from cdrkit"
+
+/*
+ * This hack that is needed as long as VMS has no POSIX shell.
+ */
+#ifdef VMS
+#      define  USE_STATIC_CONF
+#endif
+
+#ifdef USE_STATIC_CONF
+#include <xmconfig.h>  /* This is the current static autoconf stuff */
+#else
+#include <xconfig.h>   /* This is the current dynamic autoconf stuff */
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * The NetBSD people want to bother us.
+ * They removed the definition for 'unix' and are bleating for every test
+ * for #if defined(unix). So we need to check for NetBSD early.
+ */
+#ifndef        IS_UNIX
+#      if defined(__NetBSD__)
+#              define  IS_UNIX
+#      endif
+#endif
+
+#ifndef        IS_UNIX
+#      if (defined(unix) || defined(__unix) || defined(__unix__)) && !defined(__DJGPP__)
+#              define  IS_UNIX
+#      endif
+#endif
+
+#ifdef __MSDOS__
+#      define  IS_MSDOS
+#endif
+
+#if defined(tos) || defined(__tos)
+#      define  IS_TOS
+#endif
+
+#ifdef THINK_C
+#      define  IS_MAC
+#endif
+
+#if defined(sun) || defined(__sun) || defined(__sun__)
+#      define  IS_SUN
+#endif
+
+#if defined(__CYGWIN32__) || defined(__CYGWIN__)
+#      define  IS_GCC_WIN32
+#      define  IS_CYGWIN
+
+#if    defined(unix) || defined(_X86)
+#      define  IS_CYGWIN_1
+#endif
+#endif
+
+/*--------------------------------------------------------------------------*/
+/*
+ * Some magic that cannot (yet) be figured out with autoconf.
+ */
+
+#if defined(sun3) || defined(mc68000) || defined(mc68020)
+#      ifndef  HAVE_SCANSTACK
+#      define  HAVE_SCANSTACK
+#      endif
+#endif
+#ifdef sparc
+#      ifndef  HAVE_LDSTUB
+#      define  HAVE_LDSTUB
+#      endif
+#      ifndef  HAVE_SCANSTACK
+#      define  HAVE_SCANSTACK
+#      endif
+#endif
+#if    defined(__i386_) || defined(i386)
+#      ifndef  HAVE_XCHG
+#      define  HAVE_XCHG
+#      endif
+#      ifndef  HAVE_SCANSTACK
+#      define  HAVE_SCANSTACK
+#      endif
+#endif
+
+/*
+ * Use of SCANSTACK is disabled by default
+ */
+#ifndef        USE_SCANSTACK
+#      undef   HAVE_SCANSTACK
+#else
+/*
+ * But ....
+ * The tests are much better now, so always give it a chance.
+ */
+#ifndef        HAVE_SCANSTACK
+#      define  HAVE_SCANSTACK
+#endif
+#endif
+
+/*
+ * Allow to overwrite the defines in the makefiles by calling
+ *
+ *     make COPTX=-DFORCE_SCANSTACK
+ */
+#ifdef FORCE_SCANSTACK
+#      undef   NO_SCANSTACK
+#ifndef        HAVE_SCANSTACK
+#      define  HAVE_SCANSTACK
+#endif
+#ifndef        USE_SCANSTACK
+#      define  USE_SCANSTACK
+#endif
+#endif
+
+/*
+ * This is the global switch to deactivate stack scanning
+ */
+#ifdef NO_SCANSTACK
+#      ifdef   HAVE_SCANSTACK
+#      undef   HAVE_SCANSTACK
+#      endif
+#endif
+
+#ifdef NO_FORK
+#      ifdef   HAVE_FORK
+#      undef   HAVE_FORK
+#      endif
+#      ifdef   HAVE_VFORK
+#      undef   HAVE_VFORK
+#      endif
+#endif
+#ifdef NO_VFORK
+#      ifdef   HAVE_VFORK
+#      undef   HAVE_VFORK
+#      endif
+#endif
+
+#if    defined(SOL2) || defined(SOL2) || \
+       defined(S5R4) || defined(__S5R4) || defined(SVR4)
+#      ifndef  __SVR4
+#              define  __SVR4
+#      endif
+#endif
+
+#ifdef __SVR4
+#      ifndef  SVR4
+#              define  SVR4
+#      endif
+#endif
+
+/*
+ * SunOS 4.x / SunOS 5.x
+ */
+#if defined(IS_SUN)
+#      define  HAVE_GETAV0
+#endif
+
+/*
+ * AIX
+ */
+#if    defined(_IBMR2) || defined(_AIX)
+#      ifndef  IS_UNIX
+#      define  IS_UNIX         /* ??? really ??? */
+#      endif
+#endif
+
+/*
+ * QNX
+ */
+#if defined(__QNX__)
+#      ifndef  IS_UNIX
+#      define  IS_UNIX
+#      endif
+#endif
+
+/*
+ * Silicon Graphics    (must be before SVR4)
+ */
+#if defined(sgi) || defined(__sgi)
+#      define  __NOT_SVR4__    /* Not a real SVR4 implementation */
+#endif
+
+/*
+ * Data General
+ */
+#if defined(__DGUX__)
+#ifdef XXXXXXX
+#      undef   HAVE_MTGET_DSREG
+#      undef   HAVE_MTGET_RESID
+#      undef   HAVE_MTGET_FILENO
+#      undef   HAVE_MTGET_BLKNO
+#endif
+#      define  mt_type         mt_model
+#      define  mt_dsreg        mt_status1
+#      define  mt_erreg        mt_status2
+       /*
+        * DGUX hides its flock as dg_flock.
+        */
+#      define  HAVE_FLOCK
+#      define  flock   dg_flock
+       /*
+        * Use the BSD style wait on DGUX to get the resource usages of child
+        * processes.
+        */
+#      define  _BSD_WAIT_FLAVOR
+#endif
+
+/*
+ * Apple Rhapsody (This is the name for Mac OS X beta)
+ */
+#if defined(__NeXT__) && defined(__TARGET_OSNAME) && __TARGET_OSNAME == rhapsody
+#      define  HAVE_OSDEF /* prevent later definitions to overwrite current */
+#      ifndef  IS_UNIX
+#      define  IS_UNIX
+#      endif
+#endif
+
+/*
+ * NextStep
+ */
+#if defined(__NeXT__) && !defined(HAVE_OSDEF)
+#define        NO_PRINT_OVR
+#undef HAVE_USG_STDIO          /*
+                                * NeXT Step 3.x uses __flsbuf(unsigned char, FILE *)
+                                * instead of __flsbuf(int, FILE *)
+                                */
+#      ifndef  IS_UNIX
+#      define  IS_UNIX
+#      endif
+#endif
+
+/*
+ * Mac OS X
+ */
+#if defined(__APPLE__) && defined(__MACH__)
+#      ifndef  IS_UNIX
+#      define  IS_UNIX
+#      endif
+#      define  IS_MACOS_X
+#endif
+
+/*
+ * NextStep 3.x has a broken linker that does not allow us to override
+ * these functions.
+ */
+#ifndef        __OPRINTF__
+
+#ifdef NO_PRINT_OVR
+#      define  printf  Xprintf
+#      define  fprintf Xfprintf
+#      define  sprintf Xsprintf
+#endif
+
+#endif /* __OPRINTF__ */
+
+/*--------------------------------------------------------------------------*/
+/*
+ * If there is no flock defined by the system, use emulation
+ * through fcntl record locking.
+ */
+#ifndef HAVE_FLOCK
+#define        LOCK_SH         1       /* shared lock */
+#define        LOCK_EX         2       /* exclusive lock */
+#define        LOCK_NB         4       /* don't block when locking */
+#define        LOCK_UN         8       /* unlock */
+#endif
+
+#ifndef        _PROTOTYP_H
+#include <prototyp.h>
+#endif
+
+/*
+ * gcc 2.x generally implements the long long type.
+ */
+#ifdef __GNUC__
+#      if      __GNUC__ > 1
+#              ifndef  HAVE_LONGLONG
+#                      define  HAVE_LONGLONG
+#              endif
+#      endif
+#endif
+
+/*
+ * Convert to GNU name
+ */
+#ifdef HAVE_STDC_HEADERS
+#      ifndef  STDC_HEADERS
+#              define  STDC_HEADERS
+#      endif
+#endif
+/*
+ * Convert to SCHILY name
+ */
+#ifdef STDC_HEADERS
+#      ifndef  HAVE_STDC_HEADERS
+#              define  HAVE_STDC_HEADERS
+#      endif
+#endif
+
+#ifdef IS_UNIX
+#      define  HAVE_PATH_DELIM
+#      define  PATH_DELIM              '/'
+#      define  PATH_DELIM_STR          "/"
+#      define  PATH_ENV_DELIM          ':'
+#      define  PATH_ENV_DELIM_STR      ":"
+#      define  far
+#      define  near
+#endif
+
+/*
+ * Win32 with Gygwin
+ */
+#ifdef IS_GCC_WIN32
+#      define  HAVE_PATH_DELIM
+#      define  PATH_DELIM              '/'
+#      define  PATH_DELIM_STR          "/"
+#      define  PATH_ENV_DELIM          ':'
+#      define  PATH_ENV_DELIM_STR      ":"
+#      define  HAVE_DOS_DRIVELETTER
+#      define  far
+#      define  near
+#      define  NEED_O_BINARY
+#endif
+
+/*
+ * Win32 with Mingw32
+ */
+#ifdef __MINGW32__
+#      define  HAVE_PATH_DELIM
+#      define  PATH_DELIM              '/'
+#      define  PATH_DELIM_STR          "/"
+#      define  PATH_ENV_DELIM          ';'
+#      define  PATH_ENV_DELIM_STR      ";"
+#      define  HAVE_DOS_DRIVELETTER
+#      define  far
+#      define  near
+#      define  NEED_O_BINARY
+#endif
+
+/*
+ * OS/2 EMX
+ */
+#ifdef __EMX__                         /* We don't want to call it UNIX */
+#      define  HAVE_PATH_DELIM
+#      define  PATH_DELIM              '/'
+#      define  PATH_DELIM_STR          "/"
+#      define  PATH_ENV_DELIM          ';'
+#      define  PATH_ENV_DELIM_STR      ";"
+#      define  HAVE_DOS_DRIVELETTER
+#      define  far
+#      define  near
+#      define  NEED_O_BINARY
+#endif
+
+#ifdef __BEOS__                        /* We don't want to call it UNIX */
+#      define  HAVE_PATH_DELIM
+#      define  PATH_DELIM              '/'
+#      define  PATH_DELIM_STR          "/"
+#      define  PATH_ENV_DELIM          ':'
+#      define  PATH_ENV_DELIM_STR      ":"
+#      define  far
+#      define  near
+#endif
+
+/*
+ * DOS with DJGPP
+ */
+#ifdef __DJGPP__                       /* We don't want to call it UNIX */
+#      define  HAVE_PATH_DELIM
+#      define  PATH_DELIM              '/'
+#      define  PATH_DELIM_STR          "/"
+#      define  PATH_ENV_DELIM          ';'
+#      define  PATH_ENV_DELIM_STR      ";"
+#      define  HAVE_DOS_DRIVELETTER
+
+#      define  NEED_O_BINARY
+#endif
+
+/*
+ * Vanilla DOS
+ */
+#if    defined(IS_MSDOS) && !defined(__DJGPP__)
+#      define  HAVE_PATH_DELIM
+#      define  PATH_DELIM              '\\'
+#      define  PATH_DELIM_STR          "\\"
+#      define  PATH_ENV_DELIM          ';'
+#      define  PATH_ENV_DELIM_STR      ";"
+#      define  HAVE_DOS_DRIVELETTER
+
+#      define  NEED_O_BINARY
+#endif
+
+/*
+ * ATARI TOS
+ */
+#ifdef IS_TOS
+#      define  HAVE_PATH_DELIM
+#      define  PATH_DELIM              '\\'
+#      define  PATH_DELIM_STR          "\\"
+#      define  PATH_ENV_DELIM          ','
+#      define  PATH_ENV_DELIM_STR      ","
+#      define  HAVE_DOS_DRIVELETTER
+#      define  far
+#      define  near
+#endif
+
+/*
+ * Mac OS 9
+ */
+#ifdef IS_MAC
+#      define  HAVE_PATH_DELIM
+#      define  PATH_DELIM              ':'
+#      define  PATH_DELIM_STR          ":"
+#      define  PATH_ENV_DELIM          ';'     /* ??? */
+#      define  PATH_ENV_DELIM_STR      ";"     /* ??? */
+#      define  far
+#      define  near
+#endif
+
+/*
+ * I hope this will make compilation on unknown OS easier.
+ */
+#ifndef        HAVE_PATH_DELIM                 /* Default to POSIX rules */
+#      define  HAVE_PATH_DELIM
+#      define  PATH_DELIM              '/'
+#      define  PATH_DELIM_STR          "/"
+#      define  PATH_ENV_DELIM          ':'
+#      define  PATH_ENV_DELIM_STR      ":"
+#      define  far
+#      define  near
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _MCONFIG_H */
diff --git a/include/mmapdefs.h b/include/mmapdefs.h
new file mode 100644 (file)
index 0000000..82d5256
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)mmapdefs.h      1.1 01/02/25 Copyright 2001 J. Schilling */
+/*
+ *     Definitions to be used for mmap()
+ *
+ *     Copyright (c) 2001 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef        _MMAPDEFS_H
+#define        _MMAPDEFS_H
+
+#ifndef        _MCONFIG_H
+#include <mconfig.h>
+#endif
+
+#ifndef        _INCL_SYS_TYPES_H
+#include <sys/types.h>
+#define        _INCL_SYS_TYPES_H
+#endif
+
+#if defined(HAVE_SMMAP)
+
+#ifndef        _INCL_SYS_MMAN_H
+#include <sys/mman.h>
+#define        _INCL_SYS_MMAN_H
+#endif
+
+#ifndef        MAP_ANONYMOUS
+#      ifdef   MAP_ANON
+#      define  MAP_ANONYMOUS   MAP_ANON
+#      endif
+#endif
+
+#ifndef MAP_FILE
+#      define MAP_FILE         0       /* Needed on Apollo Domain/OS */
+#endif
+
+/*
+ * Needed for Apollo Domain/OS and may be for others?
+ */
+#ifdef _MMAP_WITH_SIZEP
+#      define  mmap_sizeparm(s)        (&(s))
+#else
+#      define  mmap_sizeparm(s)        (s)
+#endif
+
+#endif /* defined(HAVE_SMMAP) */
+
+#endif /* _MMAPDEFS_H */
diff --git a/include/patmatch.h b/include/patmatch.h
new file mode 100644 (file)
index 0000000..20ddc77
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)patmatch.h      1.10 03/08/24 Copyright 1985 J. Schilling */
+
+#ifndef        _PATMATCH_H
+#define        _PATMATCH_H
+/*
+ *     Definitions for the pattern matching functions.
+ *
+ *     Copyright (c) 1985,1995 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/*
+ *     The pattern matching functions are based on the algorithm
+ *     presented by Martin Richards in:
+ *
+ *     "A Compact Function for Regular Expression Pattern Matching",
+ *     Software-Practice and Experience, Vol. 9, 527-534 (1979)
+ *
+ *     Several changes have been made to the original source which has been
+ *     written in BCPL:
+ *
+ *     '/'     is replaced by  '!'             (to allow UNIX filenames)
+ *     '(',')' are replaced by '{', '}'
+ *     '\''    is replaced by  '\\'            (UNIX compatible quote)
+ *
+ *     Character classes have been added to allow "[<character list>]"
+ *     to be used.
+ *     Start of line '^' and end of line '$' have been added.
+ *
+ *     Any number in the following comment is zero or more occurrencies
+ */
+#ifndef _MCONFIG_H
+#include <mconfig.h>
+#endif
+#ifndef _PROTOTYP_H
+#include <prototyp.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define        ALT     '!'     /* Alternation in match i.e. this!that!the_other */
+#define        REP     '#'     /* Any number of occurrences of the following expr */
+#define        NIL     '%'     /* Empty string (exactly nothing) */
+#define        STAR    '*'     /* Any number of any character (equivalent of #?) */
+#define        ANY     '?'     /* Any one character */
+#define        QUOTE   '\\'    /* Quotes the next character */
+#define        LBRACK  '{'     /* Begin of precedence grouping */
+#define        RBRACK  '}'     /* End of precedence grouping */
+#define        LCLASS  '['     /* Begin of character set */
+#define        RCLASS  ']'     /* End of character set */
+#define        NOT     '^'     /* If first in set: invert set content */
+#define        RANGE   '-'     /* Range notation in sets */
+#define        START   '^'     /* Begin of a line */
+#define        END     '$'     /* End of a line */
+
+/*
+ * A list of case statements that may be used for a issimple() or ispattern()
+ * funtion that checks whether a string conrtains characters that need the
+ * pattern matcher.
+ *
+ * Note that this list does not contain NOT or RANGE because you need
+ * LCLASS and RCLASS in addition.
+ */
+#define        casePAT case ALT: case REP: case NIL: case STAR: case ANY:      \
+               case QUOTE: case LBRACK: case RBRACK:                   \
+               case LCLASS: case RCLASS: case START: case END:
+
+
+#define        MAXPAT  128     /* Maximum length of pattern */
+
+extern int patcompile(const unsigned char *__pat, int __patlen, int *__aux);
+
+extern unsigned char *opatmatch(const unsigned char *__pat, const int *__aux,
+                                                                                        const unsigned char *__str, int __soff, 
+                                                                                        int __slen, int __alt);
+extern unsigned char *opatlmatch(const unsigned char *__pat, const int *__aux,
+                                                                                         const unsigned char *__str, int __soff, 
+                                                                                         int __slen, int __alt);
+extern unsigned char *patmatch(const unsigned char *__pat, const int *__aux,
+                                                                                       const unsigned char *__str, int __soff, 
+                                                                                       int __slen, int __alt, int __state[]);
+extern unsigned char *patlmatch(const unsigned char *__pat, const int *__aux,
+                                                                                        const unsigned char *__str, int __soff, 
+                                                                                        int __slen, int __alt, int __state[]);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PATMATCH_H */
diff --git a/include/prototyp.h b/include/prototyp.h
new file mode 100644 (file)
index 0000000..70d06ca
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)prototyp.h      1.11 03/08/23 Copyright 1995 J. Schilling */
+/*
+ *     Definitions for dealing with ANSI / KR C-Compilers
+ *
+ *     Copyright (c) 1995 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * mconfig.h includes prototype.h so we must do this include before we test
+ * for _PROTOTYP_H
+ */
+#ifndef _MCONFIG_H
+#include <mconfig.h>
+#endif
+
+#ifndef        _PROTOTYP_H
+#define        _PROTOTYP_H
+
+#ifndef        PROTOTYPES
+       /*
+        * If this has already been defined,
+        * someone else knows better than us...
+        */
+#      ifdef   __STDC__
+#              if      __STDC__                                /* ANSI C */
+#                      define  PROTOTYPES
+#              endif
+#              if      defined(sun) && __STDC__ - 0 == 0       /* Sun C */
+#                      define  PROTOTYPES
+#              endif
+#      endif
+#endif /* PROTOTYPES */
+
+#if    !defined(PROTOTYPES) && (defined(__cplusplus) || defined(_MSC_VER))
+       /*
+        * C++ always supports prototypes.
+        * Define PROTOTYPES so we are not forced to make
+        * a separtate autoconf run for C++
+        *
+        * Microsoft C has prototypes but does not define __STDC__
+        */
+#      define  PROTOTYPES
+#endif
+
+/*
+ * If we have prototypes, we should have stdlib.h string.h stdarg.h
+ */
+#ifdef PROTOTYPES
+#if    !(defined(SABER) && defined(sun))
+#      ifndef  HAVE_STDARG_H
+#              define  HAVE_STDARG_H
+#      endif
+#endif
+#ifndef        JOS
+#      ifndef  HAVE_STDLIB_H
+#              define  HAVE_STDLIB_H
+#      endif
+#      ifndef  HAVE_STRING_H
+#              define  HAVE_STRING_H
+#      endif
+#      ifndef  HAVE_STDC_HEADERS
+#              define  HAVE_STDC_HEADERS
+#      endif
+#      ifndef  STDC_HEADERS
+#              define  STDC_HEADERS    /* GNU name */
+#      endif
+#endif
+#endif
+
+#ifdef NO_PROTOTYPES           /* Force not to use prototypes */
+#      undef   PROTOTYPES
+#endif
+
+#ifdef PROTOTYPES
+#      define  __PR(a) a
+#else
+#      define  __PR(a) ()
+#endif
+
+#endif /* _PROTOTYP_H */
diff --git a/include/rmtio.h b/include/rmtio.h
new file mode 100644 (file)
index 0000000..1bf46ec
--- /dev/null
@@ -0,0 +1,167 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)rmtio.h 1.5 03/06/15 Copyright 1995,2000 J. Schilling */
+/*
+ *     Definition for enhanced remote tape IO
+ *
+ *     Copyright (c) 1995,2000-2002 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef        _RMTIO_H
+#define        _RMTIO_H
+
+#ifndef _MCONFIG_H
+#include <mconfig.h>
+#endif
+#ifndef        _UTYPES_H
+#include <utypes.h>
+#endif
+
+/*
+ * values for mt_op
+ */
+#define        RMTWEOF         0       /* write an end-of-file record */
+#define        RMTFSF          1       /* forward space over file mark */
+#define        RMTBSF          2       /* backward space over file mark (1/2" only ) */
+#define        RMTFSR          3       /* forward space to inter-record gap */
+#define        RMTBSR          4       /* backward space to inter-record gap */
+#define        RMTREW          5       /* rewind */
+#define        RMTOFFL         6       /* rewind and put the drive offline */
+#define        RMTNOP          7       /* no operation, sets status only */
+
+#ifdef __needed__
+#define        MTRETEN         8       /* retension the tape (cartridge tape only) */
+#define        MTERASE         9       /* erase the entire tape */
+#define        MTEOM           10      /* position to end of media */
+#define        MTNBSF          11      /* backward space file to BOF */
+
+#define        MTSRSZ          12      /* set record size */
+#define        MTGRSZ          13      /* get record size */
+#define        MTLOAD          14      /* for loading a tape (use o_delay to open */
+                               /* the tape device) */
+#endif
+
+/*
+ * Definitions for the new RMT Protocol version 1
+ *
+ * The new Protocol version tries to make the use
+ * of rmtioctl() more portable between different platforms.
+ */
+#define        RMTIVERSION     -1      /* Opcode to request version */
+#define        RMT_NOVERSION   -1      /* Old version code */
+#define        RMT_VERSION     1       /* New (current) version code */
+
+/*
+ * Support for commands bejond MTWEOF..MTNOP (0..7)
+ */
+#define        RMTICACHE       0       /* enable controller cache */
+#define        RMTINOCACHE     1       /* disable controller cache */
+#define        RMTIRETEN       2       /* retension the tape (cartridge tape only) */
+#define        RMTIERASE       3       /* erase the entire tape */
+#define        RMTIEOM         4       /* position to end of media */
+#define        RMTINBSF        5       /* backward space file to BOF */
+
+/*
+ * Old MTIOCGET copies a binary version of struct mtget back
+ * over the wire. This is highly non portable.
+ * MTS_* retrieves ascii versions (%d format) of a single
+ * field in the struct mtget.
+ * NOTE: MTS_ERREG may only be valid on the first call and
+ *      must be retrived first.
+ */
+#define        MTS_TYPE        'T'             /* mtget.mt_type */
+#define        MTS_DSREG       'D'             /* mtget.mt_dsreg */
+#define        MTS_ERREG       'E'             /* mtget.mt_erreg */
+#define        MTS_RESID       'R'             /* mtget.mt_resid */
+#define        MTS_FILENO      'F'             /* mtget.mt_fileno */
+#define        MTS_BLKNO       'B'             /* mtget.mt_blkno */
+#define        MTS_FLAGS       'f'             /* mtget.mt_flags */
+#define        MTS_BF          'b'             /* mtget.mt_bf */
+
+/*
+ * structure for remote MTIOCGET - mag tape get status command
+ */
+struct rmtget  {
+       Llong           mt_type;        /* type of magtape device           */
+       /* the following two registers are grossly device dependent         */
+       Llong           mt_dsreg;       /* ``drive status'' register        */
+       Int32_t         mt_dsreg1;      /* ``drive status'' register        */
+       Int32_t         mt_dsreg2;      /* ``drive status'' register        */
+       Llong           mt_gstat;       /* ``generic status'' register      */
+       Llong           mt_erreg;       /* ``error'' register               */
+       /* optional error info.                                             */
+       Llong           mt_resid;       /* residual count                   */
+       Llong           mt_fileno;      /* file number of current position  */
+       Llong           mt_blkno;       /* block number of current position */
+       Llong           mt_flags;
+       Llong           mt_gflags;      /* generic flags                    */
+       long            mt_bf;          /* optimum blocking factor          */
+       int             mt_xflags;      /* eXistence flags for struct members */
+};
+
+/*
+ * Values for mt_xflags
+ */
+#define        RMT_TYPE                0x0001  /* mt_type/mt_model present     */
+#define        RMT_DSREG               0x0002  /* mt_dsreg present             */
+#define        RMT_DSREG1              0x0004  /* mt_dsreg1 present            */
+#define        RMT_DSREG2              0x0008  /* mt_dsreg2 present            */
+#define        RMT_GSTAT               0x0010  /* mt_gstat present             */
+#define        RMT_ERREG               0x0020  /* mt_erreg present             */
+#define        RMT_RESID               0x0040  /* mt_resid present             */
+#define        RMT_FILENO              0x0080  /* mt_fileno present            */
+#define        RMT_BLKNO               0x0100  /* mt_blkno present             */
+#define        RMT_FLAGS               0x0200  /* mt_flags present             */
+#define        RMT_BF                  0x0400  /* mt_bf present                */
+#define        RMT_COMPAT              0x0800  /* Created from old compat data */
+
+/*
+ * values for mt_flags
+ */
+#define        RMTF_SCSI               0x01
+#define        RMTF_REEL               0x02
+#define        RMTF_ASF                0x04
+#define        RMTF_TAPE_HEAD_DIRTY    0x08
+#define        RMTF_TAPE_CLN_SUPPORTED 0x10
+
+/*
+ * these are recommended
+ */
+#ifdef __needed__
+#define        MT_ISQIC        0x32            /* generic QIC tape drive */
+#define        MT_ISREEL       0x33            /* generic reel tape drive */
+#define        MT_ISDAT        0x34            /* generic DAT tape drive */
+#define        MT_IS8MM        0x35            /* generic 8mm tape drive */
+#define        MT_ISOTHER      0x36            /* generic other type of tape drive */
+
+/* more Sun devices */
+#define        MT_ISTAND25G    0x37            /* sun: SCSI Tandberg 2.5 Gig QIC */
+#define        MT_ISDLT        0x38            /* sun: SCSI DLT tape drive */
+#define        MT_ISSTK9840    0x39            /* sun: STK 9840 (Ironsides) */
+#endif
+
+#endif /* _RMTIO_H */
diff --git a/include/schily.h b/include/schily.h
new file mode 100644 (file)
index 0000000..ec7cbb4
--- /dev/null
@@ -0,0 +1,288 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)schily.h        1.54 06/01/12 Copyright 1985-2006 J. Schilling */
+/*
+ *     Definitions for libschily
+ *
+ *     This file should be included past:
+ *
+ *     mconfig.h / config.h
+ *     standard.h
+ *     stdio.h
+ *     stdlib.h        (better use stdxlib.h)
+ *     unistd.h        (better use unixstd.h) needed LARGEFILE support
+ *     string.h
+ *     sys/types.h
+ *
+ *     If you need stdio.h, you must include it before schily.h
+ *
+ *     NOTE: If you need ctype.h and did not include stdio.h you need to
+ *     include ctype.h past schily.h as OpenBSD does not follow POSIX and
+ *     defines EOF in ctype.h
+ *
+ *     Copyright (c) 1985-2006 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _SCHILY_H
+#define        _SCHILY_H
+
+#ifndef _STANDARD_H
+#include <standard.h>
+#endif
+#ifndef _CCOMDEFS_H
+#include <ccomdefs.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if    defined(_INCL_SYS_TYPES_H) || defined(off_t)
+#      ifndef  FOUND_OFF_T
+#      define  FOUND_OFF_T
+#      endif
+#endif
+#if    defined(_INCL_SYS_TYPES_H) || defined(size_t)
+#      ifndef  FOUND_SIZE_T
+#      define  FOUND_SIZE_T
+#      endif
+#endif
+
+#ifdef __never_def__
+/*
+ * It turns out that we cannot use the folloginw definition because there are
+ * some platforms that do not behave application friendly. These are mainly
+ * BSD-4.4 based systems (which #undef a definition when size_t is available.
+ * We actually removed this code because of a problem with QNX Neutrino.
+ * For this reason, it is important not to include <sys/types.h> directly but
+ * via the Schily SING include files so we know whether it has been included
+ * before we come here.
+ */
+#if    defined(_SIZE_T)        || defined(_T_SIZE_)    || defined(_T_SIZE) || \
+       defined(__SIZE_T)       || defined(_SIZE_T_)    || \
+       defined(_GCC_SIZE_T)    || defined(_SIZET_)     || \
+       defined(__sys_stdtypes_h) || defined(___int_size_t_h) || defined(size_t)
+
+#ifndef        FOUND_SIZE_T
+#      define  FOUND_SIZE_T    /* We already included a size_t definition */
+#endif
+#endif
+#endif /* __never_def__ */
+
+#if    defined(HAVE_LARGEFILES)
+#      define  _fcons          _fcons64
+#      define  fdup            fdup64
+#      define  fileluopen      fileluopen64
+#      define  fileopen        fileopen64
+#      define  filemopen       filemopen64
+#      define  filepos         filepos64
+#      define  filereopen      filereopen64
+#      define  fileseek        fileseek64
+#      define  filesize        filesize64
+#      define  filestat        filestat64
+#      define  _openfd         _openfd64
+#endif
+
+#ifdef EOF     /* stdio.h has been included */
+extern int     _cvmod(const char *, int *, int *);
+extern FILE    *_fcons(FILE *, int, int);
+extern FILE    *fdup(FILE *);
+extern int     fdown(FILE *);
+extern int     rols_fexecl(const char *, FILE *, FILE *, FILE *, const char *, ...);
+extern int     rols_fexecle(const char *, FILE *, FILE *, FILE *, const char *, ...);
+               /* 6th arg not const, fexecv forces av[ac] = NULL */
+extern int     rols_fexecv(const char *, FILE *, FILE *, FILE *, int, char **);
+extern int     rols_fexecve(const char *, FILE *, FILE *, FILE *, char * const *, 
+                                                         char * const *);
+extern int     fspawnv(FILE *, FILE *, FILE *, int, char * const *);
+extern int     fspawnl(FILE *, FILE *, FILE *, const char *, const char *, ...);
+extern int     fspawnv_nowait(FILE *, FILE *, FILE *, const char *, int, 
+                                                                               char *const*);
+extern int     rols_fgetline(FILE *, char *, int);
+extern int     fgetstr(FILE *, char *, int);
+extern void    file_raise(FILE *, int);
+extern int     fileclose(FILE *);
+extern FILE    *fileluopen(int, const char *);
+extern FILE    *fileopen(const char *, const char *);
+#ifdef _INCL_SYS_TYPES_H
+extern FILE    *filemopen(const char *, const char *, mode_t);
+#endif
+#ifdef FOUND_OFF_T
+extern off_t   filepos(FILE *);
+#endif
+extern int     fileread(FILE *, void *, int);
+extern int     ffileread(FILE *, void *, int);
+extern FILE    *filereopen(const char *, const char *, FILE *);
+#ifdef FOUND_OFF_T
+extern int     fileseek(FILE *, off_t);
+extern off_t   filesize(FILE *);
+#endif
+#ifdef S_IFMT
+extern int     filestat(FILE *, struct stat *);
+#endif
+extern int     filewrite(FILE *, void *, int);
+extern int     ffilewrite(FILE *, void *, int);
+extern int     flush(void);
+extern int     fpipe(FILE **);
+extern int     getbroken(FILE *, char *, char, char **, int);
+extern int     ofindline(FILE *, char, const char *, int, char **, int);
+extern int     peekc(FILE *);
+
+#ifdef __never_def__
+/*
+ * We cannot define this or we may get into problems with DOS based systems.
+ */
+extern int     spawnv(FILE *, FILE *, FILE *, int, char * const *);
+extern int     spawnl(FILE *, FILE *, FILE *, const char *, const char *, ...);
+extern int     spawnv_nowait(FILE *, FILE *, FILE *, const char *, int, 
+                                                                         char *const*);
+#endif /* __never_def__m */
+#endif /* EOF */
+
+extern int     _niread(int, void *, int);
+extern int     _niwrite(int, void *, int);
+extern int     _nixread(int, void *, int);
+extern int     _nixwrite(int, void *, int);
+extern int     _openfd(const char *, int);
+extern int     on_comerr(void (*fun)(int, void *), void *arg);
+/*PRINTFLIKE1*/
+extern void    comerr(const char *, ...) __printflike__(1, 2);
+/*PRINTFLIKE2*/
+extern void    comerrno(int, const char *, ...) __printflike__(2, 3);
+/*PRINTFLIKE1*/
+extern int     errmsg(const char *, ...) __printflike__(1, 2);
+/*PRINTFLIKE2*/
+extern int     errmsgno(int, const char *, ...) __printflike__(2, 3);
+#ifdef FOUND_SIZE_T
+/*PRINTFLIKE3*/
+extern int     serrmsg(char *, size_t, const char *, ...) __printflike__(3, 4);
+/*PRINTFLIKE4*/
+extern int     serrmsgno(int, char *, size_t, const char *, ...) __printflike__(4, 5);
+#endif
+extern void    comexit(int);
+extern char    *errmsgstr(int);
+/*PRINTFLIKE1*/
+extern int     schily_error(const char *, ...) __printflike__(1, 2);
+extern char    *fillbytes(void *, int, char);
+extern char    *findbytes(const void *, int, char);
+extern int     findline(const char *, char, const char *, int, char **, int);
+extern int     rols_getline(char *, int);
+extern int     getstr(char *, int);
+extern int     breakline(char *, char, char **, int);
+extern int     getallargs(int *, char * const**, const char *, ...);
+extern int     getargs(int *, char * const**, const char *, ...);
+extern int     getfiles(int *, char * const**, const char *);
+extern char    *astoi(const char *, int *);
+extern char    *astol(const char *, long *);
+extern char    *astolb(const char *, long *, int base);
+#ifdef _UTYPES_H
+extern char    *astoll(const char *, Llong *);
+extern char    *astollb(const char *, Llong *, int);
+extern char    *astoull(const char *, Ullong *);
+extern char    *astoullb(const char *, Ullong *, int);
+#endif
+
+/*extern       void    handlecond __PR((const char *, SIGBLK *, int(*)(const char *, long, long), long));*/
+/*extern       void    unhandlecond __PR((SIGBLK *));*/
+
+extern int             patcompile(const unsigned char *, int, int *);
+extern unsigned char   *patmatch(const unsigned char *, const int *,
+                                                                                        const unsigned char *, int, int, int, int[]);
+extern unsigned char   *patlmatch(const unsigned char *, const int *,
+                                                                                         const unsigned char *, int, int, int, int[]);
+
+extern char    *movebytes(const void *, void *, int);
+
+extern void    save_args(int, char **);
+extern int     saved_ac(void);
+extern char    **saved_av(void);
+extern char    *saved_av0(void);
+#ifndef        seterrno
+extern int     seterrno(int);
+#endif
+extern void    set_progname(const char *);
+extern char    *get_progname(void);
+
+extern void    setfp(void * const *);
+extern int     wait_chld(int);         /* for fspawnv_nowait() */
+extern int     geterrno(void);
+extern void    raisecond(const char *, long);
+extern char    *strcatl(char *, ...);
+extern int     streql(const char *, const char *);
+#ifdef va_arg
+extern int     format(void (*)(char, long), long, const char *, va_list);
+#else
+extern int     format(void (*)(char, long), long, const char *, void *);
+#endif
+
+extern int     ftoes(char *, double, int, int);
+extern int     ftofs(char *, double, int, int);
+
+extern void    swabbytes(void *, int);
+extern char    **getmainfp(void);
+extern char    **getavp(void);
+extern char    *getav0(void);
+extern void    **getfp(void);
+extern int     flush_reg_windows(int);
+extern int     cmpbytes(const void *, const void *, int);
+extern int     cmpnullbytes(const void *, int);
+
+#ifdef nonono
+#if    defined(HAVE_LARGEFILES)
+/*
+ * To allow this, we need to figure out how to do autoconfiguration for off64_t
+ */
+extern FILE    *_fcons64(FILE *, int, int);
+extern FILE    *fdup64(FILE *);
+extern FILE    *fileluopen64(int, const char *);
+extern FILE    *fileopen64(const char *, const char *);
+#ifdef FOUND_OFF_T
+extern off64_t filepos64(FILE *);
+#endif
+extern FILE    *filereopen64(const char *, const char *, FILE *);
+#ifdef FOUND_OFF_T
+extern int     fileseek64(FILE *, off64_t);
+extern off64_t filesize64(FILE *);
+#endif
+#ifdef S_IFMT
+extern int     filestat64(FILE *, struct stat *);
+#endif
+extern int     _openfd64(const char *, int);
+#endif
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#if defined(_JOS) || defined(JOS)
+#      ifndef  _JOS_IO_H
+#      include <jos_io.h>
+#      endif
+#endif
+
+#endif /* _SCHILY_H */
diff --git a/include/sigblk.h b/include/sigblk.h
new file mode 100644 (file)
index 0000000..afb125a
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)sigblk.h        1.10 03/07/10 Copyright 1985, 1995-2003 J. Schilling */
+/*
+ *     software signal block definition
+ *
+ *     Copyright (c) 1985, 1995-2003 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef        _SIGBLK_H
+#define        _SIGBLK_H
+
+#ifndef _MCONFIG_H
+#include <mconfig.h>
+#endif
+#ifndef _STANDARD_H
+#include <standard.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct sigblk {
+       long            **sb_savfp;     /* Real saved framepointer      */
+       struct sigblk   *sb_signext;    /* Next sw signal blk for this func */
+       short           sb_siglen;      /* Strlen for sb_signame        */
+       const char      *sb_signame;    /* Name of software signal      */
+
+                                       /* sb_sigfun: function to call  */
+       int             (*sb_sigfun)(const char *, long, long);
+
+       long            sb_sigarg;      /* Second arg for sb_sigfun     */
+} SIGBLK;
+
+/*
+ * The handler function is called with three arguments:
+ *
+ *     1)      The name of the software signal
+ *     2)      The argument from the handlecond() call
+ *     3)      The argument from the raisecond() call
+ */
+typedef        int     (*handlefunc_t)(const char *, long, long);
+
+extern void    handlecond(const char *, SIGBLK *,
+                                                         int(*)(const char *, long, long),
+                                                                 long);
+extern void    raisecond(const char *, long);
+extern void    starthandlecond(SIGBLK *);
+extern void    unhandlecond(SIGBLK *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SIGBLK_H */
diff --git a/include/sigdefs.h b/include/sigdefs.h
new file mode 100644 (file)
index 0000000..8e8ba7e
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)sigdefs.h       1.5 02/01/19 Copyright 1997 J. Schilling */
+/*
+ *     Signal abstraction for BSD/SVR4 signals
+ *
+ *     Copyright (c) 1997 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef        _SIGDEFS_H
+#define        _SIGDEFS_H
+
+#ifndef _MCONFIG_H
+#include <mconfig.h>
+#endif
+
+#ifdef HAVE_SIGSET
+/*
+ * Try to by default use the function that sets up signal handlers in a way
+ * that does not reset the handler after it has been called.
+ */
+#define        signal          sigset
+#endif
+
+#ifdef HAVE_SIGPROCMASK
+#define        block_sigs(a)   { \
+                               sigset_t        __new;  \
+                                                       \
+                               sigfillset(&__new);     \
+                               sigprocmask(SIG_BLOCK, &__new, &a);\
+                       }
+#define        unblock_sig(s)  { \
+                               sigset_t        __new;  \
+                                                       \
+                               sigemptyset(&__new);    \
+                               sigaddset(&__new, (s)); \
+                               sigprocmask(SIG_UNBLOCK, &__new, NULL);\
+                       }
+#define        restore_sigs(a) sigprocmask(SIG_SETMASK, &a, 0);
+
+#else  /* !HAVE_SIGPROCMASK */
+
+#define        sigset_t        int
+#define        block_sigs(a)   a = sigblock(0xFFFFFFFF)
+#define        restore_sigs(a) sigsetmask(a);
+#define        unblock_sig(s)  { \
+                               int     __old, __new;   \
+                                                       \
+                               block_sigs(__old);      \
+                               __new = sigmask(s);     \
+                               __new = __old & ~__new; \
+                               sigsetmask(__new);      \
+                       }
+
+#endif /* HAVE_SIGPROCMASK */
+
+#endif /* _SIGDEFS_H */
diff --git a/include/standard.h b/include/standard.h
new file mode 100644 (file)
index 0000000..d884973
--- /dev/null
@@ -0,0 +1,165 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)standard.h      1.31 03/08/23 Copyright 1985 J. Schilling */
+/*
+ *     standard definitions
+ *
+ *     This file should be included past:
+ *
+ *     mconfig.h / config.h
+ *     stdio.h
+ *     stdlib.h        (better use stdxlib.h)
+ *     unistd.h        (better use unixstd.h) needed LARGEFILE support
+ *
+ *     If you need stdio.h, you must include it before standard.h
+ *
+ *     Copyright (c) 1985 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _STANDARD_H
+#define        _STANDARD_H
+
+#ifndef _MCONFIG_H
+#include <mconfig.h>
+#endif
+#ifndef _PROTOTYP_H
+#include <prototyp.h>
+#endif
+
+#ifdef M68000
+#      ifndef  tos
+#              define  JOS     1
+#      endif
+#endif
+
+/*
+ *     fundamental constants
+ */
+#ifndef        NULL
+#      define  NULL            0
+#endif
+#ifndef        TRUE
+#      define  TRUE            1
+#      define  FALSE           0
+#endif
+
+/*
+ *     Program exit codes
+ */
+#define        EX_BAD                  (-1)
+
+/*
+ *     standard storage class definitions
+ */
+#define        GLOBAL  extern
+#define        IMPORT  extern
+#define        EXPORT
+#define        INTERN  static
+#define        LOCAL   static
+#define        FAST    register
+
+#ifndef        PROTOTYPES
+#      ifndef  const
+#              define  const
+#      endif
+#      ifndef  signed
+#              define  signed
+#      endif
+#      ifndef  volatile
+#              define  volatile
+#      endif
+#endif /* PROTOTYPES */
+
+/*
+ *     standard type definitions
+ *
+ *     The hidden Schily BOOL definition is used in case we need to deal
+ *     with other BOOL defines on systems we like to port to.
+ */
+typedef int __SBOOL;
+typedef int BOOL;
+#ifdef JOS
+#      ifndef  __GNUC__
+#      define  NO_VOID
+#      endif
+#endif
+#ifdef NO_VOID
+       typedef int     VOID;
+#      ifndef  lint
+               typedef int void;
+#      endif
+#else
+       typedef void    VOID;
+#endif
+
+#if    defined(_INCL_SYS_TYPES_H) || defined(off_t)
+#      ifndef  FOUND_OFF_T
+#      define  FOUND_OFF_T
+#      endif
+#endif
+#if    defined(_INCL_SYS_TYPES_H) || defined(size_t)
+#      ifndef  FOUND_SIZE_T
+#      define  FOUND_SIZE_T
+#      endif
+#endif
+
+#ifdef __never_def__
+/*
+ * It turns out that we cannot use the folloginw definition because there are
+ * some platforms that do not behave application friendly. These are mainly
+ * BSD-4.4 based systems (which #undef a definition when size_t is available.
+ * We actually removed this code because of a problem with QNX Neutrino.
+ * For this reason, it is important not to include <sys/types.h> directly but
+ * via the Schily SING include files so we know whether it has been included
+ * before we come here.
+ */
+#if    defined(_SIZE_T)        || defined(_T_SIZE_)    || defined(_T_SIZE) || \
+       defined(__SIZE_T)       || defined(_SIZE_T_)    || \
+       defined(_GCC_SIZE_T)    || defined(_SIZET_)     || \
+       defined(__sys_stdtypes_h) || defined(___int_size_t_h) || defined(size_t)
+
+#ifndef        FOUND_SIZE_T
+#      define  FOUND_SIZE_T    /* We already included a size_t definition */
+#endif
+#endif
+#endif /* __never_def__ */
+
+#if defined(_JOS) || defined(JOS)
+#      ifndef  _SCHILY_H
+#      include <schily.h>
+#      endif
+
+#      ifndef  _JOS_DEFS_H
+#      include <jos_defs.h>
+#      endif
+
+#      ifndef  _JOS_IO_H
+#      include <jos_io.h>
+#      endif
+#endif
+
+#endif /* _STANDARD_H */
diff --git a/include/statdefs.h b/include/statdefs.h
new file mode 100644 (file)
index 0000000..cfaa96d
--- /dev/null
@@ -0,0 +1,350 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)statdefs.h      1.9 03/06/15 Copyright 1998 J. Schilling */
+/*
+ *     Definitions for stat() file mode
+ *
+ *     Copyright (c) 1998 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef        _STATDEFS_H
+#define        _STATDEFS_H
+
+#ifndef _MCONFIG_H
+#include <mconfig.h>
+#endif
+
+#ifndef        _INCL_SYS_TYPES_H
+#include <sys/types.h>         /* Needed for sys/stat.h                */
+#define        _INCL_SYS_TYPES_H
+#endif
+#ifndef        _INCL_SYS_STAT_H
+#include <sys/stat.h>          /* For S_IS* and S_IF*                  */
+#define        _INCL_SYS_STAT_H
+#endif
+
+/*
+ * Apollo Domain/OS has a broken sys/stat.h that defines
+ * S_IFIFO == S_IFSOCK and creates trouble if the constants
+ * are used as case labels.
+ */
+#if S_IFIFO == S_IFSOCK
+#      undef   S_IFSOCK
+#endif
+
+#ifdef STAT_MACROS_BROKEN
+#undef S_ISFIFO                        /* Named pipe           */
+#undef S_ISCHR                         /* Character special    */
+#undef S_ISMPC                         /* UNUSED multiplexed c */
+#undef S_ISDIR                         /* Directory            */
+#undef S_ISNAM                         /* Named file (XENIX)   */
+#undef S_ISBLK                         /* Block special        */
+#undef S_ISMPB                         /* UNUSED multiplexed b */
+#undef S_ISREG                         /* Regular file         */
+#undef S_ISCNT                         /* Contiguous file      */
+#undef S_ISLNK                         /* Symbolic link        */
+#undef S_ISSHAD                        /* Solaris shadow inode */
+#undef S_ISSOCK                        /* UNIX domain socket   */
+#undef S_ISDOOR                        /* Solaris DOOR         */
+#undef S_ISWHT                         /* BSD whiteout         */
+#undef S_ISEVC                         /* UNOS eventcount      */
+#endif
+
+#ifndef        S_ISFIFO                        /* 1 Named pipe         */
+#      ifdef   S_IFIFO
+#              define  S_ISFIFO(m)     (((m) & S_IFMT) == S_IFIFO)
+#      else
+#              define  S_ISFIFO(m)     (0)
+#      endif
+#endif
+#ifndef        S_ISCHR                         /* 2 Character special  */
+#      ifdef   S_IFCHR
+#              define  S_ISCHR(m)      (((m) & S_IFMT) == S_IFCHR)
+#      else
+#              define  S_ISCHR(m)      (0)
+#      endif
+#endif
+#ifndef        S_ISMPC                         /* 3 UNUSED multiplexed char    */
+#      ifdef   S_IFMPC
+#              define  S_ISMPC(m)      (((m) & S_IFMT) == S_IFMPC)
+#      else
+#              define  S_ISMPC(m)      (0)
+#      endif
+#endif
+#ifndef        S_ISDIR                         /* 4 Directory                  */
+#      ifdef   S_IFDIR
+#              define  S_ISDIR(m)      (((m) & S_IFMT) == S_IFDIR)
+#      else
+#              define  S_ISDIR(m)      (0)
+#      endif
+#endif
+#ifndef        S_ISNAM                         /* 5 Named file (XENIX)         */
+#      ifdef   S_IFNAM
+#              define  S_ISNAM(m)      (((m) & S_IFMT) == S_IFNAM)
+#      else
+#              define  S_ISNAM(m)      (0)
+#      endif
+#endif
+#ifndef        S_ISBLK                         /* 6 Block special              */
+#      ifdef   S_IFBLK
+#              define  S_ISBLK(m)      (((m) & S_IFMT) == S_IFBLK)
+#      else
+#              define  S_ISBLK(m)      (0)
+#      endif
+#endif
+#ifndef        S_ISMPB                         /* 7 UNUSED multiplexed block   */
+#      ifdef   S_IFMPB
+#              define  S_ISMPB(m)      (((m) & S_IFMT) == S_IFMPB)
+#      else
+#              define  S_ISMPB(m)      (0)
+#      endif
+#endif
+#ifndef        S_ISREG                         /* 8 Regular file               */
+#      ifdef   S_IFREG
+#              define  S_ISREG(m)      (((m) & S_IFMT) == S_IFREG)
+#      else
+#              define  S_ISREG(m)      (0)
+#      endif
+#endif
+#ifndef        S_ISCNT                         /* 9 Contiguous file            */
+#      ifdef   S_IFCNT
+#              define  S_ISCNT(m)      (((m) & S_IFMT) == S_IFCNT)
+#      else
+#              define  S_ISCNT(m)      (0)
+#      endif
+#endif
+#ifndef        S_ISLNK                         /* 10 Symbolic link             */
+#      ifdef   S_IFLNK
+#              define  S_ISLNK(m)      (((m) & S_IFMT) == S_IFLNK)
+#      else
+#              define  S_ISLNK(m)      (0)
+#      endif
+#endif
+#ifndef        S_ISSHAD                        /* 11 Solaris shadow inode      */
+#      ifdef   S_IFSHAD
+#              define  S_ISSHAD(m)     (((m) & S_IFMT) == S_IFSHAD)
+#      else
+#              define  S_ISSHAD(m)     (0)
+#      endif
+#endif
+#ifndef        S_ISSOCK                        /* 12 UNIX domain socket        */
+#      ifdef   S_IFSOCK
+#              define  S_ISSOCK(m)     (((m) & S_IFMT) == S_IFSOCK)
+#      else
+#              define  S_ISSOCK(m)     (0)
+#      endif
+#endif
+#ifndef        S_ISDOOR                        /* 13 Solaris DOOR              */
+#      ifdef   S_IFDOOR
+#              define  S_ISDOOR(m)     (((m) & S_IFMT) == S_IFDOOR)
+#      else
+#              define  S_ISDOOR(m)     (0)
+#      endif
+#endif
+#ifndef        S_ISWHT                         /* 14 BSD whiteout              */
+#      ifdef   S_IFWHT
+#              define  S_ISWHT(m)      (((m) & S_IFMT) == S_ISWHT)
+#      else
+#              define  S_ISWHT(m)      (0)
+#      endif
+#endif
+#ifndef        S_IFEVC                         /* 15 UNOS eventcount           */
+#      ifdef   S_IFEVC
+#              define  S_ISEVC(m)      (((m) & S_IFMT) == S_IFEVC)
+#      else
+#              define  S_ISEVC(m)      (0)
+#      endif
+#endif
+
+#ifndef        S_TYPEISMQ
+/*
+ * XXX ??? where is a definition of a message queue ???
+ */
+#              define  S_TYPEISMQ(_stbuf)      (0)
+#endif
+#ifndef        S_TYPEISSEM
+#      ifdef   S_INSEM
+#              define  S_TYPEISSEM(_stbuf)     (S_ISNAM((_stbuf)->st_mode) && (_stbuf)->st_rdev == S_INSEM)
+#      else
+#              define  S_TYPEISSEM(_stbuf)     (0)
+#      endif
+#endif
+#ifndef        S_TYPEISSHM
+#      ifdef   S_INSHD
+#              define  S_TYPEISSHM(_stbuf)     (S_ISNAM((_stbuf)->st_mode) && (_stbuf)->st_rdev == S_INSHD)
+#      else
+#              define  S_TYPEISSHM(_stbuf)     (0)
+#      endif
+#endif
+
+/*
+ * Mode permission bits.
+ * UNIX V.7 has only   S_ISUID/S_ISGID/S_ISVTX and S_IREAD/S_IWRITE/S_IEXEC
+ */
+#ifndef        S_ISUID                 /* Set-user-ID on execution */
+#define        S_ISUID 0               /* If it is not defined, it is not supported */
+#endif
+#ifndef        S_ISGID                 /* Set-group-ID on execution */
+#define        S_ISGID 0               /* If it is not defined, it is not supported */
+#endif
+#ifndef        S_ISVTX                 /* On directories, restricted deletion flag */
+#define        S_ISVTX 0               /* If it is not defined, it is not supported */
+#endif
+
+#ifndef        S_IRUSR                 /* Read permission, owner */
+#ifdef S_IREAD
+#define        S_IRUSR S_IREAD         /* Needed on old UNIX systems */
+#else
+#define        S_IRUSR 0400
+#endif
+#endif
+#ifndef        S_IWUSR                 /* Write permission, owner */
+#ifdef S_IWRITE
+#define        S_IWUSR S_IWRITE        /* Needed on old UNIX systems */
+#else
+#define        S_IWUSR 0200
+#endif
+#endif
+#ifndef        S_IXUSR                 /* Execute/search permission, owner */
+#ifdef S_IEXEC
+#define        S_IXUSR S_IEXEC         /* Needed on old UNIX systems */
+#else
+#define        S_IXUSR 0100
+#endif
+#endif
+#ifndef        S_IRGRP                 /* Read permission, group */
+#ifdef S_IREAD
+#define        S_IRGRP (S_IREAD >> 3)  /* Needed on old UNIX systems */
+#else
+#define        S_IRGRP 040
+#endif
+#endif
+#ifndef        S_IWGRP                 /* Write permission, group */
+#ifdef S_IWRITE
+#define        S_IWGRP (S_IWRITE >> 3) /* Needed on old UNIX systems */
+#else
+#define        S_IWGRP 020
+#endif
+#endif
+#ifndef        S_IXGRP                 /* Execute/search permission, group */
+#ifdef S_IEXEC
+#define        S_IXGRP (S_IEXEC >> 3)  /* Needed on old UNIX systems */
+#else
+#define        S_IXGRP 010
+#endif
+#endif
+#ifndef        S_IROTH                 /* Read permission, others */
+#ifdef S_IREAD
+#define        S_IROTH (S_IREAD >> 6)  /* Needed on old UNIX systems */
+#else
+#define        S_IROTH 004
+#endif
+#endif
+#ifndef        S_IWOTH                 /* Write permission, others */
+#ifdef S_IWRITE
+#define        S_IWOTH (S_IWRITE >> 6) /* Needed on old UNIX systems */
+#else
+#define        S_IWOTH 002
+#endif
+#endif
+#ifndef        S_IXOTH                 /* Execute/search permission, others */
+#ifdef S_IEXEC
+#define        S_IXOTH (S_IEXEC >> 6)  /* Needed on old UNIX systems */
+#else
+#define        S_IXOTH 001
+#endif
+#endif
+
+#ifndef        S_IRWXU                 /* Read, write, execute/search by owner */
+#define        S_IRWXU (S_IRUSR|S_IWUSR|S_IXUSR)
+#endif
+#ifndef        S_IRWXG                 /* Read, write, execute/search by group */
+#define        S_IRWXG (S_IRGRP|S_IWGRP|S_IXGRP)
+#endif
+#ifndef        S_IRWXO                 /* Read, write, execute/search by others */
+#define        S_IRWXO (S_IROTH|S_IWOTH|S_IXOTH)
+#endif
+
+/*
+ * SCO UnixWare has st_atim.st__tim.tv_nsec but the st_atim.tv_nsec tests also
+ * succeeds. If we use st_atim.tv_nsec on UnixWare, we get a warning about
+ * illegal structure usage. For this reason, our code needs to have
+ * #ifdef HAVE_ST__TIM before #ifdef HAVE_ST_NSEC.
+ */
+#if    defined(HAVE_ST_ATIMENSEC)
+
+#define        stat_ansecs(s)          ((s)->st_atimensec)
+#define        stat_mnsecs(s)          ((s)->st_mtimensec)
+#define        stat_cnsecs(s)          ((s)->st_ctimensec)
+
+#define        _FOUND_STAT_NSECS_
+#endif
+
+#if    defined(HAVE_ST_SPARE1) && !defined(_FOUND_STAT_NSECS_)
+
+#define        stat_ansecs(s)          ((s)->st_spare1 * 1000)
+#define        stat_mnsecs(s)          ((s)->st_spare2 * 1000)
+#define        stat_cnsecs(s)          ((s)->st_spare3 * 1000)
+
+#define        _FOUND_STAT_USECS_
+#define        _FOUND_STAT_NSECS_
+#endif
+
+#if    defined(HAVE_ST__TIM) && !defined(_FOUND_STAT_NSECS_)
+
+#define        stat_ansecs(s)          ((s)->st_atim.st__tim.tv_nsec)
+#define        stat_mnsecs(s)          ((s)->st_mtim.st__tim.tv_nsec)
+#define        stat_cnsecs(s)          ((s)->st_ctim.st__tim.tv_nsec)
+
+#define        _FOUND_STAT_NSECS_
+#endif
+
+#if    defined(HAVE_ST_NSEC) && !defined(_FOUND_STAT_NSECS_)
+
+#define        stat_ansecs(s)          ((s)->st_atim.tv_nsec)
+#define        stat_mnsecs(s)          ((s)->st_mtim.tv_nsec)
+#define        stat_cnsecs(s)          ((s)->st_ctim.tv_nsec)
+
+#define        _FOUND_STAT_NSECS_
+#endif
+
+#if    defined(HAVE_ST_ATIMESPEC) && !defined(_FOUND_STAT_NSECS_)
+
+#define        stat_ansecs(s)          ((s)->st_atimespec.tv_nsec)
+#define        stat_mnsecs(s)          ((s)->st_mtimespec.tv_nsec)
+#define        stat_cnsecs(s)          ((s)->st_ctimespec.tv_nsec)
+
+#define        _FOUND_STAT_NSECS_
+#endif
+
+#if    !defined(_FOUND_STAT_NSECS_)
+#define        stat_ansecs(s)          (0)
+#define        stat_mnsecs(s)          (0)
+#define        stat_cnsecs(s)          (0)
+#endif
+
+#endif /* _STATDEFS_H */
diff --git a/include/stdxlib.h b/include/stdxlib.h
new file mode 100644 (file)
index 0000000..cf377af
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)stdxlib.h       1.6 01/07/15 Copyright 1996 J. Schilling */
+/*
+ *     Definitions for stdlib
+ *
+ *     Copyright (c) 1996 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _STDXLIB_H
+#define        _STDXLIB_H
+
+#ifndef        _MCONFIG_H
+#include <mconfig.h>
+#endif
+
+#ifdef HAVE_STDLIB_H
+#ifndef        _INCL_STDLIB_H
+#include <stdlib.h>
+#define        _INCL_STDLIB_H
+#endif
+#else
+
+extern char    *malloc();
+extern char    *realloc();
+
+extern double  atof();
+
+#endif /* HAVE_STDLIB_H */
+
+#ifndef        EXIT_FAILURE
+#define        EXIT_FAILURE    1
+#endif
+#ifndef        EXIT_SUCCESS
+#define        EXIT_SUCCESS    0
+#endif
+#ifndef        RAND_MAX
+#define        RAND_MAX        32767
+#endif
+
+#endif /* _STDXLIB_H */
diff --git a/include/stkframe.h b/include/stkframe.h
new file mode 100644 (file)
index 0000000..fc1ae22
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)stkframe.h      1.10 03/06/15 Copyright 1995 J. Schilling */
+/*
+ * Common definitions for routines that parse the stack frame.
+ *
+ * This file has to be fixed if you want to port routines which use getfp().
+ * Have a look at struct frame below and use it as a sample,
+ * the new struct frame must at least contain a member 'fr_savfp'.
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _STKFRAME_H
+#define        _STKFRAME_H
+
+#ifndef _MCONFIG_H
+#include <mconfig.h>
+#endif
+
+#if defined(sun) && (defined(SVR4) || defined(__SVR4) || defined(__SVR4__))
+       /*
+        * Solaris 2.x aka SunOS 5.x
+        */
+#      ifdef   i386
+               /*
+                * On Solaris 2.1 x86 sys/frame.h is not useful at all
+                * On Solaris 2.4 x86 sys/frame.h is buggy (fr_savfp is int!!)
+                */
+#              ifndef  _INCL_SYS_REG_H
+#              include <sys/reg.h>
+#              define  _INCL_SYS_REG_H
+#              endif
+#      endif
+#      ifndef  _INCL_SYS_FRAME_H
+#      include <sys/frame.h>
+#      define  _INCL_SYS_FRAME_H
+#      endif
+
+#else
+# if   defined(sun)
+       /*
+        * SunOS 4.x
+        */
+#      ifndef  _INCL_MACHINE_FRAME_H
+#      include <machine/frame.h>
+#      define  _INCL_MACHINE_FRAME_H
+#      endif
+# else
+       /*
+        * Anything that is not SunOS
+        */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * XXX: I hope this will be useful on other machines (no guarantee)
+ * XXX: It is taken from a sun Motorola system, but should also be useful
+ * XXX: on a i386.
+ * XXX: In general you have to write a sample program, set a breakpoint
+ * XXX: on a small function and inspect the stackframe with adb.
+ */
+
+struct frame {
+       struct frame    *fr_savfp;      /* saved frame pointer */
+       int             fr_savpc;       /* saved program counter */
+       int             fr_arg[1];      /* array of arguments */
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+# endif        /* ! defined (sun) */
+#endif /* ! defined (sun) && (defined(SVR4) || defined(__SVR4) || defined(__SVR4__)) */
+
+#endif /* _STKFRAME_H */
diff --git a/include/strdefs.h b/include/strdefs.h
new file mode 100644 (file)
index 0000000..36bdcaa
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)strdefs.h       1.8 03/03/09 Copyright 1996 J. Schilling */
+/*
+ *     Definitions for strings
+ *
+ *     Copyright (c) 1996 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _STRDEFS_H
+#define        _STRDEFS_H
+
+#ifndef        _MCONFIG_H
+#include <mconfig.h>
+#endif
+#ifndef _PROTOTYP_H
+#include <prototyp.h>
+#endif
+
+/*
+ * It may be that IBM's AIX has problems when doing
+ * #include <string.h>
+ * #include <strings.h>
+ * So I moved the #include <strings.h> to the top. As the file strings.h
+ * defines strcasecmp() we may need it...
+ *
+ * Note that the only real problem appears if we use rubbish FSF based code that
+ * #defines _NO_PROTO
+ */
+#ifdef HAVE_STRINGS_H
+#ifndef        _INCL_STRINGS_H
+#include <strings.h>
+#define        _INCL_STRINGS_H
+#endif
+#endif /* HAVE_STRINGS_H */
+
+
+#ifdef HAVE_STRING_H
+#ifndef        _INCL_STRING_H
+#include <string.h>
+#define        _INCL_STRING_H
+#endif
+#else  /* HAVE_STRING_H */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef NULL
+#define        NULL    0
+#endif
+
+extern void *memcpy(void *, const void *, int);
+extern void *memmove(void *, const void *, int);
+extern char *strcpy(char *, const char *);
+extern char *strncpy(char *, const char *, int);
+
+extern char *strcat(char *, const char *);
+extern char *strncat(char *, const char *, int);
+
+extern int memcmp(const void *, const void *, int);
+extern int strcmp(const char *, const char *);
+extern int strcoll(const char *, const char *);
+extern int strncmp(const char *, const char *, int);
+extern int strxfrm(char *, const char *, int);
+
+extern void *memchr(const void *, int, int);
+extern char *strchr(const char *, int);
+
+extern int strcspn(const char *, const char *);
+/*#pragma int_to_unsigned strcspn*/
+
+extern char *strpbrk(const char *, const char *);
+extern char *strrchr(const char *, int);
+
+extern int strspn(const char *, const char *);
+/*#pragma int_to_unsigned strspn*/
+
+extern char *strstr(const char *, const char *);
+extern char *strtok(char *, const char *);
+extern void *memset(void *, int, int);
+extern char *strerror(int);
+
+extern int strlen(const char *);
+/*#pragma int_to_unsigned strlen*/
+
+extern void *memccpy(void *, const void *, int, int);
+
+extern int strcasecmp(const char *, const char *);
+extern int strncasecmp(const char *, const char *, int);
+
+/*#define      index   strchr*/
+/*#define      rindex  strrchr*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAVE_STRING_H */
+
+#endif /* _STRDEFS_H */
diff --git a/include/termcap.h b/include/termcap.h
new file mode 100644 (file)
index 0000000..b220b2a
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)termcap.h       1.6 03/06/15 Copyright 1995 J. Schilling */
+/*
+ *     Copyright (c) 1995 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef        _TERMCAP_H
+#define        _TERMCAP_H
+
+#ifndef _MCONFIG_H
+#include <mconfig.h>
+#endif
+#ifndef _PROTOTYP_H
+#include <prototyp.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Flags for tcsetflags()
+ */
+#define        TCF_NO_TC               0x0001  /* Don't follow tc= entries */
+#define        TCF_NO_SIZE             0x0002  /* Don't get actual ttysize (li#/co#)*/
+#define        TCF_NO_STRIP            0x0004  /* Don't strip down termcap buffer */
+
+extern char    PC;             /* Pad character */
+extern char    *BC;            /* Backspace if not "\b" from "bc" capability*/
+extern char    *UP;            /* Cursor up string from "up" capability */
+extern short   ospeed;         /* output speed coded as in ioctl */
+
+extern int     tgetent(char *bp, char *name);
+extern int     tcsetflags(int flags);
+extern char    *tcgetbuf(void);
+extern int     tgetnum(char *ent);
+extern BOOL    tgetflag(char *ent);
+extern char    *tgetstr(char *ent, char **array);
+extern char    *tdecode(char *ep, char **array);
+
+extern int     tputs(char *cp, int affcnt, int (*outc)(int c));
+extern char    *tgoto(char *cm, int destcol, int destline);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _TERMCAP_H */
diff --git a/include/test_BITFIELDS_HTOL.c b/include/test_BITFIELDS_HTOL.c
new file mode 100644 (file)
index 0000000..674c457
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* test_BITFIELD_HTOL.c derived from cdrtools aclocal.m4 by Joerg Schilling */
+/* Return 1 if bitfields are high-to-low, 0 if bitfields are low-to-high */
+int main()
+{
+       union {
+               unsigned char ch;
+               struct { unsigned char bf1:4, bf2:4; } bf;
+       } u;
+       u.ch = 0x12;
+       return (u.bf.bf1 == 1);
+}
diff --git a/include/test_VA_LIST_IS_ARRAY.c b/include/test_VA_LIST_IS_ARRAY.c
new file mode 100644 (file)
index 0000000..2cd80c7
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+#include <stdarg.h>
+
+int main() {
+
+va_list a, b;
+
+a = b;
+; return 0; }
+
diff --git a/include/timedefs.h b/include/timedefs.h
new file mode 100644 (file)
index 0000000..08a9145
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)timedefs.h      1.13 05/08/22 Copyright 1996 J. Schilling */
+/*
+ *     Generic header for users of time(), gettimeofday() ...
+ *
+ *     It includes definitions for time_t, struct timeval, ...
+ *
+ *     Copyright (c) 1996 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef        _TIMEDEFS_H
+#define        _TIMEDEFS_H
+
+#ifndef        _MCONFIG_H
+#include <mconfig.h>
+#endif
+
+#ifndef        _INCL_SYS_TYPES_H
+#include <sys/types.h>         /* Needed for time_t            */
+#define        _INCL_SYS_TYPES_H
+#endif
+
+#ifdef TIME_WITH_SYS_TIME
+#      ifndef  _INCL_SYS_TIME_H
+#      include <sys/time.h>
+#      define  _INCL_SYS_TIME_H
+#      endif
+#      ifndef  _INCL_TIME_H
+#      include <time.h>
+#      define  _INCL_TIME_H
+#      endif
+#else
+#ifdef HAVE_SYS_TIME_H
+#      ifndef  _INCL_SYS_TIME_H
+#      include <sys/time.h>
+#      define  _INCL_SYS_TIME_H
+#      endif
+#else
+#      ifndef  _INCL_TIME_H
+#      include <time.h>
+#      define  _INCL_TIME_H
+#      endif
+#endif
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if    defined(__CYGWIN32__) || defined(__EMX__) || defined(__linux__) || defined(__DJGPP__)
+/*
+ * Cygnus defines struct timeval in sys/time.h but not timerclear
+ * timerclear is defined in windows32/Sockets.h ???
+ *
+ * EMX for OS/2 defines struct timeval in sys/time.h but not timerclear
+ *
+ * Linux defines struct timeval in sys/time.h but if __USE_BSD is not
+ * defined, timerclear is missing.
+ */
+#ifndef        timerclear
+#define        timerclear(tvp)         (tvp)->tv_sec = (tvp)->tv_usec = 0
+#endif
+#endif
+
+#ifndef        timerclear
+
+#ifndef        VMS
+struct timeval {
+       long    tv_sec;
+       long    tv_usec;
+};
+#endif
+
+struct timezone {
+       int     tz_minuteswest;
+       int     tz_dsttime;
+};
+
+#define        timerclear(tvp)         (tvp)->tv_sec = (tvp)->tv_usec = 0
+
+#endif
+
+#undef timerfix
+#define        timerfix1(tvp)          while ((tvp)->tv_usec < 0) {            \
+                                       (tvp)->tv_sec--;                \
+                                       (tvp)->tv_usec += 1000000;      \
+                               }
+
+#define        timerfix2(tvp)          while ((tvp)->tv_usec > 1000000) {      \
+                                       (tvp)->tv_sec++;                \
+                                       (tvp)->tv_usec -= 1000000;      \
+                               }
+
+#define        timerfix(tvp)           do { timerfix1(tvp); timerfix2(tvp); } while (0)
+
+/*
+ * timersub() and timeradd() are defined on FreeBSD with a different
+ * interface (3 parameters).
+ */
+#undef timersub
+#define        timersub(tvp1, tvp2)    do {                                    \
+                                       (tvp1)->tv_sec -= (tvp2)->tv_sec; \
+                                       (tvp1)->tv_usec -= (tvp2)->tv_usec; \
+                                       timerfix1(tvp1); timerfix2(tvp1); \
+                               } while (0)
+
+#undef timeradd
+#define        timeradd(tvp1, tvp2)    do {                                    \
+                                       (tvp1)->tv_sec += (tvp2)->tv_sec; \
+                                       (tvp1)->tv_usec += (tvp2)->tv_usec; \
+                                       timerfix1(tvp1); timerfix2(tvp1); \
+                               } while (0)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _TIMEDEFS_H */
diff --git a/include/ttydefs.h b/include/ttydefs.h
new file mode 100644 (file)
index 0000000..8eed081
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)ttydefs.h       1.26 03/02/28 Copyright 1984-2003 J. Schilling */
+/*
+ *     Terminal driver tty mode handling
+ *
+ *     Copyright (c) 1984-2003 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef        _TTYDEFS_H
+#define        _TTYDEFS_H
+
+#ifndef        _MCONFIG_H
+#include <mconfig.h>
+#endif
+
+#ifndef        _INCL_SYS_TYPES_H
+#include <sys/types.h>
+#define        _INCL_SYS_TYPES_H
+#endif
+
+#ifdef JOS
+#      include <ttymodes.h>
+#      include <spfcode.h>
+#else
+#ifdef HAVE_TERMIOS_H
+#      include <termios.h>
+#      define  _INCL_TERMIOS_H
+#      ifdef TIOCGETA                          /* FreeBSD */
+#              define  TCGETS  TIOCGETA
+#              define  TCSETSW TIOCSETAW
+#      endif
+#      ifdef TCGETATTR
+#              define  TCGETS  TCGETATTR
+#              define  TCSETSW TCSETATTRD
+#      endif
+#else
+#      ifdef   HAVE_TERMIO_H
+#              include <termio.h>
+#              define  _INCL_TERMIO_H
+#              ifndef  TCGETS
+#              define  termios termio
+#              define  TCGETS  TCGETA
+#              define  TCSETSW TCSETAW
+#              endif
+#      else
+#              define  USE_V7_TTY
+#      endif
+#endif
+#endif
+
+#if !defined(HAVE_TCGETATTR) || !defined(HAVE_TCSETATTR)
+#      undef   TCSANOW
+#endif
+
+#ifndef        TCSANOW
+#      if      !defined(TCGETS) || !defined(TCSETSW)
+#              define  USE_V7_TTY
+#      endif
+#endif
+
+#if !defined(_INCL_TERMIOS_H) && !defined(_INCL_TERMIO_H)
+#ifdef HAVE_SYS_IOCTL_H
+#      ifndef  _INCL_SYS_IOCTl_H
+#      include <sys/ioctl.h>
+#      define  _INCL_SYS_IOCTL_H
+#      endif
+#endif
+#endif
+
+#ifdef HAVE_SYS_BSDTTY_H
+#include <sys/bsdtty.h>
+#endif
+
+#if    !defined(TIOCGWINSZ) && ! defined(TIOCGSIZE)
+#      ifndef  _INCL_SYS_IOCTl_H
+#      include <sys/ioctl.h>
+#      define  _INCL_SYS_IOCTL_H
+#      endif
+#endif
+
+#ifndef        OXTABS                                  /* OS/2 EMX */
+#define        OXTABS  0
+#endif
+#ifndef        XTABS
+#      ifndef  TAB3                            /* FreeBSD */
+#      define  TABDLY  OXTABS
+#      define  XTABS   OXTABS
+#      else
+#      define  XTABS   TAB3
+#      endif
+#endif
+#ifndef        ONLCR                                   /* OS/2 EMX */
+#define        ONLCR   0
+#endif
+#ifndef        OCRNL                                   /* FreeBSD */
+#      define  OCRNL   0
+#endif
+#ifndef        ONLRET                                  /* FreeBSD */
+#      define  ONLRET  0
+#endif
+#ifndef        _POSIX_VDISABLE
+#      define  _POSIX_VDISABLE 0
+#endif
+
+#endif /* _TTYDEFS_H */
diff --git a/include/unixstd.h b/include/unixstd.h
new file mode 100644 (file)
index 0000000..16c8816
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)unixstd.h       1.12 04/06/17 Copyright 1996 J. Schilling */
+/*
+ *     Definitions for unix system interface
+ *
+ *     Copyright (c) 1996 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _UNIXSTD_H
+#define        _UNIXSTD_H
+
+#ifndef        _MCONFIG_H
+#include <mconfig.h>
+#endif
+
+#ifdef HAVE_UNISTD_H
+
+#ifndef        _INCL_SYS_TYPES_H
+#include <sys/types.h>
+#define        _INCL_SYS_TYPES_H
+#endif
+#ifndef        _INCL_UNISTD_H
+#include <unistd.h>
+#define        _INCL_UNISTD_H
+#endif
+
+#ifndef        _SC_PAGESIZE
+#ifdef _SC_PAGE_SIZE   /* HP/UX & OSF */
+#define        _SC_PAGESIZE    _SC_PAGE_SIZE
+#endif
+#endif
+
+#else  /* HAVE_UNISTD_H */
+
+/*
+ * unistd.h grants things like off_t to be typedef'd.
+ */
+#ifndef        _INCL_SYS_TYPES_H
+#include <sys/types.h>
+#define        _INCL_SYS_TYPES_H
+#endif
+
+#endif /* HAVE_UNISTD_H */
+
+#ifndef        STDIN_FILENO
+#      ifdef   JOS
+#              ifndef  _JOS_IO_H
+#              include <jos_io.h>
+#              endif
+#      else
+#              define  STDIN_FILENO    0
+#              define  STDOUT_FILENO   1
+#              define  STDERR_FILENO   2
+#      endif
+#endif
+
+#ifndef        R_OK
+/* Symbolic constants for the "access" routine: */
+#define        R_OK    4       /* Test for Read permission */
+#define        W_OK    2       /* Test for Write permission */
+#define        X_OK    1       /* Test for eXecute permission */
+#define        F_OK    0       /* Test for existence of File */
+#endif
+#ifndef        E_OK
+#ifdef HAVE_ACCESS_E_OK
+#ifdef EFF_ONLY_OK
+#define        E_OK    EFF_ONLY_OK /* Irix */
+#else
+#ifdef EUID_OK
+#define        E_OK    EUID_OK /* UNICOS (0400) */
+#else
+#define        E_OK    010     /* Test effective uids */
+#endif /* EUID_OK */
+#endif /* EFF_ONLY_OK */
+#else
+#define        E_OK    0
+#endif /* HAVE_ACCESS_E_OK */
+#endif /* !E_OK */
+
+/* Symbolic constants for the "lseek" routine: */
+#ifndef        SEEK_SET
+#define        SEEK_SET        0       /* Set file pointer to "offset" */
+#endif
+#ifndef        SEEK_CUR
+#define        SEEK_CUR        1       /* Set file pointer to current plus "offset" */
+#endif
+#ifndef        SEEK_END
+#define        SEEK_END        2       /* Set file pointer to EOF plus "offset" */
+#endif
+
+#if    !defined(HAVE_UNISTD_H) || !defined(_POSIX_VERSION)
+/*
+ * Maybe we need a lot more definitions here...
+ * It is not clear whether we should have prototyped definitions.
+ */
+extern int     access(const char *, int);
+extern int     close(int);
+extern int     dup(int);
+extern int     dup2(int, int);
+extern void    _exit(int);
+extern int     link(const char *, const char *);
+extern int     read(int, void *, size_t);
+extern int     unlink(const char *);
+extern int     write(int, void *, size_t);
+#endif
+
+#endif /* _UNIXSTD_H */
diff --git a/include/unls.h b/include/unls.h
new file mode 100644 (file)
index 0000000..8a5c633
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)unls.h  1.6 05/04/21 Copyright 2000-2005 J. Schilling */
+/*
+ *     Definitions fur users of libunls
+ *
+ *     Copyright (c) 2000-2005 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _UNLS_H
+#define        _UNLS_H
+
+#ifndef _MCONFIG_H
+#include <mconfig.h>
+#endif
+#ifndef _PROTOTYP_H
+#include <prototyp.h>
+#endif
+
+#ifdef USE_ICONV
+#include <iconv.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct unls_unicode {
+       unsigned char   unls_low;               /* Low Byte */
+       unsigned char   unls_high;              /* High Byte */
+};
+
+struct unls_table {
+       char            *unls_name;             /* UNLS charset name    */
+       unsigned char   **unls_uni2cs;          /* Unicode -> Charset   */
+       struct unls_unicode *unls_cs2uni;       /* Charset -> Unicode   */
+       struct unls_table *unls_next;           /* Next table           */
+#ifdef USE_ICONV
+    iconv_t iconv_d;
+#endif
+};
+
+extern int             init_unls(void);
+extern int             register_unls(struct unls_table *);
+extern int             unregister_unls(struct unls_table *);
+extern struct unls_table *find_unls(char *);
+extern void            list_unls(void);
+extern struct unls_table *load_unls(char *);
+extern void            unload_unls(struct unls_table *);
+extern struct unls_table *load_unls_default(void);
+extern int             init_unls_file(char * name);
+
+#ifdef USE_ICONV
+extern int             init_nls_iconv(char * name);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _UNLS_H */
diff --git a/include/usal b/include/usal
new file mode 120000 (symlink)
index 0000000..02d7e2f
--- /dev/null
@@ -0,0 +1 @@
+../libusal/usal
\ No newline at end of file
diff --git a/include/utimdefs.h b/include/utimdefs.h
new file mode 100644 (file)
index 0000000..d54af42
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)utimdefs.h      1.5 03/06/15 Copyright 2001 J. Schilling */
+/*
+ *     Defines for utimes() / utime()
+ *
+ *     Copyright (c) 2001 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef        _UTIMDEFS_H
+#define        _UTIMDEFS_H
+
+#ifndef _MCONFIG_H
+#include <mconfig.h>
+#endif
+
+#ifndef        _INCL_SYS_TYPES_H
+#include <sys/types.h>
+#define        _INCL_SYS_TYPES_H
+#endif
+
+#ifdef HAVE_UTIMES
+#ifndef _TIMEDEFS_H
+#include <timedefs.h>
+#endif
+#endif
+
+#ifdef HAVE_UTIME_H
+#ifndef        _INCL_UTIME_H
+#include <utime.h>
+#define        _INCL_UTIME_H
+#endif
+#else
+#ifdef HAVE_SYS_UTIME_H
+#ifndef        _INCL_SYS_UTIME_H
+#include <sys/utime.h>
+#define        _INCL_SYS_UTIME_H
+#endif
+#else
+struct utimbuf {
+       time_t  actime;
+       time_t  modtime;
+};
+#endif
+#endif
+
+#ifdef __comment__
+/*
+ * file.c contains this
+ * I am not sure if it is really needed.
+ * It may be a good idea to add a test for HAVE_STRUCT_UTIMBUF
+ * as in gnutar.
+ */
+#if (__COHERENT__ >= 0x420)
+# include <sys/utime.h>
+#else
+#  include <utime.h>
+#endif
+
+#endif /* __comment__ */
+
+
+#endif /* _UTIMDEFS_H */
diff --git a/include/utypes.h b/include/utypes.h
new file mode 100644 (file)
index 0000000..9a4049f
--- /dev/null
@@ -0,0 +1,440 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)utypes.h        1.15 05/11/06 Copyright 1997 J. Schilling */
+/*
+ *     Definitions for some user defined types
+ *
+ *     Copyright (c) 1997 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef        _UTYPES_H
+#define        _UTYPES_H
+
+#ifndef        _MCONFIG_H
+#include <mconfig.h>
+#endif
+
+/*
+ * Include limits.h for CHAR_BIT
+ */
+#ifdef HAVE_LIMITS_H
+#ifndef        _INCL_LIMITS_H
+#include <limits.h>
+#define        _INCL_LIMITS_H
+#endif
+#endif
+
+/*
+ * Include sys/param.h for NBBY
+ */
+#ifdef HAVE_SYS_PARAM_H
+#ifndef        _INCL_SYS_PARAM_H
+#include       <sys/param.h>
+#define        _INCL_SYS_PARAM_H
+#endif
+#endif
+
+#ifndef        CHAR_BIT
+#ifdef NBBY
+#define        CHAR_BIT        NBBY 
+#endif
+#endif
+
+#ifndef        CHAR_BIT
+#define        CHAR_BIT        8
+#endif
+
+/*
+ * These macros may not work on all platforms but as we depend
+ * on two's complement in many places, they do not reduce portability.
+ * The macros below work with 2s complement and ones complement machines.
+ * Verify with this table...
+ *
+ *     Bits    1's c.  2's complement.
+ *     100     -3      -4
+ *     101     -2      -3
+ *     110     -1      -2
+ *     111     -0      -1
+ *     000     +0       0
+ *     001     +1      +1
+ *     010     +2      +2
+ *     011     +3      +3
+ *
+ * Computing -TYPE_MINVAL(type) will not work on 2's complement machines
+ * if 'type' is int or more. Use -(UIntmax_t)TYPE_MINVAL(type), it works
+ * for both 1's complement and 2's complement machines.
+ */
+#define        TYPE_ISSIGNED(t)        (((t)-1) < ((t)0))
+#define        TYPE_ISUNSIGNED(t)      (!TYPE_ISSIGNED(t))
+#define        TYPE_MSBVAL(t)          ((t)(~((t)0) << (sizeof (t)*CHAR_BIT - 1)))
+#define        TYPE_MINVAL(t)          (TYPE_ISSIGNED(t)                       \
+                                   ? TYPE_MSBVAL(t)                    \
+                                   : ((t)0))
+#define        TYPE_MAXVAL(t)          ((t)(~((t)0) - TYPE_MINVAL(t)))
+
+/*
+ * Let us include system defined types too.
+ */
+#ifndef        _INCL_SYS_TYPES_H
+#include <sys/types.h>
+#define        _INCL_SYS_TYPES_H
+#endif
+
+/*
+ * Several unsigned cardinal types
+ */
+typedef        unsigned long   Ulong;
+typedef        unsigned int    Uint;
+typedef        unsigned short  Ushort;
+typedef        unsigned char   Uchar;
+
+/*
+ * This is a definition for a compiler dependant 64 bit type.
+ * It currently is silently a long if the compiler does not
+ * support it. Check if this is the right way.
+ */
+#ifndef        NO_LONGLONG
+#      if      defined(HAVE_LONGLONG)
+#              define  USE_LONGLONG
+#      endif
+#endif
+
+#ifdef USE_LONGLONG
+
+typedef        long long               Llong;
+typedef        unsigned long long      Ullong; /* We should avoid this */
+typedef        unsigned long long      ULlong;
+
+#define        SIZEOF_LLONG            SIZEOF_LONG_LONG
+#define        SIZEOF_ULLONG           SIZEOF_UNSIGNED_LONG_LONG
+
+#else
+
+typedef        long                    Llong;
+typedef        unsigned long           Ullong; /* We should avoid this */
+typedef        unsigned long           ULlong;
+
+#define        SIZEOF_LLONG            SIZEOF_LONG
+#define        SIZEOF_ULLONG           SIZEOF_UNSIGNED_LONG
+
+#endif
+#ifndef        LLONG_MIN
+#define        LLONG_MIN       TYPE_MINVAL(Llong)
+#endif
+#ifndef        LLONG_MAX
+#define        LLONG_MAX       TYPE_MAXVAL(Llong)
+#endif
+#ifndef        ULLONG_MAX
+#define        ULLONG_MAX      TYPE_MAXVAL(Ullong)
+#endif
+
+/*
+ * The IBM AIX C-compiler seems to be the only compiler on the world
+ * which does not allow to use unsigned char bit fields as a hint
+ * for packed bit fields. Define a pesical type to avoid warnings.
+ * The packed attribute is honored wit unsigned int in this case too.
+ */
+#if    defined(_AIX) && !defined(__GNUC__)
+
+typedef unsigned int   Ucbit;
+
+#else
+
+typedef unsigned char  Ucbit;
+
+#endif
+
+/*
+ * Start inttypes.h emulation.
+ *
+ * Thanks to Solaris 2.4 and even recent 1999 Linux versions, we
+ * cannot use the official UNIX-98 names here. Old Solaris versions
+ * define parts of the types in some exotic include files.
+ * Linux even defines incompatible types in <sys/types.h>.
+ */
+
+#ifdef HAVE_INTTYPES_H
+#      ifndef  _INCL_INTTYPES_H
+#      include <inttypes.h>
+#      define  _INCL_INTTYPES_H
+#      endif
+#      define  HAVE_INT64_T
+#      define  HAVE_UINT64_T
+
+#define        Int8_t                  int8_t
+#define        Int16_t                 int16_t
+#define        Int32_t                 int32_t
+#define        Int64_t                 int64_t
+#define        Intmax_t                intmax_t
+#define        UInt8_t                 uint8_t
+#define        UInt16_t                uint16_t
+#define        UInt32_t                uint32_t
+#define        UInt64_t                uint64_t
+#define        UIntmax_t               uintmax_t
+
+#define        Intptr_t                intptr_t
+#define        UIntptr_t               uintptr_t
+
+#else  /* !HAVE_INTTYPES_H */
+
+#if SIZEOF_CHAR != 1 || SIZEOF_UNSIGNED_CHAR != 1
+/*
+ * #error will not work for all compilers (e.g. sunos4)
+ * The following line will abort compilation on all compilers
+ * if the above is true. And that's what we want.
+ */
+error  Sizeof char is not equal 1
+#endif
+
+typedef signed char                    Int8_t;
+
+#if SIZEOF_SHORT_INT == 2
+       typedef short                   Int16_t;
+#else
+       error           No int16_t found
+#endif
+
+#if SIZEOF_INT == 4
+       typedef int                     Int32_t;
+#else
+       error           No int32_t found
+#endif
+
+#if SIZEOF_LONG_INT == 8
+       typedef         long            Int64_t;
+#      define  HAVE_INT64_T
+#else
+#if SIZEOF_LONG_LONG == 8
+       typedef         long long       Int64_t;
+#      define  HAVE_INT64_T
+#else
+/*     error           No int64_t found*/
+#endif
+#endif
+
+#if SIZEOF_CHAR_P == SIZEOF_INT
+       typedef         int             Intptr_t;
+#else
+#if SIZEOF_CHAR_P == SIZEOF_LONG_INT
+       typedef         long            Intptr_t;
+#else
+       error           No intptr_t found
+#endif
+#endif
+
+typedef        unsigned char           UInt8_t;
+
+#if SIZEOF_UNSIGNED_SHORT_INT == 2
+       typedef unsigned short          UInt16_t;
+#else
+       error           No uint16_t found
+#endif
+
+#if SIZEOF_UNSIGNED_INT == 4
+       typedef unsigned int            UInt32_t;
+#else
+       error           No int32_t found
+#endif
+
+#if SIZEOF_UNSIGNED_LONG_INT == 8
+       typedef unsigned long           UInt64_t;
+#      define  HAVE_UINT64_T
+#else
+#if SIZEOF_UNSIGNED_LONG_LONG == 8
+       typedef unsigned long long      UInt64_t;
+#      define  HAVE_UINT64_T
+#else
+/*     error           No uint64_t found*/
+#endif
+#endif
+
+#define        Intmax_t        Llong
+#define        UIntmax_t       Ullong
+
+#if SIZEOF_CHAR_P == SIZEOF_UNSIGNED_INT
+       typedef         unsigned int    UIntptr_t;
+#else
+#if SIZEOF_CHAR_P == SIZEOF_UNSIGNED_LONG_INT
+       typedef         unsigned long   UIntptr_t;
+#else
+       error           No uintptr_t found
+#endif
+#endif
+
+#endif /* HAVE_INTTYPES_H */
+
+#ifndef        CHAR_MIN
+#define        CHAR_MIN        TYPE_MINVAL(char)
+#endif
+#ifndef        CHAR_MAX
+#define        CHAR_MAX        TYPE_MAXVAL(char)
+#endif
+#ifndef        UCHAR_MAX
+#define        UCHAR_MAX       TYPE_MAXVAL(unsigned char)
+#endif
+
+#ifndef        SHRT_MIN
+#define        SHRT_MIN        TYPE_MINVAL(short)
+#endif
+#ifndef        SHRT_MAX
+#define        SHRT_MAX        TYPE_MAXVAL(short)
+#endif
+#ifndef        USHRT_MAX
+#define        USHRT_MAX       TYPE_MAXVAL(unsigned short)
+#endif
+
+#ifndef        INT_MIN
+#define        INT_MIN         TYPE_MINVAL(int)
+#endif
+#ifndef        INT_MAX
+#define        INT_MAX         TYPE_MAXVAL(int)
+#endif
+#ifndef        UINT_MAX
+#define        UINT_MAX        TYPE_MAXVAL(unsigned int)
+#endif
+
+#ifndef        LONG_MIN
+#define        LONG_MIN        TYPE_MINVAL(long)
+#endif
+#ifndef        LONG_MAX
+#define        LONG_MAX        TYPE_MAXVAL(long)
+#endif
+#ifndef        ULONG_MAX
+#define        ULONG_MAX       TYPE_MAXVAL(unsigned long)
+#endif
+
+#ifndef        INT8_MIN
+#define        INT8_MIN        TYPE_MINVAL(Int8_t)
+#endif
+#ifndef        INT8_MAX
+#define        INT8_MAX        TYPE_MAXVAL(Int8_t)
+#endif
+#ifndef        UINT8_MAX
+#define        UINT8_MAX       TYPE_MAXVAL(UInt8_t)
+#endif
+
+#ifndef        INT16_MIN
+#define        INT16_MIN       TYPE_MINVAL(Int16_t)
+#endif
+#ifndef        INT16_MAX
+#define        INT16_MAX       TYPE_MAXVAL(Int16_t)
+#endif
+#ifndef        UINT16_MAX
+#define        UINT16_MAX      TYPE_MAXVAL(UInt16_t)
+#endif
+
+#ifndef        INT32_MIN
+#define        INT32_MIN       TYPE_MINVAL(Int32_t)
+#endif
+#ifndef        INT32_MAX
+#define        INT32_MAX       TYPE_MAXVAL(Int32_t)
+#endif
+#ifndef        UINT32_MAX
+#define        UINT32_MAX      TYPE_MAXVAL(UInt32_t)
+#endif
+
+#ifdef HAVE_INT64_T
+#ifndef        INT64_MIN
+#define        INT64_MIN       TYPE_MINVAL(Int64_t)
+#endif
+#ifndef        INT64_MAX
+#define        INT64_MAX       TYPE_MAXVAL(Int64_t)
+#endif
+#endif
+#ifdef HAVE_UINT64_T
+#ifndef        UINT64_MAX
+#define        UINT64_MAX      TYPE_MAXVAL(UInt64_t)
+#endif
+#endif
+
+#ifndef        INTMAX_MIN
+#define        INTMAX_MIN      TYPE_MINVAL(Intmax_t)
+#endif
+#ifndef        INTMAX_MAX
+#define        INTMAX_MAX      TYPE_MAXVAL(Intmax_t)
+#endif
+#ifndef        UINTMAX_MAX
+#define        UINTMAX_MAX     TYPE_MAXVAL(UIntmax_t)
+#endif
+
+#define        SIZE_T_MIN      TYPE_MINVAL(size_t)
+#ifndef SIZE_T_MAX
+#define        SIZE_T_MAX      TYPE_MAXVAL(size_t)
+#endif
+
+#define        SSIZE_T_MIN     TYPE_MINVAL(ssize_t)
+#define        SSIZE_T_MAX     TYPE_MAXVAL(ssize_t)
+
+#define        OFF_T_MIN       TYPE_MINVAL(off_t)
+#define        OFF_T_MAX       TYPE_MAXVAL(off_t)
+
+#define        UID_T_MIN       TYPE_MINVAL(uid_t)
+#define        UID_T_MAX       TYPE_MAXVAL(uid_t)
+
+#define        GID_T_MIN       TYPE_MINVAL(gid_t)
+#define        GID_T_MAX       TYPE_MAXVAL(gid_t)
+
+#define        PID_T_MIN       TYPE_MINVAL(pid_t)
+#define        PID_T_MAX       TYPE_MAXVAL(pid_t)
+
+#define        MODE_T_MIN      TYPE_MINVAL(mode_t)
+#define        MODE_T_MAX      TYPE_MAXVAL(mode_t)
+
+#define        TIME_T_MIN      TYPE_MINVAL(time_t)
+#define        TIME_T_MAX      TYPE_MAXVAL(time_t)
+
+#define        CADDR_T_MIN     TYPE_MINVAL(caddr_t)
+#define        CADDR_T_MAX     TYPE_MAXVAL(caddr_t)
+
+#define        DADDR_T_MIN     TYPE_MINVAL(daddr_t)
+#define        DADDR_T_MAX     TYPE_MAXVAL(daddr_t)
+
+#define        DEV_T_MIN       TYPE_MINVAL(dev_t)
+#define        DEV_T_MAX       TYPE_MAXVAL(dev_t)
+
+#define        MAJOR_T_MIN     TYPE_MINVAL(major_t)
+#define        MAJOR_T_MAX     TYPE_MAXVAL(major_t)
+
+#define        MINOR_T_MIN     TYPE_MINVAL(minor_t)
+#define        MINOR_T_MAX     TYPE_MAXVAL(minor_t)
+
+#define        INO_T_MIN       TYPE_MINVAL(ino_t)
+#define        INO_T_MAX       TYPE_MAXVAL(ino_t)
+
+#define        NLINK_T_MIN     TYPE_MINVAL(nlink_t)
+#define        NLINK_T_MAX     TYPE_MAXVAL(nlink_t)
+
+#define        BLKCNT_T_MIN    TYPE_MINVAL(blkcnt_t)
+#define        BLKCNT_T_MAX    TYPE_MAXVAL(blkcnt_t)
+
+#define        CLOCK_T_MIN     TYPE_MINVAL(clock_t)
+#define        CLOCK_T_MAX     TYPE_MAXVAL(clock_t)
+
+#define        SOCKLEN_T_MIN   TYPE_MINVAL(socklen_t)
+#define        SOCKLEN_T_MAX   TYPE_MAXVAL(socklen_t)
+
+#endif /* _UTYPES_H */
diff --git a/include/vadefs.h b/include/vadefs.h
new file mode 100644 (file)
index 0000000..a686074
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)vadefs.h        1.5 01/07/15 Copyright 1998 J. Schilling */
+/*
+ *     Generic header for users of var args ...
+ *
+ *     Includes a default definition for va_copy()
+ *     and some magic know how about the SVr4 Power PC var args ABI
+ *     to create a __va_arg_list() macro.
+ *
+ *     Copyright (c) 1998 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef        _VADEFS_H
+#define        _VADEFS_H
+
+#ifndef        _MCONFIG_H
+#include <mconfig.h>
+#endif
+
+#ifdef PROTOTYPES
+/*
+ * For ANSI C-compilers prefer stdarg.h
+ */
+#      ifdef   HAVE_STDARG_H
+#              ifndef  _INCL_STDARG_H
+#              include <stdarg.h>
+#              define  _INCL_STDARG_H
+#              endif
+#      else
+#              ifndef  _INCL_VARARGS_H
+#              include <varargs.h>
+#              define  _INCL_VARARGS_H
+#              endif
+#      endif
+#else
+/*
+ * For K&R C-compilers prefer varargs.h
+ */
+#      ifdef   HAVE_VARARGS_H
+#              ifndef  _INCL_VARARGS_H
+#              include <varargs.h>
+#              define  _INCL_VARARGS_H
+#              endif
+#      else
+#              ifndef  _INCL_STDARG_H
+#              include <stdarg.h>
+#              define  _INCL_STDARG_H
+#              endif
+#      endif
+#endif
+
+#if (defined(__linux__) || defined(__linux) || defined(sun)) && \
+               (defined(__ppc) || defined(__PPC) || defined(powerpc) || defined(__powerpc__))
+
+#      ifndef  VA_LIST_IS_ARRAY
+#      define  VA_LIST_IS_ARRAY
+#      endif
+#endif
+
+
+/*
+ * __va_copy() is used by GCC 2.8 or newer until va_copy() becomes
+ * a final ISO standard.
+ */
+#if !defined(va_copy) && !defined(HAVE_VA_COPY)
+#      if      defined(__va_copy)
+#              define  va_copy(to, from)       __va_copy(to, from)
+#      endif
+#endif
+
+/*
+ * va_copy() is a Solaris extension to provide a portable way to perform a
+ * variable argument list "bookmarking" function.
+ * If it is not available via stdarg.h, use a simple assignement for backward
+ * compatibility.
+ */
+#if !defined(va_copy) && !defined(HAVE_VA_COPY)
+#ifdef VA_LIST_IS_ARRAY
+#      define  va_copy(to, from)       ((to)[0] = (from)[0])
+#else
+#      define  va_copy(to, from)       ((to) = (from))
+#endif
+#endif
+
+/*
+ * I don't know any portable way to get an arbitrary
+ * C object from a var arg list so I use a
+ * system-specific routine __va_arg_list() that knows
+ * if 'va_list' is an array. You will not be able to
+ * assign the value of __va_arg_list() but it works
+ * to be used as an argument of a function.
+ * It is a requirement for recursive printf to be able
+ * to use this function argument. If your system
+ * defines va_list to be an array you need to know this
+ * via autoconf or another mechanism.
+ * It would be nice to have something like
+ * __va_arg_list() in stdarg.h
+ */
+
+#ifdef VA_LIST_IS_ARRAY
+#      define  __va_arg_list(list)     va_arg(list, void *)
+#else
+#      define  __va_arg_list(list)     va_arg(list, va_list)
+#endif
+
+#endif /* _VADEFS_H */
diff --git a/include/waitdefs.h b/include/waitdefs.h
new file mode 100644 (file)
index 0000000..d363b4f
--- /dev/null
@@ -0,0 +1,152 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)waitdefs.h      1.10 03/02/25 Copyright 1995-2003 J. Schilling */
+/*
+ *     Definitions to deal with various kinds of wait flavour
+ *
+ *     Copyright (c) 1995-2003 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef        _WAITDEFS_H
+#define        _WAITDEFS_H
+
+#ifndef _MCONFIG_H
+#include <mconfig.h>
+#endif
+
+/*
+ * Needed for SysVr4
+ */
+#ifndef        _INCL_SYS_TYPES_H
+#include <sys/types.h>
+#define        _INCL_SYS_TYPES_H
+#endif
+
+#if    defined(HAVE_WAIT_H)
+#      ifndef  _INCL_WAIT_H
+#      include <wait.h>
+#      define  _INCL_WAIT_H
+#      endif
+#else
+/*
+ * K&R Compiler doesn't like #elif
+ */
+#      if      defined(HAVE_SYS_WAIT_H)        /* POSIX.1 compl. sys/wait.h */
+#      undef   HAVE_UNION_WAIT                 /* POSIX.1 doesn't use U_W   */
+#              ifndef  _INCL_SYS_WAIT_H
+#              include <sys/wait.h>
+#              define  _INCL_SYS_WAIT_H
+#              endif
+#      else
+#      if      defined(HAVE_UNION_WAIT)        /* Pure BSD U_W / sys/wait.h */
+#              ifndef  _INCL_SYS_WAIT_H
+#              include <sys/wait.h>
+#              define  _INCL_SYS_WAIT_H
+#              endif
+#      endif
+#      endif
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef HAVE_UNION_WAIT
+#      define WAIT_T union wait
+#      ifndef WSTOPPED
+#              define  WSTOPPED        0x7F
+#      endif
+#      ifndef WTERMSIG
+#              define WTERMSIG(status)         ((status).w_termsig)
+#      endif
+#      ifndef WCOREDUMP
+#              define WCOREDUMP(status)        ((status).w_coredump)
+#      endif
+#      ifndef WEXITSTATUS
+#              define WEXITSTATUS(status)      ((status).w_retcode)
+#      endif
+#      ifndef WSTOPSIG
+#              define WSTOPSIG(status)         ((status).w_stopsig)
+#      endif
+#      ifndef WIFSTOPPED
+#              define WIFSTOPPED(status)       ((status).w_stopval == \
+                                                               WSTOPPED)
+#      endif
+#      ifndef WIFSIGNALED
+#              define WIFSIGNALED(status)      ((status).w_stopval != \
+                                               WSTOPPED && \
+                                               (status).w_termsig != 0)
+#      endif
+#      ifndef WIFEXITED
+#              define WIFEXITED(status)        ((status).w_stopval != \
+                                               WSTOPPED && \
+                                               (status).w_termsig == 0)
+#      endif
+#else
+#      define WAIT_T int
+#      ifndef WTERMSIG
+#              define WTERMSIG(status)         ((status) & 0x7F)
+#      endif
+#      ifndef WCOREDUMP
+#              define WCOREDUMP(status)        ((status) & 0x80)
+#      endif
+#      ifndef WEXITSTATUS
+#              define WEXITSTATUS(status)      (((status) >> 8) & 0xFF)
+#      endif
+#      ifndef WSTOPSIG
+#              define WSTOPSIG(status)         (((status) >> 8) & 0xFF)
+#      endif
+#      ifndef WIFSTOPPED
+#              define  WIFSTOPPED(status)      (((status) & 0xFF) == 0x7F)
+#      endif
+#      ifndef WIFSIGNALED
+#              define  WIFSIGNALED(status)     (((status) & 0xFF) != 0x7F && \
+                                               WTERMSIG(status) != 0)
+#      endif
+#      ifndef WIFEXITED
+#              define  WIFEXITED(status)       (((status) & 0xFF) == 0)
+#      endif
+#endif
+
+
+#ifndef        WCOREFLG
+#define        WCOREFLG        0x80
+#endif
+
+#ifndef        WSTOPFLG
+#define        WSTOPFLG        0x7F
+#endif
+
+#ifndef        WCONTFLG
+#define        WCONTFLG        0xFFFF
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _WAITDEFS_H */
diff --git a/include/xconfig.h.in b/include/xconfig.h.in
new file mode 100644 (file)
index 0000000..c130600
--- /dev/null
@@ -0,0 +1,286 @@
+/* xconfig.h.in Prototype for xconfig.h, generated automatically by cmake in
+ * cdrkit's build system.
+ *
+ * Most features are expected to be available on every modern unixoide systems,
+ * others are probed.
+ *
+ * NOTE: Be carefull, there are some double checks for the 1 value hidden in
+ * the source, just defining it may be not enough.
+ * */
+
+/* 
+ * Copyright Eduard Bloch, 2006
+ *
+ * Using constants names and comments from xconfig.h.in by J. Schilling,
+ * Copyright (c) 1998-2003
+ *
+ */
+
+/*
+ * Header Files
+ */
+#define PROTOTYPES 1   /* if Compiler supports ANSI C prototypes */
+#cmakedefine HAVE_STDARG_H
+       /* to use stdarg.h, else use varargs.h NOTE: SaberC on a Sun has prototypes but no stdarg.h */
+
+#cmakedefine HAVE_STDLIB_H
+       /* to use general utility defines (malloc(), size_t ...) and general C library prototypes */
+
+#cmakedefine HAVE_STRING_H
+       /* to get NULL and ANSI C string function prototypes */
+#cmakedefine HAVE_STRINGS_H
+       /* to get BSD string function prototypes */
+#define STDC_HEADERS 1 /* if ANSI compliant stdlib.h, stdarg.h, string.h, float.h are present */
+#cmakedefine HAVE_UNISTD_H
+       /* to get POSIX syscall prototypes XXX sys/file.h fcntl.h (unixstd/fctl)XXX*/
+#cmakedefine HAVE_GETOPT_H
+       /* to get getopt() prototype from getopt.h instead of unistd.h */
+#cmakedefine HAVE_LIMITS_H
+       /* to get POSIX numeric limits constants */
+
+#cmakedefine HAVE_FCNTL_H
+       /* to access, O_XXX constants for open(), otherwise use sys/file.h */
+#cmakedefine HAVE_SYS_FILE_H
+       /* to use O_XXX constants for open() and flock() defs */
+#cmakedefine HAVE_INTTYPES_H
+       /* to use UNIX-98 inttypes.h */
+#cmakedefine HAVE_DIRENT_H
+       /* to use POSIX dirent.h */
+
+#cmakedefine HAVE_ALLOCA_H
+       /* if alloca.h exists */
+
+#cmakedefine HAVE_TERMIOS_H
+       /* to use POSIX termios.h */
+#cmakedefine HAVE_TERMIO_H
+       /* to use SVR4 termio.h */
+#cmakedefine HAVE_PWD_H
+       /* if pwd.h exists */
+
+#cmakedefine HAVE_SYS_TIME_H
+       /* may include sys/time.h for struct timeval */
+#define TIME_WITH_SYS_TIME 1   /* may include both time.h and sys/time.h */
+
+#define HAVE_UTIME 1           /* to use AT&T utime() and utimbuf */
+#define HAVE_UTIMES 1          /* to use BSD utimes() and sys/time.h */
+
+#cmakedefine HAVE_UTIME_H
+               /* to use utime.h for the utimbuf structure declaration, else declare struct utimbuf yourself */
+
+#cmakedefine HAVE_SYS_IOCTL_H
+               /* if sys/ioctl.h is present */
+
+#cmakedefine HAVE_SYS_PARAM_H
+               /* if sys/param.h is present */
+
+/* to use wait.h for prototypes and union wait */
+#cmakedefine HAVE_WAIT_H
+/* else use sys/wait.h */
+#cmakedefine define HAVE_SYS_WAIT_H
+#cmakedefine HAVE_SYS_RESOURCE_H
+       /* to use sys/resource.h for rlimit() and wait3() */
+
+#cmakedefine HAVE_SYS_UTSNAME_H
+       /* to use uname() */
+
+#cmakedefine HAVE_SYS_MTIO_H
+               /* to use mtio definitions from sys/mtio.h */
+
+#cmakedefine HAVE_SYS_MMAN_H
+               /* to use definitions for mmap()/madvise()... from sys/mman.h */
+#define MAJOR_IN_SYSMACROS 1   /* if we should include sys/sysmacros.h to get major()/minor()/makedev() */
+#cmakedefine HAVE_SYS_DKIO_H
+#cmakedefine HAVE_SUN_DKIO_H
+#cmakedefine HAVE_POLL_H
+               /* if we may include poll.h to use poll() */
+#cmakedefine HAVE_SYS_POLL_H
+               /* if we may include sys/poll.h to use poll() */
+
+
+#cmakedefine HAVE_NETDB_H
+               /* if we have netdb.h for get*by*() and rcmd() */
+#cmakedefine HAVE_SYS_SOCKET_H
+       /* if we have sys/socket.h for socket() */
+
+#cmakedefine HAVE_LINUX_PG_H
+               /* if we may include linux/pg.h for PP ATAPI sypport */
+#define HAVE_ERRNO_DEF 1               /* if we have errno definition in <errno.h> */
+
+#cmakedefine HAVE_ARPA_INET_H
+               /* if we have arpa/inet.h (missing on BeOS) */
+                               /* BeOS has inet_ntoa() in <netdb.h> */
+
+#cmakedefine HAVE_ICONV_H
+
+/*
+ * Convert to SCHILY name
+ */
+#ifdef STDC_HEADERS
+#      ifndef  HAVE_STDC_HEADERS
+#              define  HAVE_STDC_HEADERS
+#      endif
+#endif
+
+/*
+ * Library Functions
+ */
+#define HAVE_ACCESS 1          /* access() is present in libc */
+#define HAVE_STRERROR 1                /* strerror() is present in libc */
+#define HAVE_MEMMOVE 1         /* memmove() is present in libc */
+
+#define HAVE_MLOCK 1           /* mlock() is present in libc */
+#cmakedefine HAVE_MLOCKALL
+       /* working mlockall() is present in libc */
+#define HAVE_FLOCK 1           /* *BSD flock() is present in libc */
+#define HAVE_SETREUID 1                /* setreuid() is present in libc */
+#define HAVE_SETEUID 1         /* seteuid() is present in libc */
+#define HAVE_SETUID 1          /* setuid() is present in libc */
+#define HAVE_SETREGID 1                /* setregid() is present in libc */
+#define HAVE_SETEGID 1         /* setegid() is present in libc */
+#define HAVE_SETGID 1          /* setgid() is present in libc */
+#define HAVE_TCGETATTR 1               /* tcgetattr() is present in libc */
+#define HAVE_TCSETATTR 1               /* tcsetattr() is present in libc */
+#define HAVE_GETHOSTID 1               /* gethostid() is present in libc */
+#define HAVE_GETHOSTNAME 1             /* gethostname() is present in libc */
+#define HAVE_GETDOMAINNAME 1   /* getdomainname() is present in libc */
+#define HAVE_GETPAGESIZE 1             /* getpagesize() is present in libc */
+#define HAVE_POLL 1            /* poll() is present in libc */
+#define HAVE_SELECT 1          /* select() is present in libc */
+#define HAVE_LCHOWN 1          /* lchown() is present in libc */
+#define HAVE_SBRK 1            /* sbrk() is present in libc */
+#define HAVE_VA_COPY 1         /* va_copy() is present in varargs.h/stdarg.h */
+#define HAVE_DUP2 1            /* dup2() is present in libc */
+#define HAVE_GETCWD 1          /* POSIX getcwd() is present in libc */
+#define HAVE_SMMAP 1           /* may map anonymous memory to get shared mem */
+#define HAVE_SHMAT 1           /* shmat() is present in libc */
+#define HAVE_SEMGET 1          /* semget() is present in libc */
+#define HAVE_LSTAT 1           /* lstat() is present in libc */
+#define HAVE_READLINK 1                /* readlink() is present in libc */
+#define HAVE_RENAME 1          /* rename() is present in libc */
+
+#cmakedefine HAVE_RAND 
+               /* rand() is present in libc */
+#cmakedefine HAVE_DRAND48
+  /* drand48() is present in libc */
+#define HAVE_SETPRIORITY 1             /* setpriority() is present in libc */
+#define HAVE_NICE 1            /* nice() is present in libc */
+#define HAVE_UNAME 1           /* uname() is present in libc */
+#define HAVE_SNPRINTF 1                /* snprintf() is present in libc */
+#define HAVE_STRCASECMP 1              /* strcasecmp() is present in libc */
+#define HAVE_STRDUP 1          /* strdup() is present in libc */
+#define HAVE_SIGPROCMASK 1             /* sigprocmask() is present in libc (POSIX) */
+#define HAVE_SIGSET 1          /* sigset() is present in libc (POSIX) */
+#define HAVE_NANOSLEEP 1               /* nanosleep() is present in libc */
+#define HAVE_USLEEP 1          /* usleep() is present in libc */
+#define HAVE_FORK 1            /* fork() is present in libc */
+#define HAVE_ALLOCA 1          /* alloca() is present (else use malloc())*/
+#define HAVE_VALLOC 1          /* valloc() is present in libc (else use malloc())*/
+
+/*
+ * Important:  This must be a result from a check _before_ the Large File test
+ *             has been run. It then tells us whether these functions are
+ *             available even when not in Large File mode.
+ *
+ *     Do not run the AC_FUNC_FSEEKO test from the GNU tar Large File test
+ *     siute. It will use the same cache names and interfere with our test.
+ *     Instead use the tests AC_SMALL_FSEEKO/AC_SMALL/STELLO and make sure
+ *     they are placed before the large file tests.
+ */
+
+#define HAVE_RCMD 1            /* rcmd() is present in libc/libsocket */
+#define HAVE_SOCKET 1          /* socket() is present in libc/libsocket */
+#define HAVE_SOCKETPAIR 1              /* socketpair() is present in libc/libsocket */
+#define HAVE_GETSERVBYNAME 1   /* getservbyname() is present in libc/libsocket */
+/* inet_ntoa() is present in libc/libsocket */
+#cmakedefine HAVE_INET_NTOA
+
+/* getnameinfo() is present in libc/libsocket */
+#cmakedefine define HAVE_GETNAMEINFO
+
+/*
+ * We need to test for the include files too because Apollo Domain/OS has a
+ * libc that includes the functions but the includes files are not visible
+ * from the BSD compile environment.
+ */
+#if    defined(HAVE_SHMAT) && defined(HAVE_SYS_SHM_H) && defined(HAVE_SYS_IPC_H)
+#      define  HAVE_USGSHM     /* USG shared memory is present */
+#endif
+#if    defined(HAVE_SEMGET) && defined(HAVE_SYS_SHM_H) && defined(HAVE_SYS_IPC_H)
+#      define  HAVE_USGSEM     /* USG semaphores are present */
+#endif
+
+#if    defined(HAVE_GETPGRP) && !defined(HAVE_BSD_GETPGRP)
+#define        HAVE_POSIX_GETPGRP 1    /* getpgrp() in libc is POSIX compliant */
+#endif
+#if    defined(HAVE_SETPGRP) && !defined(HAVE_BSD_SETPGRP)
+#define        HAVE_POSIX_SETPGRP 1    /* setpgrp() in libc is POSIX compliant */
+#endif
+
+/*
+ * Structures
+ */
+
+/* have union wait in wait.h */
+#cmakedefine HAVE_UNION_WAIT
+
+#define HAVE_ST_NSEC 1         /* if struct stat contains st_atim.tv_nsec (nanosecs) */
+#define HAVE_ST_RDEV 1         /* if struct stat contains st_rdev */
+#define HAVE_SOCKADDR_STORAGE 1        /* if socket.h defines struct sockaddr_storage */
+
+/*
+ * Byteorder/Bitorder
+ */
+/* If using network byte order             */
+#cmakedefine WORDS_BIGENDIAN
+/* If high bits come first in structures   */
+#cmakedefine BITFIELDS_HTOL
+#define        HAVE_C_BIGENDIAN        /* Flag that WORDS_BIGENDIAN test was done */
+#define        HAVE_C_BITFIELDS        /* Flag that BITFIELDS_HTOL test was done  */
+
+/*
+ * Types/Keywords
+ */
+#define SIZEOF_CHAR 1
+#define SIZEOF_SHORT_INT  @SIZE_SHORT@
+#define SIZEOF_INT  @SIZE_INT@
+#define SIZEOF_LONG_INT @SIZE_LONG@
+#define SIZEOF_LONG_LONG @SIZE_LLONG@
+#define SIZEOF_CHAR_P @SIZE_PTR@
+#define SIZEOF_UNSIGNED_CHAR 1
+#define SIZEOF_UNSIGNED_SHORT_INT @SIZE_SHORT@
+#define SIZEOF_UNSIGNED_INT @SIZE_INT@
+#define SIZEOF_UNSIGNED_LONG_INT  @SIZE_LONG@
+#define SIZEOF_UNSIGNED_LONG_LONG @SIZE_LLONG@
+#define SIZEOF_UNSIGNED_CHAR_P @SIZE_PTR@
+
+#define HAVE_LONGLONG 1                /* Compiler defines long long type */
+
+
+/* 
+ * Critical on some of Debian architectures (EB) */
+/* #define VA_LIST_IS_ARRAY 1          */
+
+#cmakedefine VA_LIST_IS_ARRAY
+
+#define GETGROUPS_T gid_t
+#define GID_T          GETGROUPS_T
+
+/*
+ * Define as the return type of signal handlers (int or void).
+ */
+#define RETSIGTYPE void
+
+#define        HAVE_LARGEFILES 1
+#define _FILE_OFFSET_BITS 64 /* glibc style */
+#define _LARGEFILE_SOURCE 1    /* To make ftello() visible (HP-UX 10.20). */
+#define _LARGE_FILES 1         /* Large file defined on AIX-style hosts.  */
+
+/*
+ * Misc CC / LD related stuff
+ */
+/* If the compiler allows dynamic sized arrays */
+#cmakedefine HAVE_DYN_ARRAYS   
+
+#define HOST_SYSTEM "@CMAKE_SYSTEM_NAME@"
+#cmakedefine CDRKIT_VERSION "@CDRKIT_VERSION@"
+/*[$Rev: 467 $]" */
diff --git a/libedc/CMakeLists.txt b/libedc/CMakeLists.txt
new file mode 100644 (file)
index 0000000..5ea1dd2
--- /dev/null
@@ -0,0 +1,6 @@
+PROJECT (LIBEDC C)
+INCLUDE_DIRECTORIES(../include . ${CMAKE_BINARY_DIR} ${CMAKE_BINARY_DIR}/include)
+
+AUX_SOURCE_DIRECTORY(. LIBEDC_SRCS)
+
+ADD_LIBRARY (edc STATIC ${LIBEDC_SRCS})
diff --git a/libedc/README b/libedc/README
new file mode 100644 (file)
index 0000000..4788aed
--- /dev/null
@@ -0,0 +1,123 @@
+This describes the program as shipped with cdrkit, a spinoff from the
+cdrtools project. However, the cdrtools developers are no longer 
+involved in the development of this spinoff and therefore shall not
+be made responsible for any problem caused by it. Do not try to get 
+support for this program by contacting the original authors.
+
+This is a small description for the Reed-Solomon library intended for
+CD sector formatting.
+
+Basics:
+It is assumed that you have a basic knowledge of cd sector formats.
+
+The library can handle three types of sector data:
+  data sectors,
+  audio sectors, and
+  sub channel r-w sectors
+
+Currently only encoding is implemented. Decoding and optionally
+error correction is planned for later.
+
+Stages:
+
+The process of sector formatting has several stages. Beginning with
+a data sector (2048, 2324, or 2336 bytes) a sector of 2352 bytes is
+built. This format can be read raw by SCSI MMC-2 and ATAPI drives and
+is accepted by cd burners. The additions are an optionally 32 bit CRC
+checksum and two layers of Reed-Solomon codes (called Reed-Solomon
+Product Code RSPC).
+This sector is then scrambled (exor'ed with a bitstream).
+The result is called F1 frames. Afterwards even and odd bytes are
+swapped, this is called F2 frames. The result is equivalent to an
+audio sector and is treated as such by the cd burner.
+So, if we wrote a series of sectors (F2 frames) into a CDR file and
+later burned them as 'audio', they would turn up as perfect data sectors.
+
+So, now we are at the level of audio sectors. Audio sectors get their
+own error correction data (called CIRC). Sector size goes up to 
+3136 bytes (that is 4/3 times 2352 bytes). Furthermore different
+words get delayed differently and swap positions. The result is ready
+to be fed into the so-called EightFourteenModulator (when subchannels
+have been added).
+
+Now, only sub channels are missing. While the p and q sub
+channels have to be generated elsewhere, any supplied r-w subchannel
+user data is protected by two levels of error correction
+codes. This format is read by cd burners when burning cd+graphics.
+The cdimage is a sequence of sectors, each containing audio data and
+after that subchannel data.
+Similar to audio sectors delaying and permutation of words
+takes place. After that the cd burner would mix sub channel data with
+the formatted audio sectors to feed the EFModulator.
+
+NOTE: Most of the described stages need not to be done in order to
+prepare sectors for burning, since all cd burners do at least CIRC,
+delaying and swaps. For data sectors they also do scrambling and f2
+frame generation.
+
+Encoding routines:
+
+For data sectors
+ int do_encode_L2(unsigned char *inout, int sectortype, unsigned address);
+
+ encodes data sectors. The returned data is __unscrambled__ and not in
+ F2-frame format.
+
+Parameters are:
+  inout        pointer to an array of at least 2352 bytes.
+  sectortype   One of the MODE_* constants from ecc.h. This defines
+               how to format the sector.
+  address      The logical address to be used in the header 
+               (150 = 0:2.0 MSF).
+
+NOTE: the data portion has be to aligned properly for performance
+reasons (see ecc.h for details). So, no moves are necessary here.
+
+Generating f2 frames to be used like audio sectors
+ int scramble_L2(unsigned char *inout)
+
+ generates f2 frames in place from sectors generated by do_encode_L2().
+
+Parameters are:
+  inout        pointer to an array of at least 2352 bytes.
+
+
+
+For sub channels
+ int do_encode_sub(unsigned char in[LSUB_RAW*PACKETS_PER_SUBCHANNELFRAME],
+               unsigned char out[(LSUB_RAW+LSUB_Q+LSUB_P)*
+                                       PACKETS_PER_SUBCHANNELFRAME],
+               int delay1, int permute);
+
+ repack user data and add error correction data. P and q subchannels
+should be added later, since all bytes are in place then.
+
+Parameters are:
+  in           pointer to an array of at least 72 bytes. It contains
+               the user data for one frame.
+  out          pointer to an array of at least 96 bytes. Here is
+               output frame is placed.
+  delay1       do low level delaying, when set to 1.
+  permute      do low level permutations, when set to 1.
+
+NOTE: Probably both options need either to be set on (1) or off (0) together.
+
+There is more, but that is seldomly used.
+
+Tests:
+The library is accompanied by small verify programs, that compare real
+raw sectors with the formatted results. They are also intended as demo
+applications (how to use the library). In order to be able to feed
+real raw sectors into them, the package read2448 is recommended/needed.
+You can only verify sector streams of one sector type, currently no mix.
+
+For more information have a look into ecc.h
+
+recommended Documents:
+Yellow Book or ISO 10149
+Appendix Red Book
+Red Book or IEC 908
+
+Source: libedc/README from cdrtools package
+Edited for cdrkit by Christian Fromme <kaner@strace.org>
+
diff --git a/libedc/crctable.out b/libedc/crctable.out
new file mode 100644 (file)
index 0000000..3c99306
--- /dev/null
@@ -0,0 +1,171 @@
+/* @(#)crctable.out    1.2 02/10/17 joerg */
+
+/*****************************************************************/
+/*                                                               */
+/* CRC LOOKUP TABLE                                              */
+/* ================                                              */
+/* The following CRC lookup table was generated automagically    */
+/* by the Rocksoft^tm Model CRC Algorithm Table Generation       */
+/* Program V1.0 using the following model parameters:            */
+/*                                                               */
+/*    Width   : 4 bytes.                                         */
+/*    Poly    : 0x8001801BL                                      */
+/*    Reverse : TRUE.                                            */
+/*                                                               */
+/* For more information on the Rocksoft^tm Model CRC Algorithm,  */
+/* see the document titled "A Painless Guide to CRC Error        */
+/* Detection Algorithms" by Ross Williams                        */
+/* (ross@guest.adelaide.edu.au.). This document is likely to be  */
+/* in the FTP archive "ftp.adelaide.edu.au/pub/rocksoft".        */
+/*                                                               */
+/*****************************************************************/
+
+#ifdef PROTOTYPES
+
+static unsigned int EDC_crctable[256] =
+{
+ 0x00000000U, 0x90910101U, 0x91210201U, 0x01B00300U,
+ 0x92410401U, 0x02D00500U, 0x03600600U, 0x93F10701U,
+ 0x94810801U, 0x04100900U, 0x05A00A00U, 0x95310B01U,
+ 0x06C00C00U, 0x96510D01U, 0x97E10E01U, 0x07700F00U,
+ 0x99011001U, 0x09901100U, 0x08201200U, 0x98B11301U,
+ 0x0B401400U, 0x9BD11501U, 0x9A611601U, 0x0AF01700U,
+ 0x0D801800U, 0x9D111901U, 0x9CA11A01U, 0x0C301B00U,
+ 0x9FC11C01U, 0x0F501D00U, 0x0EE01E00U, 0x9E711F01U,
+ 0x82012001U, 0x12902100U, 0x13202200U, 0x83B12301U,
+ 0x10402400U, 0x80D12501U, 0x81612601U, 0x11F02700U,
+ 0x16802800U, 0x86112901U, 0x87A12A01U, 0x17302B00U,
+ 0x84C12C01U, 0x14502D00U, 0x15E02E00U, 0x85712F01U,
+ 0x1B003000U, 0x8B913101U, 0x8A213201U, 0x1AB03300U,
+ 0x89413401U, 0x19D03500U, 0x18603600U, 0x88F13701U,
+ 0x8F813801U, 0x1F103900U, 0x1EA03A00U, 0x8E313B01U,
+ 0x1DC03C00U, 0x8D513D01U, 0x8CE13E01U, 0x1C703F00U,
+ 0xB4014001U, 0x24904100U, 0x25204200U, 0xB5B14301U,
+ 0x26404400U, 0xB6D14501U, 0xB7614601U, 0x27F04700U,
+ 0x20804800U, 0xB0114901U, 0xB1A14A01U, 0x21304B00U,
+ 0xB2C14C01U, 0x22504D00U, 0x23E04E00U, 0xB3714F01U,
+ 0x2D005000U, 0xBD915101U, 0xBC215201U, 0x2CB05300U,
+ 0xBF415401U, 0x2FD05500U, 0x2E605600U, 0xBEF15701U,
+ 0xB9815801U, 0x29105900U, 0x28A05A00U, 0xB8315B01U,
+ 0x2BC05C00U, 0xBB515D01U, 0xBAE15E01U, 0x2A705F00U,
+ 0x36006000U, 0xA6916101U, 0xA7216201U, 0x37B06300U,
+ 0xA4416401U, 0x34D06500U, 0x35606600U, 0xA5F16701U,
+ 0xA2816801U, 0x32106900U, 0x33A06A00U, 0xA3316B01U,
+ 0x30C06C00U, 0xA0516D01U, 0xA1E16E01U, 0x31706F00U,
+ 0xAF017001U, 0x3F907100U, 0x3E207200U, 0xAEB17301U,
+ 0x3D407400U, 0xADD17501U, 0xAC617601U, 0x3CF07700U,
+ 0x3B807800U, 0xAB117901U, 0xAAA17A01U, 0x3A307B00U,
+ 0xA9C17C01U, 0x39507D00U, 0x38E07E00U, 0xA8717F01U,
+ 0xD8018001U, 0x48908100U, 0x49208200U, 0xD9B18301U,
+ 0x4A408400U, 0xDAD18501U, 0xDB618601U, 0x4BF08700U,
+ 0x4C808800U, 0xDC118901U, 0xDDA18A01U, 0x4D308B00U,
+ 0xDEC18C01U, 0x4E508D00U, 0x4FE08E00U, 0xDF718F01U,
+ 0x41009000U, 0xD1919101U, 0xD0219201U, 0x40B09300U,
+ 0xD3419401U, 0x43D09500U, 0x42609600U, 0xD2F19701U,
+ 0xD5819801U, 0x45109900U, 0x44A09A00U, 0xD4319B01U,
+ 0x47C09C00U, 0xD7519D01U, 0xD6E19E01U, 0x46709F00U,
+ 0x5A00A000U, 0xCA91A101U, 0xCB21A201U, 0x5BB0A300U,
+ 0xC841A401U, 0x58D0A500U, 0x5960A600U, 0xC9F1A701U,
+ 0xCE81A801U, 0x5E10A900U, 0x5FA0AA00U, 0xCF31AB01U,
+ 0x5CC0AC00U, 0xCC51AD01U, 0xCDE1AE01U, 0x5D70AF00U,
+ 0xC301B001U, 0x5390B100U, 0x5220B200U, 0xC2B1B301U,
+ 0x5140B400U, 0xC1D1B501U, 0xC061B601U, 0x50F0B700U,
+ 0x5780B800U, 0xC711B901U, 0xC6A1BA01U, 0x5630BB00U,
+ 0xC5C1BC01U, 0x5550BD00U, 0x54E0BE00U, 0xC471BF01U,
+ 0x6C00C000U, 0xFC91C101U, 0xFD21C201U, 0x6DB0C300U,
+ 0xFE41C401U, 0x6ED0C500U, 0x6F60C600U, 0xFFF1C701U,
+ 0xF881C801U, 0x6810C900U, 0x69A0CA00U, 0xF931CB01U,
+ 0x6AC0CC00U, 0xFA51CD01U, 0xFBE1CE01U, 0x6B70CF00U,
+ 0xF501D001U, 0x6590D100U, 0x6420D200U, 0xF4B1D301U,
+ 0x6740D400U, 0xF7D1D501U, 0xF661D601U, 0x66F0D700U,
+ 0x6180D800U, 0xF111D901U, 0xF0A1DA01U, 0x6030DB00U,
+ 0xF3C1DC01U, 0x6350DD00U, 0x62E0DE00U, 0xF271DF01U,
+ 0xEE01E001U, 0x7E90E100U, 0x7F20E200U, 0xEFB1E301U,
+ 0x7C40E400U, 0xECD1E501U, 0xED61E601U, 0x7DF0E700U,
+ 0x7A80E800U, 0xEA11E901U, 0xEBA1EA01U, 0x7B30EB00U,
+ 0xE8C1EC01U, 0x7850ED00U, 0x79E0EE00U, 0xE971EF01U,
+ 0x7700F000U, 0xE791F101U, 0xE621F201U, 0x76B0F300U,
+ 0xE541F401U, 0x75D0F500U, 0x7460F600U, 0xE4F1F701U,
+ 0xE381F801U, 0x7310F900U, 0x72A0FA00U, 0xE231FB01U,
+ 0x71C0FC00U, 0xE151FD01U, 0xE0E1FE01U, 0x7070FF00U,
+};
+
+/*****************************************************************/
+/*                   End of CRC Lookup Table                     */
+/*****************************************************************/
+
+#else  /* PROTOTYPES */
+
+static unsigned int EDC_crctable[256] =
+{
+ 0x00000000, 0x90910101, 0x91210201, 0x01B00300,
+ 0x92410401, 0x02D00500, 0x03600600, 0x93F10701,
+ 0x94810801, 0x04100900, 0x05A00A00, 0x95310B01,
+ 0x06C00C00, 0x96510D01, 0x97E10E01, 0x07700F00,
+ 0x99011001, 0x09901100, 0x08201200, 0x98B11301,
+ 0x0B401400, 0x9BD11501, 0x9A611601, 0x0AF01700,
+ 0x0D801800, 0x9D111901, 0x9CA11A01, 0x0C301B00,
+ 0x9FC11C01, 0x0F501D00, 0x0EE01E00, 0x9E711F01,
+ 0x82012001, 0x12902100, 0x13202200, 0x83B12301,
+ 0x10402400, 0x80D12501, 0x81612601, 0x11F02700,
+ 0x16802800, 0x86112901, 0x87A12A01, 0x17302B00,
+ 0x84C12C01, 0x14502D00, 0x15E02E00, 0x85712F01,
+ 0x1B003000, 0x8B913101, 0x8A213201, 0x1AB03300,
+ 0x89413401, 0x19D03500, 0x18603600, 0x88F13701,
+ 0x8F813801, 0x1F103900, 0x1EA03A00, 0x8E313B01,
+ 0x1DC03C00, 0x8D513D01, 0x8CE13E01, 0x1C703F00,
+ 0xB4014001, 0x24904100, 0x25204200, 0xB5B14301,
+ 0x26404400, 0xB6D14501, 0xB7614601, 0x27F04700,
+ 0x20804800, 0xB0114901, 0xB1A14A01, 0x21304B00,
+ 0xB2C14C01, 0x22504D00, 0x23E04E00, 0xB3714F01,
+ 0x2D005000, 0xBD915101, 0xBC215201, 0x2CB05300,
+ 0xBF415401, 0x2FD05500, 0x2E605600, 0xBEF15701,
+ 0xB9815801, 0x29105900, 0x28A05A00, 0xB8315B01,
+ 0x2BC05C00, 0xBB515D01, 0xBAE15E01, 0x2A705F00,
+ 0x36006000, 0xA6916101, 0xA7216201, 0x37B06300,
+ 0xA4416401, 0x34D06500, 0x35606600, 0xA5F16701,
+ 0xA2816801, 0x32106900, 0x33A06A00, 0xA3316B01,
+ 0x30C06C00, 0xA0516D01, 0xA1E16E01, 0x31706F00,
+ 0xAF017001, 0x3F907100, 0x3E207200, 0xAEB17301,
+ 0x3D407400, 0xADD17501, 0xAC617601, 0x3CF07700,
+ 0x3B807800, 0xAB117901, 0xAAA17A01, 0x3A307B00,
+ 0xA9C17C01, 0x39507D00, 0x38E07E00, 0xA8717F01,
+ 0xD8018001, 0x48908100, 0x49208200, 0xD9B18301,
+ 0x4A408400, 0xDAD18501, 0xDB618601, 0x4BF08700,
+ 0x4C808800, 0xDC118901, 0xDDA18A01, 0x4D308B00,
+ 0xDEC18C01, 0x4E508D00, 0x4FE08E00, 0xDF718F01,
+ 0x41009000, 0xD1919101, 0xD0219201, 0x40B09300,
+ 0xD3419401, 0x43D09500, 0x42609600, 0xD2F19701,
+ 0xD5819801, 0x45109900, 0x44A09A00, 0xD4319B01,
+ 0x47C09C00, 0xD7519D01, 0xD6E19E01, 0x46709F00,
+ 0x5A00A000, 0xCA91A101, 0xCB21A201, 0x5BB0A300,
+ 0xC841A401, 0x58D0A500, 0x5960A600, 0xC9F1A701,
+ 0xCE81A801, 0x5E10A900, 0x5FA0AA00, 0xCF31AB01,
+ 0x5CC0AC00, 0xCC51AD01, 0xCDE1AE01, 0x5D70AF00,
+ 0xC301B001, 0x5390B100, 0x5220B200, 0xC2B1B301,
+ 0x5140B400, 0xC1D1B501, 0xC061B601, 0x50F0B700,
+ 0x5780B800, 0xC711B901, 0xC6A1BA01, 0x5630BB00,
+ 0xC5C1BC01, 0x5550BD00, 0x54E0BE00, 0xC471BF01,
+ 0x6C00C000, 0xFC91C101, 0xFD21C201, 0x6DB0C300,
+ 0xFE41C401, 0x6ED0C500, 0x6F60C600, 0xFFF1C701,
+ 0xF881C801, 0x6810C900, 0x69A0CA00, 0xF931CB01,
+ 0x6AC0CC00, 0xFA51CD01, 0xFBE1CE01, 0x6B70CF00,
+ 0xF501D001, 0x6590D100, 0x6420D200, 0xF4B1D301,
+ 0x6740D400, 0xF7D1D501, 0xF661D601, 0x66F0D700,
+ 0x6180D800, 0xF111D901, 0xF0A1DA01, 0x6030DB00,
+ 0xF3C1DC01, 0x6350DD00, 0x62E0DE00, 0xF271DF01,
+ 0xEE01E001, 0x7E90E100, 0x7F20E200, 0xEFB1E301,
+ 0x7C40E400, 0xECD1E501, 0xED61E601, 0x7DF0E700,
+ 0x7A80E800, 0xEA11E901, 0xEBA1EA01, 0x7B30EB00,
+ 0xE8C1EC01, 0x7850ED00, 0x79E0EE00, 0xE971EF01,
+ 0x7700F000, 0xE791F101, 0xE621F201, 0x76B0F300,
+ 0xE541F401, 0x75D0F500, 0x7460F600, 0xE4F1F701,
+ 0xE381F801, 0x7310F900, 0x72A0FA00, 0xE231FB01,
+ 0x71C0FC00, 0xE151FD01, 0xE0E1FE01, 0x7070FF00,
+};
+
+#endif /* PROTOTYPES */
+
+/*****************************************************************/
+/*                   End of CRC Lookup Table                     */
+/*****************************************************************/
diff --git a/libedc/ecc.h b/libedc/ecc.h
new file mode 100644 (file)
index 0000000..76062b2
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)ecc.h   1.4 02/10/19 Copyright 1998-2002 Heiko Eissfeldt, Joerg Schilling */
+
+/*
+ * compact disc reed-solomon routines
+ *
+ * (c) 1998-2002 by Heiko Eissfeldt, heiko@colossus.escape.de
+ * (c) 2002 by Joerg Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#define RS_L12_BITS 8
+
+/* audio sector definitions for CIRC */
+#define FRAMES_PER_SECTOR 98
+/* user data bytes per frame */
+#define L1_RAW 24
+/* parity bytes with 8 bit */
+#define L1_Q   4
+#define L1_P   4
+
+/* audio sector Cross Interleaved Reed-Solomon Code (CIRC) encoder (layer 1) */
+/* adds P- and Q- parity information to audio (f2) frames. Also
+   optionally handles the various delays and permutations. The output with all
+   stages enabled can be fed into the Eight-Fourteen-Modulator.
+   On input: 2352 bytes of audio data is given.
+   On output: 3136 bytes of CIRC enriched audio data are returned.
+ */
+int do_encode_L1(unsigned char in[L1_RAW*FRAMES_PER_SECTOR],
+                                         unsigned char out[(L1_RAW+L1_Q+L1_P)*FRAMES_PER_SECTOR],
+                                         int delay1, int delay2, int delay3, int scramble);
+
+/* data sector definitions for RSPC */
+/* user data bytes per frame */
+#define L2_RAW (1024*2)
+/* parity bytes for 16 bit units */
+#define L2_Q   (26*2*2)
+#define L2_P   (43*2*2)
+
+/* known sector types */
+#define MODE_0 0
+#define MODE_1 1
+#define MODE_2 2
+#define MODE_2_FORM_1  3
+#define MODE_2_FORM_2  4
+
+/* set one of the MODE_* constants for subsequent data sector formatting */
+int set_sector_type(int st);
+/* get the current sector type setting for data sector formatting */
+int get_sector_type(void);
+
+/* data sector layer 2 Reed-Solomon Product Code encoder */
+/* encode the given data portion depending on sector type (see
+   get/set_sector_type() functions). Use the given address for the header.
+   The returned data is __unscrambled__ and not in F2-frame format (for that
+   see function scramble_L2()).
+   Supported sector types:
+     MODE_0: a 12-byte sync field, a header and 2336 zeros are returned.
+     MODE_1: the user data portion (2048 bytes) has to be given
+             at offset 16 in the inout array.
+             Sync-, header-, edc-, spare-, p- and q- fields will be added.
+     MODE_2: the user data portion (2336 bytes) has to be given
+             at offset 16 in the inout array.
+             Sync- and header- fields will be added.
+     MODE_2_FORM_1: the user data portion (8 bytes subheader followed
+                    by 2048 bytes data) has to be given at offset 16
+                    in the inout array.
+                    Sync-, header-, edc-, p- and q- fields will be added.
+     MODE_2_FORM_2: the user data portion (8 bytes subheader followed
+                    by 2324 bytes data) has to be given at offset 16
+                    in the inout array.
+                    Sync-, header- and edc- fields will be added.
+*/
+int do_encode_L2(unsigned char *inout, int sectortype, unsigned address);
+int decode_L2_Q(unsigned char inout[4 + L2_RAW + 12 + L2_Q]);
+int decode_L2_P(unsigned char inout[4 + L2_RAW + 12 + L2_Q + L2_P]);
+unsigned int build_edc(unsigned char inout[], int from, int upto);
+
+/* generates f2 frames from otherwise fully formatted sectors (generated by
+   do_encode_L2()). */
+#define        EDC_SCRAMBLE_NOSWAP     1       /* Do not swap bytes while scrambling */
+int scramble_L2(unsigned char *inout);
+
+/* r-w sub channel definitions */
+#define RS_SUB_RW_BITS 6
+
+#define PACKETS_PER_SUBCHANNELFRAME 4
+#define LSUB_RAW 18
+#define LSUB_QRAW 2
+/* 6 bit */
+#define LSUB_Q 2
+#define LSUB_P 4
+
+/* R-W subchannel encoder */
+/* On input: 72 bytes packed user data, four frames with each 18 bytes.
+   On output: per frame: 2 bytes user data, 2 bytes Q parity, 
+                         16 bytes user data, 4 bytes P parity.
+   Options:
+     delay1: use low level delay line
+     scramble: perform low level permutations
+ */
+int do_encode_sub(unsigned char in[LSUB_RAW*PACKETS_PER_SUBCHANNELFRAME],
+               unsigned char out[(LSUB_RAW+LSUB_Q+LSUB_P)*PACKETS_PER_SUBCHANNELFRAME],
+               int delay1, int scramble);
+int do_decode_sub(unsigned char in[(LSUB_RAW+LSUB_Q+LSUB_P)*PACKETS_PER_SUBCHANNELFRAME],
+                                               unsigned char out[LSUB_RAW*PACKETS_PER_SUBCHANNELFRAME],
+                                               int delay1, int scramble);
+
+int decode_LSUB_Q(unsigned char inout[LSUB_QRAW + LSUB_Q]);
+int decode_LSUB_P(unsigned char inout[LSUB_RAW + LSUB_Q + LSUB_P]);
diff --git a/libedc/edc_ecc.c b/libedc/edc_ecc.c
new file mode 100644 (file)
index 0000000..f98d4c5
--- /dev/null
@@ -0,0 +1,983 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)edc_ecc.c       1.21 03/04/04 Copyright 1998-2002 Heiko Eissfeldt, Joerg Schilling */
+
+/*
+ * Copyright 1998-2002 by Heiko Eissfeldt
+ * Copyright 2002 by Joerg Schilling
+ *
+ * This file contains protected intellectual property.
+ *
+ * reed-solomon encoder / decoder for compact discs.
+ *
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <mconfig.h>
+#include <stdio.h>
+#include <align.h>
+#include <utypes.h>
+#include <stdxlib.h>
+#include <strdefs.h>
+#include "ecc.h"
+
+#ifndef        HAVE_MEMMOVE
+/*#define      memmove(dst, src, size)         movebytes((src), (dst), (size))*/
+#define memmove(d, s, n) bcopy ((s), (d), (n))
+#endif
+
+/* these prototypes will become public when the function are implemented */
+static int do_decode_L2(unsigned char in[(L2_RAW+L2_Q+L2_P)], 
+                                                               unsigned char out[L2_RAW]);
+
+static int do_decode_L1(unsigned char in[(L1_RAW+L1_Q+L1_P)*FRAMES_PER_SECTOR],
+                                                               unsigned char out[L1_RAW*FRAMES_PER_SECTOR],
+                                                               int delay1, int delay2, int delay3, int scramble);
+
+
+/* ------------- tables generated by gen_encodes --------------*/
+
+#include "scramble_table"
+
+#define        DO4(a)  a;a;a;a;
+#define        DO13(a) a;a;a;a;a;a;a;a;a;a;a;a;a;
+
+/*
+ * Scrambles 2352 - 12 = 2340 bytes
+ */
+int scramble_L2(unsigned char *inout);
+
+int scramble_L2(unsigned char *inout)
+{
+#ifndef        EDC_SCRAMBLE_NOSWAP
+       unsigned int *f = (unsigned int *)inout;
+#endif
+
+       if (!xaligned(inout + 12, sizeof(UInt32_t)-1)) {
+
+               Uchar           *r = inout + 12;
+               const Uchar     *s = yellowbook_scrambler;
+               register int    i;
+
+               for (i = (L2_RAW + L2_Q + L2_P +16)/sizeof(unsigned char)/4; --i >= 0;) {
+                       DO4(*r++ ^= *s++);
+               }
+
+       } else {
+               UInt32_t        *r = (UInt32_t *) (inout + 12);
+               const UInt32_t  *s = yellowbook_scrambler_uint32;
+               register int    i;
+
+               for (i = (L2_RAW + L2_Q + L2_P +16)/sizeof(UInt32_t)/13; --i >= 0;) {
+                       DO13(*r++ ^= *s++);
+               }
+       }
+
+#ifndef        EDC_SCRAMBLE_NOSWAP
+
+       /* generate F1 frames */
+       for (i = 2352/sizeof(unsigned int); i; i--) {
+               *f++ = ((*f & 0xff00ff00UL) >> 8) | ((*f & 0x00ff00ffUL) << 8);
+       }
+#endif
+
+       return (0);
+}
+
+#include "l2sq_table"
+
+static int encode_L2_Q(unsigned char inout[4 + L2_RAW + 4 + 8 + L2_P + L2_Q]);
+
+static int encode_L2_Q(unsigned char inout[4 + L2_RAW + 4 + 8 + L2_P + L2_Q])
+{
+       unsigned char *dps;
+       unsigned char *dp;
+       unsigned char *Q;
+       register int i;
+       int j;
+
+       Q = inout + 4 + L2_RAW + 4 + 8 + L2_P;
+
+       dps = inout;
+       for (j = 0; j < 26; j++) {
+               register unsigned short a;
+               register unsigned short b;
+               a = b = 0;
+
+               dp = dps;
+               for (i = 0; i < 43; i++) {
+
+                       /* LSB */
+                       a ^= L2sq[i][*dp++];
+
+                       /* MSB */
+                       b ^= L2sq[i][*dp];
+
+                       dp += 2*44-1;
+                       if (dp >= &inout[(4 + L2_RAW + 4 + 8 + L2_P)]) {
+                               dp -= (4 + L2_RAW + 4 + 8 + L2_P);
+                       } 
+               }
+               Q[0]      = a >> 8;
+               Q[26*2]   = a;
+               Q[1]      = b >> 8;
+               Q[26*2+1] = b;
+
+               Q += 2;
+               dps += 2*43;
+       }
+       return (0);
+}
+
+static int encode_L2_P(unsigned char inout[4 + L2_RAW + 4 + 8 + L2_P]);
+
+static int encode_L2_P(unsigned char inout[4 + L2_RAW + 4 + 8 + L2_P])
+{
+       unsigned char *dp;
+       unsigned char *P;
+       register int i;
+       int j;
+
+       P = inout + 4 + L2_RAW + 4 + 8;
+
+       for (j = 0; j < 43; j++) {
+               register unsigned short a;
+               register unsigned short b;
+
+               a = b = 0;
+               dp = inout;
+               for (i = 19; i < 43; i++) {
+
+                       /* LSB */
+                       a ^= L2sq[i][*dp++];
+
+                       /* MSB */
+                       b ^= L2sq[i][*dp];
+
+                       dp += 2*43 -1;
+               }
+               P[0]      = a >> 8;
+               P[43*2]   = a;
+               P[1]      = b >> 8;
+               P[43*2+1] = b;
+
+               P += 2;
+               inout += 2;
+       }
+       return (0);
+}
+
+static unsigned char bin2bcd(unsigned p);
+
+static unsigned char bin2bcd(unsigned p)
+{
+       return ((p/10)<<4)|(p%10);
+}
+
+static int build_address(unsigned char inout[], int sectortype, unsigned address);
+
+static int 
+build_address(unsigned char inout[], int sectortype, unsigned address)
+{
+       inout[12] = bin2bcd(address / (60*75));
+       inout[13] = bin2bcd((address / 75) % 60);
+       inout[14] = bin2bcd(address % 75);
+       if (sectortype == MODE_0)
+               inout[15] = 0;
+       else if (sectortype == MODE_1)
+               inout[15] = 1;
+       else if (sectortype == MODE_2)
+               inout[15] = 2;
+       else if (sectortype == MODE_2_FORM_1)
+               inout[15] = 2;
+       else if (sectortype == MODE_2_FORM_2)
+               inout[15] = 2;
+       else
+               return (-1);
+       return (0);
+}
+
+#include "crctable.out"
+
+/*
+ * Called with 2064, 2056 or 2332 byte difference - all dividable by 4.
+ */
+unsigned int build_edc(unsigned char inout[], int from, int upto);
+
+unsigned int build_edc(unsigned char inout[], int from, int upto)
+{
+       unsigned char *p = inout+from;
+       unsigned int result = 0;
+
+       upto -= from-1;
+       upto /= 4;
+       while (--upto >= 0) {
+               result = EDC_crctable[(result ^ *p++) & 0xffL] ^ (result >> 8);
+               result = EDC_crctable[(result ^ *p++) & 0xffL] ^ (result >> 8);
+               result = EDC_crctable[(result ^ *p++) & 0xffL] ^ (result >> 8);
+               result = EDC_crctable[(result ^ *p++) & 0xffL] ^ (result >> 8);
+       }
+       return (result);
+}
+
+/* Layer 2 Product code en/decoder */
+int do_encode_L2(unsigned char inout[(12 + 4 + L2_RAW+4+8+L2_Q+L2_P)], 
+                                         int sectortype, unsigned address);
+
+int
+do_encode_L2(unsigned char inout[(12 + 4 + L2_RAW+4+8+L2_Q+L2_P)], 
+             int sectortype, unsigned address)
+{
+       unsigned int result;
+
+/*     SYNCPATTERN "\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" */
+#define SYNCPATTERN "\000\377\377\377\377\377\377\377\377\377\377"
+
+       /* supply initial sync pattern */
+       memcpy(inout, SYNCPATTERN, sizeof(SYNCPATTERN));
+
+       if (sectortype == MODE_0) {
+               memset(inout + sizeof(SYNCPATTERN), 0, 4 + L2_RAW + 12 + L2_P + L2_Q);
+               build_address(inout, sectortype, address);
+               return (0);
+       }
+
+       switch (sectortype) {
+
+       case MODE_1:
+               build_address(inout, sectortype, address);
+               result = build_edc(inout, 0, 16+2048-1);
+               inout[2064+0] = result >> 0L;
+               inout[2064+1] = result >> 8L;
+               inout[2064+2] = result >> 16L;
+               inout[2064+3] = result >> 24L;
+               memset(inout+2064+4, 0, 8);
+               encode_L2_P(inout+12);
+               encode_L2_Q(inout+12);
+               break;
+       case MODE_2:
+               build_address(inout, sectortype, address);
+               break;
+       case MODE_2_FORM_1:
+               result = build_edc(inout, 16, 16+8+2048-1);
+               inout[2072+0] = result >> 0L;
+               inout[2072+1] = result >> 8L;
+               inout[2072+2] = result >> 16L;
+               inout[2072+3] = result >> 24L;
+
+               /* clear header for P/Q parity calculation */
+               inout[12] = 0;
+               inout[12+1] = 0;
+               inout[12+2] = 0;
+               inout[12+3] = 0;
+               encode_L2_P(inout+12);
+               encode_L2_Q(inout+12);
+               build_address(inout, sectortype, address);
+               break;
+       case MODE_2_FORM_2:
+               build_address(inout, sectortype, address);
+               result = build_edc(inout, 16, 16+8+2324-1);
+               inout[2348+0] = result >> 0L;
+               inout[2348+1] = result >> 8L;
+               inout[2348+2] = result >> 16L;
+               inout[2348+3] = result >> 24L;
+               break;
+       default:
+               return (-1);
+       }
+
+       return (0);
+}
+
+
+/*--------------------------------------------------------------------------*/
+#include "encoder_tables"
+
+static int encode_L1_Q(unsigned char inout[L1_RAW + L1_Q]);
+
+static int encode_L1_Q(unsigned char inout[L1_RAW + L1_Q])
+{
+       unsigned char *Q;
+       int     i;
+
+       memmove(inout+L1_RAW/2+L1_Q, inout+L1_RAW/2, L1_RAW/2);
+       Q = inout + L1_RAW/2;
+
+       memset(Q, 0, L1_Q);
+       for (i = 0; i < L1_RAW + L1_Q; i++) {
+               unsigned char data;
+
+               if (i == L1_RAW/2) i += L1_Q;
+               data = inout[i];
+               if (data != 0) {
+                       unsigned char base = rs_l12_log[data];
+
+                       Q[0] ^= rs_l12_alog[(base+AQ[0][i]) % (unsigned)((1 << RS_L12_BITS)-1)];
+                       Q[1] ^= rs_l12_alog[(base+AQ[1][i]) % (unsigned)((1 << RS_L12_BITS)-1)];
+                       Q[2] ^= rs_l12_alog[(base+AQ[2][i]) % (unsigned)((1 << RS_L12_BITS)-1)];
+                       Q[3] ^= rs_l12_alog[(base+AQ[3][i]) % (unsigned)((1 << RS_L12_BITS)-1)];
+               }
+       }
+       return (0);
+}
+
+static int encode_L1_P(unsigned char inout[L1_RAW + L1_Q + L1_P]);
+
+static int encode_L1_P(unsigned char inout[L1_RAW + L1_Q + L1_P])
+{
+       unsigned char *P;
+       int     i;
+
+       P = inout + L1_RAW + L1_Q;
+
+       memset(P, 0, L1_P);
+       for (i = 0; i < L2_RAW + L2_Q + L2_P; i++) {
+               unsigned char data;
+
+               data = inout[i];
+               if (data != 0) {
+                       unsigned char base = rs_l12_log[data];
+
+                       P[0] ^= rs_l12_alog[(base+AP[0][i]) % (unsigned)((1 << RS_L12_BITS)-1)];
+                       P[1] ^= rs_l12_alog[(base+AP[1][i]) % (unsigned)((1 << RS_L12_BITS)-1)];
+                       P[2] ^= rs_l12_alog[(base+AP[2][i]) % (unsigned)((1 << RS_L12_BITS)-1)];
+                       P[3] ^= rs_l12_alog[(base+AP[3][i]) % (unsigned)((1 << RS_L12_BITS)-1)];
+               }
+       }
+       return (0);
+}
+
+static int decode_L1_Q(unsigned char inout[L1_RAW + L1_Q]);
+
+static int decode_L1_Q(unsigned char inout[L1_RAW + L1_Q])
+{
+       return (0);
+}
+
+static int decode_L1_P(unsigned char in[L1_RAW + L1_Q + L1_P]);
+
+static int decode_L1_P(unsigned char in[L1_RAW + L1_Q + L1_P])
+{
+       return (0);
+}
+
+int decode_L2_Q(unsigned char inout[4 + L2_RAW + 12 + L2_Q]);
+
+int decode_L2_Q(unsigned char inout[4 + L2_RAW + 12 + L2_Q])
+{
+       return (0);
+}
+
+int decode_L2_P(unsigned char inout[4 + L2_RAW + 12 + L2_Q + L2_P]);
+
+int decode_L2_P(unsigned char inout[4 + L2_RAW + 12 + L2_Q + L2_P])
+{
+       return (0);
+}
+
+static int encode_LSUB_Q(unsigned char inout[LSUB_RAW + LSUB_Q]);
+
+static int encode_LSUB_Q(unsigned char inout[LSUB_RAW + LSUB_Q])
+{
+       unsigned char *Q;
+       int i;
+
+       memmove(inout+LSUB_QRAW+LSUB_Q, inout+LSUB_QRAW, LSUB_RAW-LSUB_QRAW);
+       Q = inout + LSUB_QRAW;
+
+       memset(Q, 0, LSUB_Q);
+
+       for (i = 0; i < LSUB_QRAW; i++) {
+               unsigned char data;
+
+               data = inout[i] & 0x3f;
+               if (data != 0) {
+                       unsigned char base = rs_sub_rw_log[data];
+
+                       Q[0] ^= rs_sub_rw_alog[(base+SQ[0][i]) % (unsigned)((1 << RS_SUB_RW_BITS)-1)];
+                       Q[1] ^= rs_sub_rw_alog[(base+SQ[1][i]) % (unsigned)((1 << RS_SUB_RW_BITS)-1)];
+               }
+       }
+       return (0);
+}
+
+
+static int encode_LSUB_P(unsigned char inout[LSUB_RAW + LSUB_Q + LSUB_P]);
+
+static int encode_LSUB_P(unsigned char inout[LSUB_RAW + LSUB_Q + LSUB_P])
+{
+       unsigned char *P;
+       int i;
+
+       P = inout + LSUB_RAW + LSUB_Q;
+
+       memset(P, 0, LSUB_P);
+       for (i = 0; i < LSUB_RAW + LSUB_Q; i++) {
+               unsigned char data;
+
+               data = inout[i] & 0x3f;
+               if (data != 0) {
+                       unsigned char base = rs_sub_rw_log[data];
+
+                       P[0] ^= rs_sub_rw_alog[(base+SP[0][i]) % (unsigned)((1 << RS_SUB_RW_BITS)-1)];
+                       P[1] ^= rs_sub_rw_alog[(base+SP[1][i]) % (unsigned)((1 << RS_SUB_RW_BITS)-1)];
+                       P[2] ^= rs_sub_rw_alog[(base+SP[2][i]) % (unsigned)((1 << RS_SUB_RW_BITS)-1)];
+                       P[3] ^= rs_sub_rw_alog[(base+SP[3][i]) % (unsigned)((1 << RS_SUB_RW_BITS)-1)];
+               }
+       }
+       return (0);
+}
+
+int decode_LSUB_Q(unsigned char inout[LSUB_QRAW + LSUB_Q]);
+
+int decode_LSUB_Q(unsigned char inout[LSUB_QRAW + LSUB_Q])
+{
+       unsigned char Q[LSUB_Q];
+       int i;
+
+       memset(Q, 0, LSUB_Q);
+       for (i = LSUB_QRAW + LSUB_Q -1; i>=0; i--) {
+               unsigned char data;
+
+               data = inout[LSUB_QRAW + LSUB_Q -1 -i] & 0x3f;
+               if (data != 0) {
+                       unsigned char base = rs_sub_rw_log[data];
+
+                       Q[0] ^= rs_sub_rw_alog[(base+0*i) % (unsigned)((1 << RS_SUB_RW_BITS)-1)];
+                       Q[1] ^= rs_sub_rw_alog[(base+1*i) % (unsigned)((1 << RS_SUB_RW_BITS)-1)];
+               }
+       }
+       return (Q[0] != 0 || Q[1] != 0);
+}
+
+int decode_LSUB_P(unsigned char inout[LSUB_RAW + LSUB_Q + LSUB_P]);
+
+int decode_LSUB_P(unsigned char inout[LSUB_RAW + LSUB_Q + LSUB_P])
+{
+       unsigned char P[LSUB_P];
+       int i;
+
+       memset(P, 0, LSUB_P);
+       for (i = LSUB_RAW + LSUB_Q + LSUB_P-1; i>=0; i--) {
+               unsigned char data;
+
+               data = inout[LSUB_RAW + LSUB_Q + LSUB_P -1 -i] & 0x3f;
+               if (data != 0) {
+                       unsigned char base = rs_sub_rw_log[data];
+
+                       P[0] ^= rs_sub_rw_alog[(base+0*i) % (unsigned)((1 << RS_SUB_RW_BITS)-1)];
+                       P[1] ^= rs_sub_rw_alog[(base+1*i) % (unsigned)((1 << RS_SUB_RW_BITS)-1)];
+                       P[2] ^= rs_sub_rw_alog[(base+2*i) % (unsigned)((1 << RS_SUB_RW_BITS)-1)];
+                       P[3] ^= rs_sub_rw_alog[(base+3*i) % (unsigned)((1 << RS_SUB_RW_BITS)-1)];
+               }
+       }
+       return (P[0] != 0 || P[1] != 0 || P[2] != 0 || P[3] != 0);
+}
+
+/* Layer 1 CIRC en/decoder */
+#define MAX_L1_DEL1 2
+static unsigned char l1_delay_line1[MAX_L1_DEL1][L1_RAW];
+#define MAX_L1_DEL2 108
+static unsigned char l1_delay_line2[MAX_L1_DEL2][L1_RAW+L1_Q];
+#define MAX_L1_DEL3 1
+static unsigned char l1_delay_line3[MAX_L1_DEL3][L1_RAW+L1_Q+L1_P];
+static unsigned l1_del_index;
+
+int do_encode_L1(unsigned char in[L1_RAW*FRAMES_PER_SECTOR],
+                                         unsigned char out[(L1_RAW+L1_Q+L1_P)*FRAMES_PER_SECTOR],
+                                         int delay1, int delay2, int delay3, int permute);
+
+int do_encode_L1(unsigned char in[L1_RAW*FRAMES_PER_SECTOR], 
+                 unsigned char out[(L1_RAW+L1_Q+L1_P)*FRAMES_PER_SECTOR], 
+                 int delay1, int delay2, int delay3, int permute)
+{
+       int i;
+
+       for (i = 0; i < FRAMES_PER_SECTOR; i++) {
+               int j;
+               unsigned char t;
+
+               if (in != out)
+                       memcpy(out, in, L1_RAW);
+
+               if (delay1) {
+                       /* shift through delay line 1 */
+                       for (j = 0; j < L1_RAW; j++) {
+                               if (((j/4) % MAX_L1_DEL1) == 0) {
+                                       t = l1_delay_line1[l1_del_index % (MAX_L1_DEL1)][j];
+                                       l1_delay_line1[l1_del_index % (MAX_L1_DEL1)][j] = out[j];
+                                       out[j] = t;
+                               }
+                       }
+               }
+
+               if (permute) {
+                       /* permute */
+                       t = out[2]; out[2] = out[8]; out[8] = out[10]; out[10] = out[18];
+                       out[18] = out[6]; out [6] = t;
+                       t = out[3]; out[3] = out[9]; out[9] = out[11]; out[11] = out[19];
+                       out[19] = out[7]; out [7] = t;
+                       t = out[4]; out[4] = out[16]; out[16] = out[20]; out[20] = out[14];
+                       out[14] = out[12]; out [12] = t;
+                       t = out[5]; out[5] = out[17]; out[17] = out[21]; out[21] = out[15];
+                       out[15] = out[13]; out [13] = t;
+               }
+
+               /* build Q parity */
+               encode_L1_Q(out);
+
+               if (delay2) {
+                       /* shift through delay line 2 */
+                       for (j = 0; j < L1_RAW+L1_Q; j++) {
+                               if (j != 0) {
+                                       t = l1_delay_line2[(l1_del_index) % MAX_L1_DEL2][j];
+                                       l1_delay_line2[(l1_del_index + j*4) % MAX_L1_DEL2][j] = out[j];
+                                       out[j] = t;
+                               }
+                       }
+               }
+
+               /* build P parity */
+               encode_L1_P(out);
+
+               if (delay3) {
+                       /* shift through delay line 3 */
+                       for (j = 0; j < L1_RAW+L1_Q+L1_P; j++) {
+                               if (((j) & MAX_L1_DEL3) == 0) {
+                                       t = l1_delay_line3[0][j];
+                                       l1_delay_line3[0][j] = out[j];
+                                       out[j] = t;
+                               }
+                       }
+               }
+
+               /* invert Q and P parity */
+               for (j = 0; j < L1_Q; j++)
+                       out[j+12] = ~out[j+12];
+               for (j = 0; j < L1_P; j++)
+                       out[j+28] = ~out[j+28];
+
+               l1_del_index++;
+               out += L1_RAW+L1_Q+L1_P;
+               in += L1_RAW;
+       }
+       return (0);
+}
+
+static
+int do_decode_L1(unsigned char in[(L1_RAW+L1_Q+L1_P)*FRAMES_PER_SECTOR],
+                                         unsigned char out[L1_RAW*FRAMES_PER_SECTOR],
+                                         int delay1, int delay2, int delay3, int permute);
+
+static /* XXX should be non static XXX*/ 
+
+int do_decode_L1(unsigned char in[(L1_RAW+L1_Q+L1_P)*FRAMES_PER_SECTOR], 
+                 unsigned char out[L1_RAW*FRAMES_PER_SECTOR], 
+                 int delay1, int delay2, int delay3, int permute)
+{
+       int i;
+
+       for (i = 0; i < FRAMES_PER_SECTOR; i++) {
+               int j;
+               unsigned char t;
+
+               if (delay3) {
+                       /* shift through delay line 3 */
+                       for (j = 0; j < L1_RAW+L1_Q+L1_P; j++) {
+                               if (((j) & MAX_L1_DEL3) != 0) {
+                                       t = l1_delay_line3[0][j];
+                                       l1_delay_line3[0][j] = in[j];
+                                       in[j] = t;
+                               }
+                       }
+               }
+
+               /* invert Q and P parity */
+               for (j = 0; j < L1_Q; j++)
+                       in[j+12] = ~in[j+12];
+               for (j = 0; j < L1_P; j++)
+                       in[j+28] = ~in[j+28];
+
+               /* build P parity */
+               decode_L1_P(in);
+
+               if (delay2) {
+                       /* shift through delay line 2 */
+                       for (j = 0; j < L1_RAW+L1_Q; j++) {
+                               if (j != L1_RAW+L1_Q-1) {
+                                       t = l1_delay_line2[(l1_del_index) % MAX_L1_DEL2][j];
+                                       l1_delay_line2[(l1_del_index + (MAX_L1_DEL2 - j*4)) % MAX_L1_DEL2][j] = in[j];
+                                       in[j] = t;
+                               }
+                       }
+               }
+
+               /* build Q parity */
+               decode_L1_Q(in);
+
+               if (permute) {
+                       /* permute */
+                       t = in[2]; in[2] = in[6]; in[6] = in[18]; in[18] = in[10];
+                       in[10] = in[8]; in [8] = t;
+                       t = in[3]; in[3] = in[7]; in[7] = in[19]; in[19] = in[11];
+                       in[11] = in[9]; in [9] = t;
+                       t = in[4]; in[4] = in[12]; in[12] = in[14]; in[14] = in[20];
+                       in[20] = in[16]; in [16] = t;
+                       t = in[5]; in[5] = in[13]; in[13] = in[15]; in[15] = in[21];
+                       in[21] = in[17]; in [17] = t;
+               }
+
+               if (delay1) {
+                       /* shift through delay line 1 */
+                       for (j = 0; j < L1_RAW; j++) {
+                               if (((j/4) % MAX_L1_DEL1) != 0) {
+                                       t = l1_delay_line1[l1_del_index % (MAX_L1_DEL1)][j];
+                                       l1_delay_line1[l1_del_index % (MAX_L1_DEL1)][j] = in[j];
+                                       in[j] = t;
+                               }
+                       }
+               }
+
+               if (in != out)
+                       memcpy(out, in, (L1_RAW));
+
+               l1_del_index++;
+               in += L1_RAW+L1_Q+L1_P;
+               out += L1_RAW;
+       }
+       return (0);
+}
+
+static int do_decode_L2(unsigned char in[(L2_RAW+L2_Q+L2_P)],
+                                                               unsigned char out[L2_RAW]);
+
+static int do_decode_L2(unsigned char in[(L2_RAW+L2_Q+L2_P)], 
+                        unsigned char out[L2_RAW])
+{
+       return (0);
+}
+
+
+
+#define MAX_SUB_DEL 8
+static unsigned char sub_delay_line[MAX_SUB_DEL][LSUB_RAW+LSUB_Q+LSUB_P];
+static unsigned sub_del_index;
+
+/* R-W Subchannel en/decoder */
+
+int do_encode_sub(unsigned char in[LSUB_RAW*PACKETS_PER_SUBCHANNELFRAME],
+               unsigned char out[(LSUB_RAW+LSUB_Q+LSUB_P)*PACKETS_PER_SUBCHANNELFRAME],
+               int delay1, int permute);
+
+int do_encode_sub(unsigned char in[LSUB_RAW*PACKETS_PER_SUBCHANNELFRAME], 
+                  unsigned char out[(LSUB_RAW+LSUB_Q+LSUB_P)*PACKETS_PER_SUBCHANNELFRAME], 
+                  int delay1, int permute)
+{
+       int i;
+
+       if (in == out) return -1;
+
+       for (i = 0; i < PACKETS_PER_SUBCHANNELFRAME; i++) {
+               int j;
+               unsigned char t;
+
+               memcpy(out, in, (LSUB_RAW));
+
+               /* build Q parity */
+               encode_LSUB_Q(out);
+
+               /* build P parity */
+               encode_LSUB_P(out);
+
+               if (permute) {
+                       /* permute */
+                       t = out[1]; out[1] = out[18]; out[18] = t;
+                       t = out[2]; out[2] = out[ 5]; out[ 5] = t;
+                       t = out[3]; out[3] = out[23]; out[23] = t;
+               }
+
+               if (delay1) {
+                       /* shift through delay_line */
+                       for (j = 0; j < LSUB_RAW+LSUB_Q+LSUB_P; j++) {
+                               if ((j % MAX_SUB_DEL) != 0) {
+                                       t = sub_delay_line[(sub_del_index) % MAX_SUB_DEL][j];
+                                       sub_delay_line[(sub_del_index + j) % MAX_SUB_DEL][j] = out[j];
+                                       out[j] = t;
+                               }
+                       }
+               }
+               sub_del_index++;
+               out += LSUB_RAW+LSUB_Q+LSUB_P;
+               in += LSUB_RAW;
+       }
+       return (0);
+}
+
+int 
+do_decode_sub(
+               unsigned char in[(LSUB_RAW+LSUB_Q+LSUB_P)*PACKETS_PER_SUBCHANNELFRAME],
+               unsigned char out[LSUB_RAW*PACKETS_PER_SUBCHANNELFRAME],
+               int delay1, int permute);
+
+int 
+do_decode_sub(unsigned char in[(LSUB_RAW+LSUB_Q+LSUB_P)*PACKETS_PER_SUBCHANNELFRAME], 
+              unsigned char out[LSUB_RAW*PACKETS_PER_SUBCHANNELFRAME], 
+              int delay1, int permute)
+{
+       int i;
+
+       if (in == out) return -1;
+
+       for (i = 0; i < PACKETS_PER_SUBCHANNELFRAME; i++) {
+               int j;
+               unsigned char t;
+
+               if (delay1) {
+                       /* shift through delay_line */
+                       for (j = 0; j < LSUB_RAW+LSUB_Q+LSUB_P; j++) {
+                               if ((j % MAX_SUB_DEL) != MAX_SUB_DEL-1) {
+                                       t = sub_delay_line[(sub_del_index) % MAX_SUB_DEL][j];
+                                       sub_delay_line[(sub_del_index + (MAX_SUB_DEL - j)) % MAX_SUB_DEL][j] = in[j];
+                                       in[j] = t;
+                               }
+                       }
+               }
+
+               if (permute) {
+                       /* permute */
+                       t = in[1]; in[1] = in[18]; in[18] = t;
+                       t = in[2]; in[2] = in[ 5]; in[ 5] = t;
+                       t = in[3]; in[3] = in[23]; in[23] = t;
+               }
+
+               /* build P parity */
+               decode_LSUB_P(in);
+
+               /* build Q parity */
+               decode_LSUB_Q(in);
+
+               memcpy(out, in, LSUB_QRAW);
+               memcpy(out+LSUB_QRAW, in+LSUB_QRAW+LSUB_Q, LSUB_RAW-LSUB_QRAW);
+
+               sub_del_index++;
+               in += LSUB_RAW+LSUB_Q+LSUB_P;
+               out += LSUB_RAW;
+       }
+       return (0);
+}
+
+static int sectortype = MODE_0;
+
+int get_sector_type(void);
+
+int get_sector_type()
+{
+       return (sectortype);
+}
+
+int set_sector_type(int st);
+
+int set_sector_type(int st)
+{
+       switch(st) {
+
+       case MODE_0:
+       case MODE_1:
+       case MODE_2:
+       case MODE_2_FORM_1:
+       case MODE_2_FORM_2:
+               sectortype = st;
+               return 0;
+       default:
+               return -1;
+       }
+}
+
+/* ------------- --------------*/
+#ifdef MAIN
+
+#define DO_L1 1
+#define DO_L2 2
+#define DO_SUB 4
+
+static const unsigned sect_size[8][2] = {
+/* nothing */
+{0,0},
+/* Layer 1 decode/encode */
+{ (L1_RAW+L1_Q+L1_P)*FRAMES_PER_SECTOR, L1_RAW*FRAMES_PER_SECTOR},
+/* Layer 2 decode/encode */
+{ 16+L2_RAW+12+L2_Q+L2_P, L2_RAW},
+/* Layer 1 and 2 decode/encode */
+{ (L1_RAW+L1_Q+L1_P)*FRAMES_PER_SECTOR, L1_RAW*FRAMES_PER_SECTOR},
+/* Subchannel decode/encode */
+{ (LSUB_RAW+LSUB_Q+LSUB_P)*PACKETS_PER_SUBCHANNELFRAME,
+ LSUB_RAW*PACKETS_PER_SUBCHANNELFRAME},
+/* Layer 1 and subchannel decode/encode */
+{ (L1_RAW+L1_Q+L1_P)*FRAMES_PER_SECTOR +
+   (LSUB_RAW+LSUB_Q+LSUB_P)*PACKETS_PER_SUBCHANNELFRAME,
+  LSUB_RAW*PACKETS_PER_SUBCHANNELFRAME +
+   L1_RAW*FRAMES_PER_SECTOR},
+/* Layer 2 and subchannel decode/encode */
+{ L2_RAW+L2_Q+L2_P+
+   (LSUB_RAW+LSUB_Q+LSUB_P)*PACKETS_PER_SUBCHANNELFRAME,
+  LSUB_RAW*PACKETS_PER_SUBCHANNELFRAME +
+   L2_RAW},
+/* Layer 1, 2 and subchannel decode/encode */
+{ (L1_RAW+L1_Q+L1_P)*FRAMES_PER_SECTOR +
+   (LSUB_RAW+LSUB_Q+LSUB_P)*PACKETS_PER_SUBCHANNELFRAME,
+  LSUB_RAW*PACKETS_PER_SUBCHANNELFRAME +
+   L1_RAW*FRAMES_PER_SECTOR},
+};
+
+int main(int argc, char *argv[])
+{
+       int encode = 1;
+       int mask = DO_L2;
+       FILE *infp;
+       FILE *outfp;
+       unsigned address = 0;
+       unsigned char *l1_inbuf;
+       unsigned char *l1_outbuf;
+       unsigned char *l2_inbuf;
+       unsigned char *l2_outbuf;
+       unsigned char *sub_inbuf;
+       unsigned char *sub_outbuf;
+       unsigned char *last_outbuf;
+       unsigned char inbuf[(LSUB_RAW+LSUB_Q+LSUB_P)*PACKETS_PER_SUBCHANNELFRAME +
+                       (L1_RAW+L1_Q+L1_P)*FRAMES_PER_SECTOR];
+       unsigned char outbuf[(LSUB_RAW+LSUB_Q+LSUB_P)*PACKETS_PER_SUBCHANNELFRAME +
+                       (L1_RAW+L1_Q+L1_P)*FRAMES_PER_SECTOR];
+       unsigned load_offset;
+
+       l1_inbuf = l2_inbuf = sub_inbuf = inbuf;
+       l1_outbuf = l2_outbuf = sub_outbuf = last_outbuf = outbuf;
+
+       infp = fopen("sectors_in", "rb");
+       outfp = fopen("sectors_out", "wb");
+
+       sectortype= MODE_1;
+       address = 0 + 75*2;
+
+       switch (sectortype) {
+
+       case MODE_1:
+       case MODE_2:
+               load_offset = 16;
+               break;
+       case MODE_2_FORM_1:
+       case MODE_2_FORM_2:
+               load_offset = 24;
+               break;
+       default:
+               load_offset = 0;
+       }
+       while(1) {
+
+               if (1 != fread(inbuf+load_offset,
+                               sect_size[mask][encode], 1, infp)) {
+                       perror("");
+                       break;
+               }
+               if (encode == 1) {
+                       if (mask & DO_L2) {
+                               switch (sectortype) {
+
+                               case MODE_0:
+                                       break;
+                               case MODE_1:
+                                       break;
+                               case MODE_2:
+                                       if (1 !=
+                                         fread(inbuf+load_offset+
+                                               sect_size[mask][encode],
+                                         2336 - sect_size[mask][encode],
+                                               1, infp)) { perror(""); break; }
+                                       break;
+                               case MODE_2_FORM_1:
+                                       break;
+                               case MODE_2_FORM_2:
+                                       if (1 !=
+                                         fread(inbuf+load_offset+
+                                               sect_size[mask][encode],
+                                         2324 - sect_size[mask][encode],
+                                               1, infp)) { perror(""); break; }
+                                       break;
+                               default:
+                                       if (1 !=
+                                         fread(inbuf+load_offset+
+                                               sect_size[mask][encode],
+                                         2448 - sect_size[mask][encode],
+                                               1, infp)) { perror(""); break; }
+                                       memset(inbuf,0,16);
+                                       /*memset(inbuf+16+2048,0,12+272);*/
+                                       break;
+                               }
+                               do_encode_L2(l2_inbuf, MODE_1, address);
+                               if (0) scramble_L2(l2_inbuf);
+                               last_outbuf = l1_inbuf = l2_inbuf;
+                               l1_outbuf = l2_inbuf;
+                               sub_inbuf = l2_inbuf + L2_RAW;
+                               sub_outbuf = l2_outbuf + 12 + 4+ L2_RAW+4+ 8+ L2_Q+L2_P;
+                       }
+                       if (mask & DO_L1) {
+                               do_encode_L1(l1_inbuf, l1_outbuf,1,1,1,1);
+                               last_outbuf = l1_outbuf;
+                               sub_inbuf = l1_inbuf + L1_RAW*FRAMES_PER_SECTOR;
+                               sub_outbuf = l1_outbuf + (L1_RAW+L1_Q+L1_P)*FRAMES_PER_SECTOR;
+                       }
+                       if (mask & DO_SUB) {
+                               do_encode_sub(sub_inbuf, sub_outbuf, 0, 0);
+                       }
+               } else {
+                       if (mask & DO_L1) {
+                               do_decode_L1(l1_inbuf, l1_outbuf,1,1,1,1);
+                               last_outbuf = l2_inbuf = l1_outbuf;
+                               l2_outbuf = l1_inbuf;
+                               sub_inbuf = l1_inbuf + (L1_RAW+L1_Q+L1_P)*FRAMES_PER_SECTOR;
+                               sub_outbuf = l1_outbuf + L1_RAW*FRAMES_PER_SECTOR;
+                       }
+                       if (mask & DO_L2) {
+                               do_decode_L2(l2_inbuf, l2_outbuf);
+                               last_outbuf = l2_outbuf;
+                               sub_inbuf = l2_inbuf + L2_RAW+L2_Q+L2_P;
+                               sub_outbuf = l2_outbuf + L2_RAW;
+                       }
+                       if (mask & DO_SUB) {
+                               do_decode_sub(sub_inbuf, sub_outbuf, 1, 1);
+                       }
+               }
+               if (1 != fwrite(last_outbuf, sect_size[mask][1 - encode], 1, outfp)) {
+                       perror("");
+                       break;
+               }
+               address++;
+       }
+#if 0
+       /* flush the data from the delay lines with zeroed sectors, if necessary */
+#endif
+       return (0);
+}
+#endif
diff --git a/libedc/edcspeed.c b/libedc/edcspeed.c
new file mode 100644 (file)
index 0000000..d72ff6b
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+#include <mconfig.h>
+#include <stdio.h>
+#include <standard.h>
+#include <stdxlib.h>
+#include <timedefs.h>
+#include <strdefs.h>
+
+#define        Uchar   unsigned char
+
+static int encspeed(void);
+
+static int encspeed()
+{
+       register Uchar  *sect;
+       register int    i;
+       register int    end;
+       register int    secs;
+       struct  timeval tv;
+       struct  timeval tv2;
+
+       sect = malloc(2352);
+
+       secs = 10;
+       end = 75*1000000 * secs;
+
+       memset(sect, 0, sizeof(sect));
+       for (i=0; i < 2352; ) {
+               sect[i++] = 'J';
+               sect[i++] = 'S';
+       }
+
+       gettimeofday(&tv, (struct timezone *)0);
+       for (i=0; i < end; i++) {
+#ifdef OLD_LIBEDC
+               do_encode_L2(sect, 1, 1);
+               scramble_L2(sect);
+#else
+
+/*             lec_encode_mode1_sector(12345, sect);*/
+/*             lec_scramble(sect);*/
+#endif
+/*             if ((i & 31) == 0) {*/
+               if (1) {
+                       gettimeofday(&tv2, (struct timezone *)0);
+                       if (tv2.tv_sec >= (tv.tv_sec+secs) &&
+                           tv2.tv_usec >= tv.tv_usec)
+                               break;
+               }
+       }
+       printf("%d sectors/%ds\n", i, secs);
+       printf("%d sectors/s\n", i/secs);
+       printf("speed: %5.2fx\n", (1.0*i)/750.0);
+       return ((i+74)/75) / secs ;
+}
+
+int main(int argc, char *argv[])
+{
+/*     lec_init();*/
+
+/*     printf("speed: %d\n",  encspeed());*/
+       encspeed();
+       return (0);
+}
diff --git a/libedc/encoder_tables b/libedc/encoder_tables
new file mode 100644 (file)
index 0000000..7b46485
--- /dev/null
@@ -0,0 +1,47 @@
+/* @(#)encoder_tables  1.4 02/10/19 */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+static const unsigned char rs_l12_alog[255] = {
+ 1, 2, 4, 8,16,32,64,128,29,58,116,232,205,135,19,38,76,152,45,90,180,117,234,201,143, 3, 6,12,24,48,96,192,157,39,78,156,37,74,148,53,106,212,181,119,238,193,159,35,70,140, 5,10,20,40,80,160,93,186,105,210,185,111,222,161,95,190,97,194,153,47,94,188,101,202,137,15,30,60,120,240,253,231,211,187,107,214,177,127,254,225,223,163,91,182,113,226,217,175,67,134,17,34,68,136,13,26,52,104,208,189,103,206,129,31,62,124,248,237,199,147,59,118,236,197,151,51,102,204,133,23,46,92,184,109,218,169,79,158,33,66,132,21,42,84,168,77,154,41,82,164,85,170,73,146,57,114,228,213,183,115,230,209,191,99,198,145,63,126,252,229,215,179,123,246,241,255,227,219,171,75,150,49,98,196,149,55,110,220,165,87,174,65,130,25,50,100,200,141, 7,14,28,56,112,224,221,167,83,166,81,162,89,178,121,242,249,239,195,155,43,86,172,69,138, 9,18,36,72,144,61,122,244,245,247,243,251,235,203,139,11,22,44,88,176,125,250,233,207,131,27,54,108,216,173,71,142,};
+static const unsigned char rs_l12_log[256] = {
+ 0, 0, 1,25, 2,50,26,198, 3,223,51,238,27,104,199,75, 4,100,224,14,52,141,239,129,28,193,105,248,200, 8,76,113, 5,138,101,47,225,36,15,33,53,147,142,218,240,18,130,69,29,181,194,125,106,39,249,185,201,154, 9,120,77,228,114,166, 6,191,139,98,102,221,48,253,226,152,37,179,16,145,34,136,54,208,148,206,143,150,219,189,241,210,19,92,131,56,70,64,30,66,182,163,195,72,126,110,107,58,40,84,250,133,186,61,202,94,155,159,10,21,121,43,78,212,229,172,115,243,167,87, 7,112,192,247,140,128,99,13,103,74,222,237,49,197,254,24,227,165,153,119,38,184,180,124,17,68,146,217,35,32,137,46,55,63,209,91,149,188,207,205,144,135,151,178,220,252,190,97,242,86,211,171,20,42,93,158,132,60,57,83,71,109,65,162,31,45,67,216,183,123,164,118,196,23,73,236,127,12,111,246,108,161,59,82,41,157,85,170,251,96,134,177,187,204,62,90,203,89,95,176,156,169,160,81,11,245,22,235,122,117,44,215,79,174,213,233,230,231,173,232,116,214,244,234,168,80,88,175,};
+static const unsigned char rs_sub_rw_alog[63] = {
+ 1, 2, 4, 8,16,32, 3, 6,12,24,48,35, 5,10,20,40,19,38,15,30,60,59,53,41,17,34, 7,14,28,56,51,37, 9,18,36,11,22,44,27,54,47,29,58,55,45,25,50,39,13,26,52,43,21,42,23,46,31,62,63,61,57,49,33,};
+static const unsigned char rs_sub_rw_log[63] = {
+ 0, 0, 1, 6, 2,12, 7,26, 3,32,13,35, 8,48,27,18, 4,24,33,16,14,52,36,54, 9,45,49,38,28,41,19,56, 5,62,25,11,34,31,17,47,15,23,53,51,37,44,55,40,10,61,46,30,50,22,39,43,29,60,42,21,20,59,57,};
+static const unsigned char SQ[2][2] = {
+{26,6,},
+{7,1,},
+};
+static const unsigned char SP[4][20] = {
+{57,38,44,29,17,57,53,58,60,39,12,38,18,41,6,25,39,37,5,18,},
+{38,62,42,13,30,11,46,5,54,26,12,49,48,46,8,50,28,9,12,39,},
+{32,18,41,49,52,62,38,36,39,58,37,24,34,51,51,27,28,36,22,21,},
+{44,50,35,23,0,59,1,3,45,18,44,24,47,12,31,45,43,11,24,6,},
+};
+static const unsigned char AQ[4][24] = {
+{58,152,173,95,88,43,134,205,143,131,163,75,37,109,194,159,168,227,153,59,101,},
+{30,214,148,138,112,154,157,96,49,198,189,249,83,23,70,237,70,41,47,52,125,247,},
+{162,244,13,171,213,236,71,177,253,162,59,78,46,68,238,112,147,197,115,200,117,15,236,},
+{158,179,101,94,49,140,211,149,137,169,81,6,33,30,27,24,21,18,15,12,9,6,3,0,},
+};
+static const unsigned char AP[4][32] = {
+{140,143,52,103,249,142,180,197,5,155,153,132,143,244,101,76,102,155,203,104,58,152,173,95,88,43,134,205,143,131,163,75,},
+{104,97,17,162,205,252,218,199,202,41,136,106,119,238,193,103,123,242,83,178,30,214,148,138,112,154,157,96,49,198,189,249,},
+{240,119,29,185,67,11,131,40,7,41,80,147,151,17,245,253,208,66,228,116,162,244,13,171,213,236,71,177,253,162,59,78,},
+{149,58,109,0,148,186,203,11,161,159,138,149,250,107,82,108,161,209,110,64,158,179,101,94,49,140,211,149,137,169,81,6,},
+};
diff --git a/libedc/l2sq_table b/libedc/l2sq_table
new file mode 100644 (file)
index 0000000..29ab0cd
--- /dev/null
@@ -0,0 +1,1180 @@
+/* @(#)l2sq_table      1.2 02/10/19 Copyright 2002 J. Schilling */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+static const unsigned short L2sq[43][256] = {
+{0,44719,16707,61420,33414,11305,50117,28010,6417,47038,
+   22610,63229,39831,13624,56020,29819,12834,40077,29537,56782,
+   45220,7691,61927,24392,11059,34204,27248,50399,43445,1818,
+   59638,18009,25668,51947,9479,35752,59074,18541,42881,2350,
+   32085,54266,15382,37561,65491,20860,48784,4159,22118,63689,
+   5925,47498,54496,31311,38307,15116,20343,57816,3636,41115,
+   52721,25438,36018,8733,51336,26151,35275,10084,18958,58529,
+   2893,42466,53657,32566,37082,15989,21279,64944,4700,48371,
+   64170,21509,48105,5446,30764,54915,14703,38848,58299,19732,
+   41720,3159,24893,53138,8318,36561,44236,611,60815,17184,
+   11850,32997,28425,49574,46557,7026,62622,23089,14171,39412,
+   30232,55479,40686,12353,57261,28930,7272,45767,23851,62340,
+   34815,10576,50876,26643,1401,43990,17466,60053,36109,9122,
+   52302,25313,3979,41252,20168,57447,37916,15027,54623,31728,
+   5786,47157,22489,63862,48943,4480,65132,20675,15785,37638,
+   31978,53829,42558,2193,59261,18898,9400,35351,26107,52052,
+   59721,18406,43018,1701,27599,50528,10892,33827,61528,24311,
+   45339,8116,29406,56433,13213,40242,56171,30148,39464,13447,
+   23021,63298,6318,46593,49786,27861,33593,11670,16636,61011,
+   447,44816,17797,60202,1222,43625,50947,27052,34368,10479,
+   23700,62011,7639,45944,56850,28861,40785,12798,30631,55560,
+   14052,38987,62753,23438,46178,6861,28342,49177,12277,33114,
+   60464,17055,44403,988,8641,36718,24706,52781,41799,3560,
+   57860,19627,14544,38527,31123,55100,47702,5369,64277,21946,
+   5091,48460,21152,64527,37221,16330,53286,32393,2802,42077,
+   19377,58654,34932,9947,51511,26520,
+},
+{0,55768,44973,30325,17223,39583,60650,13618,34446,24406,
+   10531,61691,50633,7185,27236,46012,4353,51417,48812,26484,
+   21062,35742,65003,9267,38799,20055,14370,57850,54472,3344,
+   31589,41661,8706,64474,36271,21623,24901,47261,52968,5936,
+   42124,32084,2849,54009,59339,15891,18534,37310,13059,60123,
+   40110,17782,28740,43420,57321,1585,46477,27733,6688,50168,
+   63178,12050,22887,32959,17412,40412,60329,12913,1859,56987,
+   43246,28982,49802,6994,27943,46335,33229,22549,11872,63416,
+   21765,36061,64168,9072,5698,53146,47599,24631,54155,2643,
+   31782,42494,37068,18708,16225,59065,26118,49118,51627,4211,
+   9537,64665,35564,21300,57480,14672,20261,38653,41935,31255,
+   3170,54714,30471,44767,55466,370,13376,60824,39917,16949,
+   61833,10321,24100,34812,45774,27414,7523,50363,34824,20944,
+   10149,65149,52047,4759,25826,48442,3718,55134,41259,30963,
+   19905,37913,57964,15284,39177,16593,13988,61308,55886,918,
+   30179,44091,8071,50783,45098,27122,23744,34072,62317,10933,
+   43530,29650,1447,56447,59725,12437,18144,40760,11396,62812,
+   33577,23281,28611,46619,49262,6582,47883,25299,5286,52606,
+   63564,8596,22497,36409,15749,58461,37416,19440,32450,42778,
+   53615,2231,52236,5588,25505,47737,36683,22163,8422,63806,
+   19074,37722,58671,15607,2501,53277,42600,32688,56589,1237,
+   29344,43896,40522,18322,12775,59455,23427,33371,62510,11766,
+   6340,49436,46953,28337,60942,14294,16803,39035,44361,29841,
+   740,56124,26752,45400,50989,7925,11207,61983,33898,23986,
+   65295,9943,20642,35194,48200,26000,5093,51773,31105,41049,
+   54828,4084,15046,58142,38251,19635,
+},
+{0,27757,55514,46263,44457,49604,30067,6430,18255,11042,
+   40853,62456,60134,34443,12860,24145,36510,58099,22084,14889,
+   9015,20314,64493,38784,51665,42428,4363,32102,25720,2069,
+   48290,53455,289,27980,55803,46486,44168,49381,29778,6207,
+   18030,10755,40628,62169,60359,34730,13085,24432,36799,58322,
+   22373,15112,8726,20091,64204,38561,51440,42141,4138,31815,
+   25945,2356,48515,53742,578,28207,55960,46837,45035,50054,
+   30513,7004,17677,10592,40407,61882,59556,33993,12414,23571,
+   36060,57521,21510,14443,8565,19736,63919,38338,52115,43006,
+   4937,32548,26170,2647,48864,53901,867,28430,56249,47060,
+   44746,49831,30224,6781,17452,10305,40182,61595,59781,34280,
+   12639,23858,36349,57744,21799,14666,8276,19513,63630,38115,
+   51890,42719,4712,32261,26395,2934,49089,54188,1156,26857,
+   56414,45107,43309,50496,29175,7578,17355,12198,39697,63356,
+   61026,33295,14008,23253,35354,58999,21184,16045,10163,19422,
+   65385,37636,52565,41272,5519,31202,24828,3217,47142,54347,
+   1445,27080,56703,45330,43020,50273,28886,7355,17130,11911,
+   39472,63069,61251,33582,14233,23540,35643,59222,21473,16268,
+   9874,19199,65096,37413,52340,40985,5294,30915,25053,3504,
+   47367,54634,1734,27307,56860,45681,43887,50946,29621,8152,
+   16777,11748,39251,62782,60448,32845,13562,22679,34904,58421,
+   20610,15599,9713,18844,64811,37190,53015,41850,6093,31648,
+   25278,3795,47716,54793,2023,27530,57149,45904,43598,50723,
+   29332,7929,16552,11461,39026,62495,60673,33132,13787,22966,
+   35193,58644,20899,15822,9424,18621,64522,36967,52790,41563,
+   5868,31361,25503,4082,47941,55080,
+},
+{0,47289,28015,54742,56030,25191,47025,3848,43425,4376,
+   50382,31863,29567,52166,7696,42665,20319,63462,8752,39561,
+   38273,11576,63726,16471,59134,24135,35729,13096,15392,33945,
+   20815,59894,40638,9735,62417,19304,17504,64729,10511,37302,
+   14111,36774,23152,58057,60865,21880,32942,14359,53729,26968,
+   48270,1079,2879,45958,26192,57065,30784,49401,5423,44438,
+   41630,6695,53233,30536,8545,39384,19470,62647,64447,17158,
+   38608,11881,35008,12409,58799,23830,21022,60071,16241,34760,
+   28222,54919,849,48104,46304,3161,55695,24886,51103,32550,
+   43760,4681,7489,42488,28718,51351,49119,1894,53936,27145,
+   25857,56760,2158,45271,5758,44743,31505,50088,52384,29721,
+   41423,6518,61568,18489,40431,9558,10846,37607,18225,65416,
+   22817,57752,13390,36087,33791,15174,61072,22057,17090,64123,
+   12205,38676,38940,8357,62835,19914,60259,21466,34316,16053,
+   12733,35076,23762,58475,3485,46372,24818,55371,55107,28666,
+   47660,661,42044,7301,51539,29162,32482,50779,5005,43828,
+   56444,25797,45331,2474,1698,48667,27597,54132,30173,52580,
+   6322,40971,44803,6074,49772,31445,37667,11162,65100,18165,
+   18941,61764,9362,39979,14978,33339,22509,61268,57436,22757,
+   36147,13706,25507,56090,3788,46709,47485,452,54290,27819,
+   51714,29371,42861,8148,4316,43109,32179,50442,11516,37957,
+   16787,63786,63010,20123,39757,9204,34141,15844,59442,20619,
+   24451,59194,13036,35413,64797,17828,36978,10443,10179,40826,
+   19116,61973,21692,60421,14803,33130,36450,14043,58125,23476,
+   45634,2811,57133,26516,26780,53285,1523,48458,7139,41818,
+   30348,52789,49469,31108,44114,5355,
+},
+{0,53971,47547,27496,28523,48568,54992,1027,57046,3077,
+   26477,46526,45501,25454,2054,56021,41393,29538,6154,51929,
+   52954,7177,30561,42418,32615,44468,50908,5135,4108,49887,
+   43447,31588,24447,36268,59076,13335,12308,58055,35247,23420,
+   33193,21370,14354,60097,61122,15377,22393,34218,65230,11293,
+   18293,38310,37285,17270,10270,64205,8216,62155,39331,19312,
+   20339,40352,63176,9243,48894,27693,1861,54678,53653,838,
+   26670,47869,24616,45819,55699,2880,3907,56720,46840,25643,
+   8015,52636,42740,29735,28708,41719,51615,6988,49561,4938,
+   30754,43761,44786,31777,5961,50586,57729,13138,22586,35561,
+   36586,23609,14161,58754,16215,60804,34540,21567,20540,33519,
+   59783,15188,16432,37603,63883,11096,12123,64904,38624,17459,
+   40678,19509,10077,62862,61837,9054,18486,39653,25057,45874,
+   55386,2697,3722,56409,46897,26082,48951,28132,1676,54367,
+   53340,655,27111,47924,49232,4739,31211,43832,44859,32232,
+   5760,50259,7814,52309,42813,30190,29165,41790,51286,6789,
+   16030,60493,34597,22006,20981,33574,59470,15005,57416,12955,
+   23027,35616,36643,24048,13976,58443,40751,19964,9876,62535,
+   61508,8855,18943,39724,16889,37674,63554,10897,11922,64577,
+   38697,17914,57119,3532,26276,46199,45172,25255,2511,56092,
+   457,54042,47218,27297,28322,48241,55065,1482,32430,44157,
+   50965,5574,4549,49942,43134,31405,41080,29355,6595,51984,
+   53011,7616,30376,42107,32864,21171,14811,60168,61195,15832,
+   22192,33891,24246,35941,59149,13790,12765,58126,34918,23221,
+   8657,62210,39018,19129,20154,40041,63233,9682,65287,11732,
+   18108,37999,36972,17087,10711,64260,
+},
+{0,59366,54225,13367,48063,23641,26734,36744,27491,35973,
+   47282,24404,53468,14138,781,58603,54982,12576,1303,58097,
+   28025,35487,48808,22862,48549,23107,28276,35218,1562,57852,
+   54731,12845,45457,22135,25152,34214,2606,60872,55807,15897,
+   56050,15636,2339,61125,24909,34475,45724,21882,26455,32945,
+   46214,21344,56552,15118,3897,59615,3124,60370,57317,14339,
+   46987,20589,25690,33724,32575,39129,44270,19208,50304,9062,
+   5969,61623,5212,62394,51085,8299,45027,18437,31794,39892,
+   43513,19999,31272,40398,4678,62880,49559,9841,49818,9596,
+   4427,63149,31013,40643,43764,19730,52910,10568,7551,64153,
+   29969,37623,42688,16678,42445,16939,30236,37370,7794,63892,
+   52643,10821,6248,65422,52153,11359,41943,17457,28678,38880,
+   29451,38125,41178,18236,51380,12114,7013,64643,65150,6552,
+   11695,51785,17857,41511,38416,29174,38173,29435,18124,41258,
+   11938,51524,64883,6805,10424,53086,64361,7311,37639,29921,
+   16598,42800,17371,42045,36874,30700,63588,8066,11189,52307,
+   20463,43017,39998,31704,62544,5046,10113,49255,9356,50026,
+   63325,4283,40755,30933,19682,43780,39209,32463,19192,44318,
+   8854,50544,61767,5793,62026,5548,8603,50813,18933,44563,
+   39460,32194,33089,26279,21136,46454,15102,56600,59695,3785,
+   59938,3524,14835,56853,20893,46715,33356,26026,22407,45153,
+   33878,25520,60472,3038,16361,55311,15588,56066,61237,2259,
+   34651,24765,21642,45932,12496,55094,58113,1255,35695,27785,
+   22718,48984,23475,48213,34914,28548,57356,2026,13277,54331,
+   58902,496,13767,53793,23977,47695,36472,27038,36213,27283,
+   24228,47426,14026,53548,58651,765,
+},
+{0,29554,59108,38294,53717,41639,14129,17475,49079,52421,
+   22867,10785,28258,7440,34950,64500,25459,4097,34199,63205,
+   45734,49620,21570,10032,56516,44982,14880,18770,3345,32355,
+   60405,39047,50918,46484,8194,21360,5939,25665,61911,33445,
+   31057,2595,40885,60615,43140,56310,20064,15634,42389,55015,
+   17265,12291,29760,1842,37540,57814,6690,26960,64710,36788,
+   52215,47237,11539,24161,37329,58019,30517,1095,16388,13174,
+   42720,54674,11878,23828,51330,48112,65459,36033,6487,27173,
+   62114,33232,5190,26420,9079,20485,50579,46817,19733,15975,
+   44017,55427,40128,61362,31268,2390,22327,9285,45523,49825,
+   34530,62864,24582,4980,59520,39922,3684,32022,14677,18983,
+   57265,44227,13380,18230,53920,41426,58769,38627,885,28679,
+   35827,63617,27927,7781,23078,10580,48322,53168,16319,19661,
+   55643,43561,61034,40216,2190,31740,32776,62330,26348,5534,
+   20957,8879,46905,50251,23756,12222,47656,51546,36121,65131,
+   27645,6287,58235,36873,1439,30445,12974,16860,54346,42808,
+   63833,35371,8125,27855,10380,23550,52840,48410,18158,13724,
+   40970,54136,38715,58441,29151,685,39466,59736,31950,4028,
+   19455,14477,44315,56937,9629,22255,50041,45067,62536,34618,
+   4780,25054,44654,56604,18570,15352,32699,3273,39263,59949,
+   4569,25259,63293,33871,49164,45950,9960,21914,52509,48751,
+   11257,22667,7368,28602,64044,35166,29354,472,37966,59196,
+   41855,53261,17819,14057,26760,7162,36460,64798,47453,51759,
+   24505,11467,55103,42061,12763,17065,1770,30104,57358,37756,
+   3067,30857,60703,40557,55854,43356,15562,20408,46156,51006,
+   21160,8666,26009,5867,33661,61455,
+},
+{0,14648,29296,19272,58592,56792,38544,44968,54749,60645,
+   42925,40597,12605,2053,17229,31349,47015,36511,50647,64751,
+   21319,27263,8503,6159,25210,23362,4106,10546,34458,49058,
+   62698,52690,29523,19051,291,14363,38835,44683,58819,56571,
+   42638,40886,54526,60870,17006,31574,12318,2342,50420,64972,
+   46724,36796,8212,6444,21092,27484,4393,10257,25433,23137,
+   62921,52465,34745,48769,59046,57246,38102,44526,582,15230,
+   28726,18702,13179,2627,16651,30771,55195,61091,42475,40147,
+   20737,26681,9073,6729,46561,36057,51089,65193,34012,48612,
+   63148,53140,24636,22788,4684,11124,38389,44237,59269,57021,
+   28949,18477,869,14941,16424,30992,12888,2912,42184,40432,
+   54968,61312,8786,7018,20514,26906,50866,65418,46274,36346,
+   63375,52919,34303,48327,4975,10839,24863,22567,53585,59497,
+   41761,39449,13745,3209,18369,32505,1164,15796,30460,20420,
+   57452,55636,37404,43812,26358,24526,5254,11710,33302,47918,
+   61542,51550,45867,35347,49499,63587,22475,28403,9659,7299,
+   41474,39738,53362,59722,18146,32730,13458,3498,30687,20199,
+   1455,15511,37695,43527,57679,55415,5541,11421,26581,24301,
+   61765,51325,33589,47629,49272,63808,45576,35632,9368,7584,
+   22248,28624,14327,3791,17799,31935,54039,59951,41319,39007,
+   57898,56082,36954,43362,1738,16370,29882,19842,32848,47464,
+   61984,51992,25776,23944,5824,12280,21901,27829,10237,7877,
+   45421,34901,49949,64037,17572,32156,14036,4076,41028,39292,
+   53812,60172,37241,43073,58121,55857,30105,19617,2025,16081,
+   62211,51771,33139,47179,6115,11995,26003,23723,9950,8166,
+   21678,28054,49726,64262,45134,35190,
+},
+{0,7197,14394,9255,28788,27753,18510,21587,57576,64757,
+   55506,50383,37020,35969,43174,46267,56781,49616,58871,63978,
+   44473,45476,38275,35230,15653,8504,1311,6402,19793,20812,
+   30059,26998,42887,48026,40893,33696,55283,52206,61385,62420,
+   18287,23410,32597,25416,14107,11014,3873,4924,31306,26199,
+   17008,24173,2622,5667,12804,11801,39586,34495,41624,48773,
+   60118,63179,53996,52977,21267,20238,27433,30516,9063,16250,
+   7005,1856,46075,45030,35777,38876,50063,57234,64437,59304,
+   36574,37571,46820,43769,65194,58039,50832,55949,28214,29227,
+   22028,18961,7746,607,9848,14949,62612,59529,52398,53427,
+   34016,39165,48346,41159,5244,2145,11334,12379,25608,30741,
+   23602,16431,10585,13636,4451,3454,22829,17712,24855,32010,
+   51633,54700,61835,60822,47557,42456,33279,40418,42534,47675,
+   40476,33281,54866,51791,61032,62069,18126,23251,32500,25321,
+   14010,10919,3712,4765,31723,26614,17361,24524,2975,6018,
+   13221,12216,39683,34590,41785,48932,60279,63338,54093,53072,
+   417,7612,14747,9606,29141,28104,18927,22002,57673,64852,
+   55667,50542,37181,36128,43271,46362,56428,49265,58454,63563,
+   44056,45061,37922,34879,15492,8345,1214,6307,19696,20717,
+   29898,26839,62773,59688,52495,53522,34113,39260,48507,41318,
+   5597,2496,11751,12794,26025,31156,23955,16782,10488,13541,
+   4290,3295,22668,17553,24758,31915,51216,54285,61482,60471,
+   47204,42105,32862,40003,21170,20143,27272,30357,8902,16091,
+   6908,1761,45658,44615,35424,38525,49710,56883,64020,58889,
+   36735,37730,46917,43864,65291,58134,50993,56108,28567,29578,
+   22445,19376,8163,1022,10201,15300,
+},
+{0,32897,7455,40350,14910,47807,10017,42912,29820,62717,
+   26979,59874,20034,52931,21341,54236,59640,26745,62951,30054,
+   53958,21063,53209,20312,40068,7173,33179,282,42682,9787,
+   48037,15140,52717,19820,53490,20595,63443,30546,60108,27213,
+   47505,14608,42126,9231,33711,814,40624,7729,9493,42388,
+   14346,47243,7979,40874,564,33461,20841,53736,19574,52471,
+   27479,60374,30280,63177,34759,1862,39640,6745,48633,15736,
+   41190,8295,62395,29498,61092,28197,51589,18692,54426,21531,
+   28479,61374,29216,62113,21761,54656,18462,51359,6979,39874,
+   1628,34525,8573,41468,15458,48355,18986,51883,22325,55220,
+   28692,61589,27915,60810,15958,48855,9033,41928,1128,34025,
+   6519,39414,41682,8787,49101,16204,39148,6253,34291,1394,
+   54958,22063,52145,19248,60560,27665,61839,28942,5011,37650,
+   3724,36365,10669,43308,13490,46131,26607,59246,31472,64113,
+   24017,56656,16590,49231,64363,31722,58996,26357,49493,16852,
+   56394,23755,36631,3990,37384,4745,46377,13736,43062,10423,
+   56958,24319,50017,17376,58432,25793,63839,31198,43522,10883,
+   46877,14236,36924,4285,36131,3490,13958,46599,11161,43800,
+   3256,35897,4519,37158,17146,49787,24549,57188,30916,63557,
+   26075,58714,37972,5333,35147,2506,44650,12011,45941,13300,
+   57384,24745,64823,32182,55830,23191,50953,18312,31916,64557,
+   25011,57650,18066,50707,23437,56076,2256,34897,5583,38222,
+   13038,45679,12273,44912,22969,55608,17574,50215,25479,58118,
+   32408,65049,11717,44356,12506,45147,6139,38778,2788,35429,
+   45377,12736,44126,11487,35711,3070,38496,5857,50493,17852,
+   55330,22691,65283,32642,57884,25245,
+},
+{0,52943,33155,20300,7963,53716,40600,20567,15926,61689,
+   49077,29050,8493,61410,41134,28257,31852,45731,65007,13088,
+   25463,44472,58100,11323,16986,35989,50137,3350,23873,37774,
+   56514,4621,63704,13847,31067,46996,59331,10508,26176,43151,
+   50926,2081,18285,35234,55797,5946,22646,38585,33972,19067,
+   1335,52216,39855,21856,6700,54499,47746,29773,15105,62926,
+   42393,27478,9242,60117,60845,9058,27694,41697,62134,15481,
+   29493,48634,54171,7508,21016,40151,52352,591,19715,33740,
+   37313,24334,4162,56973,36570,16405,3929,49558,45047,24888,
+   11892,57531,45292,32291,12655,65440,5493,56250,38134,23097,
+   2670,50337,35821,17698,11075,58764,43712,25615,13400,64151,
+   46555,31508,26905,42966,59546,9813,30210,47309,63361,14670,
+   22319,39392,54956,6243,18484,34555,51639,1912,51015,2440,
+   18116,34827,55388,5779,23007,38672,63857,14270,30962,46653,
+   58986,10405,26601,43302,47915,30180,15016,62567,42032,27391,
+   9651,60284,34077,19410,1182,51793,39430,21705,7045,54602,
+   16287,61776,48668,28883,8324,61003,41223,28616,425,53094,
+   32810,20197,7858,53373,40753,20990,17395,36156,49776,3263,
+   23784,37415,56683,5028,32197,45834,64582,12937,25310,44049,
+   58205,11666,10986,58405,43881,26022,13809,64318,46194,31421,
+   5340,55827,38239,23440,3015,50440,35396,17547,22150,38985,
+   55045,6602,18845,34642,51230,1745,26800,42623,59699,10236,
+   30635,47460,63016,14567,53810,7421,21425,40318,52521,998,
+   19626,33381,60420,8907,28039,41800,62239,15824,29340,48211,
+   44638,24721,12253,57618,45381,32650,12486,65033,36968,24231,
+   4587,57124,36723,16828,3824,49215,
+},
+{0,59880,53197,9765,33671,27247,19530,42402,6931,62203,
+   54494,15670,39060,29052,22361,48817,13862,57294,63979,4099,
+   46497,23625,31340,37764,11573,50397,58104,2832,44722,18266,
+   24959,34967,27724,34212,41857,19049,61387,1571,8198,51694,
+   30559,40631,47250,20858,62680,7472,15125,54013,23146,45954,
+   38311,31823,55789,12293,5664,65480,16761,43153,36532,26460,
+   49918,11030,3379,58587,55448,12656,5973,65213,23327,45815,
+   38098,32058,50059,10851,3142,58798,16396,43492,36801,26153,
+   61118,1878,8563,51355,27961,34001,41716,19228,62893,7237,
+   14944,54152,30250,40898,47591,20495,46292,23868,31513,37617,
+   14163,57019,63646,4470,44999,17967,24586,35298,11328,50600,
+   58253,2661,33522,27418,19775,42199,373,59549,52920,10064,
+   39393,28681,22060,49092,6758,62350,54699,15427,44333,17605,
+   25312,35592,11946,51010,57703,2191,46654,24534,31219,36891,
+   13753,56401,64116,5020,39691,29411,21702,48430,6284,61796,
+   55105,16041,32792,27120,20437,42557,927,60023,52306,9658,
+   49505,10377,3756,59204,17126,43790,36139,25795,55922,13210,
+   5567,64599,23029,45085,38456,32720,63303,7855,14474,53602,
+   29888,40232,47885,21221,60500,1468,9113,51825,28627,34363,
+   40990,18934,30133,40029,47736,21392,63026,8154,14847,53271,
+   28326,34638,41323,18563,60705,1225,8940,51972,17299,43643,
+   35934,26038,49172,10748,4057,58929,22656,45416,38733,32421,
+   56071,13039,5322,64802,6649,61457,54836,16348,39550,29590,
+   21939,48219,746,60162,52519,9423,33133,26757,20128,42824,
+   12255,50743,57362,2554,44120,17840,25493,35453,13516,56612,
+   64257,4841,46923,24227,30854,37230,
+},
+{0,29813,59626,40095,52681,47548,9507,20822,34703,62458,
+   28517,6928,19014,15923,41644,55001,4867,26486,64489,36764,
+   57034,43711,13856,16981,38028,57593,31846,2067,22853,11568,
+   45487,50650,9734,21107,52972,47769,60367,40890,805,30544,
+   41353,54780,18787,15638,27712,6197,33962,61663,13573,16752,
+   56815,43418,63692,36025,4134,25683,45706,50943,23136,11797,
+   32579,2870,38825,58332,19468,14457,42214,53395,33221,62896,
+   26927,7514,52099,49142,9065,22300,1610,29247,61088,39637,
+   24335,11130,47077,50064,37574,59059,31276,3673,55424,44277,
+   12394,17439,5449,24892,64931,35286,27146,7807,33504,63125,
+   42947,54198,20265,15196,60805,39408,1391,28954,8268,21561,
+   51366,48339,30985,3452,37347,58774,46272,49333,23594,10335,
+   65158,35571,5740,25113,13135,18234,56229,45008,38936,60525,
+   28914,1159,21969,8612,48443,51534,8087,27618,63357,33544,
+   53854,42539,15028,20161,35611,65390,25585,6020,18130,12967,
+   44600,55885,3220,30945,58494,36875,49501,46376,10679,24002,
+   48670,51819,22260,8833,29655,1954,39741,61256,14737,19940,
+   53627,42254,62552,32813,7346,26823,44317,55656,17911,12674,
+   24788,5281,34878,64587,10898,24295,49784,46605,59227,37678,
+   4017,31684,54292,41057,15614,18571,6621,28072,61751,34114,
+   21403,10222,47985,52996,40530,59943,30392,717,50967,45922,
+   12285,23432,2782,32427,57908,38465,16536,13549,43122,56327,
+   36177,63780,26043,4558,61970,34407,6904,28301,16347,19374,
+   55089,41796,30109,488,40311,59650,47188,52257,20670,9419,
+   57617,38244,2555,32142,11480,22701,50226,45127,26270,4843,
+   36468,64001,43863,57122,17341,14280,
+},
+{0,46261,30071,49602,60142,24155,40857,11052,51649,32116,
+   48310,2051,9007,38810,22104,58093,36767,15146,64232,20061,
+   25969,53700,4102,42163,18014,62187,13097,34716,44208,6149,
+   55751,28018,803,46998,30292,49889,59853,23928,40122,10255,
+   51938,32343,49045,2848,8204,38073,21883,57806,36028,14345,
+   63947,19838,26194,53991,4901,42896,17789,61896,12298,33983,
+   44947,6950,56036,28241,1606,45811,29489,51076,60584,22557,
+   39391,11626,53127,31538,47856,3653,9577,37340,20510,58539,
+   35289,15724,64686,18459,25399,55170,5696,41717,16408,62637,
+   13679,33242,43766,7747,57217,27444,1381,45520,28690,50343,
+   61323,23358,39676,11849,52388,30737,47571,3430,9802,37631,
+   21309,59272,35578,15951,65421,19256,24596,54433,5475,41430,
+   17211,63374,13900,33529,43477,7520,56482,26647,3212,47161,
+   31227,52558,58978,21207,37653,10144,50509,29176,45114,1167,
+   12195,39702,23252,61025,33555,14246,63076,17105,27133,56648,
+   7306,43071,19154,65127,16293,35600,41020,5257,54603,25086,
+   4015,47898,31448,52845,58689,20980,36918,9347,50798,29403,
+   45849,1964,11392,38965,23031,60738,32816,13445,62791,16882,
+   27358,56939,8105,43804,18929,64836,15494,34867,41759,6058,
+   54888,25309,2762,48767,32701,51976,57380,21649,38227,8678,
+   49931,30654,46716,713,10725,40272,23698,59431,34133,12768,
+   61474,17559,28603,56078,6860,44665,19604,63521,14819,36182,
+   42618,4815,54029,26552,2537,48476,31902,51243,58119,22450,
+   38512,8901,49192,29853,46431,490,10950,40563,24497,60164,
+   34422,12995,62209,18356,27800,55341,6639,44378,20407,64258,
+   15040,36469,42329,4588,53294,25755,
+},
+{0,54485,46519,24930,30579,41894,49860,5649,61158,14899,
+   23377,36740,39317,19776,11298,63735,49617,5380,29798,41139,
+   46754,25207,789,55232,12087,64482,39552,20053,22596,35985,
+   60915,14630,40895,19306,10760,65245,59596,15385,23931,35246,
+   29017,42380,50414,4155,1578,54015,45981,26440,24174,35515,
+   60377,16140,10525,64968,40106,18559,45192,25693,1343,53738,
+   51195,4910,29260,42649,9059,63414,38612,16897,21520,32965,
+   57767,13682,52613,6480,30770,44263,47862,28195,3905,56212,
+   58034,13927,22277,33744,38337,16660,8310,62627,3156,55425,
+   47587,27958,31527,45042,52880,6725,48348,26633,2411,56766,
+   52143,8058,32280,43725,21050,34543,59277,13144,9545,61852,
+   37118,17451,32013,43480,51386,7279,2686,57003,49097,27420,
+   37867,18238,9820,62089,58520,12365,20783,34298,18118,37395,
+   62321,10148,12725,58720,33794,20695,43040,31989,7575,51522,
+   57171,2950,27364,48689,34583,21442,12960,58997,61540,9393,
+   17875,37126,27121,48420,56390,2195,7810,51799,43829,32736,
+   55673,3500,27854,47131,44554,31455,7101,53096,14239,58186,
+   33320,22269,16620,37945,62811,8590,6312,52349,44319,31178,
+   28635,47886,55916,3769,63054,8859,17401,38700,33085,21992,
+   13450,57439,26021,45424,53266,1223,4822,50691,42849,29620,
+   35651,24470,16116,59937,64560,10469,18823,40274,42100,28833,
+   4547,50454,54023,2002,26288,45669,19090,40519,65317,11248,
+   15841,59700,34902,23683,64026,11983,20397,39800,36201,22972,
+   14558,60427,5372,49193,41291,30110,25487,46938,54840,749,
+   15307,61214,36476,23209,19640,39021,63759,11738,54573,504,
+   24730,46159,41566,30347,6121,49980,
+},
+{0,58597,54743,12594,47027,21334,25188,34433,29563,38814,
+   42668,16969,50376,8237,4383,62970,59126,531,13089,55236,
+   20805,46496,33938,24695,38285,29032,16474,42175,8766,50907,
+   63465,4876,53745,13588,1062,57539,26178,33447,45973,22384,
+   41610,18031,30557,37816,5433,61916,49390,9227,14087,54242,
+   58064,1589,32948,25681,21859,45446,17532,41113,37291,30030,
+   62415,5930,9752,49917,49151,23322,27176,36557,2124,60585,
+   56731,14718,52356,10337,6483,64950,31543,40914,44768,18949,
+   22793,48620,36062,26683,61114,2655,15213,57224,10866,52887,
+   65445,6976,40385,31012,18454,44275,28174,35563,48089,24380,
+   55741,15704,3178,59535,7541,63888,51362,11335,43718,20003,
+   32529,39924,35064,27677,23855,47562,16203,56238,60060,3705,
+   64387,8038,11860,51889,19504,43221,39399,32002,25571,34566,
+   46644,21201,54352,12469,391,58722,4248,62589,50511,8618,
+   42795,17358,29436,38425,34069,25072,20674,46119,12966,54851,
+   59249,916,63086,4747,9145,51036,16861,42296,37898,28911,
+   45586,22263,26565,33568,1441,57668,53366,13459,49513,9612,
+   5310,61531,30426,37439,41741,18408,21732,45057,33075,26070,
+   58199,1970,13952,53861,10143,50042,62024,5805,36908,29897,
+   17915,41246,56348,14585,2507,60718,27567,36682,48760,23197,
+   44903,19330,31408,40533,6356,64561,52483,10726,15082,56847,
+   61245,3032,36185,27068,22670,48235,18833,44404,40006,30883,
+   65058,6855,11253,53008,3565,59656,55354,15583,47710,24251,
+   28553,35692,32406,39539,43841,20388,51493,11712,7410,63511,
+   60187,4094,16076,55849,23720,47181,35199,28058,39008,31877,
+   19895,43346,12243,52022,64004,7905,
+},
+{0,64765,58855,6426,55251,11054,12852,52937,46011,20294,
+   22108,43681,25704,39061,33167,32114,31595,34710,40588,25201,
+   44216,20549,18783,46498,51408,13357,11575,53706,7939,58366,
+   64228,1561,63190,2603,4913,61388,8453,56824,50402,14367,
+   17773,47504,41098,23671,37566,28227,30553,35748,36285,28992,
+   26714,38055,23150,42643,49033,17268,15878,49915,56289,10012,
+   59861,5416,3122,61647,61873,3404,5206,59563,9826,55967,
+   50053,16248,16906,48887,42989,23312,38361,26916,28734,36035,
+   35546,30247,28477,37824,23817,41460,47342,17427,14689,50588,
+   56454,8315,61106,4687,2901,63400,1895,64410,57984,7805,
+   53428,11337,13651,51630,46300,18465,20795,44486,25359,40946,
+   34536,31253,31756,33009,39403,25878,43999,22306,20024,45765,
+   53175,13130,10832,54957,6244,58521,64899,382,65407,898,
+   6808,58981,10412,54353,52555,12726,19652,45113,43299,21982,
+   39703,26602,32496,33293,33812,30953,25075,40206,21447,44858,
+   46624,19165,14255,52050,53832,11957,57468,7297,1435,63846,
+   2473,62804,60494,4275,56954,8839,15261,51040,47634,18159,
+   24565,41736,28097,37180,34854,29915,29378,36415,38693,27608,
+   42257,23020,16630,48139,49529,15748,9374,55395,5802,59991,
+   62285,4016,3790,62003,60201,6100,55581,9696,15610,49159,
+   48501,16776,22674,42095,27302,38491,36673,29628,30117,35160,
+   36930,27839,41590,24203,18321,47980,50718,15075,9209,57092,
+   4557,60720,62506,2263,63512,1253,7679,57602,12235,54070,
+   51756,14033,19363,46942,44612,21177,40048,24717,31127,34154,
+   33651,32654,26260,39529,21664,43101,45383,19898,12488,52277,
+   54575,10706,59163,7142,764,65025,
+},
+{0,61681,65023,3342,59363,5906,6684,60141,54235,9002,
+   11812,57045,13368,50377,51655,14646,48043,19290,18004,46757,
+   23624,44217,41399,20806,26736,39041,38287,25982,36755,32610,
+   29292,33437,27467,39866,38580,26181,36008,31833,29015,33190,
+   47248,18529,17775,46494,24435,44930,41612,21117,53472,8209,
+   11551,56814,14083,51186,51964,14861,827,62410,65220,3637,
+   58584,5161,6439,59862,54934,9831,11113,56216,12661,49540,
+   52362,15483,1357,62908,63666,2115,58030,4703,8017,61344,
+   27965,40396,37058,24627,35550,31279,30497,34768,48870,19991,
+   17177,46056,22789,43508,42234,21515,48605,19756,16418,45267,
+   23102,43727,42945,22320,28166,40695,37881,25352,35301,30996,
+   29722,34027,1654,63111,64393,2936,57749,4452,7274,60571,
+   54701,9564,10322,55459,12878,49855,53169,16192,45361,16832,
+   19662,48191,22226,42531,43821,23516,25322,37403,40725,28644,
+   34057,30200,30966,34823,2714,64107,63333,1940,60793,7560,
+   4230,57463,55617,10672,9406,54351,16034,52819,50013,13228,
+   55930,10891,10117,55156,15769,52584,49254,12439,2465,63824,
+   62558,1199,60994,7859,5053,58188,25041,37152,39982,27871,
+   34354,30403,31693,35644,45578,17147,20469,48900,21993,42264,
+   43030,22759,26535,38742,39512,27305,32836,28853,32187,36170,
+   46204,17549,18819,47474,21407,41838,44640,24209,56332,11517,
+   8691,53506,15343,51998,50704,14049,4055,65318,61992,729,
+   59444,6341,5579,58682,3308,64541,61715,482,60175,7166,
+   5872,58881,57143,12230,8904,53817,14548,51237,50475,13786,
+   46919,18358,19128,47689,20644,41045,44379,23978,25756,37997,
+   39267,27026,33663,29582,32384,36465,
+},
+{0,63223,61939,1796,65531,2316,3592,63743,58347,5404,
+   4632,58607,7184,60135,60899,6932,56267,11580,10808,56527,
+   9264,53959,54723,9012,14368,52951,51667,16164,51163,12588,
+   13864,49375,43915,23932,23160,44175,21616,41607,42371,21364,
+   18528,48791,47507,20324,47003,16748,18024,45215,28736,34487,
+   33203,30532,36795,31052,32328,35007,37803,25948,25176,38063,
+   27728,39591,40355,27476,19211,48636,47864,19471,46320,16903,
+   17667,46068,43232,24087,22803,45028,22299,41452,42728,20511,
+   37056,26167,24883,38852,28475,39372,40648,26687,29483,34268,
+   33496,29743,36048,31271,32035,35796,57472,5751,4467,59268,
+   8059,59788,61064,6271,875,62876,62104,1135,64656,2663,
+   3427,64404,15179,52668,51896,15439,50352,12871,13635,50100,
+   55456,11863,10579,57252,10075,53676,54952,8287,38422,24801,
+   26597,37138,27117,40730,38942,28393,30205,33546,33806,29433,
+   35334,31985,31733,36098,19933,47914,48174,19161,45606,17617,
+   17365,46370,44598,22721,24517,43314,20941,42810,41022,22217,
+   15773,52074,52334,15001,49766,13457,13205,50530,56950,10369,
+   12165,55666,8589,55162,53374,9865,58966,4257,6053,57682,
+   6573,61274,59486,7849,1469,62282,62542,697,64070,3249,
+   2997,64834,56605,11242,11502,55833,8934,54289,54037,9698,
+   16118,51201,52997,14834,49421,14330,12542,50697,1750,61473,
+   63269,466,63789,4058,2270,65065,58685,5066,5326,57913,
+   6854,60465,60213,7618,30358,32865,34661,29074,35181,32666,
+   30878,36457,38269,25482,25742,37497,27270,40049,39797,28034,
+   44381,23466,23726,43609,21158,42065,41813,21922,20150,47169,
+   48965,18866,45389,18362,16574,46665,
+},
+{0,62964,63477,513,62455,1539,1026,61942,64499,3591,
+   3078,63986,2052,65008,65521,2565,60411,7695,7182,59898,
+   6156,60920,61433,6669,4104,58876,59389,4617,58367,5643,
+   5130,57854,52203,15903,15390,51690,14364,52712,53225,14877,
+   12312,50668,51181,12825,50159,13851,13338,49646,8208,54756,
+   55269,8721,54247,9747,9234,53734,56291,11799,11286,55778,
+   10260,56800,57313,10773,35787,32319,31806,35274,30780,36296,
+   36809,31293,28728,34252,34765,29241,33743,30267,29754,33230,
+   24624,38340,38853,25137,37831,26163,25650,37318,39875,28215,
+   27702,39362,26676,40384,40897,27189,16416,46548,47061,16929,
+   46039,17955,17442,45526,48083,20007,19494,47570,18468,48592,
+   49105,18981,43995,24111,23598,43482,22572,44504,45017,23085,
+   20520,42460,42973,21033,41951,22059,21546,41438,2955,65151,
+   64638,2442,63612,3464,3977,64125,61560,1420,1933,62073,
+   911,63099,62586,398,57456,5508,6021,57969,4999,58995,
+   58482,4486,7043,61047,60534,6530,59508,7552,8065,60021,
+   49248,13716,14229,49761,13207,50787,50274,12694,15251,52839,
+   52326,14738,51300,15760,16273,51813,11163,56943,56430,10650,
+   55404,11672,12185,55917,53352,9628,10141,53865,9119,54891,
+   54378,8606,32832,30132,30645,33345,29623,34371,33858,29110,
+   31667,36423,35910,31154,34884,32176,32689,35397,27579,40527,
+   40014,27066,38988,28088,28601,39501,36936,26044,26557,37449,
+   25535,38475,37962,25022,19371,48735,48222,18858,47196,19880,
+   20393,47709,45144,17836,18349,45657,17327,46683,46170,16814,
+   41040,21924,22437,41553,21415,42579,42066,20902,23459,44631,
+   44118,22946,43092,23968,24481,43605,
+},
+{0,31355,62710,36493,62961,36746,263,31612,63487,36228,
+   777,31090,526,30837,63224,35971,62435,35224,1813,32110,
+   1554,31849,62180,34975,1052,32359,61674,35473,61933,35734,
+   1307,32608,64475,33184,3885,30038,3626,29777,64220,32935,
+   3108,30303,63698,33449,63957,33710,3363,30552,2104,29251,
+   64718,34485,64969,34738,2367,29508,65479,34236,2865,29002,
+   2614,28749,65216,33979,60331,37328,8029,25894,7770,25633,
+   60076,37079,7252,26159,59554,37593,59813,37854,7507,26408,
+   6216,25139,60606,38597,60857,38850,6479,25396,61367,38348,
+   6977,24890,6726,24637,61104,38091,4208,27147,58502,40701,
+   58753,40954,4471,27404,59279,40436,4985,26882,4734,26629,
+   59016,40179,58259,39400,5989,27934,5730,27673,58004,39151,
+   5228,28183,57498,39649,57757,39910,5483,28432,52043,45360,
+   16317,17862,16058,17601,51788,45111,15540,18127,51266,45625,
+   51525,45886,15795,18376,14504,17107,52318,46629,52569,46882,
+   14767,17364,53079,46380,15265,16858,15014,16605,52816,46123,
+   12432,19179,50278,48669,50529,48922,12695,19436,51055,48404,
+   13209,18914,12958,18661,50792,48147,50035,47368,14213,19966,
+   13954,19705,49780,47119,13452,20215,49274,47617,49533,47878,
+   13707,20464,8416,23195,54294,44653,54545,44906,8679,23452,
+   55071,44388,9193,22930,8942,22677,54808,44131,54019,43384,
+   10229,23950,9970,23689,53764,43135,9468,24199,53258,43633,
+   53517,43894,9723,24448,56123,41280,12237,21942,11978,21681,
+   55868,41031,11460,22207,55346,41545,55605,41806,11715,22456,
+   10456,21155,56366,42581,56617,42834,10719,21412,57127,42332,
+   11217,20906,10966,20653,56864,42075,
+},
+{0,46002,31609,51403,63218,17728,36235,15929,61945,16971,
+   35456,14642,1803,46265,31858,53184,65519,19549,33942,14116,
+   2333,47791,29284,49622,3606,48548,30063,50909,63716,19286,
+   33693,12335,58307,20593,39098,11016,5425,42627,28232,56826,
+   4666,41352,26947,56049,58568,22394,40881,11267,7212,44958,
+   26453,54503,60126,22892,37287,8725,60885,24167,38572,9502,
+   6951,43157,24670,54252,56219,26665,41186,4944,11625,40667,
+   22032,58786,10850,39376,20763,58025,56464,28450,42985,5211,
+   9332,38854,24333,60607,53894,24884,43519,6733,54669,26175,
+   44788,7494,9087,37069,22534,60340,14424,35818,17185,61587,
+   52906,32024,46547,1633,51617,31251,45784,362,16211,36065,
+   17450,63384,51127,29701,48334,3964,12613,33527,19004,63886,
+   13902,34300,19767,65157,49340,29454,48069,2167,43819,6297,
+   53330,25568,24025,61035,9888,38162,23250,59744,8619,37401,
+   44064,8082,55129,25835,21700,59254,12221,39951,41526,4484,
+   55631,27389,42301,5775,56900,28150,21455,57469,10422,39684,
+   18664,64346,13201,32803,48666,3496,50531,30417,47377,2723,
+   49768,29146,20451,64593,13466,34600,46855,1205,52350,32716,
+   16885,62023,14988,35134,18174,62796,15751,36405,45068,958,
+   52085,30919,28848,49922,3017,47227,34370,13808,64827,20105,
+   33097,13051,64048,18818,30651,50185,3266,49008,36703,15597,
+   62502,18324,31149,51743,724,45414,32422,52500,1503,46701,
+   34900,15334,62253,16543,37747,8385,59402,23480,25985,54835,
+   7928,44362,25226,53560,6643,43585,38008,10186,61185,23731,
+   27804,57134,6117,42071,39534,10716,57623,21157,40293,11991,
+   58908,21934,27543,55333,4334,41820,
+},
+{0,22872,45744,60392,31101,8229,52173,37525,62202,43938,
+   16458,6418,35719,53983,14647,24687,63977,41137,19289,4609,
+   32916,55756,12836,27516,2835,21067,47523,57595,29294,11062,
+   49374,39302,61391,46743,23935,1063,38578,53226,9218,32090,
+   7477,17517,44933,63197,25672,15632,55032,36768,5670,20350,
+   42134,64974,28507,13827,56811,33971,58588,48516,22124,3892,
+   40353,50425,12049,30281,50051,39643,28979,10347,47870,58278,
+   2126,20758,12665,26657,33737,55953,18436,4444,64180,41964,
+   14954,25394,35034,53634,17175,6735,61863,43263,51344,37320,
+   31264,9080,45549,59573,861,23045,11340,29972,40700,51108,
+   21809,3177,59265,48857,57014,34798,27654,13662,42955,65171,
+   5499,19491,54693,36093,26389,15949,44248,62848,7784,18224,
+   10079,32263,38383,52407,24098,1914,60562,46538,39707,49731,
+   10667,28915,57958,47934,20694,2446,27105,12473,56145,33289,
+   4252,18884,41516,64372,25330,15274,53314,35098,7055,17111,
+   43327,61543,36872,51536,8888,31712,59765,45101,23493,669,
+   29908,11660,50788,40764,3497,21745,48921,58945,34350,57206,
+   13470,28102,65363,42507,19939,5307,36157,54373,16269,26325,
+   62528,44312,18160,8104,32711,9887,52599,37935,1722,24546,
+   46090,60754,22680,448,59944,45936,8677,30909,37717,51725,
+   43618,62266,6354,16778,54047,35399,25007,14583,41329,63529,
+   5057,19097,55308,33108,27324,13284,21387,2771,57659,47203,
+   10998,29614,38982,49438,46935,60943,1511,23743,52778,38770,
+   31898,9666,17837,7413,63261,44613,15568,25992,36448,55096,
+   20158,6118,64526,42326,14275,28315,34163,56363,48196,58652,
+   3828,22444,50489,40033,30601,11985,
+},
+{0,11309,22618,29815,45236,40089,59630,50371,32117,20824,
+   9519,2306,52673,57836,38299,47542,64234,54983,41648,36509,
+   19038,26227,4612,15913,34719,43954,57285,62440,14123,6918,
+   28529,17244,59849,50660,45459,40382,22909,30032,295,11530,
+   38076,47249,52454,57547,9224,2085,31826,20607,4899,16142,
+   19321,26452,41879,36794,64461,55264,28246,17019,13836,6689,
+   57058,62159,34488,43669,53135,58274,38869,48120,32571,21270,
+   10081,2892,45818,40663,60064,50829,590,11875,23060,30265,
+   13669,6472,27967,16658,34257,43516,56715,61862,18448,25661,
+   4170,15463,63652,54409,41214,36051,9798,2667,32284,21041,
+   38642,47839,52904,57989,23347,30494,873,12100,60295,51114,
+   46045,40944,56492,61569,34038,43227,27672,16437,13378,6255,
+   41433,36340,63875,54702,4461,15680,18743,25882,33539,44846,
+   56153,63348,13239,8090,27629,18368,65142,53851,42540,35329,
+   20162,25327,5784,15029,31209,21956,8627,3486,51549,58736,
+   37127,48426,1180,10417,23750,28907,46120,38917,60530,49247,
+   27338,18151,12944,7869,55934,63059,33316,44553,6079,15250,
+   20453,25544,42763,35622,65361,54140,36896,48141,51322,58455,
+   8340,3257,30926,21731,60757,49528,46351,39202,24033,29132,
+   1467,10646,19596,24737,5334,14587,64568,53269,42082,34895,
+   12793,7636,27043,17806,33101,44384,55575,62778,46694,39499,
+   60988,49681,1746,11007,24200,29349,51987,59198,37705,48996,
+   31655,22410,9213,4048,42309,35176,64799,53554,5617,14812,
+   19883,24966,55344,62493,32874,44103,26756,17577,12510,7411,
+   24495,29570,2037,11224,61211,49974,46913,39788,8922,3831,
+   31360,22189,37486,48707,51764,58905,
+},
+{0,39065,11567,46518,23134,49863,30577,61416,46268,11301,
+   39315,266,61154,30331,50125,23380,30053,60924,22602,49363,
+   12091,47010,532,39565,49625,22848,60662,29807,39815,798,
+   46760,11825,60106,29267,51173,24444,45204,10253,40379,1314,
+   24182,50927,29529,60352,1064,40113,10503,45470,40879,1846,
+   45696,10777,50673,23912,59614,28743,11027,45962,1596,40613,
+   29005,59860,23650,50427,51593,20752,58534,31807,37847,2894,
+   48888,9825,32053,58796,20506,51331,10091,49138,2628,37597,
+   48364,9333,37315,2394,59058,32299,52125,21252,2128,37065,
+   9599,48614,21006,51863,32545,59320,9027,48090,3692,38645,
+   31005,57732,21554,52395,38911,3942,47824,8777,52641,21816,
+   57486,30743,22054,52927,31497,58256,3192,38113,8535,47566,
+   58010,31235,53173,22316,47300,8285,38379,3442,36623,6038,
+   41504,15033,54609,19912,63614,24807,15283,41770,5788,36357,
+   25069,63860,19650,54363,64106,25331,55109,20444,41012,14509,
+   36123,5506,20182,54863,25593,64352,5256,35857,14759,41278,
+   26053,64860,18666,53363,16283,42754,4788,35373,53625,18912,
+   64598,25807,35623,5054,42504,16017,4256,34873,15759,42262,
+   19198,53863,26577,65352,42012,15493,35123,4522,65090,26331,
+   54125,19444,18054,56863,27561,62256,7384,33857,12791,43374,
+   62010,27299,57109,18316,43108,12541,34123,7634,13283,43898,
+   7884,34389,27069,61732,17554,56331,34655,8134,43632,13033,
+   56577,17816,61486,26807,44108,13525,33123,6650,62994,28299,
+   56125,17316,6384,32873,13791,44358,17070,55863,28545,63256,
+   55593,16816,62470,27807,33655,7150,44632,14017,28053,62732,
+   16570,55331,14283,44882,6884,33405,
+},
+{0,49859,39323,23384,12075,60904,46768,29811,24150,40085,
+   51149,1294,29053,46014,59622,10789,48300,32367,9527,59380,
+   37767,20804,2588,51423,58106,8249,31585,47522,52689,3858,
+   21578,38537,25925,42886,64734,15901,19054,34989,54261,4406,
+   15123,63952,41608,24651,5176,55035,36259,20320,55785,6954,
+   16498,33457,63170,13313,28505,44442,34751,17788,7716,56551,
+   43156,27223,12559,62412,51850,2121,21265,37330,58785,10082,
+   31802,48889,38108,22047,3399,53124,48119,31028,8812,57519,
+   30246,46309,61373,11646,22797,39886,49302,597,10352,60083,
+   45547,29480,1883,50584,40640,23555,45007,27916,13908,62615,
+   32996,16935,6527,56252,61849,13146,26626,43713,57010,7281,
+   18217,34282,4963,53664,35576,18491,15432,65163,42451,26384,
+   19765,36854,54446,5741,25118,41181,64389,14662,35081,19402,
+   4242,53841,42530,25825,16313,64890,55135,5532,20164,35847,
+   63604,15031,25071,41772,13733,63334,44094,28413,6798,55373,
+   33557,16854,27635,43312,62056,12459,17624,34331,56643,8064,
+   60492,11919,30167,46868,50023,420,23292,38975,45594,28889,
+   11137,59714,40241,24562,1194,50793,20704,37411,51579,3000,
+   32715,48392,58960,9363,3766,52341,38701,21998,8605,58206,
+   47110,31429,17283,33088,55832,6363,27816,44651,62771,14320,
+   7637,57110,33870,18061,13054,61501,43877,27046,65327,15852,
+   26292,42103,53252,4807,18847,35676,41337,25530,14562,64033,
+   36434,19601,6089,54538,9926,58373,48989,32158,2541,52014,
+   36982,21173,30864,47699,57611,9160,22459,38264,52768,3299,
+   39530,22697,1009,49458,46401,30594,11482,60953,50236,1791,
+   23975,40804,60183,10708,29324,45135,
+},
+{0,61422,50113,11311,39839,29809,22622,47024,11043,50381,
+   59618,1804,45244,24402,29565,40083,22086,47528,38279,31337,
+   52697,8759,3608,57846,32101,37515,48804,20810,59130,2324,
+   9531,51925,44172,17250,28493,32931,14099,55549,62674,6972,
+   34735,26689,17518,43904,7216,62430,57329,12319,64202,5412,
+   14603,55013,24917,36539,41620,19834,53737,15879,4648,64966,
+   19062,42392,35255,26201,17669,43755,34500,26922,56986,12660,
+   7515,62133,28198,33224,44519,16905,62905,6743,13944,55702,
+   4931,64685,53378,16236,35036,26418,19229,42227,14432,55182,
+   64417,5199,41983,19473,24638,36816,59785,1639,10824,50598,
+   29206,40440,45527,24121,49834,11588,363,61061,22837,46811,
+   39668,29978,49103,20513,31758,37856,9296,52158,59281,2175,
+   38124,31490,22317,47299,3955,57501,52402,9052,35338,26084,
+   18891,42533,4501,65147,53844,15802,41257,20167,25320,36102,
+   15030,54616,63863,5785,56396,13218,8077,61539,18387,43069,
+   33810,27644,63343,6273,13486,56128,27888,33566,44849,16607,
+   9862,51560,58695,2729,48409,21239,32472,37174,3493,57931,
+   52836,8586,38458,31188,22011,47637,28864,40750,45825,23791,
+   60255,1201,10398,51056,23523,46093,38946,30668,49276,12178,
+   957,60499,53007,8417,3278,58144,21648,47998,38737,30911,
+   58412,3010,10221,51203,32691,36957,48242,21404,39241,30375,
+   23176,46438,726,60728,49431,12025,45674,23940,29099,40517,
+   10741,50715,59956,1498,25475,35949,41026,20396,63516,6130,
+   15325,54323,18592,42830,35681,25743,54079,15569,4350,65296,
+   13765,55851,62980,6634,44634,16820,28059,33397,7910,61704,
+   56615,13001,34169,27287,18104,43350,
+},
+{0,30582,61164,39322,49605,46771,12073,22623,40855,59617,
+   29051,1549,24146,10532,45246,51144,9011,21573,52703,47785,
+   58102,38272,3098,31596,48292,52178,21064,9534,32097,2583,
+   37773,58619,18022,12560,43146,57340,34723,61653,26959,7737,
+   55793,44679,14109,16491,6196,28482,63192,33198,25941,4643,
+   35769,64719,42128,54246,19068,15626,64194,36276,5166,25432,
+   15111,19569,54763,41629,36044,64442,25120,5462,19721,14975,
+   41957,54419,4955,25645,64951,35521,53918,42472,15474,19204,
+   45055,55433,16659,13925,28218,6476,32982,63392,12392,18206,
+   56964,43506,61869,34523,8001,26679,51882,48604,9286,21296,
+   2927,31769,58755,37621,21821,8779,48081,52391,38136,58254,
+   31252,3426,59801,40687,1909,28675,10332,24362,50864,45510,
+   30222,376,39138,61332,47051,49341,22823,11857,1413,29427,
+   60265,39967,50240,45878,10924,24026,39442,60772,29950,904,
+   23511,11425,46395,49741,9910,20928,51290,48940,59251,36869,
+   2463,32489,47393,52823,22477,8379,30948,3986,38408,57726,
+   17379,13461,44303,55929,33318,62800,27850,7100,56436,43778,
+   12952,17902,7601,27335,62301,33835,24784,6054,36412,63818,
+   41237,54883,20473,14479,65351,34865,4523,26333,16002,18932,
+   53358,42776,35145,65087,26533,4307,18572,16378,42592,53526,
+   5854,25000,63538,36676,55067,41069,14839,20097,43642,56588,
+   17558,13280,27583,7369,34131,61989,13805,17051,56065,44151,
+   62504,33630,6852,28082,53039,47193,8643,22197,3818,31132,
+   57350,38768,20664,10190,48724,51490,37245,58891,32657,2279,
+   60444,39786,752,30086,11737,23215,49973,46147,29579,1277,
+   40295,59921,45646,50488,23714,11220,
+},
+{0,15162,30324,19790,60648,55250,39580,41382,50637,65271,
+   46009,34947,10533,4639,24401,25707,38791,44221,57843,56009,
+   31599,16469,3355,13857,21066,26992,9278,7940,48802,34200,
+   51414,62444,13075,2089,17767,32349,57339,58561,43407,37557,
+   63198,52708,32938,48016,6710,8460,27714,22392,42132,40878,
+   53984,59866,18556,29510,15880,1330,24921,23139,5933,11287,
+   36273,46731,64453,49407,26150,23836,4178,11112,35534,45556,
+   64698,51072,41963,39121,54687,61093,20227,29753,14711,589,
+   61857,51867,34773,48367,7497,9843,27453,20487,13420,3926,
+   16920,31010,55428,58302,44784,38346,21813,28175,9025,6267,
+   47581,33511,53161,62611,37112,43970,59020,56758,31760,18218,
+   2660,12638,49842,63880,46278,36860,11866,5472,22574,25364,
+   1919,15429,28939,18993,60311,53421,40419,42713,52300,63350,
+   47672,33026,8356,7070,22224,28138,2433,12987,32757,17615,
+   58729,56915,37661,43047,23499,24817,11711,5765,46883,35865,
+   49495,64109,40454,42300,59506,54088,29422,18900,1178,16288,
+   65375,50277,35115,45585,5047,10381,26051,24313,14994,424,
+   19686,30684,54906,60736,40974,39732,26840,21474,7852,9622,
+   33840,48906,62020,51582,44309,38447,56161,57435,16893,31431,
+   14217,3251,43626,37200,56350,59172,18050,32184,12534,3020,
+   28583,21661,6611,8937,33615,47221,62779,52737,15853,1751,
+   19353,28835,53509,59967,42865,40011,63520,49946,36436,46446,
+   5320,12274,25276,22918,39289,41539,61197,54327,30097,20139,
+   997,14559,23732,26510,10944,4602,45148,35686,50728,64786,
+   3838,13764,30858,17328,57878,55596,37986,44888,52019,61449,
+   48455,34429,10203,7393,20911,27285,
+},
+{0,7452,14904,10020,29808,26988,20040,21332,59616,62972,
+   53976,53188,40080,33164,42664,48052,52701,53441,63461,60153,
+   47533,42161,33685,40585,9533,14369,7941,537,20813,19537,
+   27509,30313,34727,39611,48543,41091,62423,61131,51695,54515,
+   28487,29275,21887,18531,6967,1579,8463,15379,19066,22374,
+   28738,27998,15882,8982,1074,6446,41626,49030,39074,34238,
+   55018,52214,60626,61902,4947,3663,10603,13431,26403,31295,
+   23835,16391,64435,59055,49547,56471,36803,37599,46587,43239,
+   56974,50066,58550,63914,43774,47074,37062,36314,13934,11122,
+   3158,4426,16926,24322,30758,25914,38132,35304,44748,46032,
+   57476,64920,55996,51104,31764,24840,17964,23344,2148,5496,
+   12892,12096,22825,17461,25361,32269,11609,12357,5985,2685,
+   45513,44245,35825,38637,50617,55461,65409,58013,9894,15290,
+   7326,386,21206,20426,26862,30194,52806,54106,62590,59746,
+   47670,42794,32782,40210,60283,63079,53571,52319,40715,33303,
+   42291,47151,923,7815,14755,9407,30699,27383,19923,20687,
+   41217,48157,39737,34341,54641,51309,61257,62037,18913,21757,
+   29657,28357,15761,8333,1961,6837,27868,29120,22244,19448,
+   6316,1456,8852,16264,33852,39200,48644,41752,61516,60752,
+   51828,55144,13813,10473,4045,4817,16773,23705,31677,26273,
+   56597,49161,59181,64049,43365,46201,37725,36417,63528,58676,
+   49680,57100,35928,37188,46688,43900,4296,3540,10992,14316,
+   25784,31140,24192,17308,45650,44878,34922,38262,50722,56126,
+   64538,57606,23218,18350,24714,32150,11970,13278,5370,2534,
+   32655,25235,17847,22699,3071,5859,12743,11483,38767,35443,
+   44375,45131,58143,65027,55591,50235,
+},
+{0,3599,7198,4625,14396,13875,9250,10797,28792,32375,
+   27750,25193,18500,17995,21594,23125,57584,61183,64750,62177,
+   55500,54979,50386,51933,37000,40583,35990,33433,43188,42683,
+   46250,47781,56829,54258,49635,53228,58817,60366,63967,63440,
+   44421,41866,45467,49044,38329,39862,35239,34728,15629,13058,
+   8467,12060,1329,2878,6447,5920,19829,17274,20843,24420,
+   30025,31558,26967,26456,42983,43496,48121,46582,40923,37332,
+   33733,36298,55199,55696,52097,50574,61347,57772,62397,64946,
+   18199,18712,23305,21766,32555,28964,25397,27962,14191,14688,
+   11121,9598,3923,348,4941,7490,31258,29717,26116,26635,
+   16934,19497,24120,20535,2658,1133,5756,6259,12894,15441,
+   11840,8271,39658,38117,34548,35067,41686,44249,48840,45255,
+   60050,58525,63116,63619,53934,56481,52912,49343,21459,24028,
+   20429,16834,27631,26080,30705,31230,9131,11684,16309,12730,
+   7063,5528,1929,2438,45859,48428,44861,41266,35615,34064,
+   38657,39182,50011,52564,57157,53578,64359,62824,59257,59766,
+   36398,32801,37424,39999,46610,47133,43532,41987,65110,61529,
+   57928,60487,50794,51301,55924,54395,28382,24785,29376,31951,
+   22242,22765,19196,17651,7846,4265,696,3255,9882,10389,
+   14980,13451,62516,64059,59434,58917,52232,49671,53270,56857,
+   33868,35395,38994,38493,48240,45695,41070,44641,5316,6859,
+   2266,1749,11512,8951,12518,16105,25788,27315,30882,30381,
+   23680,21135,16542,20113,10697,10182,13783,15320,4597,8186,
+   3563,996,22961,22462,17839,19360,24973,28546,32147,29596,
+   51513,50998,54567,56104,61701,65290,60699,58132,47425,46926,
+   42335,43856,33149,36722,40291,37740,
+},
+{0,35208,3853,34437,7706,38802,4375,39071,15412,46524,
+   13113,47793,8750,43942,11555,42155,30824,61920,30565,65261,
+   26226,61434,27007,57591,17500,52692,19281,49881,23110,54222,
+   21835,56515,61648,31064,65501,30293,61130,26434,57799,26703,
+   52452,17772,50153,19041,54014,23414,56819,21627,35000,304,
+   34741,3645,38562,7978,39343,4135,46220,15620,48001,12809,
+   43670,8990,42395,11283,64957,29749,62128,31544,58279,27183,
+   60586,25890,49545,18433,52868,18188,57235,22043,53406,22806,
+   34261,3165,35544,848,39887,4679,38082,7498,47585,12393,
+   46828,16228,43003,11891,43254,8574,3437,34021,608,35816,
+   4983,39679,7290,38386,12633,47313,15956,47068,12099,42699,
+   8270,43462,29957,64653,31240,62336,27423,58007,25618,60826,
+   18737,49337,17980,53172,22315,56995,22566,53678,59239,28399,
+   59498,25058,63869,28917,63088,32760,56147,21211,54366,24022,
+   50505,19649,51780,17356,40719,5767,36866,6538,33045,2205,
+   36376,1936,41787,10931,44086,9662,48417,13481,45612,15268,
+   6071,40511,6330,37170,2477,32805,1696,36648,11139,41483,
+   9358,44294,13721,48145,14996,45852,28639,58967,24786,59738,
+   29125,63565,32456,63296,21483,55907,23782,54638,19953,50297,
+   17148,52084,6874,37714,5591,40031,1216,36168,3021,33349,
+   9966,44902,10723,41067,14580,45436,14329,48753,25266,60218,
+   28095,58423,31912,62752,29605,64045,24198,55054,20875,55299,
+   16540,51476,20369,50713,59914,25474,58631,27791,62480,32152,
+   64285,29333,54846,24502,55603,20667,51236,16812,50985,20129,
+   37474,7146,40303,5351,35960,1520,33653,2813,44630,10206,
+   41307,10451,45132,14788,48961,14025,
+},
+{0,17477,34954,52431,3337,18764,34179,49606,6674,24151,
+   37528,55005,5915,21342,40849,56276,13348,28769,48302,63723,
+   14637,32104,45479,62946,11830,27251,42684,58105,9023,26490,
+   43957,61424,26696,11277,57538,42119,25921,8452,60875,43406,
+   29274,13855,64208,48789,32595,15126,63449,45980,23660,6185,
+   54502,37027,20837,5408,55791,40362,18046,571,52980,35505,
+   19319,3890,50173,34744,53392,38101,22554,7263,56729,39388,
+   21779,4438,51842,36551,16904,1613,51083,33742,20225,2884,
+   58548,41201,27710,10363,59837,44536,24887,9586,65190,47843,
+   30252,12905,62383,47082,31525,16224,47320,64669,12370,29719,
+   46545,61844,15707,31006,41674,59023,10816,28165,44995,60294,
+   10057,25356,36092,51385,1142,16435,33269,50608,2431,19770,
+   38638,53931,7780,23073,39911,57250,4973,22312,48445,63864,
+   13751,29170,45108,62577,14526,31995,42799,58218,12197,27616,
+   43558,61027,8876,26345,35097,52572,403,17878,33808,49237,
+   3226,18655,37643,55118,7041,24516,40450,55879,5768,21197,
+   54645,37168,24063,6586,55420,39993,20726,5299,53095,35618,
+   18413,936,49774,34347,19172,3745,57681,42260,27099,11678,
+   60504,43037,25810,8343,64323,48902,29641,14220,63050,45583,
+   32448,14981,28077,10728,58663,41314,24740,9441,59438,44139,
+   30655,13306,65333,47984,31414,16115,62012,46713,22921,7628,
+   53507,38214,21632,4293,56330,38991,17307,2014,51985,36692,
+   20114,2775,50712,33373,1509,16800,36207,51498,2284,19625,
+   32870,50211,8183,23474,38781,54072,4862,22203,39540,56881,
+   12737,30084,47435,64782,15560,30861,46146,61447,11219,28566,
+   41817,59164,9946,25247,44624,59925,
+},
+{0,44205,17735,59882,35470,9763,53193,25444,2305,42412,
+   19526,57579,33679,12066,50888,27237,4610,48815,22341,64488,
+   39052,13345,56779,29030,6915,47022,24132,62185,37261,15648,
+   54474,30823,9220,34985,24899,52718,44682,551,60365,18272,
+   11525,33192,26690,50415,42891,2854,58060,20065,13830,39595,
+   29505,57324,48264,4133,63951,21858,16135,37802,31296,55021,
+   46473,6436,61646,23651,18440,58533,3407,41442,49798,28203,
+   34753,11116,16649,60836,1102,43235,52103,26410,36544,8813,
+   23050,63143,8013,46048,53380,31785,38339,14702,21259,65446,
+   5708,47841,55685,29992,40130,12399,27660,49313,10571,34278,
+   59010,18991,41925,3944,25869,51616,8266,36071,61315,17198,
+   43716,1641,32270,53923,15177,38884,62592,22573,45511,7530,
+   30479,56226,12872,40677,64897,20780,47302,5227,36880,15549,
+   54615,31226,6814,46643,24537,62324,39185,13756,56406,28923,
+   5023,48946,22232,64117,33298,11967,51029,27640,2204,42033,
+   19931,57718,35603,10174,52820,25337,413,44336,17626,59511,
+   46100,6329,61779,24062,16026,37431,31709,55152,48405,4536,
+   63570,21759,14235,39734,29404,56945,42518,2747,58193,20476,
+   11416,32821,27103,50546,44823,954,59984,18173,9625,35124,
+   24798,52339,55320,29877,40287,12786,21142,65083,6097,47996,
+   53529,32180,37982,14579,23447,63290,7888,45693,51738,26295,
+   36701,9200,16532,60473,1491,43390,49947,28598,34396,10993,
+   18837,58680,3282,41087,64540,20657,47451,5622,30354,55871,
+   13269,40824,62749,22960,45146,7415,32659,54078,15060,38521,
+   60958,17075,43865,2036,25744,51261,8663,36218,59167,19378,
+   41560,3829,28049,49468,10454,33915,
+},
+{0,55513,44463,30070,18243,40858,60140,12853,36486,22111,
+   9001,64496,51653,4380,25706,48307,273,55752,44222,29799,
+   18002,40587,60413,13092,36759,22350,8760,64225,51412,4109,
+   25979,48546,546,56059,44941,30548,17761,40376,59598,12311,
+   36004,21629,8459,63954,52199,4926,26184,48785,819,56298,
+   44700,30277,17520,40105,59871,12550,36277,21868,8218,63683,
+   51958,4655,26457,49024,1092,56477,43499,28978,17159,39902,
+   61096,13937,35522,21019,10093,65460,52609,5464,24622,47351,
+   1365,56716,43258,28707,16918,39631,61369,14176,35795,21258,
+   9852,65189,52368,5193,24895,47590,1638,57023,43977,29456,
+   16677,39420,60554,13395,35040,20537,9551,64918,53155,6010,
+   25100,47829,1911,57262,43736,29185,16436,39149,60827,13634,
+   35313,20776,9310,64647,52914,5739,25373,48068,2184,53329,
+   42279,32254,20427,38674,57956,15037,34318,24279,11169,62328,
+   49485,6548,27874,46139,2457,53568,42038,31983,20186,38403,
+   58229,15276,34591,24518,10928,62057,49244,6277,28147,46378,
+   2730,53875,42757,32732,19945,38192,57414,14495,33836,23797,
+   10627,61786,50031,7094,28352,46617,3003,54114,42516,32461,
+   19704,37921,57687,14734,34109,24036,10386,61515,49790,6823,
+   28625,46856,3276,54293,41315,31162,19343,37718,58912,16121,
+   33354,23187,12261,63292,50441,7632,26790,45183,3549,54532,
+   41074,30891,19102,37447,59185,16360,33627,23426,12020,63021,
+   50200,7361,27063,45422,3822,54839,41793,31640,18861,37236,
+   58370,15579,32872,22705,11719,62750,50987,8178,27268,45661,
+   4095,55078,41552,31369,18620,36965,58643,15818,33145,22944,
+   11478,62479,50746,7907,27541,45900,
+},
+{0,58083,55771,15160,44971,19784,30320,38035,17227,41384,
+   39568,30835,60640,3587,13627,55256,34454,25717,24397,48558,
+   10557,52190,61670,4613,50653,10046,7174,65253,27254,34965,
+   45997,20814,4401,62418,51434,10761,48794,23673,26433,34210,
+   21114,45209,35745,26946,64977,7986,9226,50921,38823,30020,
+   20092,44191,14348,56047,57815,820,54508,13839,3383,61396,
+   31559,39332,41628,16511,8802,49281,64441,6490,36297,28458,
+   21522,46833,24873,33738,47346,23057,52866,11361,5977,62906,
+   42228,17943,32047,40908,2911,59836,53892,12391,59327,1372,
+   15972,56455,18452,43767,37327,29484,13139,53680,60040,2155,
+   40184,32283,17699,42944,28696,37627,43459,19232,57267,15696,
+   1640,58507,46533,22310,27678,36605,6766,63629,50101,8534,
+   63118,5229,12117,52662,22821,48070,33022,25117,17604,42535,
+   40223,32764,60271,2444,12980,53335,1935,58732,56916,15543,
+   43044,19143,29183,37660,49746,8369,7049,63850,28153,36634,
+   46114,22209,33049,25594,22722,47649,11954,52305,63337,5514,
+   22005,46870,35886,28365,64094,6333,9093,49510,5822,62557,
+   53093,11654,47381,23542,24782,33325,54115,12672,2744,59483,
+   31944,40491,42259,18416,36904,29387,18931,43792,16259,56672,
+   58968,1211,26278,33861,49021,23966,51469,11246,4310,62005,
+   9709,50958,64566,7893,35398,26789,21405,45438,57392,723,
+   14827,56072,20379,44408,38464,29859,41851,16792,31392,38979,
+   3280,60979,54539,14312,30615,38260,44620,19631,55356,15071,
+   487,58116,13532,54847,60679,4068,39799,31124,17068,41039,
+   61697,5090,10458,51769,24234,48201,34673,26002,45642,20649,
+   27537,35186,7649,65282,50234,9945,
+},
+{0,65534,58337,7199,56287,9249,14398,51136,43939,21597,
+   18498,47036,28796,36738,37789,27747,19291,46245,43194,22340,
+   36996,28538,29541,35995,57592,7942,793,64743,15143,50393,
+   55494,10040,38582,26952,30039,35497,19817,45719,44680,20854,
+   15637,49899,57076,8458,59082,6452,1323,64213,56813,8723,
+   15884,49650,1586,63948,58835,6701,30286,35248,38319,27217,
+   44433,21103,20080,45454,12657,52879,53904,11630,60078,5456,
+   2383,63153,39634,25900,31027,34509,16653,48883,41708,23826,
+   31274,34260,39371,26165,41461,24075,16916,48618,53641,11895,
+   12904,52630,2646,62888,59831,5705,42951,22585,17446,48088,
+   31768,33766,40953,24583,3172,62362,61317,4219,55227,10309,
+   13402,52132,60572,4962,3965,61571,14147,51389,54434,11100,
+   18239,47297,42206,23328,40160,25374,32513,33023,25314,40220,
+   33027,32509,47421,18115,23260,42274,51521,14015,10912,54622,
+   4766,60768,61823,3713,10681,54855,51800,13734,62054,3480,
+   4487,61049,33306,32228,25083,40453,22981,42555,47652,17882,
+   62548,2986,6069,59467,12171,53365,52330,13204,24567,40969,
+   48150,17384,33832,31702,26569,38967,48911,16625,23790,41744,
+   25808,39726,34609,30927,5292,60242,63309,2227,53107,12429,
+   11410,54124,21395,44141,45170,20364,34892,30642,27565,37971,
+   63536,1998,7121,58415,9199,56337,49166,16368,6344,59190,
+   64297,1239,49943,15593,8438,57096,45931,19605,20618,44916,
+   26804,38730,35669,29867,50469,15067,9924,55610,7930,57604,
+   64795,741,28294,37240,36199,29337,46425,19111,22200,43334,
+   36478,29056,28063,37473,21921,43615,46656,18878,9693,55843,
+   50748,14786,65026,508,7651,57885,
+},
+{0,32638,65276,33154,57829,40603,7961,24679,57303,41129,
+   8491,24149,15922,16716,49358,49072,41907,56525,23887,8753,
+   16982,15656,48298,50132,31844,794,33432,64998,40321,58111,
+   25469,7171,23419,9221,42375,56057,47774,50656,17506,15132,
+   33964,64466,31312,1326,25929,6711,39861,58571,63688,34742,
+   1588,31050,6445,26195,59345,39087,10015,22625,55779,42653,
+   50938,47492,14342,18296,46838,51592,18442,14196,22291,10349,
+   43503,54929,26913,5727,38877,59555,35012,63418,30264,2374,
+   5445,27195,60345,38087,62624,35806,2652,29986,51858,46572,
+   13422,19216,11127,21513,54667,43765,60813,37619,4977,27663,
+   3176,29462,62100,36330,12890,19748,52390,46040,54207,44225,
+   11587,21053,20030,12608,45250,53180,45019,53413,20775,11865,
+   37353,61079,28437,4203,28684,3954,36592,61838,29169,3727,
+   36621,61555,36884,61290,28392,4502,44582,53592,20698,12196,
+   20419,12477,45375,52801,53826,44348,11454,21440,13223,19673,
+   52571,45605,3477,29419,62313,35863,60528,37646,4748,28146,
+   10890,22004,54390,43784,52079,46097,13715,19181,62813,35363,
+   2977,29919,5304,27590,59972,38202,35129,63047,30661,2235,
+   26844,6050,38432,59742,22254,10640,43026,55148,46859,51317,
+   18935,13961,50951,47225,14843,18053,9954,22940,55326,42848,
+   6352,26542,58924,39250,63797,34379,1993,30903,25780,7114,
+   39496,58678,34129,64047,31661,1235,47971,50205,17823,15073,
+   23174,9720,42106,56068,40060,58114,25216,7678,32153,743,
+   33637,64539,17323,15573,48471,49705,41550,56624,23730,9164,
+   16335,16561,49459,48717,56874,41300,8406,24488,57368,40806,
+   7908,24986,509,32387,65281,32895,
+},
+{0,16190,32380,16706,64760,50118,33412,48570,58861,56019,
+   39825,42159,6421,9771,26473,22615,55239,59641,43451,38533,
+   11071,5121,21827,27261,12842,3348,19542,29544,52946,61932,
+   45230,36752,45971,36013,52719,62161,20331,28757,12567,3625,
+   22142,26944,10242,5948,43654,38328,54522,60356,25684,23402,
+   6696,9494,39084,42898,59088,55790,33209,48775,65477,49403,
+   32065,17023,829,15363,31547,17413,1351,14969,34755,47357,
+   63935,50817,40662,41448,57514,57236,25134,23824,7250,9068,
+   44284,37826,53888,60862,20484,28474,11896,4422,18705,30255,
+   14189,2131,46569,35543,52117,62635,51368,63382,46804,35306,
+   13392,2926,18988,29970,11589,4731,21305,27655,53693,61059,
+   44993,37119,8047,8273,24851,24109,58263,56489,40427,41685,
+   64130,50620,34046,48064,1658,14660,30726,18232,63094,51528,
+   34826,46900,2702,13744,29938,19404,5019,11429,28135,21209,
+   61283,53341,37151,44577,8625,7823,24525,24819,56649,57975,
+   41781,39947,50268,64354,47648,34078,14500,1946,18136,31206,
+   17893,31451,15257,1191,47389,34339,51041,63583,40968,40758,
+   56948,57674,23792,25550,8844,7602,37410,44316,60510,54112,
+   28378,20964,4262,12184,30671,18673,2483,13965,35639,46089,
+   62795,51829,36173,45683,62257,52239,29109,20107,4041,12535,
+   26784,22430,5852,10722,37976,43878,59940,54554,23178,26036,
+   9462,7112,42610,39244,55310,59184,48999,32857,49435,65061,
+   17311,31905,15843,733,16094,480,16546,32668,49702,64792,
+   48218,33636,56115,58381,42319,39537,10187,6389,22967,26249,
+   59673,54823,38757,43099,5601,10975,27549,21667,3316,13258,
+   29320,19894,61452,53042,36464,45390,
+},
+{0,7966,15932,8482,31864,25446,16964,23898,63728,59374,
+   50892,55762,33928,39830,47796,42410,60925,62179,54209,52447,
+   37253,36507,44985,45223,5389,2579,11057,13359,26997,30315,
+   22345,18519,51175,55545,63963,59077,48031,42113,34211,39613,
+   16151,8201,299,7733,17263,23665,32083,25165,10778,13572,
+   5158,2872,22114,18812,26718,30528,53994,52724,60630,62408,
+   44690,45452,37038,36784,37843,36045,44527,45809,61355,61621,
+   53655,52873,27427,29757,21791,18945,5979,2117,10599,13945,
+   32302,24880,16402,24332,598,7496,15466,9076,34526,39360,
+   47330,43004,64166,58808,50330,56196,21556,19242,27144,29974,
+   10316,14162,5744,2414,44228,46042,37624,36326,53436,53154,
+   61056,61854,47561,42711,34805,39147,50609,55983,64397,58515,
+   16697,24103,32517,24603,15681,8799,893,7267,15291,9381,
+   1415,6809,18371,22749,31231,26337,49995,56405,64887,57961,
+   48947,41005,33039,40465,54854,51544,59514,63332,43582,46368,
+   37890,35612,11958,12712,4234,3988,21198,19920,27890,29676,
+   64604,58178,49760,56702,32804,40762,48664,41222,1196,7090,
+   14992,9614,30932,26570,18152,23030,4513,3775,12189,12419,
+   28121,29383,21477,19707,59729,63055,55149,51315,38185,35383,
+   43797,46091,43112,46966,38484,35146,54288,51982,59948,62770,
+   20632,20358,28324,29114,11488,13310,4828,3522,17813,23179,
+   31657,25783,14829,9971,2001,6351,48485,41595,33625,40007,
+   49437,56835,65313,57407,28559,28817,20915,20141,5111,3305,
+   11723,13013,38783,34913,43331,46685,60167,62489,54587,51749,
+   33394,40300,48206,41808,65034,57620,49206,57128,31362,26012,
+   17598,23456,1786,6628,14534,10200,
+},
+{0,3854,7708,4370,15416,13110,8740,11562,30832,30590,
+   26220,26978,17480,19270,23124,21850,61664,65518,61180,57842,
+   52440,50134,53956,56778,34960,34718,38540,39298,46248,48038,
+   43700,42426,64989,62163,58305,60623,49637,52971,57337,53495,
+   34221,35491,39857,38079,47509,46747,42889,43143,3389,563,
+   4897,7215,12549,15883,12057,8215,30029,31299,27473,25695,
+   18805,18043,22377,22631,59303,59561,63931,63157,56223,54417,
+   50563,51853,40919,37081,33227,36549,41967,44257,48627,45821,
+   5959,6217,2395,1621,11135,9329,13667,14957,28471,24633,
+   28971,32293,21263,23553,19731,16925,6778,5492,1126,2920,
+   9794,10572,14430,14160,25098,27908,31766,29464,24114,20796,
+   16430,20256,60058,58772,62598,64392,54946,55724,51390,51120,
+   37610,40420,36086,33784,44754,41436,45262,49088,54099,56413,
+   52559,49729,61291,57445,61815,65145,43811,42029,46399,47665,
+   38683,38933,35079,34313,9139,11453,15791,12961,8075,4229,
+   407,3737,23491,21709,17887,19153,26619,26869,31207,30441,
+   11918,8576,12434,16284,4790,7608,3242,932,22270,23024,
+   18658,18412,27334,26056,29914,31700,56942,53600,49266,53116,
+   57942,60760,64586,62276,42526,43280,47106,46860,39462,38184,
+   33850,35636,13556,15354,10984,9702,2252,1986,5840,6622,
+   19588,17290,21144,23958,28860,32690,28320,25006,50196,51994,
+   55816,54534,63532,63266,58928,59710,48228,45930,41592,44406,
+   32860,36690,40512,37198,51497,50727,55093,55355,62737,64031,
+   60173,58371,45401,48727,44869,41035,36193,33391,37757,40051,
+   14793,14023,10197,10459,1521,2815,7149,5347,16825,20151,
+   24485,20651,32129,29327,25501,27795,
+},
+{0,1798,3596,2314,7192,6942,4628,5394,14384,16182,
+   13884,12602,9256,9006,10788,11554,28768,30566,32364,31082,
+   27768,27518,25204,25970,18512,20310,18012,16730,21576,21326,
+   23108,23874,57536,59334,61132,59850,64728,64478,62164,62930,
+   55536,57334,55036,53754,50408,50158,51940,52706,37024,38822,
+   40620,39338,36024,35774,33460,34226,43152,44950,42652,41370,
+   46216,45966,47748,48514,56733,55963,54161,54423,49541,50819,
+   53129,51343,58797,58027,60321,60583,63925,65203,63417,61631,
+   44541,43771,41969,42231,45541,46819,49129,47343,38349,37579,
+   39873,40135,35285,36563,34777,32991,15709,14939,13137,13399,
+   8517,9795,12105,10319,1389,619,2913,3175,6517,7795,
+   6009,4223,19773,19003,17201,17463,20773,22051,24361,22575,
+   29965,29195,31489,31751,26901,28179,26393,24607,42791,40993,
+   43307,44589,47935,48185,46387,45621,40727,38929,37147,38429,
+   33551,33801,36099,35333,55111,53313,55627,56909,52063,52313,
+   50515,49749,61303,59505,57723,59005,62319,62569,64867,64101,
+   18407,16609,18923,20205,23551,23801,22003,21237,32727,30929,
+   29147,30429,25551,25801,28099,27333,14215,12417,14731,16013,
+   11167,11417,9619,8853,4023,2225,443,1725,5039,5289,
+   7587,6821,31418,32188,29878,29616,26274,24996,26798,28584,
+   17034,17804,19590,19328,24210,22932,20638,22424,2778,3548,
+   1238,976,5826,4548,6350,8136,13034,13804,15590,15328,
+   12018,10740,8446,10232,39546,40316,38006,37744,34402,33124,
+   34926,36712,41546,42316,44102,43840,48722,47444,45150,46936,
+   59930,60700,58390,58128,62978,61700,63502,65288,53802,54572,
+   56358,56096,52786,51508,49214,51000,
+},
+{0,770,1540,1286,3080,3850,2572,2318,6160,6930,
+   7700,7446,5144,5914,4636,4382,12320,13090,13860,13606,
+   15400,16170,14892,14638,10288,11058,11828,11574,9272,10042,
+   8764,8510,24640,25410,26180,25926,27720,28490,27212,26958,
+   30800,31570,32340,32086,29784,30554,29276,29022,20576,21346,
+   22116,21862,23656,24426,23148,22894,18544,19314,20084,19830,
+   17528,18298,17020,16766,49280,50050,50820,50566,52360,53130,
+   51852,51598,55440,56210,56980,56726,54424,55194,53916,53662,
+   61600,62370,63140,62886,64680,65450,64172,63918,59568,60338,
+   61108,60854,58552,59322,58044,57790,41152,41922,42692,42438,
+   44232,45002,43724,43470,47312,48082,48852,48598,46296,47066,
+   45788,45534,37088,37858,38628,38374,40168,40938,39660,39406,
+   35056,35826,36596,36342,34040,34810,33532,33278,40221,40479,
+   39705,38939,37141,37399,38673,37907,34061,34319,33545,32779,
+   35077,35335,36609,35843,44349,44607,43833,43067,41269,41527,
+   42801,42035,46381,46639,45865,45099,47397,47655,48929,48163,
+   64861,65119,64345,63579,61781,62039,63313,62547,58701,58959,
+   58185,57419,59717,59975,61249,60483,52605,52863,52089,51323,
+   49525,49783,51057,50291,54637,54895,54121,53355,55653,55911,
+   57185,56419,23965,24223,23449,22683,20885,21143,22417,21651,
+   17805,18063,17289,16523,18821,19079,20353,19587,28093,28351,
+   27577,26811,25013,25271,26545,25779,30125,30383,29609,28843,
+   31141,31399,32673,31907,15837,16095,15321,14555,12757,13015,
+   14289,13523,9677,9935,9161,8395,10693,10951,12225,11459,
+   3581,3839,3065,2299,501,759,2033,1267,5613,5871,
+   5097,4331,6629,6887,8161,7395,
+},
+};
diff --git a/libedc/scramble_table b/libedc/scramble_table
new file mode 100644 (file)
index 0000000..41b8309
--- /dev/null
@@ -0,0 +1,621 @@
+/* @(#)scramble_table  1.2 02/10/19 */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+static const unsigned char yellowbook_scrambler[2340] = {
+  1,128,0,96,0,40,0,30,128,8,96,6,168,2,254,129,128,96,96,40,40,30,158,
+  136,104,102,174,170,252,127,1,224,0,72,0,54,128,22,224,14,200,4,86,131,126,225,
+  224,72,72,54,182,150,246,238,198,204,82,213,253,159,1,168,0,126,128,32,96,24,40,
+  10,158,135,40,98,158,169,168,126,254,160,64,120,48,34,148,25,175,74,252,55,1,214,
+  128,94,224,56,72,18,182,141,182,229,182,203,54,215,86,222,190,216,112,90,164,59,59,
+  83,83,125,253,225,129,136,96,102,168,42,254,159,0,104,0,46,128,28,96,9,232,6,
+  206,130,212,97,159,104,104,46,174,156,124,105,225,238,200,76,86,181,254,247,0,70,128,
+  50,224,21,136,15,38,132,26,227,75,9,247,70,198,178,210,245,157,135,41,162,158,249,
+  168,66,254,177,128,116,96,39,104,26,174,139,60,103,81,234,188,79,49,244,20,71,79,
+  114,180,37,183,91,54,187,86,243,126,197,224,83,8,61,198,145,146,236,109,141,237,165,
+  141,187,37,179,91,53,251,87,3,126,129,224,96,72,40,54,158,150,232,110,206,172,84,
+  125,255,97,128,40,96,30,168,8,126,134,160,98,248,41,130,158,225,168,72,126,182,160,
+  118,248,38,194,154,209,171,28,127,73,224,54,200,22,214,142,222,228,88,75,122,183,99,
+  54,169,214,254,222,192,88,80,58,188,19,49,205,212,85,159,127,40,32,30,152,8,106,
+  134,175,34,252,25,129,202,224,87,8,62,134,144,98,236,41,141,222,229,152,75,42,183,
+  95,54,184,22,242,142,197,164,83,59,125,211,97,157,232,105,142,174,228,124,75,97,247,
+  104,70,174,178,252,117,129,231,32,74,152,55,42,150,159,46,232,28,78,137,244,102,199,
+  106,210,175,29,188,9,177,198,244,82,199,125,146,161,173,184,125,178,161,181,184,119,50,
+  166,149,186,239,51,12,21,197,207,19,20,13,207,69,148,51,47,85,220,63,25,208,10,
+  220,7,25,194,138,209,167,28,122,137,227,38,201,218,214,219,30,219,72,91,118,187,102,
+  243,106,197,239,19,12,13,197,197,147,19,45,205,221,149,153,175,42,252,31,1,200,0,
+  86,128,62,224,16,72,12,54,133,214,227,30,201,200,86,214,190,222,240,88,68,58,179,
+  83,53,253,215,1,158,128,104,96,46,168,28,126,137,224,102,200,42,214,159,30,232,8,
+  78,134,180,98,247,105,134,174,226,252,73,129,246,224,70,200,50,214,149,158,239,40,76,
+  30,181,200,119,22,166,142,250,228,67,11,113,199,100,82,171,125,191,97,176,40,116,30,
+  167,72,122,182,163,54,249,214,194,222,209,152,92,106,185,239,50,204,21,149,207,47,20,
+  28,15,73,196,54,211,86,221,254,217,128,90,224,59,8,19,70,141,242,229,133,139,35,
+  39,89,218,186,219,51,27,85,203,127,23,96,14,168,4,126,131,96,97,232,40,78,158,
+  180,104,119,110,166,172,122,253,227,1,137,192,102,208,42,220,31,25,200,10,214,135,30,
+  226,136,73,166,182,250,246,195,6,209,194,220,81,153,252,106,193,239,16,76,12,53,197,
+  215,19,30,141,200,101,150,171,46,255,92,64,57,240,18,196,13,147,69,173,243,61,133,
+  209,163,28,121,201,226,214,201,158,214,232,94,206,184,84,114,191,101,176,43,52,31,87,
+  72,62,182,144,118,236,38,205,218,213,155,31,43,72,31,118,136,38,230,154,202,235,23,
+  15,78,132,52,99,87,105,254,174,192,124,80,33,252,24,65,202,176,87,52,62,151,80,
+  110,188,44,113,221,228,89,139,122,231,99,10,169,199,62,210,144,93,172,57,189,210,241,
+  157,132,105,163,110,249,236,66,205,241,149,132,111,35,108,25,237,202,205,151,21,174,143,
+  60,100,17,235,76,79,117,244,39,7,90,130,187,33,179,88,117,250,167,3,58,129,211,
+  32,93,216,57,154,146,235,45,143,93,164,57,187,82,243,125,133,225,163,8,121,198,162,
+  210,249,157,130,233,161,142,248,100,66,171,113,191,100,112,43,100,31,107,72,47,118,156,
+  38,233,218,206,219,20,91,79,123,116,35,103,89,234,186,207,51,20,21,207,79,20,52,
+  15,87,68,62,179,80,117,252,39,1,218,128,91,32,59,88,19,122,141,227,37,137,219,
+  38,219,90,219,123,27,99,75,105,247,110,198,172,82,253,253,129,129,160,96,120,40,34,
+  158,153,168,106,254,175,0,124,0,33,192,24,80,10,188,7,49,194,148,81,175,124,124,
+  33,225,216,72,90,182,187,54,243,86,197,254,211,0,93,192,57,144,18,236,13,141,197,
+  165,147,59,45,211,93,157,249,169,130,254,225,128,72,96,54,168,22,254,142,192,100,80,
+  43,124,31,97,200,40,86,158,190,232,112,78,164,52,123,87,99,126,169,224,126,200,32,
+  86,152,62,234,144,79,44,52,29,215,73,158,182,232,118,206,166,212,122,223,99,24,41,
+  202,158,215,40,94,158,184,104,114,174,165,188,123,49,227,84,73,255,118,192,38,208,26,
+  220,11,25,199,74,210,183,29,182,137,182,230,246,202,198,215,18,222,141,152,101,170,171,
+  63,63,80,16,60,12,17,197,204,83,21,253,207,1,148,0,111,64,44,48,29,212,9,
+  159,70,232,50,206,149,148,111,47,108,28,45,201,221,150,217,174,218,252,91,1,251,64,
+  67,112,49,228,20,75,79,119,116,38,167,90,250,187,3,51,65,213,240,95,4,56,3,
+  82,129,253,160,65,184,48,114,148,37,175,91,60,59,81,211,124,93,225,249,136,66,230,
+  177,138,244,103,7,106,130,175,33,188,24,113,202,164,87,59,126,147,96,109,232,45,142,
+  157,164,105,187,110,243,108,69,237,243,13,133,197,163,19,57,205,210,213,157,159,41,168,
+  30,254,136,64,102,176,42,244,31,7,72,2,182,129,182,224,118,200,38,214,154,222,235,
+  24,79,74,180,55,55,86,150,190,238,240,76,68,53,243,87,5,254,131,0,97,192,40,
+  80,30,188,8,113,198,164,82,251,125,131,97,161,232,120,78,162,180,121,183,98,246,169,
+  134,254,226,192,73,144,54,236,22,205,206,213,148,95,47,120,28,34,137,217,166,218,250,
+  219,3,27,65,203,112,87,100,62,171,80,127,124,32,33,216,24,90,138,187,39,51,90,
+  149,251,47,3,92,1,249,192,66,208,49,156,20,105,207,110,212,44,95,93,248,57,130,
+  146,225,173,136,125,166,161,186,248,115,2,165,193,187,16,115,76,37,245,219,7,27,66,
+  139,113,167,100,122,171,99,63,105,208,46,220,28,89,201,250,214,195,30,209,200,92,86,
+  185,254,242,192,69,144,51,44,21,221,207,25,148,10,239,71,12,50,133,213,163,31,57,
+  200,18,214,141,158,229,168,75,62,183,80,118,188,38,241,218,196,91,19,123,77,227,117,
+  137,231,38,202,154,215,43,30,159,72,104,54,174,150,252,110,193,236,80,77,252,53,129,
+  215,32,94,152,56,106,146,175,45,188,29,177,201,180,86,247,126,198,160,82,248,61,130,
+  145,161,172,120,125,226,161,137,184,102,242,170,197,191,19,48,13,212,5,159,67,40,49,
+  222,148,88,111,122,172,35,61,217,209,154,220,107,25,239,74,204,55,21,214,143,30,228,
+  8,75,70,183,114,246,165,134,251,34,195,89,145,250,236,67,13,241,197,132,83,35,125,
+  217,225,154,200,107,22,175,78,252,52,65,215,112,94,164,56,123,82,163,125,185,225,178,
+  200,117,150,167,46,250,156,67,41,241,222,196,88,83,122,189,227,49,137,212,102,223,106,
+  216,47,26,156,11,41,199,94,210,184,93,178,185,181,178,247,53,134,151,34,238,153,140,
+  106,229,239,11,12,7,69,194,179,17,181,204,119,21,230,143,10,228,7,11,66,135,113,
+  162,164,121,187,98,243,105,133,238,227,12,73,197,246,211,6,221,194,217,145,154,236,107,
+  13,239,69,140,51,37,213,219,31,27,72,11,118,135,102,226,170,201,191,22,240,14,196,
+  4,83,67,125,241,225,132,72,99,118,169,230,254,202,192,87,16,62,140,16,101,204,43,
+  21,223,79,24,52,10,151,71,46,178,156,117,169,231,62,202,144,87,44,62,157,208,105,
+  156,46,233,220,78,217,244,90,199,123,18,163,77,185,245,178,199,53,146,151,45,174,157,
+  188,105,177,238,244,76,71,117,242,167,5,186,131,51,33,213,216,95,26,184,11,50,135,
+  85,162,191,57,176,18,244,13,135,69,162,179,57,181,210,247,29,134,137,162,230,249,138,
+  194,231,17,138,140,103,37,234,155,15,43,68,31,115,72,37,246,155,6,235,66,207,113,
+  148,36,111,91,108,59,109,211,109,157,237,169,141,190,229,176,75,52,55,87,86,190,190,
+  240,112,68,36,51,91,85,251,127,3,96,1,232,0,78,128,52,96,23,104,14,174,132,
+  124,99,97,233,232,78,206,180,84,119,127,102,160,42,248,31,2,136,1,166,128,122,224,
+  35,8,25,198,138,210,231,29,138,137,167,38,250,154,195,43,17,223,76,88,53,250,151,
+  3,46,129,220,96,89,232,58,206,147,20,109,207,109,148,45,175,93,188,57,177,210,244,
+  93,135,121,162,162,249,185,130,242,225,133,136,99,38,169,218,254,219,0,91,64,59,112,
+  19,100,13,235,69,143,115,36,37,219,91,27,123,75,99,119,105,230,174,202,252,87,1,
+  254,128,64,96,48,40,20,30,143,72,100,54,171,86,255,126,192,32,80,24,60,10,145,
+  199,44,82,157,253,169,129,190,224,112,72,36,54,155,86,235,126,207,96,84,40,63,94,
+  144,56,108,18,173,205,189,149,177,175,52,124,23,97,206,168,84,126,191,96,112,40,36,
+  30,155,72,107,118,175,102,252,42,193,223,16,88,12,58,133,211,35,29,217,201,154,214,
+  235,30,207,72,84,54,191,86,240,62,196,16,83,76,61,245,209,135,28,98,137,233,166,
+  206,250,212,67,31,113,200,36,86,155,126,235,96,79,104,52,46,151,92,110,185,236,114,
+  205,229,149,139,47,39,92,26,185,203,50,215,85,158,191,40,112,30,164,8,123,70,163,
+  114,249,229,130,203,33,151,88,110,186,172,115,61,229,209,139,28,103,73,234,182,207,54,
+  212,22,223,78,216,52,90,151,123,46,163,92,121,249,226,194,201,145,150,236,110,205,236,
+  85,141,255,37,128,27,32,11,88,7,122,130,163,33,185,216,114,218,165,155,59,43,83,
+  95,125,248,33,130,152,97,170,168,127,62,160,16,120,12,34,133,217,163,26,249,203,2,
+  215,65,158,176,104,116,46,167,92,122,185,227,50,201,213,150,223,46,216,28,90,137,251,
+  38,195,90,209,251,28,67,73,241,246,196,70,211,114,221,229,153,
+};
+
+#ifdef PROTOTYPES
+
+#   if !defined        WORDS_BIGENDIAN
+/* little endian */
+static const UInt32_t yellowbook_scrambler_uint32[2340/4] = {
+  0x60008001UL,0x1E002800UL,0x06600880UL,0x81FE02A8UL,0x28606080UL,
+  0x889E1E28UL,0xAAAE6668UL,0xE0017FFCUL,0x36004800UL,0x0EE01680UL,
+  0x835604C8UL,0x48E0E17EUL,0x96B63648UL,0xCCC6EEF6UL,0x9FFDD552UL,
+  0x7E00A801UL,0x18602080UL,0x879E0A28UL,0xA99E6228UL,0xA0FE7EA8UL,
+  0x22307840UL,0x4AAF1994UL,0xD60137FCUL,0x38E05E80UL,0x8DB61248UL,
+  0xCBB6E5B6UL,0xDE56D736UL,0x5A70D8BEUL,0x533B3BA4UL,0xE1FD7D53UL,
+  0x66608881UL,0x9FFE2AA8UL,0x2E006800UL,0x09601C80UL,0x82CE06E8UL,
+  0x689F61D4UL,0x9CAE2E68UL,0xEEE1697CUL,0xB5564CC8UL,0x4600F7FEUL,
+  0x15E03280UL,0x84260F88UL,0x094BE31AUL,0xB2C646F7UL,0x879DF5D2UL,
+  0xF99EA229UL,0xB1FE42A8UL,0x27607480UL,0x8BAE1A68UL,0xEA51673CUL,
+  0xF4314FBCUL,0x724F4714UL,0x5BB725B4UL,0xF356BB36UL,0x53E0C57EUL,
+  0x91C63D08UL,0x8D6DEC92UL,0xBB8DA5EDUL,0x355BB325UL,0x7E0357FBUL,
+  0x4860E081UL,0x969E3628UL,0xACCE6EE8UL,0x61FF7D54UL,0x1E602880UL,
+  0x867E08A8UL,0x29F862A0UL,0xA8E19E82UL,0xA0B67E48UL,0xC226F876UL,
+  0x1CABD19AUL,0x36E0497FUL,0x8ED616C8UL,0x4B58E4DEUL,0x3663B77AUL,
+  0xDEFED6A9UL,0x3A5058C0UL,0xCD3113BCUL,0x7F9F55D4UL,0x981E2028UL,
+  0xAF866A08UL,0x8119FC22UL,0x0857E0CAUL,0x6290863EUL,0xDE8D29ECUL,
+  0x2A4B98E5UL,0xB8365FB7UL,0xC58EF216UL,0x7D3B53A4UL,0xE89D61D3UL,
+  0xE4AE8E69UL,0xF7614B7CUL,0xB2AE4668UL,0xE78175FCUL,0x37984A20UL,
+  0x2E9F962AUL,0x894E1CE8UL,0x6AC766F4UL,0xBC1DAFD2UL,0xF4C6B109UL,
+  0x927DC752UL,0x7DB8ADA1UL,0xB8B5A1B2UL,0x95A63277UL,0x0C33EFBAUL,
+  0x13CFC515UL,0x45CF0D14UL,0x552F3394UL,0xD0193FDCUL,0x1907DC0AUL,
+  0xA7D18AC2UL,0xE3897A1CUL,0xD6DAC926UL,0x48DB1EDBUL,0x66BB765BUL,
+  0xEFC56AF3UL,0xC50D0C13UL,0x2D1393C5UL,0x9995DDCDUL,0x1FFC2AAFUL,
+  0x5600C801UL,0x10E03E80UL,0x85360C48UL,0xC91EE3D6UL,0xBED656C8UL,
+  0x4458F0DEUL,0x3553B33AUL,0x9E01D7FDUL,0x2E606880UL,0x897E1CA8UL,
+  0x2AC866E0UL,0xE81E9FD6UL,0xB4864E08UL,0x8669F762UL,0x49FCE2AEUL,
+  0x46E0F681UL,0x95D632C8UL,0x4C28EF9EUL,0x77C8B51EUL,0xFA8EA616UL,
+  0x710B43E4UL,0xAB5264C7UL,0xB061BF7DUL,0xA71E7428UL,0xA3B67A48UL,
+  0xC2D6F936UL,0x5C98D1DEUL,0x32EFB96AUL,0xCF9515CCUL,0x0F1C142FUL,
+  0xD336C449UL,0xD9FEDD56UL,0x3BE05A80UL,0x8D461308UL,0x8B85E5F2UL,
+  0xDA592723UL,0x1B33DBBAUL,0x177FCB55UL,0x04A80E60UL,0x6160837EUL,
+  0x9E4E28E8UL,0x6E7768B4UL,0xFD7AACA6UL,0xC08901E3UL,0xDC2AD066UL,
+  0x0AC8191FUL,0xE21E87D6UL,0xB6A64988UL,0x06C3F6FAUL,0x51DCC2D1UL,
+  0xC16AFC99UL,0x0C4C10EFUL,0x13D7C535UL,0x65C88D1EUL,0xFF2EAB96UL,
+  0xF039405CUL,0x930DC412UL,0x3DF3AD45UL,0x1CA3D185UL,0xD6E2C979UL,
+  0xE8D69EC9UL,0x54B8CE5EUL,0xB065BF72UL,0x571F342BUL,0x90B63E48UL,
+  0xCD26EC76UL,0x1F9BD5DAUL,0x761F482BUL,0x9AE62688UL,0x0F17EBCAUL,
+  0x6334844EUL,0xAEFE6957UL,0x21507CC0UL,0xCA4118FCUL,0x3E3457B0UL,
+  0xBC6E5097UL,0xE4DD712CUL,0xE77A8B59UL,0xC7A90A63UL,0x5D90D23EUL,
+  0xD2BD39ACUL,0x69849DF1UL,0xECF96EA3UL,0x95F1CD42UL,0x6C236F84UL,
+  0xCDCAED19UL,0x8FAE1597UL,0xEB11643CUL,0xF4754F4CUL,0x825A0727UL,
+  0x58B321BBUL,0x03A7FA75UL,0x20D3813AUL,0x9A39D85DUL,0x8F2DEB92UL,
+  0xBB39A45DUL,0x857DF352UL,0x7908A3E1UL,0xF9D2A2C6UL,0xA1E9829DUL,
+  0x4264F88EUL,0x64BF71ABUL,0x1F642B70UL,0x762F486BUL,0xDAE9269CUL,
+  0x5B14DBCEUL,0x23747B4FUL,0xBAEA5967UL,0x151433CFUL,0x34144FCFUL,
+  0x3E44570FUL,0xFC7550B3UL,0x80DA0127UL,0x583B205BUL,0xE38D7A13UL,
+  0x26DB8925UL,0x7BDB5ADBUL,0x694B631BUL,0xACC66EF7UL,0x81FDFD52UL,
+  0x7860A081UL,0x999E2228UL,0xAFFE6AA8UL,0x21007C00UL,0x0A5018C0UL,
+  0xC23107BCUL,0x7CAF5194UL,0xD8E1217CUL,0xBBB65A48UL,0xC556F336UL,
+  0x5D00D3FEUL,0x129039C0UL,0xC58D0DECUL,0x2D3B93A5UL,0xF99D5DD3UL,
+  0xE1FE82A9UL,0x36604880UL,0x8EFE16A8UL,0x2B5064C0UL,0xC8611F7CUL,
+  0xBE9E5628UL,0xA44E70E8UL,0x63577B34UL,0x7EE0A97EUL,0x985620C8UL,
+  0x4F90EA3EUL,0xD71D342CUL,0xE8B69E49UL,0xD4A6CE76UL,0x1863DF7AUL,
+  0xD79ECA29UL,0xB89E5E28UL,0xA5AE7268UL,0xE3317BBCUL,0x76FF4954UL,
+  0x1AD026C0UL,0xC7190BDCUL,0x1DB7D24AUL,0xE6B689B6UL,0xD7C6CAF6UL,
+  0x988DDE12UL,0x3FABAA65UL,0x3C10503FUL,0xCCC5110CUL,0xCFFD1553UL,
+  0x6F009401UL,0x1D302C40UL,0x469F09D4UL,0x95CE32E8UL,0x6C2F6F94UL,
+  0xDDC92D1CUL,0xDAAED996UL,0xFB015BFCUL,0x31704340UL,0x4F4B14E4UL,
+  0xA7267477UL,0x03BBFA5AUL,0xF0D54133UL,0x0338045FUL,0xA0FD8152UL,
+  0x7230B841UL,0x5BAF2594UL,0xD3513B3CUL,0xF9E15D7CUL,0xB1E64288UL,
+  0x0767F48AUL,0x21AF826AUL,0xCA7118BCUL,0x7E3B57A4UL,0xE86D6093UL,
+  0xA49D8E2DUL,0xF36EBB69UL,0xF3ED456CUL,0xA3C5850DUL,0xD2CD3913UL,
+  0x299F9DD5UL,0x88FE1EA8UL,0x2AB06640UL,0x48071FF4UL,0xB681B602UL,
+  0x26C876E0UL,0xEBDE9AD6UL,0xB44A4F18UL,0x96563737UL,0x4CF0EEBEUL,
+  0x57F33544UL,0x0083FE05UL,0x5028C061UL,0x7108BC1EUL,0xFB52A4C6UL,
+  0xA161837DUL,0xA24E78E8UL,0x62B779B4UL,0xFE86A9F6UL,0x9049C0E2UL,
+  0xCD16EC36UL,0x5F94D5CEUL,0x221C782FUL,0xDAA6D989UL,0x1B03DBFAUL,
+  0x5770CB41UL,0x50AB3E64UL,0x21207C7FUL,0x8A5A18D8UL,0x5A3327BBUL,
+  0x032FFB95UL,0xC0F9015CUL,0x9C31D042UL,0x6ECF6914UL,0x5D5F2CD4UL,
+  0x928239F8UL,0x7D88ADE1UL,0xF8BAA1A6UL,0xC1A50273UL,0x4C7310BBUL,
+  0x07DBF525UL,0x718B421BUL,0xAB7A64A7UL,0xD0693F63UL,0x591CDC2EUL,
+  0xC3D6FAC9UL,0x5CC8D11EUL,0xF2FEB956UL,0x339045C0UL,0xCFDD152CUL,
+  0xEF0A9419UL,0x85320C47UL,0x391FA3D5UL,0x8DD612C8UL,0x4BA8E59EUL,
+  0x7650B73EUL,0xDAF126BCUL,0x7B135BC4UL,0x8975E34DUL,0x9ACA26E7UL,
+  0x9F1E2BD7UL,0xAE366848UL,0xC16EFC96UL,0xFC4D50ECUL,0x20D78135UL,
+  0x6A38985EUL,0xBC2DAF92UL,0xB4C9B11DUL,0xC67EF756UL,0x3DF852A0UL,
+  0xACA19182UL,0xA1E27D78UL,0xF266B889UL,0x13BFC5AAUL,0x05D40D30UL,
+  0x3128439FUL,0x6F5894DEUL,0x3D23AC7AUL,0xDC9AD1D9UL,0x4AEF196BUL,
+  0xD61537CCUL,0x08E41E8FUL,0x72B7464BUL,0xFB86A5F6UL,0x9159C322UL,
+  0x0D43ECFAUL,0x5384C5F1UL,0xE1D97D23UL,0x166BC89AUL,0x34FC4EAFUL,
+  0x5E70D741UL,0x527B38A4UL,0xE1B97DA3UL,0x9675C8B2UL,0x9CFA2EA7UL,
+  0xDEF12943UL,0x7A5358C4UL,0x8931E3BDUL,0x6ADF66D4UL,0x9C1A2FD8UL,
+  0x5EC7290BUL,0xB25DB8D2UL,0xF7B2B5B9UL,0x22978635UL,0x6A8C99EEUL,
+  0x0C0BEFE5UL,0xB3C24507UL,0x77CCB511UL,0x0A8FE615UL,0x420B07E4UL,
+  0xA4A27187UL,0xF362BB79UL,0xE3EE8569UL,0xF6C5490CUL,0xC2DD06D3UL,
+  0xEC9A91D9UL,0x45EF0D6BUL,0xD525338CUL,0x481B1FDBUL,0x6687760BUL,
+  0xBFC9AAE2UL,0xC40EF016UL,0x7D435304UL,0x4884E1F1UL,0xE6A97663UL,
+  0x57C0CAFEUL,0x108C3E10UL,0x152BCC65UL,0x34184FDFUL,0x2E47970AUL,
+  0xA9759CB2UL,0x90CA3EE7UL,0x9D3E2C57UL,0x2E9C69D0UL,0xD94EDCE9UL,
+  0x7BC75AF4UL,0xB94DA312UL,0x35C7B2F5UL,0xAE2D9792UL,0xB169BC9DUL,
+  0x474CF4EEUL,0x05A7F275UL,0x213383BAUL,0x1A5FD8D5UL,0x87320BB8UL,
+  0x39BFA255UL,0x0DF412B0UL,0xB3A24587UL,0xF7D2B539UL,0xA289861DUL,
+  0xC28AF9E6UL,0x8C8A11E7UL,0x9BEA2567UL,0x1F442B0FUL,0xF6254873UL,
+  0x42EB069BUL,0x249471CFUL,0x3B6C5B6FUL,0x9D6DD36DUL,0xBE8DA9EDUL,
+  0x344BB0E5UL,0xBE565737UL,0x4470F0BEUL,0x555B3324UL,0x60037FFBUL,
+  0x4E00E801UL,0x17603480UL,0x84AE0E68UL,0xE961637CUL,0xB4CE4EE8UL,
+  0x667F7754UL,0x1FF82AA0UL,0xA6018802UL,0x23E07A80UL,0x8AC61908UL,
+  0x8A1DE7D2UL,0xFA26A789UL,0x112BC39AUL,0x35584CDFUL,0x2E0397FAUL,
+  0x5960DC81UL,0x93CE3AE8UL,0x6DCF6D14UL,0x5DAF2D94UL,0xD2B139BCUL,
+  0x79875DF4UL,0xB9F9A2A2UL,0x85E1F282UL,0xA9266388UL,0x00DBFEDAUL,
+  0x703B405BUL,0xEB0D6413UL,0x24738F45UL,0x1B5BDB25UL,0x77634B7BUL,
+  0xCAAEE669UL,0xFE0157FCUL,0x30604080UL,0x8F1E1428UL,0xAB366448UL,
+  0xC07EFF56UL,0x3C185020UL,0x2CC7910AUL,0xA9FD9D52UL,0x70E0BE81UL,
+  0x9B362448UL,0xCF7EEB56UL,0x3F285460UL,0x6C38905EUL,0xBDCDAD12UL,
+  0x34AFB195UL,0xCE61177CUL,0xBF7E54A8UL,0x24287060UL,0x6B489B1EUL,
+  0xFC66AF76UL,0x10DFC12AUL,0x853A0C58UL,0xD91D23D3UL,0xEBD69AC9UL,
+  0x5448CF1EUL,0xF056BF36UL,0x5310C43EUL,0xD1F53D4CUL,0x89621C87UL,
+  0xFACEA6E9UL,0x711F43D4UL,0x9B5624C8UL,0x4F60EB7EUL,0x972E3468UL,
+  0xECB96E5CUL,0x95E5CD72UL,0x5C272F8BUL,0x32CBB91AUL,0xBF9E55D7UL,
+  0xA41E7028UL,0xA3467B08UL,0x82E5F972UL,0x589721CBUL,0x73ACBA6EUL,
+  0x8BD1E53DUL,0xEA49671CUL,0xD436CFB6UL,0xD84EDF16UL,0x7B975A34UL,
+  0x795CA32EUL,0xC9C2E2F9UL,0x6EEC9691UL,0x8D55ECCDUL,0x1B8025FFUL,
+  0x07580B20UL,0x21A3827AUL,0xDA72D8B9UL,0x2B3B9BA5UL,0xF87D5F53UL,
+  0x61988221UL,0x3E7FA8AAUL,0x0C7810A0UL,0xA3D98522UL,0x02CBF91AUL,
+  0xB09E41D7UL,0xA72E7468UL,0xE3B97A5CUL,0x96D5C932UL,0x1CD82EDFUL,
+  0x26FB895AUL,0xFBD15AC3UL,0xF149431CUL,0xD346C4F6UL,0x99E5DD72UL,
+  
+};
+#   endif
+#   if defined WORDS_BIGENDIAN
+/* big endian */
+static const UInt32_t yellowbook_scrambler_uint32[2340/4] = {
+  0x01800060UL,0x0028001EUL,0x80086006UL,0xA802FE81UL,0x80606028UL,
+  0x281E9E88UL,0x6866AEAAUL,0xFC7F01E0UL,0x00480036UL,0x8016E00EUL,
+  0xC8045683UL,0x7EE1E048UL,0x4836B696UL,0xF6EEC6CCUL,0x52D5FD9FUL,
+  0x01A8007EUL,0x80206018UL,0x280A9E87UL,0x28629EA9UL,0xA87EFEA0UL,
+  0x40783022UL,0x9419AF4AUL,0xFC3701D6UL,0x805EE038UL,0x4812B68DUL,
+  0xB6E5B6CBUL,0x36D756DEUL,0xBED8705AUL,0xA43B3B53UL,0x537DFDE1UL,
+  0x81886066UL,0xA82AFE9FUL,0x0068002EUL,0x801C6009UL,0xE806CE82UL,
+  0xD4619F68UL,0x682EAE9CUL,0x7C69E1EEUL,0xC84C56B5UL,0xFEF70046UL,
+  0x8032E015UL,0x880F2684UL,0x1AE34B09UL,0xF746C6B2UL,0xD2F59D87UL,
+  0x29A29EF9UL,0xA842FEB1UL,0x80746027UL,0x681AAE8BUL,0x3C6751EAUL,
+  0xBC4F31F4UL,0x14474F72UL,0xB425B75BUL,0x36BB56F3UL,0x7EC5E053UL,
+  0x083DC691UL,0x92EC6D8DUL,0xEDA58DBBUL,0x25B35B35UL,0xFB57037EUL,
+  0x81E06048UL,0x28369E96UL,0xE86ECEACUL,0x547DFF61UL,0x8028601EUL,
+  0xA8087E86UL,0xA062F829UL,0x829EE1A8UL,0x487EB6A0UL,0x76F826C2UL,
+  0x9AD1AB1CUL,0x7F49E036UL,0xC816D68EUL,0xDEE4584BUL,0x7AB76336UL,
+  0xA9D6FEDEUL,0xC058503AUL,0xBC1331CDUL,0xD4559F7FUL,0x28201E98UL,
+  0x086A86AFUL,0x22FC1981UL,0xCAE05708UL,0x3E869062UL,0xEC298DDEUL,
+  0xE5984B2AUL,0xB75F36B8UL,0x16F28EC5UL,0xA4533B7DUL,0xD3619DE8UL,
+  0x698EAEE4UL,0x7C4B61F7UL,0x6846AEB2UL,0xFC7581E7UL,0x204A9837UL,
+  0x2A969F2EUL,0xE81C4E89UL,0xF466C76AUL,0xD2AF1DBCUL,0x09B1C6F4UL,
+  0x52C77D92UL,0xA1ADB87DUL,0xB2A1B5B8UL,0x7732A695UL,0xBAEF330CUL,
+  0x15C5CF13UL,0x140DCF45UL,0x94332F55UL,0xDC3F19D0UL,0x0ADC0719UL,
+  0xC28AD1A7UL,0x1C7A89E3UL,0x26C9DAD6UL,0xDB1EDB48UL,0x5B76BB66UL,
+  0xF36AC5EFUL,0x130C0DC5UL,0xC593132DUL,0xCDDD9599UL,0xAF2AFC1FUL,
+  0x01C80056UL,0x803EE010UL,0x480C3685UL,0xD6E31EC9UL,0xC856D6BEUL,
+  0xDEF05844UL,0x3AB35335UL,0xFDD7019EUL,0x8068602EUL,0xA81C7E89UL,
+  0xE066C82AUL,0xD69F1EE8UL,0x084E86B4UL,0x62F76986UL,0xAEE2FC49UL,
+  0x81F6E046UL,0xC832D695UL,0x9EEF284CUL,0x1EB5C877UL,0x16A68EFAUL,
+  0xE4430B71UL,0xC76452ABUL,0x7DBF61B0UL,0x28741EA7UL,0x487AB6A3UL,
+  0x36F9D6C2UL,0xDED1985CUL,0x6AB9EF32UL,0xCC1595CFUL,0x2F141C0FUL,
+  0x49C436D3UL,0x56DDFED9UL,0x805AE03BUL,0x0813468DUL,0xF2E5858BUL,
+  0x232759DAUL,0xBADB331BUL,0x55CB7F17UL,0x600EA804UL,0x7E836061UL,
+  0xE8284E9EUL,0xB468776EUL,0xA6AC7AFDUL,0xE30189C0UL,0x66D02ADCUL,
+  0x1F19C80AUL,0xD6871EE2UL,0x8849A6B6UL,0xFAF6C306UL,0xD1C2DC51UL,
+  0x99FC6AC1UL,0xEF104C0CUL,0x35C5D713UL,0x1E8DC865UL,0x96AB2EFFUL,
+  0x5C4039F0UL,0x12C40D93UL,0x45ADF33DUL,0x85D1A31CUL,0x79C9E2D6UL,
+  0xC99ED6E8UL,0x5ECEB854UL,0x72BF65B0UL,0x2B341F57UL,0x483EB690UL,
+  0x76EC26CDUL,0xDAD59B1FUL,0x2B481F76UL,0x8826E69AUL,0xCAEB170FUL,
+  0x4E843463UL,0x5769FEAEUL,0xC07C5021UL,0xFC1841CAUL,0xB057343EUL,
+  0x97506EBCUL,0x2C71DDE4UL,0x598B7AE7UL,0x630AA9C7UL,0x3ED2905DUL,
+  0xAC39BDD2UL,0xF19D8469UL,0xA36EF9ECUL,0x42CDF195UL,0x846F236CUL,
+  0x19EDCACDUL,0x9715AE8FUL,0x3C6411EBUL,0x4C4F75F4UL,0x27075A82UL,
+  0xBB21B358UL,0x75FAA703UL,0x3A81D320UL,0x5DD8399AUL,0x92EB2D8FUL,
+  0x5DA439BBUL,0x52F37D85UL,0xE1A30879UL,0xC6A2D2F9UL,0x9D82E9A1UL,
+  0x8EF86442UL,0xAB71BF64UL,0x702B641FUL,0x6B482F76UL,0x9C26E9DAUL,
+  0xCEDB145BUL,0x4F7B7423UL,0x6759EABAUL,0xCF331415UL,0xCF4F1434UL,
+  0x0F57443EUL,0xB35075FCUL,0x2701DA80UL,0x5B203B58UL,0x137A8DE3UL,
+  0x2589DB26UL,0xDB5ADB7BUL,0x1B634B69UL,0xF76EC6ACUL,0x52FDFD81UL,
+  0x81A06078UL,0x28229E99UL,0xA86AFEAFUL,0x007C0021UL,0xC018500AUL,
+  0xBC0731C2UL,0x9451AF7CUL,0x7C21E1D8UL,0x485AB6BBUL,0x36F356C5UL,
+  0xFED3005DUL,0xC0399012UL,0xEC0D8DC5UL,0xA5933B2DUL,0xD35D9DF9UL,
+  0xA982FEE1UL,0x80486036UL,0xA816FE8EUL,0xC064502BUL,0x7C1F61C8UL,
+  0x28569EBEUL,0xE8704EA4UL,0x347B5763UL,0x7EA9E07EUL,0xC8205698UL,
+  0x3EEA904FUL,0x2C341DD7UL,0x499EB6E8UL,0x76CEA6D4UL,0x7ADF6318UL,
+  0x29CA9ED7UL,0x285E9EB8UL,0x6872AEA5UL,0xBC7B31E3UL,0x5449FF76UL,
+  0xC026D01AUL,0xDC0B19C7UL,0x4AD2B71DUL,0xB689B6E6UL,0xF6CAC6D7UL,
+  0x12DE8D98UL,0x65AAAB3FUL,0x3F50103CUL,0x0C11C5CCUL,0x5315FDCFUL,
+  0x0194006FUL,0x402C301DUL,0xD4099F46UL,0xE832CE95UL,0x946F2F6CUL,
+  0x1C2DC9DDUL,0x96D9AEDAUL,0xFC5B01FBUL,0x40437031UL,0xE4144B4FUL,
+  0x777426A7UL,0x5AFABB03UL,0x3341D5F0UL,0x5F043803UL,0x5281FDA0UL,
+  0x41B83072UL,0x9425AF5BUL,0x3C3B51D3UL,0x7C5DE1F9UL,0x8842E6B1UL,
+  0x8AF46707UL,0x6A82AF21UL,0xBC1871CAUL,0xA4573B7EUL,0x93606DE8UL,
+  0x2D8E9DA4UL,0x69BB6EF3UL,0x6C45EDF3UL,0x0D85C5A3UL,0x1339CDD2UL,
+  0xD59D9F29UL,0xA81EFE88UL,0x4066B02AUL,0xF41F0748UL,0x02B681B6UL,
+  0xE076C826UL,0xD69ADEEBUL,0x184F4AB4UL,0x37375696UL,0xBEEEF04CUL,
+  0x4435F357UL,0x05FE8300UL,0x61C02850UL,0x1EBC0871UL,0xC6A452FBUL,
+  0x7D8361A1UL,0xE8784EA2UL,0xB479B762UL,0xF6A986FEUL,0xE2C04990UL,
+  0x36EC16CDUL,0xCED5945FUL,0x2F781C22UL,0x89D9A6DAUL,0xFADB031BUL,
+  0x41CB7057UL,0x643EAB50UL,0x7F7C2021UL,0xD8185A8AUL,0xBB27335AUL,
+  0x95FB2F03UL,0x5C01F9C0UL,0x42D0319CUL,0x1469CF6EUL,0xD42C5F5DUL,
+  0xF8398292UL,0xE1AD887DUL,0xA6A1BAF8UL,0x7302A5C1UL,0xBB10734CUL,
+  0x25F5DB07UL,0x1B428B71UL,0xA7647AABUL,0x633F69D0UL,0x2EDC1C59UL,
+  0xC9FAD6C3UL,0x1ED1C85CUL,0x56B9FEF2UL,0xC0459033UL,0x2C15DDCFUL,
+  0x19940AEFUL,0x470C3285UL,0xD5A31F39UL,0xC812D68DUL,0x9EE5A84BUL,
+  0x3EB75076UL,0xBC26F1DAUL,0xC45B137BUL,0x4DE37589UL,0xE726CA9AUL,
+  0xD72B1E9FUL,0x486836AEUL,0x96FC6EC1UL,0xEC504DFCUL,0x3581D720UL,
+  0x5E98386AUL,0x92AF2DBCUL,0x1DB1C9B4UL,0x56F77EC6UL,0xA052F83DUL,
+  0x8291A1ACUL,0x787DE2A1UL,0x89B866F2UL,0xAAC5BF13UL,0x300DD405UL,
+  0x9F432831UL,0xDE94586FUL,0x7AAC233DUL,0xD9D19ADCUL,0x6B19EF4AUL,
+  0xCC3715D6UL,0x8F1EE408UL,0x4B46B772UL,0xF6A586FBUL,0x22C35991UL,
+  0xFAEC430DUL,0xF1C58453UL,0x237DD9E1UL,0x9AC86B16UL,0xAF4EFC34UL,
+  0x41D7705EUL,0xA4387B52UL,0xA37DB9E1UL,0xB2C87596UL,0xA72EFA9CUL,
+  0x4329F1DEUL,0xC458537AUL,0xBDE33189UL,0xD466DF6AUL,0xD82F1A9CUL,
+  0x0B29C75EUL,0xD2B85DB2UL,0xB9B5B2F7UL,0x35869722UL,0xEE998C6AUL,
+  0xE5EF0B0CUL,0x0745C2B3UL,0x11B5CC77UL,0x15E68F0AUL,0xE4070B42UL,
+  0x8771A2A4UL,0x79BB62F3UL,0x6985EEE3UL,0x0C49C5F6UL,0xD306DDC2UL,
+  0xD9919AECUL,0x6B0DEF45UL,0x8C3325D5UL,0xDB1F1B48UL,0x0B768766UL,
+  0xE2AAC9BFUL,0x16F00EC4UL,0x0453437DUL,0xF1E18448UL,0x6376A9E6UL,
+  0xFECAC057UL,0x103E8C10UL,0x65CC2B15UL,0xDF4F1834UL,0x0A97472EUL,
+  0xB29C75A9UL,0xE73ECA90UL,0x572C3E9DUL,0xD0699C2EUL,0xE9DC4ED9UL,
+  0xF45AC77BUL,0x12A34DB9UL,0xF5B2C735UL,0x92972DAEUL,0x9DBC69B1UL,
+  0xEEF44C47UL,0x75F2A705UL,0xBA833321UL,0xD5D85F1AUL,0xB80B3287UL,
+  0x55A2BF39UL,0xB012F40DUL,0x8745A2B3UL,0x39B5D2F7UL,0x1D8689A2UL,
+  0xE6F98AC2UL,0xE7118A8CUL,0x6725EA9BUL,0x0F2B441FUL,0x734825F6UL,
+  0x9B06EB42UL,0xCF719424UL,0x6F5B6C3BUL,0x6DD36D9DUL,0xEDA98DBEUL,
+  0xE5B04B34UL,0x375756BEUL,0xBEF07044UL,0x24335B55UL,0xFB7F0360UL,
+  0x01E8004EUL,0x80346017UL,0x680EAE84UL,0x7C6361E9UL,0xE84ECEB4UL,
+  0x54777F66UL,0xA02AF81FUL,0x028801A6UL,0x807AE023UL,0x0819C68AUL,
+  0xD2E71D8AUL,0x89A726FAUL,0x9AC32B11UL,0xDF4C5835UL,0xFA97032EUL,
+  0x81DC6059UL,0xE83ACE93UL,0x146DCF6DUL,0x942DAF5DUL,0xBC39B1D2UL,
+  0xF45D8779UL,0xA2A2F9B9UL,0x82F2E185UL,0x886326A9UL,0xDAFEDB00UL,
+  0x5B403B70UL,0x13640DEBUL,0x458F7324UL,0x25DB5B1BUL,0x7B4B6377UL,
+  0x69E6AECAUL,0xFC5701FEUL,0x80406030UL,0x28141E8FUL,0x486436ABUL,
+  0x56FF7EC0UL,0x2050183CUL,0x0A91C72CUL,0x529DFDA9UL,0x81BEE070UL,
+  0x4824369BUL,0x56EB7ECFUL,0x6054283FUL,0x5E90386CUL,0x12ADCDBDUL,
+  0x95B1AF34UL,0x7C1761CEUL,0xA8547EBFUL,0x60702824UL,0x1E9B486BUL,
+  0x76AF66FCUL,0x2AC1DF10UL,0x580C3A85UL,0xD3231DD9UL,0xC99AD6EBUL,
+  0x1ECF4854UL,0x36BF56F0UL,0x3EC41053UL,0x4C3DF5D1UL,0x871C6289UL,
+  0xE9A6CEFAUL,0xD4431F71UL,0xC824569BUL,0x7EEB604FUL,0x68342E97UL,
+  0x5C6EB9ECUL,0x72CDE595UL,0x8B2F275CUL,0x1AB9CB32UL,0xD7559EBFUL,
+  0x28701EA4UL,0x087B46A3UL,0x72F9E582UL,0xCB219758UL,0x6EBAAC73UL,
+  0x3DE5D18BUL,0x1C6749EAUL,0xB6CF36D4UL,0x16DF4ED8UL,0x345A977BUL,
+  0x2EA35C79UL,0xF9E2C2C9UL,0x9196EC6EUL,0xCDEC558DUL,0xFF25801BUL,
+  0x200B5807UL,0x7A82A321UL,0xB9D872DAUL,0xA59B3B2BUL,0x535F7DF8UL,
+  0x21829861UL,0xAAA87F3EUL,0xA010780CUL,0x2285D9A3UL,0x1AF9CB02UL,
+  0xD7419EB0UL,0x68742EA7UL,0x5C7AB9E3UL,0x32C9D596UL,0xDF2ED81CUL,
+  0x5A89FB26UL,0xC35AD1FBUL,0x1C4349F1UL,0xF6C446D3UL,0x72DDE599UL,
+  
+};
+#   endif
+
+#else  /* PROTOTYPES */
+
+#   if !defined        WORDS_BIGENDIAN
+/* little endian */
+static const UInt32_t yellowbook_scrambler_uint32[2340/4] = {
+  0x60008001,0x1E002800,0x06600880,0x81FE02A8,0x28606080,
+  0x889E1E28,0xAAAE6668,0xE0017FFC,0x36004800,0x0EE01680,
+  0x835604C8,0x48E0E17E,0x96B63648,0xCCC6EEF6,0x9FFDD552,
+  0x7E00A801,0x18602080,0x879E0A28,0xA99E6228,0xA0FE7EA8,
+  0x22307840,0x4AAF1994,0xD60137FC,0x38E05E80,0x8DB61248,
+  0xCBB6E5B6,0xDE56D736,0x5A70D8BE,0x533B3BA4,0xE1FD7D53,
+  0x66608881,0x9FFE2AA8,0x2E006800,0x09601C80,0x82CE06E8,
+  0x689F61D4,0x9CAE2E68,0xEEE1697C,0xB5564CC8,0x4600F7FE,
+  0x15E03280,0x84260F88,0x094BE31A,0xB2C646F7,0x879DF5D2,
+  0xF99EA229,0xB1FE42A8,0x27607480,0x8BAE1A68,0xEA51673C,
+  0xF4314FBC,0x724F4714,0x5BB725B4,0xF356BB36,0x53E0C57E,
+  0x91C63D08,0x8D6DEC92,0xBB8DA5ED,0x355BB325,0x7E0357FB,
+  0x4860E081,0x969E3628,0xACCE6EE8,0x61FF7D54,0x1E602880,
+  0x867E08A8,0x29F862A0,0xA8E19E82,0xA0B67E48,0xC226F876,
+  0x1CABD19A,0x36E0497F,0x8ED616C8,0x4B58E4DE,0x3663B77A,
+  0xDEFED6A9,0x3A5058C0,0xCD3113BC,0x7F9F55D4,0x981E2028,
+  0xAF866A08,0x8119FC22,0x0857E0CA,0x6290863E,0xDE8D29EC,
+  0x2A4B98E5,0xB8365FB7,0xC58EF216,0x7D3B53A4,0xE89D61D3,
+  0xE4AE8E69,0xF7614B7C,0xB2AE4668,0xE78175FC,0x37984A20,
+  0x2E9F962A,0x894E1CE8,0x6AC766F4,0xBC1DAFD2,0xF4C6B109,
+  0x927DC752,0x7DB8ADA1,0xB8B5A1B2,0x95A63277,0x0C33EFBA,
+  0x13CFC515,0x45CF0D14,0x552F3394,0xD0193FDC,0x1907DC0A,
+  0xA7D18AC2,0xE3897A1C,0xD6DAC926,0x48DB1EDB,0x66BB765B,
+  0xEFC56AF3,0xC50D0C13,0x2D1393C5,0x9995DDCD,0x1FFC2AAF,
+  0x5600C801,0x10E03E80,0x85360C48,0xC91EE3D6,0xBED656C8,
+  0x4458F0DE,0x3553B33A,0x9E01D7FD,0x2E606880,0x897E1CA8,
+  0x2AC866E0,0xE81E9FD6,0xB4864E08,0x8669F762,0x49FCE2AE,
+  0x46E0F681,0x95D632C8,0x4C28EF9E,0x77C8B51E,0xFA8EA616,
+  0x710B43E4,0xAB5264C7,0xB061BF7D,0xA71E7428,0xA3B67A48,
+  0xC2D6F936,0x5C98D1DE,0x32EFB96A,0xCF9515CC,0x0F1C142F,
+  0xD336C449,0xD9FEDD56,0x3BE05A80,0x8D461308,0x8B85E5F2,
+  0xDA592723,0x1B33DBBA,0x177FCB55,0x04A80E60,0x6160837E,
+  0x9E4E28E8,0x6E7768B4,0xFD7AACA6,0xC08901E3,0xDC2AD066,
+  0x0AC8191F,0xE21E87D6,0xB6A64988,0x06C3F6FA,0x51DCC2D1,
+  0xC16AFC99,0x0C4C10EF,0x13D7C535,0x65C88D1E,0xFF2EAB96,
+  0xF039405C,0x930DC412,0x3DF3AD45,0x1CA3D185,0xD6E2C979,
+  0xE8D69EC9,0x54B8CE5E,0xB065BF72,0x571F342B,0x90B63E48,
+  0xCD26EC76,0x1F9BD5DA,0x761F482B,0x9AE62688,0x0F17EBCA,
+  0x6334844E,0xAEFE6957,0x21507CC0,0xCA4118FC,0x3E3457B0,
+  0xBC6E5097,0xE4DD712C,0xE77A8B59,0xC7A90A63,0x5D90D23E,
+  0xD2BD39AC,0x69849DF1,0xECF96EA3,0x95F1CD42,0x6C236F84,
+  0xCDCAED19,0x8FAE1597,0xEB11643C,0xF4754F4C,0x825A0727,
+  0x58B321BB,0x03A7FA75,0x20D3813A,0x9A39D85D,0x8F2DEB92,
+  0xBB39A45D,0x857DF352,0x7908A3E1,0xF9D2A2C6,0xA1E9829D,
+  0x4264F88E,0x64BF71AB,0x1F642B70,0x762F486B,0xDAE9269C,
+  0x5B14DBCE,0x23747B4F,0xBAEA5967,0x151433CF,0x34144FCF,
+  0x3E44570F,0xFC7550B3,0x80DA0127,0x583B205B,0xE38D7A13,
+  0x26DB8925,0x7BDB5ADB,0x694B631B,0xACC66EF7,0x81FDFD52,
+  0x7860A081,0x999E2228,0xAFFE6AA8,0x21007C00,0x0A5018C0,
+  0xC23107BC,0x7CAF5194,0xD8E1217C,0xBBB65A48,0xC556F336,
+  0x5D00D3FE,0x129039C0,0xC58D0DEC,0x2D3B93A5,0xF99D5DD3,
+  0xE1FE82A9,0x36604880,0x8EFE16A8,0x2B5064C0,0xC8611F7C,
+  0xBE9E5628,0xA44E70E8,0x63577B34,0x7EE0A97E,0x985620C8,
+  0x4F90EA3E,0xD71D342C,0xE8B69E49,0xD4A6CE76,0x1863DF7A,
+  0xD79ECA29,0xB89E5E28,0xA5AE7268,0xE3317BBC,0x76FF4954,
+  0x1AD026C0,0xC7190BDC,0x1DB7D24A,0xE6B689B6,0xD7C6CAF6,
+  0x988DDE12,0x3FABAA65,0x3C10503F,0xCCC5110C,0xCFFD1553,
+  0x6F009401,0x1D302C40,0x469F09D4,0x95CE32E8,0x6C2F6F94,
+  0xDDC92D1C,0xDAAED996,0xFB015BFC,0x31704340,0x4F4B14E4,
+  0xA7267477,0x03BBFA5A,0xF0D54133,0x0338045F,0xA0FD8152,
+  0x7230B841,0x5BAF2594,0xD3513B3C,0xF9E15D7C,0xB1E64288,
+  0x0767F48A,0x21AF826A,0xCA7118BC,0x7E3B57A4,0xE86D6093,
+  0xA49D8E2D,0xF36EBB69,0xF3ED456C,0xA3C5850D,0xD2CD3913,
+  0x299F9DD5,0x88FE1EA8,0x2AB06640,0x48071FF4,0xB681B602,
+  0x26C876E0,0xEBDE9AD6,0xB44A4F18,0x96563737,0x4CF0EEBE,
+  0x57F33544,0x0083FE05,0x5028C061,0x7108BC1E,0xFB52A4C6,
+  0xA161837D,0xA24E78E8,0x62B779B4,0xFE86A9F6,0x9049C0E2,
+  0xCD16EC36,0x5F94D5CE,0x221C782F,0xDAA6D989,0x1B03DBFA,
+  0x5770CB41,0x50AB3E64,0x21207C7F,0x8A5A18D8,0x5A3327BB,
+  0x032FFB95,0xC0F9015C,0x9C31D042,0x6ECF6914,0x5D5F2CD4,
+  0x928239F8,0x7D88ADE1,0xF8BAA1A6,0xC1A50273,0x4C7310BB,
+  0x07DBF525,0x718B421B,0xAB7A64A7,0xD0693F63,0x591CDC2E,
+  0xC3D6FAC9,0x5CC8D11E,0xF2FEB956,0x339045C0,0xCFDD152C,
+  0xEF0A9419,0x85320C47,0x391FA3D5,0x8DD612C8,0x4BA8E59E,
+  0x7650B73E,0xDAF126BC,0x7B135BC4,0x8975E34D,0x9ACA26E7,
+  0x9F1E2BD7,0xAE366848,0xC16EFC96,0xFC4D50EC,0x20D78135,
+  0x6A38985E,0xBC2DAF92,0xB4C9B11D,0xC67EF756,0x3DF852A0,
+  0xACA19182,0xA1E27D78,0xF266B889,0x13BFC5AA,0x05D40D30,
+  0x3128439F,0x6F5894DE,0x3D23AC7A,0xDC9AD1D9,0x4AEF196B,
+  0xD61537CC,0x08E41E8F,0x72B7464B,0xFB86A5F6,0x9159C322,
+  0x0D43ECFA,0x5384C5F1,0xE1D97D23,0x166BC89A,0x34FC4EAF,
+  0x5E70D741,0x527B38A4,0xE1B97DA3,0x9675C8B2,0x9CFA2EA7,
+  0xDEF12943,0x7A5358C4,0x8931E3BD,0x6ADF66D4,0x9C1A2FD8,
+  0x5EC7290B,0xB25DB8D2,0xF7B2B5B9,0x22978635,0x6A8C99EE,
+  0x0C0BEFE5,0xB3C24507,0x77CCB511,0x0A8FE615,0x420B07E4,
+  0xA4A27187,0xF362BB79,0xE3EE8569,0xF6C5490C,0xC2DD06D3,
+  0xEC9A91D9,0x45EF0D6B,0xD525338C,0x481B1FDB,0x6687760B,
+  0xBFC9AAE2,0xC40EF016,0x7D435304,0x4884E1F1,0xE6A97663,
+  0x57C0CAFE,0x108C3E10,0x152BCC65,0x34184FDF,0x2E47970A,
+  0xA9759CB2,0x90CA3EE7,0x9D3E2C57,0x2E9C69D0,0xD94EDCE9,
+  0x7BC75AF4,0xB94DA312,0x35C7B2F5,0xAE2D9792,0xB169BC9D,
+  0x474CF4EE,0x05A7F275,0x213383BA,0x1A5FD8D5,0x87320BB8,
+  0x39BFA255,0x0DF412B0,0xB3A24587,0xF7D2B539,0xA289861D,
+  0xC28AF9E6,0x8C8A11E7,0x9BEA2567,0x1F442B0F,0xF6254873,
+  0x42EB069B,0x249471CF,0x3B6C5B6F,0x9D6DD36D,0xBE8DA9ED,
+  0x344BB0E5,0xBE565737,0x4470F0BE,0x555B3324,0x60037FFB,
+  0x4E00E801,0x17603480,0x84AE0E68,0xE961637C,0xB4CE4EE8,
+  0x667F7754,0x1FF82AA0,0xA6018802,0x23E07A80,0x8AC61908,
+  0x8A1DE7D2,0xFA26A789,0x112BC39A,0x35584CDF,0x2E0397FA,
+  0x5960DC81,0x93CE3AE8,0x6DCF6D14,0x5DAF2D94,0xD2B139BC,
+  0x79875DF4,0xB9F9A2A2,0x85E1F282,0xA9266388,0x00DBFEDA,
+  0x703B405B,0xEB0D6413,0x24738F45,0x1B5BDB25,0x77634B7B,
+  0xCAAEE669,0xFE0157FC,0x30604080,0x8F1E1428,0xAB366448,
+  0xC07EFF56,0x3C185020,0x2CC7910A,0xA9FD9D52,0x70E0BE81,
+  0x9B362448,0xCF7EEB56,0x3F285460,0x6C38905E,0xBDCDAD12,
+  0x34AFB195,0xCE61177C,0xBF7E54A8,0x24287060,0x6B489B1E,
+  0xFC66AF76,0x10DFC12A,0x853A0C58,0xD91D23D3,0xEBD69AC9,
+  0x5448CF1E,0xF056BF36,0x5310C43E,0xD1F53D4C,0x89621C87,
+  0xFACEA6E9,0x711F43D4,0x9B5624C8,0x4F60EB7E,0x972E3468,
+  0xECB96E5C,0x95E5CD72,0x5C272F8B,0x32CBB91A,0xBF9E55D7,
+  0xA41E7028,0xA3467B08,0x82E5F972,0x589721CB,0x73ACBA6E,
+  0x8BD1E53D,0xEA49671C,0xD436CFB6,0xD84EDF16,0x7B975A34,
+  0x795CA32E,0xC9C2E2F9,0x6EEC9691,0x8D55ECCD,0x1B8025FF,
+  0x07580B20,0x21A3827A,0xDA72D8B9,0x2B3B9BA5,0xF87D5F53,
+  0x61988221,0x3E7FA8AA,0x0C7810A0,0xA3D98522,0x02CBF91A,
+  0xB09E41D7,0xA72E7468,0xE3B97A5C,0x96D5C932,0x1CD82EDF,
+  0x26FB895A,0xFBD15AC3,0xF149431C,0xD346C4F6,0x99E5DD72,
+  
+};
+#   endif
+#   if defined WORDS_BIGENDIAN
+/* big endian */
+static const UInt32_t yellowbook_scrambler_uint32[2340/4] = {
+  0x01800060,0x0028001E,0x80086006,0xA802FE81,0x80606028,
+  0x281E9E88,0x6866AEAA,0xFC7F01E0,0x00480036,0x8016E00E,
+  0xC8045683,0x7EE1E048,0x4836B696,0xF6EEC6CC,0x52D5FD9F,
+  0x01A8007E,0x80206018,0x280A9E87,0x28629EA9,0xA87EFEA0,
+  0x40783022,0x9419AF4A,0xFC3701D6,0x805EE038,0x4812B68D,
+  0xB6E5B6CB,0x36D756DE,0xBED8705A,0xA43B3B53,0x537DFDE1,
+  0x81886066,0xA82AFE9F,0x0068002E,0x801C6009,0xE806CE82,
+  0xD4619F68,0x682EAE9C,0x7C69E1EE,0xC84C56B5,0xFEF70046,
+  0x8032E015,0x880F2684,0x1AE34B09,0xF746C6B2,0xD2F59D87,
+  0x29A29EF9,0xA842FEB1,0x80746027,0x681AAE8B,0x3C6751EA,
+  0xBC4F31F4,0x14474F72,0xB425B75B,0x36BB56F3,0x7EC5E053,
+  0x083DC691,0x92EC6D8D,0xEDA58DBB,0x25B35B35,0xFB57037E,
+  0x81E06048,0x28369E96,0xE86ECEAC,0x547DFF61,0x8028601E,
+  0xA8087E86,0xA062F829,0x829EE1A8,0x487EB6A0,0x76F826C2,
+  0x9AD1AB1C,0x7F49E036,0xC816D68E,0xDEE4584B,0x7AB76336,
+  0xA9D6FEDE,0xC058503A,0xBC1331CD,0xD4559F7F,0x28201E98,
+  0x086A86AF,0x22FC1981,0xCAE05708,0x3E869062,0xEC298DDE,
+  0xE5984B2A,0xB75F36B8,0x16F28EC5,0xA4533B7D,0xD3619DE8,
+  0x698EAEE4,0x7C4B61F7,0x6846AEB2,0xFC7581E7,0x204A9837,
+  0x2A969F2E,0xE81C4E89,0xF466C76A,0xD2AF1DBC,0x09B1C6F4,
+  0x52C77D92,0xA1ADB87D,0xB2A1B5B8,0x7732A695,0xBAEF330C,
+  0x15C5CF13,0x140DCF45,0x94332F55,0xDC3F19D0,0x0ADC0719,
+  0xC28AD1A7,0x1C7A89E3,0x26C9DAD6,0xDB1EDB48,0x5B76BB66,
+  0xF36AC5EF,0x130C0DC5,0xC593132D,0xCDDD9599,0xAF2AFC1F,
+  0x01C80056,0x803EE010,0x480C3685,0xD6E31EC9,0xC856D6BE,
+  0xDEF05844,0x3AB35335,0xFDD7019E,0x8068602E,0xA81C7E89,
+  0xE066C82A,0xD69F1EE8,0x084E86B4,0x62F76986,0xAEE2FC49,
+  0x81F6E046,0xC832D695,0x9EEF284C,0x1EB5C877,0x16A68EFA,
+  0xE4430B71,0xC76452AB,0x7DBF61B0,0x28741EA7,0x487AB6A3,
+  0x36F9D6C2,0xDED1985C,0x6AB9EF32,0xCC1595CF,0x2F141C0F,
+  0x49C436D3,0x56DDFED9,0x805AE03B,0x0813468D,0xF2E5858B,
+  0x232759DA,0xBADB331B,0x55CB7F17,0x600EA804,0x7E836061,
+  0xE8284E9E,0xB468776E,0xA6AC7AFD,0xE30189C0,0x66D02ADC,
+  0x1F19C80A,0xD6871EE2,0x8849A6B6,0xFAF6C306,0xD1C2DC51,
+  0x99FC6AC1,0xEF104C0C,0x35C5D713,0x1E8DC865,0x96AB2EFF,
+  0x5C4039F0,0x12C40D93,0x45ADF33D,0x85D1A31C,0x79C9E2D6,
+  0xC99ED6E8,0x5ECEB854,0x72BF65B0,0x2B341F57,0x483EB690,
+  0x76EC26CD,0xDAD59B1F,0x2B481F76,0x8826E69A,0xCAEB170F,
+  0x4E843463,0x5769FEAE,0xC07C5021,0xFC1841CA,0xB057343E,
+  0x97506EBC,0x2C71DDE4,0x598B7AE7,0x630AA9C7,0x3ED2905D,
+  0xAC39BDD2,0xF19D8469,0xA36EF9EC,0x42CDF195,0x846F236C,
+  0x19EDCACD,0x9715AE8F,0x3C6411EB,0x4C4F75F4,0x27075A82,
+  0xBB21B358,0x75FAA703,0x3A81D320,0x5DD8399A,0x92EB2D8F,
+  0x5DA439BB,0x52F37D85,0xE1A30879,0xC6A2D2F9,0x9D82E9A1,
+  0x8EF86442,0xAB71BF64,0x702B641F,0x6B482F76,0x9C26E9DA,
+  0xCEDB145B,0x4F7B7423,0x6759EABA,0xCF331415,0xCF4F1434,
+  0x0F57443E,0xB35075FC,0x2701DA80,0x5B203B58,0x137A8DE3,
+  0x2589DB26,0xDB5ADB7B,0x1B634B69,0xF76EC6AC,0x52FDFD81,
+  0x81A06078,0x28229E99,0xA86AFEAF,0x007C0021,0xC018500A,
+  0xBC0731C2,0x9451AF7C,0x7C21E1D8,0x485AB6BB,0x36F356C5,
+  0xFED3005D,0xC0399012,0xEC0D8DC5,0xA5933B2D,0xD35D9DF9,
+  0xA982FEE1,0x80486036,0xA816FE8E,0xC064502B,0x7C1F61C8,
+  0x28569EBE,0xE8704EA4,0x347B5763,0x7EA9E07E,0xC8205698,
+  0x3EEA904F,0x2C341DD7,0x499EB6E8,0x76CEA6D4,0x7ADF6318,
+  0x29CA9ED7,0x285E9EB8,0x6872AEA5,0xBC7B31E3,0x5449FF76,
+  0xC026D01A,0xDC0B19C7,0x4AD2B71D,0xB689B6E6,0xF6CAC6D7,
+  0x12DE8D98,0x65AAAB3F,0x3F50103C,0x0C11C5CC,0x5315FDCF,
+  0x0194006F,0x402C301D,0xD4099F46,0xE832CE95,0x946F2F6C,
+  0x1C2DC9DD,0x96D9AEDA,0xFC5B01FB,0x40437031,0xE4144B4F,
+  0x777426A7,0x5AFABB03,0x3341D5F0,0x5F043803,0x5281FDA0,
+  0x41B83072,0x9425AF5B,0x3C3B51D3,0x7C5DE1F9,0x8842E6B1,
+  0x8AF46707,0x6A82AF21,0xBC1871CA,0xA4573B7E,0x93606DE8,
+  0x2D8E9DA4,0x69BB6EF3,0x6C45EDF3,0x0D85C5A3,0x1339CDD2,
+  0xD59D9F29,0xA81EFE88,0x4066B02A,0xF41F0748,0x02B681B6,
+  0xE076C826,0xD69ADEEB,0x184F4AB4,0x37375696,0xBEEEF04C,
+  0x4435F357,0x05FE8300,0x61C02850,0x1EBC0871,0xC6A452FB,
+  0x7D8361A1,0xE8784EA2,0xB479B762,0xF6A986FE,0xE2C04990,
+  0x36EC16CD,0xCED5945F,0x2F781C22,0x89D9A6DA,0xFADB031B,
+  0x41CB7057,0x643EAB50,0x7F7C2021,0xD8185A8A,0xBB27335A,
+  0x95FB2F03,0x5C01F9C0,0x42D0319C,0x1469CF6E,0xD42C5F5D,
+  0xF8398292,0xE1AD887D,0xA6A1BAF8,0x7302A5C1,0xBB10734C,
+  0x25F5DB07,0x1B428B71,0xA7647AAB,0x633F69D0,0x2EDC1C59,
+  0xC9FAD6C3,0x1ED1C85C,0x56B9FEF2,0xC0459033,0x2C15DDCF,
+  0x19940AEF,0x470C3285,0xD5A31F39,0xC812D68D,0x9EE5A84B,
+  0x3EB75076,0xBC26F1DA,0xC45B137B,0x4DE37589,0xE726CA9A,
+  0xD72B1E9F,0x486836AE,0x96FC6EC1,0xEC504DFC,0x3581D720,
+  0x5E98386A,0x92AF2DBC,0x1DB1C9B4,0x56F77EC6,0xA052F83D,
+  0x8291A1AC,0x787DE2A1,0x89B866F2,0xAAC5BF13,0x300DD405,
+  0x9F432831,0xDE94586F,0x7AAC233D,0xD9D19ADC,0x6B19EF4A,
+  0xCC3715D6,0x8F1EE408,0x4B46B772,0xF6A586FB,0x22C35991,
+  0xFAEC430D,0xF1C58453,0x237DD9E1,0x9AC86B16,0xAF4EFC34,
+  0x41D7705E,0xA4387B52,0xA37DB9E1,0xB2C87596,0xA72EFA9C,
+  0x4329F1DE,0xC458537A,0xBDE33189,0xD466DF6A,0xD82F1A9C,
+  0x0B29C75E,0xD2B85DB2,0xB9B5B2F7,0x35869722,0xEE998C6A,
+  0xE5EF0B0C,0x0745C2B3,0x11B5CC77,0x15E68F0A,0xE4070B42,
+  0x8771A2A4,0x79BB62F3,0x6985EEE3,0x0C49C5F6,0xD306DDC2,
+  0xD9919AEC,0x6B0DEF45,0x8C3325D5,0xDB1F1B48,0x0B768766,
+  0xE2AAC9BF,0x16F00EC4,0x0453437D,0xF1E18448,0x6376A9E6,
+  0xFECAC057,0x103E8C10,0x65CC2B15,0xDF4F1834,0x0A97472E,
+  0xB29C75A9,0xE73ECA90,0x572C3E9D,0xD0699C2E,0xE9DC4ED9,
+  0xF45AC77B,0x12A34DB9,0xF5B2C735,0x92972DAE,0x9DBC69B1,
+  0xEEF44C47,0x75F2A705,0xBA833321,0xD5D85F1A,0xB80B3287,
+  0x55A2BF39,0xB012F40D,0x8745A2B3,0x39B5D2F7,0x1D8689A2,
+  0xE6F98AC2,0xE7118A8C,0x6725EA9B,0x0F2B441F,0x734825F6,
+  0x9B06EB42,0xCF719424,0x6F5B6C3B,0x6DD36D9D,0xEDA98DBE,
+  0xE5B04B34,0x375756BE,0xBEF07044,0x24335B55,0xFB7F0360,
+  0x01E8004E,0x80346017,0x680EAE84,0x7C6361E9,0xE84ECEB4,
+  0x54777F66,0xA02AF81F,0x028801A6,0x807AE023,0x0819C68A,
+  0xD2E71D8A,0x89A726FA,0x9AC32B11,0xDF4C5835,0xFA97032E,
+  0x81DC6059,0xE83ACE93,0x146DCF6D,0x942DAF5D,0xBC39B1D2,
+  0xF45D8779,0xA2A2F9B9,0x82F2E185,0x886326A9,0xDAFEDB00,
+  0x5B403B70,0x13640DEB,0x458F7324,0x25DB5B1B,0x7B4B6377,
+  0x69E6AECA,0xFC5701FE,0x80406030,0x28141E8F,0x486436AB,
+  0x56FF7EC0,0x2050183C,0x0A91C72C,0x529DFDA9,0x81BEE070,
+  0x4824369B,0x56EB7ECF,0x6054283F,0x5E90386C,0x12ADCDBD,
+  0x95B1AF34,0x7C1761CE,0xA8547EBF,0x60702824,0x1E9B486B,
+  0x76AF66FC,0x2AC1DF10,0x580C3A85,0xD3231DD9,0xC99AD6EB,
+  0x1ECF4854,0x36BF56F0,0x3EC41053,0x4C3DF5D1,0x871C6289,
+  0xE9A6CEFA,0xD4431F71,0xC824569B,0x7EEB604F,0x68342E97,
+  0x5C6EB9EC,0x72CDE595,0x8B2F275C,0x1AB9CB32,0xD7559EBF,
+  0x28701EA4,0x087B46A3,0x72F9E582,0xCB219758,0x6EBAAC73,
+  0x3DE5D18B,0x1C6749EA,0xB6CF36D4,0x16DF4ED8,0x345A977B,
+  0x2EA35C79,0xF9E2C2C9,0x9196EC6E,0xCDEC558D,0xFF25801B,
+  0x200B5807,0x7A82A321,0xB9D872DA,0xA59B3B2B,0x535F7DF8,
+  0x21829861,0xAAA87F3E,0xA010780C,0x2285D9A3,0x1AF9CB02,
+  0xD7419EB0,0x68742EA7,0x5C7AB9E3,0x32C9D596,0xDF2ED81C,
+  0x5A89FB26,0xC35AD1FB,0x1C4349F1,0xF6C446D3,0x72DDE599,
+  
+};
+#   endif
+
+#endif /* PROTOTYPES */
diff --git a/libhfs_iso/CMakeLists.txt b/libhfs_iso/CMakeLists.txt
new file mode 100644 (file)
index 0000000..8558690
--- /dev/null
@@ -0,0 +1,8 @@
+PROJECT (LIBhfs_iso C)
+INCLUDE_DIRECTORIES(../include ../libhfs_iso ../wodim ${CMAKE_BINARY_DIR} ${CMAKE_BINARY_DIR}/include)
+ADD_DEFINITIONS(-DUSE_LARGEFILES -DABORT_DEEP_ISO_ONLY -DAPPLE_HYB -DUDF -DDVD_VIDEO -DSORTING -DHAVE_CONFIG_H -DUSE_LIBSCHILY -DUSE_SCG)
+
+
+SET(LIBhfs_iso_SRCS block.c btree.c data.c file.c gdata.c hfs.c low.c node.c record.c volume.c)
+
+ADD_LIBRARY (hfs_iso STATIC ${LIBhfs_iso_SRCS})
diff --git a/libhfs_iso/README b/libhfs_iso/README
new file mode 100644 (file)
index 0000000..5c6c00b
--- /dev/null
@@ -0,0 +1,41 @@
+# @(#)README   1.1 97/07/21 joerg
+                    06/09/11 christian
+
+Modified version of libhfs (v2.0) to work with mkhybrid.
+
+To complile for mkhybrid, use the #define -DAPPLE_HYB
+
+The libhfs.a created with this option must not be used with other
+hfsutils routines.
+
+James Pearson 18/7/97
+
+Copyright information from hfsutils:
+
+ hfsutils - tools for reading and writing Macintosh HFS volumes
+ Copyright (C) 1996, 1997 Robert Leslie
+
+ This describes the program as shipped with cdrkit, a spinoff from the
+ cdrtools project. However, the cdrtools developers are no longer 
+ involved in the development of this spinoff and therefore shall not
+ be made responsible for any problem caused by it. Do not try to get 
+ support for this program by contacting the original authors.
+
+ 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 of the License, 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.
+
+
+Source: lihfs_iso/README from cdrtools package
+Edited for cdrkit by Christian Fromme <kaner@strace.org>
+
diff --git a/libhfs_iso/block.c b/libhfs_iso/block.c
new file mode 100644 (file)
index 0000000..bbca145
--- /dev/null
@@ -0,0 +1,219 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)block.c 1.3 01/11/01 joerg */
+/*
+ * hfsutils - tools for reading and writing Macintosh HFS volumes
+ * Copyright (C) 1996, 1997 Robert Leslie
+ *
+ * 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 of the License, 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 <mconfig.h>
+#include <strdefs.h>
+#include <unixstd.h>
+#include <errno.h>
+
+#include "internal.h"
+#include "data.h"
+#include "block.h"
+#include "low.h"
+
+#ifdef DEBUG
+#include <stdio.h>
+#endif /* DEBUG */
+
+/*
+ * NAME:       block->readlb()
+ * DESCRIPTION:        read a logical block from a volume
+ */
+int b_readlb(hfsvol *vol, unsigned long num, block *bp)
+{
+#ifndef APPLE_HYB
+  int bytes;
+#endif
+#ifdef APPLE_HYB
+  block *b;
+  hce_mem *hce;
+
+#ifdef DEBUG
+  fprintf(stderr,"b_readlb: start block = %d\n", vol->vstart + num);
+#endif /* DEBUG */
+
+  hce = vol->hce;
+
+/* Check to see if requested block is in the HFS header or catalog/exents
+   files. If it is, read info from memory copy. If not, then something
+   has gone horribly wrong ... */
+
+  if (num < hce->hfs_hdr_size) 
+      b = (block *)hce->hfs_hdr + num;
+  else if (num < hce->hfs_hdr_size + hce->hfs_ce_size)
+      b = (block *)hce->hfs_ce + num - hce->hfs_hdr_size;
+  else
+    {
+      ERROR(EIO, "should not happen!");
+      return -1;
+    }
+
+  memcpy(bp, b, HFS_BLOCKSZ);
+
+#else
+
+  if (lseek(vol->fd, (vol->vstart + num) * HFS_BLOCKSZ, SEEK_SET) < 0)
+    {
+      ERROR(errno, "error seeking device");
+      return -1;
+    }
+
+  bytes = read(vol->fd, bp, HFS_BLOCKSZ);
+  if (bytes < 0)
+    {
+      ERROR(errno, "error reading from device");
+      return -1;
+    }
+  else if (bytes == 0)
+    {
+      ERROR(EIO, "read EOF on volume");
+      return -1;
+    }
+  else if (bytes != HFS_BLOCKSZ)
+    {
+      ERROR(EIO, "read incomplete block");
+      return -1;
+    }
+#endif /* APPLE_HYB */
+  return 0;
+}
+
+/*
+ * NAME:       block->writelb()
+ * DESCRIPTION:        write a logical block to a volume
+ */
+int b_writelb(hfsvol *vol, unsigned long num, block *bp)
+{
+#ifndef APPLE_HYB
+  int bytes;
+#endif
+#ifdef APPLE_HYB
+  block *b;
+  hce_mem *hce;
+
+#ifdef DEBUG
+  fprintf(stderr,"b_writelb: start block = %d\n", vol->vstart + num);
+#endif /* DEBUG */
+
+   hce = vol->hce;
+
+/* Check to see if requested block is in the HFS header or catalog/exents
+   files. If it is, write info to memory copy. If not, then it's a block
+   for an ordinary file - and as we are writing the files later, then just
+   ignore and return OK */
+  if (num < hce->hfs_hdr_size) 
+      b = (block *)hce->hfs_hdr + num;
+  else if (num < hce->hfs_hdr_size + hce->hfs_ce_size)
+      b = (block *)hce->hfs_ce + num - hce->hfs_hdr_size;
+  else
+    {
+#ifdef DEBUG
+      fprintf(stderr,"b_writelb: ignoring\n");
+#endif /* DEBUG */
+      return 0;
+    }
+
+  memcpy(b, bp, HFS_BLOCKSZ);
+
+#else
+
+  if (lseek(vol->fd, (vol->vstart + num) * HFS_BLOCKSZ, SEEK_SET) < 0)
+    {
+      ERROR(errno, "error seeking device");
+      return -1;
+    }
+
+  bytes = write(vol->fd, bp, HFS_BLOCKSZ);
+
+  if (bytes < 0)
+    {
+      ERROR(errno, "error writing to device");
+      return -1;
+    }
+  else if (bytes != HFS_BLOCKSZ)
+    {
+      ERROR(EIO, "wrote incomplete block");
+      return -1;
+    }
+#endif /* APPLE_HYB */
+  return 0;
+}
+
+/*
+ * NAME:       block->readab()
+ * DESCRIPTION:        read a block from an allocation block from a volume
+ */
+int b_readab(hfsvol *vol, unsigned int anum, unsigned int idx, block *bp)
+{
+  /* verify the allocation block exists and is marked as in-use */
+
+  if (anum >= vol->mdb.drNmAlBlks)
+    {
+      ERROR(EIO, "read nonexistent block");
+      return -1;
+    }
+  else if (vol->vbm && ! BMTST(vol->vbm, anum))
+    {
+      ERROR(EIO, "read unallocated block");
+      return -1;
+    }
+
+  return b_readlb(vol, vol->mdb.drAlBlSt + anum * vol->lpa + idx, bp);
+}
+
+/*
+ * NAME:       b->writeab()
+ * DESCRIPTION:        write a block to an allocation block to a volume
+ */
+int b_writeab(hfsvol *vol, unsigned int anum, unsigned int idx, block *bp)
+{
+  /* verify the allocation block exists and is marked as in-use */
+
+  if (anum >= vol->mdb.drNmAlBlks)
+    {
+      ERROR(EIO, "write nonexistent block");
+      return -1;
+    }
+  else if (vol->vbm && ! BMTST(vol->vbm, anum))
+    {
+      ERROR(EIO, "write unallocated block");
+      return -1;
+    }
+
+  vol->mdb.drAtrb &= ~HFS_ATRB_UMOUNTED;
+  vol->mdb.drLsMod = d_tomtime(time(0));
+  ++vol->mdb.drWrCnt;
+
+  vol->flags |= HFS_UPDATE_MDB;
+
+  return b_writelb(vol, vol->mdb.drAlBlSt + anum * vol->lpa + idx, bp);
+}
diff --git a/libhfs_iso/block.h b/libhfs_iso/block.h
new file mode 100644 (file)
index 0000000..ce3932d
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)block.h 1.1 00/03/05 joerg */
+/*
+ * hfsutils - tools for reading and writing Macintosh HFS volumes
+ * Copyright (C) 1996, 1997 Robert Leslie
+ *
+ * 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 of the License, 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.
+ */
+
+int b_readlb(hfsvol *, unsigned long, block *);
+int b_writelb(hfsvol *, unsigned long, block *);
+
+int b_readab(hfsvol *, unsigned int, unsigned int, block *);
+int b_writeab(hfsvol *, unsigned int, unsigned int, block *);
diff --git a/libhfs_iso/btree.c b/libhfs_iso/btree.c
new file mode 100644 (file)
index 0000000..9023428
--- /dev/null
@@ -0,0 +1,740 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)btree.c 1.3 04/06/17 joerg */
+/*
+ * hfsutils - tools for reading and writing Macintosh HFS volumes
+ * Copyright (C) 1996, 1997 Robert Leslie
+ *
+ * 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 of the License, 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 <mconfig.h>
+#include <stdxlib.h>
+#include <strdefs.h>
+#include <errno.h>
+
+#include "internal.h"
+#include "data.h"
+#include "block.h"
+#include "file.h"
+#include "btree.h"
+#include "node.h"
+
+/*
+ * NAME:       btree->getnode()
+ * DESCRIPTION:        retrieve a numbered node from a B*-tree file
+ */
+int bt_getnode(node *np)
+{
+  btree *bt = np->bt;
+  block *bp = &np->data;
+  unsigned char *ptr;
+  int i;
+
+  /* verify the node exists and is marked as in-use */
+
+       /*
+        * XXX This is the original code. As np->nnum is unsigned, the
+        * XXX comparison for < 0 makes no sense.
+        * XXX Thanks for a hint from Mike.Sullivan@Eng.Sun.COM
+        */
+/*  if (np->nnum < 0 || (np->nnum > 0 && np->nnum >= bt->hdr.bthNNodes))*/
+
+  if (np->nnum > 0 && np->nnum >= bt->hdr.bthNNodes)
+    {
+      ERROR(EIO, "read nonexistent b*-tree node");
+      return -1;
+    }
+
+  if (bt->map && ! BMTST(bt->map, np->nnum))
+    {
+      ERROR(EIO, "read unallocated b*-tree node");
+      return -1;
+    }
+
+  if (f_getblock(&bt->f, np->nnum, bp) < 0)
+    return -1;
+
+  ptr = *bp;
+
+  d_fetchl(&ptr, (long *) &np->nd.ndFLink);
+  d_fetchl(&ptr, (long *) &np->nd.ndBLink);
+  d_fetchb(&ptr, (char *) &np->nd.ndType);
+  d_fetchb(&ptr, (char *) &np->nd.ndNHeight);
+  d_fetchw(&ptr, (short *) &np->nd.ndNRecs);
+  d_fetchw(&ptr, &np->nd.ndResv2);
+
+  if (np->nd.ndNRecs > HFS_MAXRECS)
+    {
+      ERROR(EIO, "too many b*-tree node records");
+      return -1;
+    }
+
+  i = np->nd.ndNRecs + 1;
+
+  ptr = *bp + HFS_BLOCKSZ - (2 * i);
+
+  while (i--)
+    d_fetchw(&ptr, (short *) &np->roff[i]);
+
+  return 0;
+}
+
+/*
+ * NAME:       btree->putnode()
+ * DESCRIPTION:        store a numbered node into a B*-tree file
+ */
+int bt_putnode(node *np)
+{
+  btree *bt = np->bt;
+  block *bp = &np->data;
+  unsigned char *ptr;
+  int i;
+
+  /* verify the node exists and is marked as in-use */
+
+  if (np->nnum && np->nnum >= bt->hdr.bthNNodes)
+    {
+      ERROR(EIO, "write nonexistent b*-tree node");
+      return -1;
+    }
+  else if (bt->map && ! BMTST(bt->map, np->nnum))
+    {
+      ERROR(EIO, "write unallocated b*-tree node");
+      return -1;
+    }
+
+  ptr = *bp;
+
+  d_storel(&ptr, np->nd.ndFLink);
+  d_storel(&ptr, np->nd.ndBLink);
+  d_storeb(&ptr, np->nd.ndType);
+  d_storeb(&ptr, np->nd.ndNHeight);
+  d_storew(&ptr, np->nd.ndNRecs);
+  d_storew(&ptr, np->nd.ndResv2);
+
+  if (np->nd.ndNRecs > HFS_MAXRECS)
+    {
+      ERROR(EIO, "too many b*-tree node records");
+      return -1;
+    }
+
+  i = np->nd.ndNRecs + 1;
+
+  ptr = *bp + HFS_BLOCKSZ - (2 * i);
+
+  while (i--)
+    d_storew(&ptr, np->roff[i]);
+
+  if (f_putblock(&bt->f, np->nnum, bp) < 0)
+    return -1;
+
+  return 0;
+}
+
+/*
+ * NAME:       btree->readhdr()
+ * DESCRIPTION:        read the header node of a B*-tree
+ */
+int bt_readhdr(btree *bt)
+{
+  unsigned char *ptr;
+  char *map;
+  int i;
+  unsigned long nnum;
+
+  bt->hdrnd.bt   = bt;
+  bt->hdrnd.nnum = 0;
+
+  if (bt_getnode(&bt->hdrnd) < 0)
+    return -1;
+
+  if (bt->hdrnd.nd.ndType != ndHdrNode ||
+      bt->hdrnd.nd.ndNRecs != 3 ||
+      bt->hdrnd.roff[0] != 0x00e ||
+      bt->hdrnd.roff[1] != 0x078 ||
+      bt->hdrnd.roff[2] != 0x0f8 ||
+      bt->hdrnd.roff[3] != 0x1f8)
+    {
+      ERROR(EIO, "malformed b*-tree header node");
+      return -1;
+    }
+
+  /* read header record */
+
+  ptr = HFS_NODEREC(bt->hdrnd, 0);
+
+  d_fetchw(&ptr, (short *) &bt->hdr.bthDepth);
+  d_fetchl(&ptr, (long *) &bt->hdr.bthRoot);
+  d_fetchl(&ptr, (long *) &bt->hdr.bthNRecs);
+  d_fetchl(&ptr, (long *) &bt->hdr.bthFNode);
+  d_fetchl(&ptr, (long *) &bt->hdr.bthLNode);
+  d_fetchw(&ptr, (short *) &bt->hdr.bthNodeSize);
+  d_fetchw(&ptr, (short *) &bt->hdr.bthKeyLen);
+  d_fetchl(&ptr, (long *) &bt->hdr.bthNNodes);
+  d_fetchl(&ptr, (long *) &bt->hdr.bthFree);
+
+  for (i = 0; i < 76; ++i)
+    d_fetchb(&ptr, (char *) &bt->hdr.bthResv[i]);
+
+  if (bt->hdr.bthNodeSize != HFS_BLOCKSZ)
+    {
+      ERROR(EINVAL, "unsupported b*-tree node size");
+      return -1;
+    }
+
+  /* read map record; construct btree bitmap */
+  /* don't set bt->map until we're done, since getnode() checks it */
+
+  map = ALLOC(char, HFS_MAP1SZ);
+  if (map == 0)
+    {
+      ERROR(ENOMEM, 0);
+      return -1;
+    }
+
+  memcpy(map, HFS_NODEREC(bt->hdrnd, 2), HFS_MAP1SZ);
+  bt->mapsz = HFS_MAP1SZ;
+
+  /* read continuation map records, if any */
+
+  nnum = bt->hdrnd.nd.ndFLink;
+
+  while (nnum)
+    {
+      node n;
+      char *newmap;
+
+      n.bt   = bt;
+      n.nnum = nnum;
+
+      if (bt_getnode(&n) < 0)
+       {
+         FREE(map);
+         return -1;
+       }
+
+      if (n.nd.ndType != ndMapNode ||
+         n.nd.ndNRecs != 1 ||
+         n.roff[0] != 0x00e ||
+         n.roff[1] != 0x1fa)
+       {
+         FREE(map);
+         ERROR(EIO, "malformed b*-tree map node");
+         return -1;
+       }
+
+      newmap = REALLOC(map, char, bt->mapsz + HFS_MAPXSZ);
+      if (newmap == 0)
+       {
+         FREE(map);
+         ERROR(ENOMEM, 0);
+         return -1;
+       }
+      map = newmap;
+
+      memcpy(map + bt->mapsz, HFS_NODEREC(n, 0), HFS_MAPXSZ);
+      bt->mapsz += HFS_MAPXSZ;
+
+      nnum = n.nd.ndFLink;
+    }
+
+  bt->map = map;
+
+  return 0;
+}
+
+/*
+ * NAME:       btree->writehdr()
+ * DESCRIPTION:        write the header node of a B*-tree
+ */
+int bt_writehdr(btree *bt)
+{
+  unsigned char *ptr;
+  char *map;
+  unsigned long mapsz, nnum;
+  int i;
+
+  if (bt->hdrnd.bt != bt ||
+      bt->hdrnd.nnum != 0 ||
+      bt->hdrnd.nd.ndType != ndHdrNode ||
+      bt->hdrnd.nd.ndNRecs != 3)
+    abort();
+
+  ptr = HFS_NODEREC(bt->hdrnd, 0);
+
+  d_storew(&ptr, bt->hdr.bthDepth);
+  d_storel(&ptr, bt->hdr.bthRoot);
+  d_storel(&ptr, bt->hdr.bthNRecs);
+  d_storel(&ptr, bt->hdr.bthFNode);
+  d_storel(&ptr, bt->hdr.bthLNode);
+  d_storew(&ptr, bt->hdr.bthNodeSize);
+  d_storew(&ptr, bt->hdr.bthKeyLen);
+  d_storel(&ptr, bt->hdr.bthNNodes);
+  d_storel(&ptr, bt->hdr.bthFree);
+
+  for (i = 0; i < 76; ++i)
+    d_storeb(&ptr, bt->hdr.bthResv[i]);
+
+  memcpy(HFS_NODEREC(bt->hdrnd, 2), bt->map, HFS_MAP1SZ);
+
+  if (bt_putnode(&bt->hdrnd) < 0)
+    return -1;
+
+  map   = bt->map   + HFS_MAP1SZ;
+  mapsz = bt->mapsz - HFS_MAP1SZ;
+
+  nnum  = bt->hdrnd.nd.ndFLink;
+
+  while (mapsz)
+    {
+      node n;
+
+      if (nnum == 0)
+       {
+         ERROR(EIO, "truncated b*-tree map");
+         return -1;
+       }
+
+      n.bt   = bt;
+      n.nnum = nnum;
+
+      if (bt_getnode(&n) < 0)
+       return -1;
+
+      if (n.nd.ndType != ndMapNode ||
+         n.nd.ndNRecs != 1 ||
+         n.roff[0] != 0x00e ||
+         n.roff[1] != 0x1fa)
+       {
+         ERROR(EIO, "malformed b*-tree map node");
+         return -1;
+       }
+
+      memcpy(HFS_NODEREC(n, 0), map, HFS_MAPXSZ);
+
+      if (bt_putnode(&n) < 0)
+       return -1;
+
+      map   += HFS_MAPXSZ;
+      mapsz -= HFS_MAPXSZ;
+
+      nnum = n.nd.ndFLink;
+    }
+
+  bt->flags &= ~HFS_UPDATE_BTHDR;
+
+  return 0;
+}
+
+/* High-Level B*-Tree Routines ============================================= */
+
+/*
+ * NAME:       btree->space()
+ * DESCRIPTION:        assert space for new records, or extend the file
+ */
+int bt_space(btree *bt, unsigned int nrecs)
+{
+  unsigned int nnodes;
+  int space;
+
+  nnodes = nrecs * (bt->hdr.bthDepth + 1);
+
+  if (nnodes <= bt->hdr.bthFree)
+    return 0;
+
+  /* make sure the extents tree has room too */
+
+  if (bt != &bt->f.vol->ext)
+    {
+      if (bt_space(&bt->f.vol->ext, 1) < 0)
+       return -1;
+    }
+
+  space = f_alloc(&bt->f);
+  if (space < 0)
+    return -1;
+
+  nnodes = space * (bt->f.vol->mdb.drAlBlkSiz / bt->hdr.bthNodeSize);
+
+  bt->hdr.bthNNodes += nnodes;
+  bt->hdr.bthFree   += nnodes;
+
+  bt->flags |= HFS_UPDATE_BTHDR;
+
+  bt->f.vol->flags |= HFS_UPDATE_ALTMDB;
+
+  while (bt->hdr.bthNNodes > bt->mapsz * 8)
+    {
+      char *newmap;
+      node mapnd;
+
+      /* extend tree map */
+
+      newmap = REALLOC(bt->map, char, bt->mapsz + HFS_MAPXSZ);
+      if (newmap == 0)
+       {
+         ERROR(ENOMEM, 0);
+         return -1;
+       }
+
+      memset(newmap + bt->mapsz, 0, HFS_MAPXSZ);
+
+      bt->map    = newmap;
+      bt->mapsz += HFS_MAPXSZ;
+
+      n_init(&mapnd, bt, ndMapNode, 0);
+      if (n_new(&mapnd) < 0)
+       return -1;
+
+      /* link the new map node */
+
+      if (bt->hdrnd.nd.ndFLink == 0)
+       {
+         bt->hdrnd.nd.ndFLink = mapnd.nnum;
+         mapnd.nd.ndBLink     = 0;
+       }
+      else
+       {
+         node n;
+
+         n.bt   = bt;
+         n.nnum = bt->hdrnd.nd.ndFLink;
+
+         for (;;)
+           {
+             if (bt_getnode(&n) < 0)
+               return -1;
+
+             if (n.nd.ndFLink == 0)
+               break;
+
+             n.nnum = n.nd.ndFLink;
+           }
+
+         n.nd.ndFLink     = mapnd.nnum;
+         mapnd.nd.ndBLink = n.nnum;
+
+         if (bt_putnode(&n) < 0)
+           return -1;
+       }
+
+      mapnd.nd.ndNRecs = 1;
+      mapnd.roff[1]    = 0x1fa;
+
+      if (bt_putnode(&mapnd) < 0)
+       return -1;
+    }
+
+  return 0;
+}
+
+/*
+ * NAME:       btree->insertx()
+ * DESCRIPTION:        recursively locate a node and insert a record
+ */
+int bt_insertx(node *np, unsigned char *record, int *reclen)
+{
+  node child;
+  unsigned char *rec;
+
+  if (n_search(np, record))
+    {
+      ERROR(EIO, "b*-tree record already exists");
+      return -1;
+    }
+
+  switch ((unsigned char) np->nd.ndType)
+    {
+    case ndIndxNode:
+      if (np->rnum < 0)
+       rec = HFS_NODEREC(*np, 0);
+      else
+       rec = HFS_NODEREC(*np, np->rnum);
+
+      child.bt   = np->bt;
+      child.nnum = d_getl(HFS_RECDATA(rec));
+
+      if (bt_getnode(&child) < 0 ||
+         bt_insertx(&child, record, reclen) < 0)
+       return -1;
+
+      if (np->rnum < 0)
+       {
+         n_index(np->bt, HFS_NODEREC(child, 0), child.nnum, rec, 0);
+         if (*reclen == 0)
+           return bt_putnode(np);
+       }
+
+      return *reclen ? n_insert(np, record, reclen) : 0;
+
+    case ndLeafNode:
+      return n_insert(np, record, reclen);
+
+    default:
+      ERROR(EIO, "unexpected b*-tree node");
+      return -1;
+    }
+}
+
+/*
+ * NAME:       btree->insert()
+ * DESCRIPTION:        insert a new node record into a tree
+ */
+int bt_insert(btree *bt, unsigned char *record, int reclen)
+{
+  node root;
+
+  if (bt->hdr.bthRoot == 0)
+    {
+      /* create root node */
+
+      n_init(&root, bt, ndLeafNode, 1);
+      if (n_new(&root) < 0 ||
+         bt_putnode(&root) < 0)
+       return -1;
+
+      bt->hdr.bthDepth = 1;
+      bt->hdr.bthRoot  = root.nnum;
+      bt->hdr.bthFNode = root.nnum;
+      bt->hdr.bthLNode = root.nnum;
+
+      bt->flags |= HFS_UPDATE_BTHDR;
+    }
+  else
+    {
+      root.bt   = bt;
+      root.nnum = bt->hdr.bthRoot;
+
+      if (bt_getnode(&root) < 0)
+       return -1;
+    }
+
+  if (bt_insertx(&root, record, &reclen) < 0)
+    return -1;
+
+  if (reclen)
+    {
+      unsigned char oroot[HFS_MAXRECLEN];
+      int orootlen;
+
+      /* root node was split; create a new root */
+
+      n_index(bt, HFS_NODEREC(root, 0), root.nnum, oroot, &orootlen);
+
+      n_init(&root, bt, ndIndxNode, root.nd.ndNHeight + 1);
+      if (n_new(&root) < 0)
+       return -1;
+
+      ++bt->hdr.bthDepth;
+      bt->hdr.bthRoot = root.nnum;
+
+      bt->flags |= HFS_UPDATE_BTHDR;
+
+      /* insert index records for new root */
+
+      n_search(&root, oroot);
+      n_insertx(&root, oroot, orootlen);
+
+      n_search(&root, record);
+      n_insertx(&root, record, reclen);
+
+      if (bt_putnode(&root) < 0)
+       return -1;
+    }
+
+  ++bt->hdr.bthNRecs;
+  bt->flags |= HFS_UPDATE_BTHDR;
+
+  return 0;
+}
+
+/*
+ * NAME:       btree->deletex()
+ * DESCRIPTION:        recursively locate a node and delete a record
+ */
+int bt_deletex(node *np, unsigned char *key, unsigned char *record, int *flag)
+{
+  node child;
+  unsigned char *rec;
+  int found;
+
+  found = n_search(np, key);
+
+  switch ((unsigned char) np->nd.ndType)
+    {
+    case ndIndxNode:
+      if (np->rnum < 0)
+       {
+         ERROR(EIO, "b*-tree record not found");
+         return -1;
+       }
+
+      rec = HFS_NODEREC(*np, np->rnum);
+
+      child.bt   = np->bt;
+      child.nnum = d_getl(HFS_RECDATA(rec));
+
+      if (bt_getnode(&child) < 0 ||
+         bt_deletex(&child, key, rec, flag) < 0)
+       return -1;
+
+      if (*flag)
+       {
+         *flag = 0;
+
+         if (HFS_RECKEYLEN(rec) == 0)
+           return n_delete(np, record, flag);
+
+         if (np->rnum == 0)
+           {
+             n_index(np->bt, HFS_NODEREC(*np, 0), np->nnum, record, 0);
+             *flag = 1;
+           }
+
+         return bt_putnode(np);
+       }
+
+      return 0;
+
+    case ndLeafNode:
+      if (found == 0)
+       {
+         ERROR(EIO, "b*-tree record not found");
+         return -1;
+       }
+
+      return n_delete(np, record, flag);
+
+    default:
+      ERROR(EIO, "unexpected b*-tree node");
+      return -1;
+    }
+}
+
+/*
+ * NAME:       btree->delete()
+ * DESCRIPTION:        remove a node record from a tree
+ */
+int bt_delete(btree *bt, unsigned char *key)
+{
+  node root;
+  unsigned char record[HFS_MAXRECLEN];
+  int flag = 0;
+
+  root.bt   = bt;
+  root.nnum = bt->hdr.bthRoot;
+
+  if (root.nnum == 0)
+    {
+      ERROR(EIO, "empty b*-tree");
+      return -1;
+    }
+
+  if (bt_getnode(&root) < 0 ||
+      bt_deletex(&root, key, record, &flag) < 0)
+    return -1;
+
+  if (bt->hdr.bthDepth > 1 && root.nd.ndNRecs == 1)
+    {
+      unsigned char *rec;
+
+      /* chop the root */
+
+      rec = HFS_NODEREC(root, 0);
+
+      --bt->hdr.bthDepth;
+      bt->hdr.bthRoot = d_getl(HFS_RECDATA(rec));
+
+      n_free(&root);
+    }
+  else if (bt->hdr.bthDepth == 1 && root.nd.ndNRecs == 0)
+    {
+      /* delete the root node */
+
+      bt->hdr.bthDepth = 0;
+      bt->hdr.bthRoot  = 0;
+      bt->hdr.bthFNode = 0;
+      bt->hdr.bthLNode = 0;
+
+      n_free(&root);
+    }
+
+  --bt->hdr.bthNRecs;
+  bt->flags |= HFS_UPDATE_BTHDR;
+
+  return 0;
+}
+
+/*
+ * NAME:       btree->search()
+ * DESCRIPTION:        locate a data record given a search key
+ */
+int bt_search(btree *bt, unsigned char *key, node *np)
+{
+  np->bt   = bt;
+  np->nnum = bt->hdr.bthRoot;
+
+  if (np->nnum == 0)
+    {
+      ERROR(ENOENT, 0);
+      return 0;
+    }
+
+  for (;;)
+    {
+      int found;
+      unsigned char *rec;
+
+      if (bt_getnode(np) < 0)
+       return -1;
+
+      found = n_search(np, key);
+
+      switch ((unsigned char) np->nd.ndType)
+       {
+       case ndIndxNode:
+         if (np->rnum < 0)
+           {
+             ERROR(ENOENT, 0);
+             return 0;
+           }
+
+         rec = HFS_NODEREC(*np, np->rnum);
+         np->nnum = d_getl(HFS_RECDATA(rec));
+         break;
+
+       case ndLeafNode:
+         if (! found)
+           ERROR(ENOENT, 0);
+
+         return found;
+
+       default:
+         ERROR(EIO, "unexpected b*-tree node");
+         return -1;
+       }
+    }
+}
diff --git a/libhfs_iso/btree.h b/libhfs_iso/btree.h
new file mode 100644 (file)
index 0000000..c4b7629
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)btree.h 1.1 00/03/05 joerg */
+/*
+ * hfsutils - tools for reading and writing Macintosh HFS volumes
+ * Copyright (C) 1996, 1997 Robert Leslie
+ *
+ * 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 of the License, 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.
+ */
+
+int bt_getnode(node *);
+int bt_putnode(node *);
+
+int bt_readhdr(btree *);
+int bt_writehdr(btree *);
+
+int bt_space(btree *, unsigned int);
+
+int bt_insertx(node *, unsigned char *, int *);
+int bt_insert(btree *, unsigned char *, int);
+
+int bt_deletex(node *, unsigned char *, unsigned char *, int *);
+int bt_delete(btree *, unsigned char *);
+
+int bt_search(btree *, unsigned char *, node *);
diff --git a/libhfs_iso/data.c b/libhfs_iso/data.c
new file mode 100644 (file)
index 0000000..3f503f4
--- /dev/null
@@ -0,0 +1,379 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)data.c  1.5 02/02/10 joerg */
+/*
+ * hfsutils - tools for reading and writing Macintosh HFS volumes
+ * Copyright (C) 1996, 1997 Robert Leslie
+ *
+ * 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 of the License, 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 <mconfig.h>
+#include <strdefs.h>
+#include <timedefs.h>
+
+#include "internal.h"
+#include "data.h"
+#include "btree.h"
+
+#ifdef APPLE_HYB
+/*
+ *     Depending on the version, AppleDouble/Single stores dates
+ *     relative to 1st Jan 1904 (v1) or 1st Jan 2000 (v2)
+ *
+ *     DUTDIFF is the difference between 1st Jan 2000 and
+ *     1st Jan 1970 (Unix epoch)).
+ */
+
+#define DUTDIFF 946684800L
+#endif /* APPLE_HYB */
+#define MUTDIFF        2082844800L
+#define        TZNONE  0x0FFFFFFFL     /* A timezone diff that cannot occur */
+
+static void    calctzdiff(void);
+
+static
+unsigned long tzdiff = TZNONE;
+
+static
+unsigned char hfs_charorder[256] = {
+  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+  0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+  0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+  0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+
+  0x20, 0x22, 0x23, 0x28, 0x29, 0x2a, 0x2b, 0x2c,
+  0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
+  0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e,
+  0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46,
+
+  0x47, 0x48, 0x58, 0x5a, 0x5e, 0x60, 0x67, 0x69,
+  0x6b, 0x6d, 0x73, 0x75, 0x77, 0x79, 0x7b, 0x7f,
+  0x8d, 0x8f, 0x91, 0x93, 0x96, 0x98, 0x9f, 0xa1,
+  0xa3, 0xa5, 0xa8, 0xaa, 0xab, 0xac, 0xad, 0xae,
+
+  0x54, 0x48, 0x58, 0x5a, 0x5e, 0x60, 0x67, 0x69,
+  0x6b, 0x6d, 0x73, 0x75, 0x77, 0x79, 0x7b, 0x7f,
+  0x8d, 0x8f, 0x91, 0x93, 0x96, 0x98, 0x9f, 0xa1,
+  0xa3, 0xa5, 0xa8, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3,
+
+  0x4c, 0x50, 0x5c, 0x62, 0x7d, 0x81, 0x9a, 0x55,
+  0x4a, 0x56, 0x4c, 0x4e, 0x50, 0x5c, 0x62, 0x64,
+  0x65, 0x66, 0x6f, 0x70, 0x71, 0x72, 0x7d, 0x89,
+  0x8a, 0x8b, 0x81, 0x83, 0x9c, 0x9d, 0x9e, 0x9a,
+
+  0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0x95,
+  0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0x52, 0x85,
+  0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8,
+  0xc9, 0xca, 0xcb, 0x57, 0x8c, 0xcc, 0x52, 0x85,
+
+  0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0x26,
+  0x27, 0xd4, 0x20, 0x4a, 0x4e, 0x83, 0x87, 0x87,
+  0xd5, 0xd6, 0x24, 0x25, 0x2d, 0x2e, 0xd7, 0xd8,
+  0xa7, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+
+  0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
+  0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+  0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+  0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
+};
+
+/*
+ * NAME:       data->getb()
+ * DESCRIPTION:        marshal 1 byte into local host format
+ */
+char d_getb(unsigned char *ptr)
+{
+  return (char) ptr[0];
+}
+
+/*
+ * NAME:       data->getw()
+ * DESCRIPTION:        marshal 2 bytes into local host format
+ */
+short d_getw(unsigned char *ptr)
+{
+  return (short)
+    ((ptr[0] << 8) |
+     (ptr[1] << 0));
+}
+
+/*
+ * NAME:       data->getl()
+ * DESCRIPTION:        marshal 4 bytes into local host format
+ */
+long d_getl(unsigned char *ptr)
+{
+  return (long)
+    ((ptr[0] << 24) |
+     (ptr[1] << 16) |
+     (ptr[2] <<  8) |
+     (ptr[3] <<  0));
+}
+
+/*
+ * NAME:       data->putb()
+ * DESCRIPTION:        marshal 1 byte out to Macintosh (big-endian) format
+ */
+#ifdef PROTOTYPES
+void d_putb(unsigned char *ptr, char data)
+#else
+void d_putb(unsigned char *ptr, char data)
+#endif
+{
+  ptr[0] = (unsigned char) data;
+}
+
+/*
+ * NAME:       data->putw()
+ * DESCRIPTION:        marshal 2 bytes out to Macintosh (big-endian) format
+ */
+#ifdef PROTOTYPES
+void d_putw(unsigned char *ptr, short data)
+#else
+void d_putw(unsigned char *ptr, short data)
+#endif
+{
+  ptr[0] = ((unsigned) data & 0xff00) >> 8;
+  ptr[1] = ((unsigned) data & 0x00ff) >> 0;
+}
+
+/*
+ * NAME:       data->putl()
+ * DESCRIPTION:        marshal 4 bytes out to Macintosh (big-endian) format
+ */
+void d_putl(unsigned char *ptr, long data)
+{
+  ptr[0] = ((unsigned long) data & 0xff000000) >> 24;
+  ptr[1] = ((unsigned long) data & 0x00ff0000) >> 16;
+  ptr[2] = ((unsigned long) data & 0x0000ff00) >>  8;
+  ptr[3] = ((unsigned long) data & 0x000000ff) >>  0;
+}
+
+/*
+ * NAME:       data->fetchb()
+ * DESCRIPTION:        incrementally retrieve a byte of data
+ */
+void d_fetchb(unsigned char **ptr, char *dest)
+{
+  *dest = d_getb(*ptr);
+  *ptr += 1;
+}
+
+/*
+ * NAME:       data->fetchw()
+ * DESCRIPTION:        incrementally retrieve a word of data
+ */
+void d_fetchw(unsigned char **ptr, short *dest)
+{
+  *dest = d_getw(*ptr);
+  *ptr += 2;
+}
+
+/*
+ * NAME:       data->fetchl()
+ * DESCRIPTION:        incrementally retrieve a long word of data
+ */
+void d_fetchl(unsigned char **ptr, long *dest)
+{
+  *dest = d_getl(*ptr);
+  *ptr += 4;
+}
+
+/*
+ * NAME:       data->fetchs()
+ * DESCRIPTION:        incrementally retrieve a string
+ */
+void d_fetchs(unsigned char **ptr, char *dest, int size)
+{
+  int len;
+  char blen;
+
+  d_fetchb(ptr, &blen);
+  len = blen;
+
+  if (len > 0 && len < size)
+    memcpy(dest, *ptr, len);
+  else
+    len = 0;
+
+  dest[len] = 0;
+
+  *ptr += size - 1;
+}
+
+/*
+ * NAME:       data->storeb()
+ * DESCRIPTION:        incrementally store a byte of data
+ */
+#ifdef PROTOTYPES
+void d_storeb(unsigned char **ptr, char data)
+#else
+void d_storeb(unsigned char **ptr, char data)
+#endif
+{
+  d_putb(*ptr, data);
+  *ptr += 1;
+}
+
+/*
+ * NAME:       data->storew()
+ * DESCRIPTION:        incrementally store a word of data
+ */
+#ifdef PROTOTYPES
+void d_storew(unsigned char **ptr, short data)
+#else
+void d_storew(unsigned char **ptr, short data)
+#endif
+{
+  d_putw(*ptr, data);
+  *ptr += 2;
+}
+
+/*
+ * NAME:       data->storel()
+ * DESCRIPTION:        incrementally store a long word of data
+ */
+void d_storel(unsigned char **ptr, long data)
+{
+  d_putl(*ptr, data);
+  *ptr += 4;
+}
+
+/*
+ * NAME:       data->stores()
+ * DESCRIPTION:        incrementally store a string
+ */
+void d_stores(unsigned char **ptr, char *src, int size)
+{
+  int len;
+
+  len = strlen(src);
+  if (len > --size)
+    len = 0;
+
+  d_storeb(ptr, (unsigned char) len);
+
+  memcpy(*ptr, src, len);
+  memset(*ptr + len, 0, size - len);
+
+  *ptr += size;
+}
+
+/*
+ * NAME:       calctzdiff()
+ * DESCRIPTION:        calculate the timezone difference between local time and UTC
+ */
+static void calctzdiff()
+{
+  time_t t;
+  int isdst;
+  struct tm tm, *tmp;
+
+  time(&t);
+  isdst = localtime(&t)->tm_isdst;
+
+  tmp = gmtime(&t);
+  if (tmp)
+    {
+      tm = *tmp;
+      tm.tm_isdst = isdst;
+
+      tzdiff = t - mktime(&tm);
+    }
+  else
+    tzdiff = 0;
+}
+
+/*
+ * NAME:       data->tomtime()
+ * DESCRIPTION:        convert UNIX time to Macintosh time
+ */
+unsigned long d_tomtime(unsigned long secs)
+{
+  time_t utime = secs;
+
+  if (tzdiff == TZNONE)
+    calctzdiff();
+
+  return utime + tzdiff + MUTDIFF;
+}
+
+/*
+ * NAME:       data->toutime()
+ * DESCRIPTION:        convert Macintosh time to UNIX time
+ */
+unsigned long d_toutime(unsigned long secs)
+{
+  time_t utime = secs;
+
+  if (tzdiff == TZNONE)
+    calctzdiff();
+
+  return utime - MUTDIFF - tzdiff;
+}
+
+#ifdef APPLE_HYB
+/*
+ * NAME:       data->dtoutime()
+ * DESCRIPTION:        convert Apple Double v2 time to UNIX time
+ */
+unsigned long d_dtoutime(long secs)
+{
+  time_t utime = secs;
+
+  if (tzdiff == TZNONE)
+    calctzdiff();
+
+  return utime + DUTDIFF - tzdiff;
+}
+#endif /* APPLE_HYB */
+
+/*
+ * NAME:       data->relstring()
+ * DESCRIPTION:        compare two strings as per MacOS for HFS
+ */
+int d_relstring(char *str1, char *str2)
+{
+  int diff;
+
+  while (*str1 && *str2)
+    {
+      diff = hfs_charorder[(unsigned char) *str1] -
+            hfs_charorder[(unsigned char) *str2];
+
+      if (diff)
+       return diff;
+
+      ++str1, ++str2;
+    }
+
+  if (! *str1 && *str2)
+    return -1;
+  else if (*str1 && ! *str2)
+    return 1;
+
+  return 0;
+}
diff --git a/libhfs_iso/data.h b/libhfs_iso/data.h
new file mode 100644 (file)
index 0000000..b3a68a5
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)data.h  1.2 01/11/11 joerg */
+/*
+ * hfsutils - tools for reading and writing Macintosh HFS volumes
+ * Copyright (C) 1996, 1997 Robert Leslie
+ *
+ * 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 of the License, 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.
+ */
+
+char d_getb(unsigned char *);
+short d_getw(unsigned char *);
+long d_getl(unsigned char *);
+
+void d_putb(unsigned char *, char);
+void d_putw(unsigned char *, short);
+void d_putl(unsigned char *, long);
+
+void d_fetchb(unsigned char **, char *);
+void d_fetchw(unsigned char **, short *);
+void d_fetchl(unsigned char **, long *);
+void d_fetchs(unsigned char **, char *, int);
+
+void d_storeb(unsigned char **, char);
+void d_storew(unsigned char **, short);
+void d_storel(unsigned char **, long);
+void d_stores(unsigned char **, char *, int);
+
+unsigned long d_tomtime(unsigned long);
+unsigned long d_toutime(unsigned long);
+#ifdef APPLE_HYB
+unsigned long d_dtoutime(long);
+#endif /* APPLE_HYB */
+
+int d_relstring(char *, char *);
diff --git a/libhfs_iso/file.c b/libhfs_iso/file.c
new file mode 100644 (file)
index 0000000..a0198c8
--- /dev/null
@@ -0,0 +1,470 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)file.c  1.3 04/06/17 joerg */
+/*
+ * hfsutils - tools for reading and writing Macintosh HFS volumes
+ * Copyright (C) 1996, 1997 Robert Leslie
+ *
+ * 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 of the License, 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 <mconfig.h>
+#include <strdefs.h>
+#include <errno.h>
+
+#include "internal.h"
+#include "data.h"
+#include "block.h"
+#include "file.h"
+#include "btree.h"
+#include "record.h"
+#include "volume.h"
+
+/* #include <stdio.h> */
+
+
+/*
+ * NAME:       file->selectfork()
+ * DESCRIPTION:        choose a fork for file operations
+ */
+void f_selectfork(hfsfile *file, int ffork)
+{
+  if (ffork == 0)
+    {
+      file->fork = fkData;
+      memcpy(file->ext, file->cat.u.fil.filExtRec, sizeof(ExtDataRec));
+    }
+  else
+    {
+      file->fork = fkRsrc;
+      memcpy(file->ext, file->cat.u.fil.filRExtRec, sizeof(ExtDataRec));
+    }
+
+  file->fabn = 0;
+  file->pos  = 0;
+}
+
+/*
+ * NAME:       file->getptrs()
+ * DESCRIPTION:        make pointers to the current fork's lengths and extents
+ */
+void f_getptrs(hfsfile *file, unsigned long **lglen, unsigned long **pylen, 
+               ExtDataRec **extrec)
+{
+  if (file->fork == fkData)
+    {
+      if (lglen)
+       *lglen  = &file->cat.u.fil.filLgLen;
+      if (pylen)
+       *pylen  = &file->cat.u.fil.filPyLen;
+      if (extrec)
+       *extrec = &file->cat.u.fil.filExtRec;
+    }
+  else
+    {
+      if (lglen)
+       *lglen  = &file->cat.u.fil.filRLgLen;
+      if (pylen)
+       *pylen  = &file->cat.u.fil.filRPyLen;
+      if (extrec)
+       *extrec = &file->cat.u.fil.filRExtRec;
+    }
+}
+
+/*
+ * NAME:       file->doblock()
+ * DESCRIPTION:        read or write a numbered block from a file
+ */
+int f_doblock(hfsfile *file, unsigned long number, block *bp,
+              int (*func)(hfsvol *, unsigned int, unsigned int, block *))
+{
+  unsigned int abnum;
+  unsigned int blnum;
+  unsigned int fabn;
+  int i;
+
+  abnum = number / file->vol->lpa;
+  blnum = number % file->vol->lpa;
+
+  /* locate the appropriate extent record */
+
+  fabn = file->fabn;
+
+  if (abnum < fabn)
+    {
+      ExtDataRec *extrec;
+
+      f_getptrs(file, 0, 0, &extrec);
+
+      fabn = file->fabn = 0;
+      memcpy(file->ext, extrec, sizeof(ExtDataRec));
+    }
+  else
+    abnum -= fabn;
+
+  for (;;)
+    {
+      unsigned int num;
+
+      for (i = 0; i < 3; ++i)
+       {
+         num = file->ext[i].xdrNumABlks;
+
+#ifdef APPLE_HYB
+         if (i > 0) {
+/*         SHOULD NOT HAPPEN! - all the files should not be fragmented
+           if this happens, then a serious problem has occured, may be
+           a hard linked file? */
+#ifdef DEBUG
+           fprintf(stderr,"fragmented file: %s %d\n",file->name, i); */
+#endif /* DEBUG */
+           ERROR(HCE_ERROR, "Possible Catalog file overflow - please report error");
+           return -1; 
+         }
+#endif /* APPLE_HYB */
+         if (abnum < num)
+           return func(file->vol, file->ext[i].xdrStABN + abnum, blnum, bp);
+
+         fabn  += num;
+         abnum -= num;
+       }
+
+      if (v_extsearch(file, fabn, &file->ext, 0) <= 0)
+       return -1;
+
+      file->fabn = fabn;
+    }
+}
+
+/*
+ * NAME:       file->alloc()
+ * DESCRIPTION:        reserve disk blocks for a file
+ */
+int f_alloc(hfsfile *file)
+{
+  hfsvol *vol = file->vol;
+  ExtDescriptor blocks;
+  ExtDataRec *extrec;
+  unsigned long *pylen, clumpsz;
+  unsigned int start, end;
+  node n;
+  int i;
+
+  clumpsz = file->clump;
+  if (clumpsz == 0)
+    clumpsz = vol->mdb.drClpSiz;
+
+  blocks.xdrNumABlks = clumpsz / vol->mdb.drAlBlkSiz;
+
+  if (v_allocblocks(vol, &blocks) < 0)
+    return -1;
+
+  /* update the file's extents */
+
+  f_getptrs(file, 0, &pylen, &extrec);
+
+  start  = file->fabn;
+  end    = *pylen / vol->mdb.drAlBlkSiz;
+
+  n.nnum = 0;
+  i      = -1;
+
+  while (start < end)
+    {
+      for (i = 0; i < 3; ++i)
+       {
+         unsigned int num;
+
+         num    = file->ext[i].xdrNumABlks;
+         start += num;
+
+         if (start == end)
+           break;
+         else if (start > end)
+           {
+             v_freeblocks(vol, &blocks);
+             ERROR(EIO, "file extents exceed file physical length");
+             return -1;
+           }
+         else if (num == 0)
+           {
+             v_freeblocks(vol, &blocks);
+             ERROR(EIO, "empty file extent");
+             return -1;
+           }
+       }
+
+      if (start == end)
+       break;
+
+      if (v_extsearch(file, start, &file->ext, &n) <= 0)
+       {
+         v_freeblocks(vol, &blocks);
+         return -1;
+       }
+
+      file->fabn = start;
+    }
+
+  if (i >= 0 &&
+      file->ext[i].xdrStABN + file->ext[i].xdrNumABlks == blocks.xdrStABN)
+    file->ext[i].xdrNumABlks += blocks.xdrNumABlks;
+  else
+    {
+      /* create a new extent descriptor */
+
+      if (++i < 3)
+       file->ext[i] = blocks;
+      else
+       {
+         ExtKeyRec key;
+         unsigned char record[HFS_EXTRECMAXLEN];
+         int reclen;
+
+         /* record is full; create a new one */
+
+         file->ext[0] = blocks;
+
+         for (i = 1; i < 3; ++i)
+           {
+             file->ext[i].xdrStABN    = 0;
+             file->ext[i].xdrNumABlks = 0;
+           }
+
+         file->fabn = start;
+
+         r_makeextkey(&key, file->fork, file->cat.u.fil.filFlNum, end);
+         r_packextkey(&key, record, &reclen);
+         r_packextdata(&file->ext, HFS_RECDATA(record), &reclen);
+
+         if (bt_insert(&vol->ext, record, reclen) < 0)
+           {
+             v_freeblocks(vol, &blocks);
+             return -1;
+           }
+
+         i = -1;
+       }
+    }
+
+  if (i >= 0)
+    {
+      /* store the modified extent record */
+
+      if (file->fabn)
+       {
+         if ((n.nnum == 0 &&
+              v_extsearch(file, file->fabn, 0, &n) <= 0) ||
+             v_putextrec(&file->ext, &n) < 0)
+           {
+             v_freeblocks(vol, &blocks);
+             return -1;
+           }
+       }
+      else
+       memcpy(extrec, file->ext, sizeof(ExtDataRec));
+    }
+
+  *pylen += blocks.xdrNumABlks * vol->mdb.drAlBlkSiz;
+
+  file->flags |= HFS_UPDATE_CATREC;
+
+  return blocks.xdrNumABlks;
+}
+
+/*
+ * NAME:       file->trunc()
+ * DESCRIPTION:        release disk blocks unneeded by a file
+ */
+int f_trunc(hfsfile *file)
+{
+  ExtDataRec *extrec;
+  unsigned long *lglen, *pylen, alblksz, newpylen;
+  unsigned int dlen, start, end;
+  node n;
+  int i;
+
+  f_getptrs(file, &lglen, &pylen, &extrec);
+
+  alblksz  = file->vol->mdb.drAlBlkSiz;
+  newpylen = (*lglen / alblksz + (*lglen % alblksz != 0)) * alblksz;
+
+  if (newpylen > *pylen)
+    {
+      ERROR(EIO, "file size exceeds physical length");
+      return -1;
+    }
+  else if (newpylen == *pylen)
+    return 0;
+
+  dlen  = (*pylen - newpylen) / alblksz;
+
+  start = file->fabn;
+  end   = newpylen / alblksz;
+
+  if (start >= end)
+    {
+      start = file->fabn = 0;
+      memcpy(file->ext, extrec, sizeof(ExtDataRec));
+    }
+
+  n.nnum = 0;
+  i      = -1;
+
+  while (start < end)
+    {
+      for (i = 0; i < 3; ++i)
+       {
+         unsigned int num;
+
+         num    = file->ext[i].xdrNumABlks;
+         start += num;
+
+         if (start >= end)
+           break;
+         else if (num == 0)
+           {
+             ERROR(EIO, "empty file extent");
+             return -1;
+           }
+       }
+
+      if (start >= end)
+       break;
+
+      if (v_extsearch(file, start, &file->ext, &n) <= 0)
+       return -1;
+
+      file->fabn = start;
+    }
+
+  if (start > end)
+    {
+      ExtDescriptor blocks;
+
+      file->ext[i].xdrNumABlks -= start - end;
+      dlen -= start - end;
+
+      blocks.xdrStABN    = file->ext[i].xdrStABN + file->ext[i].xdrNumABlks;
+      blocks.xdrNumABlks = start - end;
+
+      v_freeblocks(file->vol, &blocks);
+    }
+
+  *pylen = newpylen;
+
+  file->flags |= HFS_UPDATE_CATREC;
+
+  do
+    {
+      while (dlen && ++i < 3)
+       {
+         unsigned int num;
+
+         num    = file->ext[i].xdrNumABlks;
+         start += num;
+
+         if (num == 0)
+           {
+             ERROR(EIO, "empty file extent");
+             return -1;
+           }
+         else if (num > dlen)
+           {
+             ERROR(EIO, "file extents exceed physical size");
+             return -1;
+           }
+
+         dlen -= num;
+         v_freeblocks(file->vol, &file->ext[i]);
+
+         file->ext[i].xdrStABN    = 0;
+         file->ext[i].xdrNumABlks = 0;
+       }
+
+      if (file->fabn)
+       {
+         if (n.nnum == 0 &&
+             v_extsearch(file, file->fabn, 0, &n) <= 0)
+           return -1;
+
+         if (file->ext[0].xdrNumABlks)
+           {
+             if (v_putextrec(&file->ext, &n) < 0)
+               return -1;
+           }
+         else
+           {
+             if (bt_delete(&file->vol->ext, HFS_NODEREC(n, n.rnum)) < 0)
+               return -1;
+
+             n.nnum = 0;
+           }
+       }
+      else
+       memcpy(extrec, file->ext, sizeof(ExtDataRec));
+
+      if (dlen)
+       {
+         if (v_extsearch(file, start, &file->ext, &n) <= 0)
+           return -1;
+
+         file->fabn = start;
+         i = -1;
+       }
+    }
+  while (dlen);
+
+  return 0;
+}
+
+/*
+ * NAME:       file->flush()
+ * DESCRIPTION:        flush all pending changes to an open file
+ */
+int f_flush(hfsfile *file)
+{
+  hfsvol *vol = file->vol;
+
+  if (! (vol->flags & HFS_READONLY))
+    {
+      if (file->flags & HFS_UPDATE_CATREC)
+       {
+         node n;
+
+         file->cat.u.fil.filStBlk   = file->cat.u.fil.filExtRec[0].xdrStABN;
+         file->cat.u.fil.filRStBlk  = file->cat.u.fil.filRExtRec[0].xdrStABN;
+         file->cat.u.fil.filClpSize = file->clump;
+
+         if (v_catsearch(file->vol, file->parid, file->name, 0, 0, &n) <= 0 ||
+             v_putcatrec(&file->cat, &n) < 0)
+           return -1;
+
+         file->flags &= ~HFS_UPDATE_CATREC;
+       }
+    }
+
+  return 0;
+}
diff --git a/libhfs_iso/file.h b/libhfs_iso/file.h
new file mode 100644 (file)
index 0000000..9b95bd6
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)file.h  1.1 00/03/05 joerg */
+/*
+ * hfsutils - tools for reading and writing Macintosh HFS volumes
+ * Copyright (C) 1996, 1997 Robert Leslie
+ *
+ * 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 of the License, 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.
+ */
+
+enum {
+  fkData = 0x00,
+  fkRsrc = 0xff
+};
+
+void f_selectfork(hfsfile *, int);
+void f_getptrs(hfsfile *, unsigned long **, unsigned long **, ExtDataRec **);
+
+int f_doblock(hfsfile *, unsigned long, block *, 
+                                 int (*)(hfsvol *, unsigned int, unsigned int, block *));
+
+# define f_getblock(file, num, bp)     f_doblock(file, num, bp, b_readab)
+# define f_putblock(file, num, bp)     f_doblock(file, num, bp, b_writeab)
+
+int f_alloc(hfsfile *);
+int f_flush(hfsfile *);
diff --git a/libhfs_iso/gdata.c b/libhfs_iso/gdata.c
new file mode 100644 (file)
index 0000000..7642083
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)gdata.c 1.1 01/01/21 Copyright 2001 J. Schilling */
+
+#include <mconfig.h>
+#include "internal.h"
+
+char *hfs_error = "no error";  /* static error string */
+hfsvol *hfs_mounts;            /* linked list of mounted volumes */
+hfsvol *hfs_curvol;            /* current volume */
diff --git a/libhfs_iso/hfs.c b/libhfs_iso/hfs.c
new file mode 100644 (file)
index 0000000..fb63ef4
--- /dev/null
@@ -0,0 +1,2098 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)hfs.c   1.9 04/06/17 joerg */
+/*
+ * hfsutils - tools for reading and writing Macintosh HFS volumes
+ * Copyright (C) 1996, 1997 Robert Leslie
+ *
+ * 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 of the License, 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.
+ */
+
+/* APPLE_HYB James Pearson j.pearson@ps.ucl.ac.uk 16/7/97 */
+
+#include <mconfig.h>
+#include <stdxlib.h>
+#include <unixstd.h>
+#include <fctldefs.h>
+#include <errno.h>
+#include <strdefs.h>
+#include <ctype.h>
+#include <statdefs.h>
+
+#include "internal.h"
+#include "data.h"
+#include "block.h"
+#include "low.h"
+#include "file.h"
+#include "btree.h"
+#include "node.h"
+#include "record.h"
+#include "volume.h"
+#include "hfs.h"
+
+/* High-Level Volume Routines ============================================== */
+
+/*
+ * NAME:       hfs->mount()
+ * DESCRIPTION:        open an HFS volume; return volume descriptor or 0 (error)
+ */
+#ifdef APPLE_HYB
+hfsvol *hfs_mount(hce_mem *hce, int pnum, int flags)
+#else
+hfsvol *hfs_mount(char *path, int pnum, int flags)
+#endif /* APPLE_HYB */
+{
+#ifndef APPLE_HYB
+  struct stat dev;
+#endif
+  hfsvol *vol = 0;
+
+#ifndef APPLE_HYB
+  /* see if the volume is already mounted */
+
+  if (stat(path, &dev) >= 0)
+    {
+      struct stat mdev;
+      hfsvol *check;
+
+      for (check = hfs_mounts; check; check = check->next)
+       {
+         if (fstat(check->fd, &mdev) >= 0 &&
+             mdev.st_dev == dev.st_dev &&
+             mdev.st_ino == dev.st_ino &&
+             (check->pnum == 0 || check->pnum == pnum))
+           {
+             /* verify compatible read/write mode */
+
+             if (((check->flags & HFS_READONLY) &&
+                  ! (flags & O_WRONLY)) ||
+                 (! (check->flags & HFS_READONLY) &&
+                  (flags & (O_WRONLY | O_RDWR))))
+               {
+                 vol = check;
+                 break;
+               }
+           }
+       }
+    }
+#endif /* APPLE_HYB */
+  if (vol == 0)
+    {
+      vol = ALLOC(hfsvol, 1);
+      if (vol == 0)
+       {
+         ERROR(ENOMEM, 0);
+         return 0;
+       }
+
+      vol->flags  = 0;
+      vol->pnum   = pnum;
+      vol->vstart = 0;
+      vol->vlen   = 0;
+      vol->lpa    = 0;
+      vol->vbm    = 0;
+      vol->cwd    = HFS_CNID_ROOTDIR;
+
+      vol->refs   = 0;
+      vol->files  = 0;
+      vol->dirs   = 0;
+      vol->prev   = 0;
+      vol->next   = 0;
+
+      vol->ext.map     = 0;
+      vol->ext.mapsz   = 0;
+      vol->ext.flags   = 0;
+      vol->ext.compare = r_compareextkeys;
+
+      vol->cat.map     = 0;
+      vol->cat.mapsz   = 0;
+      vol->cat.flags   = 0;
+      vol->cat.compare = r_comparecatkeys;
+
+      /* open and lock the device */
+
+#ifdef APPLE_HYB
+      vol->fd = 3;                     /* any +ve number will do? */
+      vol->hce = hce;                  /* store the extra with the vol info */
+#else
+      if (flags & (O_WRONLY | O_RDWR))
+       {
+         vol->fd = open(path, O_RDWR);
+         if (vol->fd >= 0 && l_lockvol(vol) < 0)
+           {
+             close(vol->fd);
+             vol->fd = -2;
+           }
+       }
+
+      if (! (flags & (O_WRONLY | O_RDWR)) ||
+         (vol->fd < 0 &&
+          (errno == EROFS || errno == EACCES || errno == EAGAIN) &&
+          (flags & O_RDWR)))
+       {
+         vol->flags |= HFS_READONLY;
+         vol->fd = open(path, O_RDONLY);
+         if (vol->fd >= 0 && l_lockvol(vol) < 0)
+           {
+             close(vol->fd);
+             vol->fd = -2;
+           }
+       }
+
+      if (vol->fd < 0)
+       {
+         if (vol->fd != -2)
+           ERROR(errno, "error opening device");
+
+         v_destruct(vol);
+
+         return 0;
+       }
+#endif /* APPLE_HYB */
+
+      /* find out what kind of media this is and read the MDB */
+
+      if (l_readblock0(vol) < 0 ||
+         l_readmdb(vol) < 0)
+       {
+#ifndef APPLE_HYB
+         close(vol->fd);
+         v_destruct(vol);
+#endif /* APPLE_HYB */
+         return 0;
+       }
+
+      /* verify this is an HFS volume */
+
+      if (vol->mdb.drSigWord != 0x4244)
+       {
+#ifndef APPLE_HYB
+         close(vol->fd);
+#endif /* APPLE_HYB */
+         v_destruct(vol);
+
+         ERROR(EINVAL, "not a Macintosh HFS volume");
+         return 0;
+       }
+
+      /* do minimal consistency checks */
+
+      if (vol->mdb.drAlBlkSiz % HFS_BLOCKSZ != 0)
+       {
+#ifndef APPLE_HYB
+         close(vol->fd);
+#endif /* APPLE_HYB */
+         v_destruct(vol);
+
+         ERROR(EINVAL, "bad volume allocation block size");
+         return 0;
+       }
+
+      if (vol->vlen == 0)
+       vol->vlen = vol->mdb.drAlBlSt +
+         vol->mdb.drNmAlBlks * (vol->mdb.drAlBlkSiz / HFS_BLOCKSZ) + 2;
+
+      /* read the volume bitmap and extents/catalog B*-tree headers */
+
+      if (l_readvbm(vol) < 0 ||
+         bt_readhdr(&vol->ext) < 0 ||
+         bt_readhdr(&vol->cat) < 0)
+       {
+#ifndef APPLE_HYB
+         close(vol->fd);
+#endif /* APPLE_HYB */
+         v_destruct(vol);
+         return 0;
+       }
+
+      if (! (vol->mdb.drAtrb & HFS_ATRB_UMOUNTED))
+       {
+         /* volume was not cleanly unmounted; scavenge free-space */
+
+         if (v_scavenge(vol) < 0)
+           {
+#ifndef APPLE_HYB
+             close(vol->fd);
+#endif /* APPLE_HYB */
+             v_destruct(vol);
+             return 0;
+           }
+       }
+
+      if (vol->flags & HFS_READONLY)
+       vol->mdb.drAtrb |= HFS_ATRB_HLOCKED;
+      else
+       vol->mdb.drAtrb &= ~HFS_ATRB_HLOCKED;
+
+      vol->prev = 0;
+      vol->next = hfs_mounts;
+
+      if (hfs_mounts)
+       hfs_mounts->prev = vol;
+
+      hfs_mounts = vol;
+    }
+
+  ++vol->refs;
+
+  return hfs_curvol = vol;
+}
+
+/*
+ * NAME:       hfs->flush()
+ * DESCRIPTION:        flush all pending changes to an HFS volume
+ */
+int hfs_flush(hfsvol *vol)
+{
+  hfsfile *file;
+
+  if (v_getvol(&vol) < 0)
+    return -1;
+
+  for (file = vol->files; file; file = file->next)
+    {
+      if (f_flush(file) < 0)
+       return -1;
+    }
+
+  if (v_flush(vol, 0) < 0)
+    return -1;
+
+  return 0;
+}
+
+/*
+ * NAME:       hfs->flushall()
+ * DESCRIPTION:        flush all pending changes to all mounted HFS volumes
+ */
+void hfs_flushall()
+{
+  hfsvol *vol;
+
+  for (vol = hfs_mounts; vol; vol = vol->next)
+    hfs_flush(vol);
+}
+
+/*
+ * NAME:       hfs->umount()
+ * DESCRIPTION:        close an HFS volume
+ */
+#ifdef APPLE_HYB
+/* extra argument used to alter the position of the extents/catalog files */
+int hfs_umount(hfsvol *vol, long end, long locked)
+#else
+int hfs_umount(hfsvol *vol)
+#endif /* APPLE_HYB */
+{
+  int result = 0;
+
+  if (v_getvol(&vol) < 0)
+    return -1;
+
+  if (--vol->refs)
+    return v_flush(vol, 0);
+
+  /* close all open files and directories */
+
+  while (vol->files)
+#ifdef APPLE_HYB
+    hfs_close(vol->files, 0, 0);
+#else
+    hfs_close(vol->files);
+#endif /* APPLE_HYB */
+
+  while (vol->dirs)
+    hfs_closedir(vol->dirs);
+
+#ifdef APPLE_HYB
+  if (end)
+  {
+       /*  move extents and catalog to end of volume ... */
+       long vbmsz = (vol->vlen / vol->lpa + 4095) / 4096;
+
+       /* we are adding this "files" to the end of the ISO volume,
+          so calculate this address in HFS speak ... */
+/*     end -= vol->mdb.drAlBlSt; */
+       end -= (vol->mdb.drAlBlSt + vol->hce->hfs_map_size);
+       end /= vol->lpa;
+
+       /* catalog file ... */
+       vol->ext.f.cat.u.fil.filExtRec[0].xdrStABN = end;
+       vol->mdb.drXTExtRec[0].xdrStABN = end;
+
+       /* move postition to start of extents file */
+       end += vol->cat.f.cat.u.fil.filExtRec[0].xdrStABN;
+
+       /* extents file ... */
+       vol->cat.f.cat.u.fil.filExtRec[0].xdrStABN = end;
+       vol->mdb.drCTExtRec[0].xdrStABN = end;
+
+       /* the volume bitmap is wrong as we have "moved" files
+          about - simple just set the whole lot (it's a readonly volume
+          anyway!) */
+       memset(vol->vbm, 0xff, vbmsz*HFS_BLOCKSZ);
+
+       /* set the free blocks to zero */
+       vol->mdb.drFreeBks = 0;
+
+       /* flag changes for flushing later */
+       vol->flags |= HFS_UPDATE_VBM;
+       vol->flags |= HFS_UPDATE_MDB;
+       vol->mdb.drAtrb |= HFS_ATRB_HLOCKED;
+       if (locked) {
+           vol->mdb.drAtrb |= HFS_ATRB_SLOCKED;
+       }
+       vol->ext.flags |= HFS_UPDATE_BTHDR;
+       vol->cat.flags |= HFS_UPDATE_BTHDR;
+  }
+#endif /* APPLE_HYB */
+
+  if (v_flush(vol, 1) < 0)
+    result = -1;
+
+#ifndef APPLE_HYB
+  if (close(vol->fd) < 0 && result == 0)
+    {
+      ERROR(errno, "error closing device");
+      result = -1;
+    }
+#endif /* APPLE_HYB */
+
+  if (vol->prev)
+    vol->prev->next = vol->next;
+  if (vol->next)
+    vol->next->prev = vol->prev;
+
+  if (vol == hfs_mounts)
+    hfs_mounts = vol->next;
+  if (vol == hfs_curvol)
+    hfs_curvol = 0;
+
+  v_destruct(vol);
+
+  return result;
+}
+
+/*
+ * NAME:       hfs->umountall()
+ * DESCRIPTION:        unmount all mounted volumes
+ */
+void hfs_umountall()
+{
+  while (hfs_mounts)
+#ifdef APPLE_HYB
+    continue;
+#else
+    hfs_umount(hfs_mounts);
+#endif /* APPLE_HYB */
+}
+
+/*
+ * NAME:       hfs->getvol()
+ * DESCRIPTION:        return a pointer to a mounted volume
+ */
+hfsvol *hfs_getvol(char *name)
+{
+  hfsvol *vol;
+
+  if (name == 0)
+    return hfs_curvol;
+
+  for (vol = hfs_mounts; vol; vol = vol->next)
+    {
+      if (d_relstring(name, vol->mdb.drVN) == 0)
+       return vol;
+    }
+
+  return 0;
+}
+
+/*
+ * NAME:       hfs->setvol()
+ * DESCRIPTION:        change the current volume
+ */
+void hfs_setvol(hfsvol *vol)
+{
+  hfs_curvol = vol;
+}
+
+/*
+ * NAME:       hfs->vstat()
+ * DESCRIPTION:        return volume statistics
+ */
+int hfs_vstat(hfsvol *vol, hfsvolent *ent)
+{
+  if (v_getvol(&vol) < 0)
+    return -1;
+
+  strcpy(ent->name, vol->mdb.drVN);
+
+  ent->flags     = (vol->flags & HFS_READONLY) ? HFS_ISLOCKED : 0;
+  ent->totbytes  = vol->mdb.drNmAlBlks * vol->mdb.drAlBlkSiz;
+  ent->freebytes = vol->mdb.drFreeBks  * vol->mdb.drAlBlkSiz;
+  ent->crdate    = d_toutime(vol->mdb.drCrDate);
+  ent->mddate    = d_toutime(vol->mdb.drLsMod);
+
+  return 0;
+}
+
+/*
+ * NAME:       hfs->format()
+ * DESCRIPTION:        write a new filesystem
+ */
+#ifdef APPLE_HYB
+int hfs_format(hce_mem *hce, int pnum, char *vname)
+#else
+int hfs_format(char *path, int pnum, char *vname)
+#endif /* APPLE_HYB */
+{
+  hfsvol vol;
+  btree *ext = &vol.ext;
+  btree *cat = &vol.cat;
+  unsigned int vbmsz;
+  int i, result = 0;
+  block vbm[16];
+  char *map;
+
+  if (strchr(vname, ':'))
+    {
+      ERROR(EINVAL, "volume name may not contain colons");
+      return -1;
+    }
+
+  i = strlen(vname);
+  if (i < 1 || i > HFS_MAX_VLEN)
+    {
+      ERROR(EINVAL, "volume name must be 1-27 chars");
+      return -1;
+    }
+
+  vol.flags  = 0;
+  vol.pnum   = pnum;
+  vol.vstart = 0;
+  vol.vlen   = 0;
+  vol.lpa    = 0;
+  vol.vbm    = vbm;
+  vol.cwd    = HFS_CNID_ROOTDIR;
+
+  vol.refs   = 0;
+  vol.files  = 0;
+  vol.dirs   = 0;
+  vol.prev   = 0;
+  vol.next   = 0;
+
+#ifndef APPLE_HYB
+  vol.fd = open(path, O_RDWR);
+  if (vol.fd < 0)
+    {
+      ERROR(errno, "error opening device for writing");
+      return -1;
+    }
+
+  if (l_lockvol(&vol) < 0)
+    {
+      close(vol.fd);
+      return -1;
+    }
+#endif /* APPLE_HYB */
+  if (pnum > 0)
+    {
+      if (l_readpm(&vol) < 0)
+       {
+         close(vol.fd);
+         return -1;
+       }
+    }
+  else  /* determine size of entire device */
+    {
+#ifdef APPLE_HYB
+      vol.vlen = hce->hfs_vol_size;
+#else
+      unsigned long low, high, mid;
+      block b;
+
+      for (low = 0, high = 2879; b_readlb(&vol, high, &b) >= 0; high *= 2)
+       low = high;
+
+      while (low < high - 1)
+       {
+         mid = (low + high) / 2;
+
+         if (b_readlb(&vol, mid, &b) < 0)
+           high = mid;
+         else
+           low = mid;
+       }
+
+      vol.vlen = low + 1;
+#endif /* APPLE_HYB */
+    }
+
+  if (vol.vlen < 800 * 1024 / HFS_BLOCKSZ)
+    {
+#ifndef APPLE_HYB
+      close(vol.fd);
+#endif /* APPLE_HYB */
+
+      ERROR(EINVAL, "volume size must be >= 800K");
+      return -1;
+    }
+
+  /* initialize volume geometry */
+
+#ifdef APPLE_HYB
+  /* force lpa to be a multiple of 4 (i.e. 2048/512) - as calculated 
+     earlier */
+  vol.lpa = hce->Csize/HFS_BLOCKSZ;
+#else
+  vol.lpa = 1 + vol.vlen / 65536;
+#endif /* APPLE_HYB */
+
+  vbmsz = (vol.vlen / vol.lpa + 4095) / 4096;
+
+  vol.mdb.drSigWord  = 0x4244;
+  vol.mdb.drCrDate   = d_tomtime(time(0));
+  vol.mdb.drLsMod    = vol.mdb.drCrDate;
+  vol.mdb.drAtrb     = 0;
+  vol.mdb.drNmFls    = 0;
+  vol.mdb.drVBMSt    = 3;
+  vol.mdb.drAllocPtr = 0;
+  vol.mdb.drNmAlBlks = (vol.vlen - 5 - vbmsz) / vol.lpa;
+  vol.mdb.drAlBlkSiz = vol.lpa * HFS_BLOCKSZ;
+  vol.mdb.drClpSiz   = vol.mdb.drAlBlkSiz * 4;
+  vol.mdb.drAlBlSt   = 3 + vbmsz;
+#ifdef APPLE_HYB
+  /* round up start block to a muliple of lpa - important later */
+/*vol.mdb.drAlBlSt   = ((vol.mdb.drAlBlSt + vol.lpa -  1) / vol.lpa) * vol.lpa; 
+*/
+  /* take in accout alignment of files wrt HFS volume start i.e we want
+     drAlBlSt plus hfs_map_size to me a multiple of lpa */
+  vol.mdb.drAlBlSt   = ((vol.mdb.drAlBlSt + hce->hfs_map_size + vol.lpa -  1) / vol.lpa) * vol.lpa; 
+  vol.mdb.drAlBlSt   -= hce->hfs_map_size;
+#endif /* APPLE_HYB */
+  vol.mdb.drNxtCNID  = HFS_CNID_ROOTDIR;  /* modified later */
+  vol.mdb.drFreeBks  = vol.mdb.drNmAlBlks;
+
+  strcpy(vol.mdb.drVN, vname);
+
+  vol.mdb.drVolBkUp  = 0;
+  vol.mdb.drVSeqNum  = 0;
+  vol.mdb.drWrCnt    = 0;
+  vol.mdb.drXTClpSiz = vol.mdb.drNmAlBlks / 128 * vol.mdb.drAlBlkSiz;
+#ifdef APPLE_HYB
+  /* adjust size of extents/catalog upwards as we may have rounded up
+     allocation size */
+  i = 1 + vol.vlen / 65536;
+
+  vol.mdb.drXTClpSiz = (vol.mdb.drXTClpSiz * vol.lpa) / i;
+
+  /* round up to lpa size */
+  vol.mdb.drXTClpSiz = ((vol.mdb.drXTClpSiz + vol.mdb.drAlBlkSiz - 1) /
+                               vol.mdb.drAlBlkSiz) * vol.mdb.drAlBlkSiz;
+
+  /* ignore above, use what we have already calculated ... */
+  vol.mdb.drXTClpSiz = hce->XTCsize;
+
+  /* make Catalog file CTC (default twice) as big - prevents further allocation
+     later which we don't want - this seems to work OK ... */
+/*vol.mdb.drCTClpSiz = vol.mdb.drXTClpSiz * CTC; */
+  vol.mdb.drCTClpSiz = vol.mdb.drXTClpSiz * hce->ctc_size;
+
+  /* we want to put things at the end of the volume later, so we'll
+     cheat here ... shouldn't matter, as we only need the volume read
+     only anyway (we won't be adding files later!) - leave some extra
+     space for the alternative MDB (in the last allocation block) */
+
+  vol.mdb.drNmAlBlks = vol.mdb.drFreeBks = vol.vlen / vol.lpa - 1;
+#else
+  vol.mdb.drCTClpSiz = vol.mdb.drXTClpSiz;
+#endif /* APPLE_HYB */
+  vol.mdb.drNmRtDirs = 0;
+  vol.mdb.drFilCnt   = 0;
+  vol.mdb.drDirCnt   = -1;  /* incremented when root folder is created */
+
+  for (i = 0; i < 8; ++i)
+    vol.mdb.drFndrInfo[i] = 0;
+
+  vol.mdb.drVCSize   = 0;
+  vol.mdb.drVBMCSize = 0;
+  vol.mdb.drCtlCSize = 0;
+
+  vol.mdb.drXTFlSize = 0;
+  vol.mdb.drCTFlSize = 0;
+
+  for (i = 0; i < 3; ++i)
+    {
+      vol.mdb.drXTExtRec[i].xdrStABN    = 0;
+      vol.mdb.drXTExtRec[i].xdrNumABlks = 0;
+
+      vol.mdb.drCTExtRec[i].xdrStABN    = 0;
+      vol.mdb.drCTExtRec[i].xdrNumABlks = 0;
+    }
+
+  /* initialize volume bitmap */
+
+  memset(vol.vbm, 0, sizeof(vbm));
+
+#ifdef APPLE_HYB
+  /* We don't want to write anything out at the moment, so we allocate
+     memory to hold the HFS "header" info and extents/catalog files.
+     Any reads/writes from/to these parts of the volume are trapped and
+     stored in memory. */
+
+  /* blocks up to the first unallocated block == HFS "header" info
+     This will be placed in the first 32kb of the ISO volume later */
+  hce->hfs_hdr_size = vol.mdb.drAlBlSt;
+
+  /* size of the extents and catalog files. This will be added
+     to the end of the ISO volume later */
+  hce->hfs_ce_size =  vol.mdb.drXTClpSiz + vol.mdb.drCTClpSiz;
+
+  /* we also allocate space for the Desktop file and the alternative
+     MDB while we're here */
+  FREE(hce->hfs_ce);
+  hce->hfs_ce = ALLOC(unsigned char, (hce->hfs_ce_size + vol.mdb.drClpSiz
+                                       + vol.mdb.drAlBlkSiz));
+
+  /* allocate memory for the map and hdr */
+  FREE(hce->hfs_map);
+  hce->hfs_map = ALLOC(unsigned char, ((hce->hfs_hdr_size + hce->hfs_map_size)
+                       *HFS_BLOCKSZ));
+
+  if (hce->hfs_ce == 0 || hce->hfs_map == 0)
+    {
+      ERROR(ENOMEM, 0);
+      result = -1;
+    }
+
+  /* hfs_hdr is immediately after the hfs_map */
+  hce->hfs_hdr = hce->hfs_map + hce->hfs_map_size*HFS_BLOCKSZ;
+
+  /* size needed in HFS_BLOCKSZ blocks for later use */
+  hce->hfs_ce_size /= HFS_BLOCKSZ;
+
+  /* note size of Desktop file */
+  hce->hfs_dt_size = vol.mdb.drClpSiz/HFS_BLOCKSZ;
+
+  /* total size of catalog/extents and desktop */
+  hce->hfs_tot_size = hce->hfs_ce_size + hce->hfs_dt_size;
+
+  /* alternative MDB in the last alocation block */
+  hce->hfs_alt_mdb = hce->hfs_ce + hce->hfs_tot_size*HFS_BLOCKSZ;
+
+  /* add the MDB to the total size */
+  hce->hfs_tot_size += vol.lpa;
+
+  /* store this info in the volume info */
+  vol.hce = hce;
+
+#endif /* APPLE_HYB */
+
+  /* create extents overflow file */
+
+  ext->f.vol   = &vol;
+  ext->f.parid = 0;
+  strcpy(ext->f.name, "extents overflow");
+
+  ext->f.cat.cdrType          = cdrFilRec;
+  /* ext->f.cat.cdrResrv2 */
+  ext->f.cat.u.fil.filFlags   = 0;
+  ext->f.cat.u.fil.filTyp     = 0;
+  /* ext->f.cat.u.fil.filUsrWds */
+  ext->f.cat.u.fil.filFlNum   = HFS_CNID_EXT;
+  ext->f.cat.u.fil.filStBlk   = 0;
+  ext->f.cat.u.fil.filLgLen   = 0;
+  ext->f.cat.u.fil.filPyLen   = 0;
+  ext->f.cat.u.fil.filRStBlk  = 0;
+  ext->f.cat.u.fil.filRLgLen  = 0;
+  ext->f.cat.u.fil.filRPyLen  = 0;
+  ext->f.cat.u.fil.filCrDat   = vol.mdb.drCrDate;
+  ext->f.cat.u.fil.filMdDat   = vol.mdb.drLsMod;
+  ext->f.cat.u.fil.filBkDat   = 0;
+  /* ext->f.cat.u.fil.filFndrInfo */
+  ext->f.cat.u.fil.filClpSize = 0;
+
+  for (i = 0; i < 3; ++i)
+    {
+      ext->f.cat.u.fil.filExtRec[i].xdrStABN     = 0;
+      ext->f.cat.u.fil.filExtRec[i].xdrNumABlks  = 0;
+
+      ext->f.cat.u.fil.filRExtRec[i].xdrStABN    = 0;
+      ext->f.cat.u.fil.filRExtRec[i].xdrNumABlks = 0;
+    }
+  /* ext->f.cat.u.fil.filResrv */
+  f_selectfork(&ext->f, 0);
+
+  ext->f.clump = vol.mdb.drXTClpSiz;
+  ext->f.flags = 0;
+
+  ext->f.prev = ext->f.next = 0;
+
+  n_init(&ext->hdrnd, ext, ndHdrNode, 0);
+
+  ext->hdrnd.nnum       = 0;
+  ext->hdrnd.nd.ndNRecs = 3;
+  ext->hdrnd.roff[1]    = 0x078;
+  ext->hdrnd.roff[2]    = 0x0f8;
+  ext->hdrnd.roff[3]    = 0x1f8;
+
+  memset(HFS_NODEREC(ext->hdrnd, 1), 0, 128);
+
+  ext->hdr.bthDepth    = 0;
+  ext->hdr.bthRoot     = 0;
+  ext->hdr.bthNRecs    = 0;
+  ext->hdr.bthFNode    = 0;
+  ext->hdr.bthLNode    = 0;
+  ext->hdr.bthNodeSize = HFS_BLOCKSZ;
+  ext->hdr.bthKeyLen   = 0x07;
+  ext->hdr.bthNNodes   = 0;
+  ext->hdr.bthFree     = 0;
+  for (i = 0; i < 76; ++i)
+    ext->hdr.bthResv[i] = 0;
+
+  map = ALLOC(char, HFS_MAP1SZ);
+  if (map == 0)
+    {
+      if (result == 0)
+       {
+         ERROR(ENOMEM, 0);
+         result = -1;
+       }
+    }
+  else
+    {
+      memset(map, 0, HFS_MAP1SZ);
+      BMSET(map, 0);
+    }
+
+  ext->map     = map;
+  ext->mapsz   = HFS_MAP1SZ;
+  ext->flags   = HFS_UPDATE_BTHDR;
+  ext->compare = r_compareextkeys;
+
+  if (result == 0 && bt_space(ext, 1) < 0)
+    result = -1;
+
+  --ext->hdr.bthFree;
+
+  /* create catalog file */
+
+  cat->f.vol   = &vol;
+  cat->f.parid = 0;
+  strcpy(cat->f.name, "catalog");
+
+  cat->f.cat.cdrType          = cdrFilRec;
+  /* cat->f.cat.cdrResrv2 */
+  cat->f.cat.u.fil.filFlags   = 0;
+  cat->f.cat.u.fil.filTyp     = 0;
+  /* cat->f.cat.u.fil.filUsrWds */
+  cat->f.cat.u.fil.filFlNum   = HFS_CNID_CAT;
+  cat->f.cat.u.fil.filStBlk   = 0;
+  cat->f.cat.u.fil.filLgLen   = 0;
+  cat->f.cat.u.fil.filPyLen   = 0;
+  cat->f.cat.u.fil.filRStBlk  = 0;
+  cat->f.cat.u.fil.filRLgLen  = 0;
+  cat->f.cat.u.fil.filRPyLen  = 0;
+  cat->f.cat.u.fil.filCrDat   = vol.mdb.drCrDate;
+  cat->f.cat.u.fil.filMdDat   = vol.mdb.drLsMod;
+  cat->f.cat.u.fil.filBkDat   = 0;
+  /* cat->f.cat.u.fil.filFndrInfo */
+  cat->f.cat.u.fil.filClpSize = 0;
+
+  for (i = 0; i < 3; ++i)
+    {
+      cat->f.cat.u.fil.filExtRec[i].xdrStABN     = 0;
+      cat->f.cat.u.fil.filExtRec[i].xdrNumABlks  = 0;
+
+      cat->f.cat.u.fil.filRExtRec[i].xdrStABN    = 0;
+      cat->f.cat.u.fil.filRExtRec[i].xdrNumABlks = 0;
+    }
+  /* cat->f.cat.u.fil.filResrv */
+  f_selectfork(&cat->f, 0);
+
+  cat->f.clump = vol.mdb.drCTClpSiz;
+  cat->f.flags = 0;
+
+  cat->f.prev = cat->f.next = 0;
+
+  n_init(&cat->hdrnd, cat, ndHdrNode, 0);
+
+  cat->hdrnd.nnum       = 0;
+  cat->hdrnd.nd.ndNRecs = 3;
+  cat->hdrnd.roff[1]    = 0x078;
+  cat->hdrnd.roff[2]    = 0x0f8;
+  cat->hdrnd.roff[3]    = 0x1f8;
+
+  memset(HFS_NODEREC(cat->hdrnd, 1), 0, 128);
+
+  cat->hdr.bthDepth    = 0;
+  cat->hdr.bthRoot     = 0;
+  cat->hdr.bthNRecs    = 0;
+  cat->hdr.bthFNode    = 0;
+  cat->hdr.bthLNode    = 0;
+  cat->hdr.bthNodeSize = HFS_BLOCKSZ;
+  cat->hdr.bthKeyLen   = 0x25;
+  cat->hdr.bthNNodes   = 0;
+  cat->hdr.bthFree     = 0;
+  for (i = 0; i < 76; ++i)
+    cat->hdr.bthResv[i] = 0;
+
+  map = ALLOC(char, HFS_MAP1SZ);
+  if (map == 0)
+    {
+      if (result == 0)
+       {
+         ERROR(ENOMEM, 0);
+         result = -1;
+       }
+    }
+  else
+    {
+      memset(map, 0, HFS_MAP1SZ);
+      BMSET(map, 0);
+    }
+
+  cat->map     = map;
+  cat->mapsz   = HFS_MAP1SZ;
+  cat->flags   = HFS_UPDATE_BTHDR;
+  cat->compare = r_comparecatkeys;
+
+  if (result == 0 && bt_space(cat, 1) < 0)
+    result = -1;
+
+  --cat->hdr.bthFree;
+
+  /* create root folder */
+
+  if (result == 0 && v_newfolder(&vol, HFS_CNID_ROOTPAR, vname) < 0)
+    result = -1;
+
+  vol.mdb.drNxtCNID = 16;
+
+  /* finish up */
+
+  if (result == 0)
+    {
+      block b;
+
+      /* write boot blocks */
+
+      memset(&b, 0, sizeof(b));
+      b_writelb(&vol, 0, &b);
+      b_writelb(&vol, 1, &b);
+
+      /* flush other disk state */
+
+      vol.flags |= HFS_UPDATE_MDB | HFS_UPDATE_ALTMDB | HFS_UPDATE_VBM;
+
+      if (v_flush(&vol, 1) < 0)
+       result = -1;
+    }
+#ifndef APPLE_HYB
+  if (close(vol.fd) < 0 && result == 0)
+    {
+      ERROR(errno, "error closing device");
+      result = -1;
+    }
+#endif /* APPLE_HYB */
+  FREE(vol.ext.map);
+  FREE(vol.cat.map);
+
+  return result;
+}
+
+/* High-Level Directory Routines =========================================== */
+
+/*
+ * NAME:       hfs->chdir()
+ * DESCRIPTION:        change current HFS directory
+ */
+int hfs_chdir(hfsvol *vol, char *path)
+{
+  CatDataRec data;
+
+  if (v_getvol(&vol) < 0 ||
+      v_resolve(&vol, path, &data, 0, 0, 0) <= 0)
+    return -1;
+
+  if (data.cdrType != cdrDirRec)
+    {
+      ERROR(ENOTDIR, 0);
+      return -1;
+    }
+
+  vol->cwd = data.u.dir.dirDirID;
+
+  return 0;
+}
+
+/*
+ * NAME:       hfs->getcwd()
+ * DESCRIPTION:        return the current working directory ID
+ */
+long hfs_getcwd(hfsvol *vol)
+{
+  if (v_getvol(&vol) < 0)
+    return 0;
+
+  return vol->cwd;
+}
+
+/*
+ * NAME:       hfs->setcwd()
+ * DESCRIPTION:        set the current working directory ID
+ */
+int hfs_setcwd(hfsvol *vol, long id)
+{
+  if (v_getvol(&vol) < 0)
+    return -1;
+
+  if (id == vol->cwd)
+    return 0;
+
+  /* make sure the directory exists */
+
+  if (v_getdthread(vol, id, 0, 0) <= 0)
+    return -1;
+
+  vol->cwd = id;
+
+  return 0;
+}
+
+/*
+ * NAME:       hfs->dirinfo()
+ * DESCRIPTION:        given a directory ID, return its (name and) parent ID
+ */
+int hfs_dirinfo(hfsvol *vol, long *id, char *name)
+{
+  CatDataRec thread;
+
+  if (v_getvol(&vol) < 0 ||
+      v_getdthread(vol, *id, &thread, 0) <= 0)
+    return -1;
+
+  *id = thread.u.dthd.thdParID;
+
+  if (name)
+    strcpy(name, thread.u.dthd.thdCName);
+
+  return 0;
+}
+
+/*
+ * NAME:       hfs->opendir()
+ * DESCRIPTION:        prepare to read the contents of a directory
+ */
+hfsdir *hfs_opendir(hfsvol *vol, char *path)
+{
+  hfsdir *dir;
+  CatKeyRec key;
+  CatDataRec data;
+  unsigned char pkey[HFS_CATKEYLEN];
+
+  if (v_getvol(&vol) < 0)
+    return 0;
+
+  dir = ALLOC(hfsdir, 1);
+  if (dir == 0)
+    {
+      ERROR(ENOMEM, 0);
+      return 0;
+    }
+
+  dir->vol = vol;
+
+  if (*path == 0)
+    {
+      /* meta-directory containing root dirs from all mounted volumes */
+
+      dir->dirid = 0;
+      dir->vptr  = hfs_mounts;
+    }
+  else
+    {
+      if (v_resolve(&vol, path, &data, 0, 0, 0) <= 0)
+       {
+         FREE(dir);
+         return 0;
+       }
+
+      if (data.cdrType != cdrDirRec)
+       {
+         FREE(dir);
+         ERROR(ENOTDIR, 0);
+         return 0;
+       }
+
+      dir->dirid = data.u.dir.dirDirID;
+      dir->vptr  = 0;
+
+      r_makecatkey(&key, dir->dirid, "");
+      r_packcatkey(&key, pkey, 0);
+
+      if (bt_search(&vol->cat, pkey, &dir->n) <= 0)
+       {
+         FREE(dir);
+         return 0;
+       }
+    }
+
+  dir->prev = 0;
+  dir->next = vol->dirs;
+
+  if (vol->dirs)
+    vol->dirs->prev = dir;
+
+  vol->dirs = dir;
+
+  return dir;
+}
+
+/*
+ * NAME:       hfs->readdir()
+ * DESCRIPTION:        return the next entry in the directory
+ */
+int hfs_readdir(hfsdir *dir, hfsdirent *ent)
+{
+  CatKeyRec key;
+  CatDataRec data;
+  unsigned char *ptr;
+
+  if (dir->dirid == 0)
+    {
+      hfsvol *vol;
+      char cname[HFS_MAX_FLEN + 1];
+
+      for (vol = hfs_mounts; vol; vol = vol->next)
+       {
+         if (vol == dir->vptr)
+           break;
+       }
+
+      if (vol == 0)
+       {
+         ERROR(ENOENT, "no more entries");
+         return -1;
+       }
+
+      if (v_getdthread(vol, HFS_CNID_ROOTDIR, &data, 0) <= 0 ||
+         v_catsearch(vol, HFS_CNID_ROOTPAR, data.u.dthd.thdCName,
+                     &data, cname, 0) < 0)
+       return -1;
+
+      r_unpackdirent(HFS_CNID_ROOTPAR, cname, &data, ent);
+
+      dir->vptr = vol->next;
+
+      return 0;
+    }
+
+  if (dir->n.rnum == -1)
+    {
+      ERROR(ENOENT, "no more entries");
+      return -1;
+    }
+
+  for (;;)
+    {
+      ++dir->n.rnum;
+
+      while (dir->n.rnum >= (int)dir->n.nd.ndNRecs)
+       {
+         dir->n.nnum = dir->n.nd.ndFLink;
+         if (dir->n.nnum == 0)
+           {
+             dir->n.rnum = -1;
+             ERROR(ENOENT, "no more entries");
+             return -1;
+           }
+
+         if (bt_getnode(&dir->n) < 0)
+           {
+             dir->n.rnum = -1;
+             return -1;
+           }
+
+         dir->n.rnum = 0;
+       }
+
+      ptr = HFS_NODEREC(dir->n, dir->n.rnum);
+
+      r_unpackcatkey(ptr, &key);
+
+      if (key.ckrParID != dir->dirid)
+       {
+         dir->n.rnum = -1;
+         ERROR(ENOENT, "no more entries");
+         return -1;
+       }
+
+      r_unpackcatdata(HFS_RECDATA(ptr), &data);
+
+      switch (data.cdrType)
+       {
+       case cdrDirRec:
+       case cdrFilRec:
+         r_unpackdirent(key.ckrParID, key.ckrCName, &data, ent);
+         return 0;
+
+       case cdrThdRec:
+       case cdrFThdRec:
+         break;
+
+       default:
+         dir->n.rnum = -1;
+
+         ERROR(EIO, "unexpected directory entry found");
+         return -1;
+       }
+    }
+}
+
+/*
+ * NAME:       hfs->closedir()
+ * DESCRIPTION:        stop reading a directory
+ */
+int hfs_closedir(hfsdir *dir)
+{
+  hfsvol *vol = dir->vol;
+
+  if (dir->prev)
+    dir->prev->next = dir->next;
+  if (dir->next)
+    dir->next->prev = dir->prev;
+  if (dir == vol->dirs)
+    vol->dirs = dir->next;
+
+  FREE(dir);
+
+  return 0;
+}
+
+/* High-Level File Routines ================================================ */
+
+/*
+ * NAME:       hfs->open()
+ * DESCRIPTION:        prepare a file for I/O
+ */
+hfsfile *hfs_open(hfsvol *vol, char *path)
+{
+  hfsfile *file;
+
+  if (v_getvol(&vol) < 0)
+    return 0;
+
+  file = ALLOC(hfsfile, 1);
+  if (file == 0)
+    {
+      ERROR(ENOMEM, 0);
+      return 0;
+    }
+
+  if (v_resolve(&vol, path, &file->cat, &file->parid, file->name, 0) <= 0)
+    {
+      FREE(file);
+      return 0;
+    }
+
+  if (file->cat.cdrType != cdrFilRec)
+    {
+      FREE(file);
+      ERROR(EISDIR, 0);
+      return 0;
+    }
+
+  file->vol   = vol;
+  file->clump = file->cat.u.fil.filClpSize;
+  file->flags = 0;
+
+  f_selectfork(file, 0);
+
+  file->prev = 0;
+  file->next = vol->files;
+
+  if (vol->files)
+    vol->files->prev = file;
+
+  vol->files = file;
+
+  return file;
+}
+
+/*
+ * NAME:       hfs->setfork()
+ * DESCRIPTION:        select file fork for I/O operations
+ */
+int hfs_setfork(hfsfile *file, int ffork)
+{
+  int result = 0;
+
+  if (! (file->vol->flags & HFS_READONLY) &&
+      f_trunc(file) < 0)
+    result = -1;
+
+  f_selectfork(file, ffork);
+
+  return result;
+}
+
+/*
+ * NAME:       hfs->getfork()
+ * DESCRIPTION:        return the current fork for I/O operations
+ */
+int hfs_getfork(hfsfile *file)
+{
+  return file->fork != fkData;
+}
+
+/*
+ * NAME:       hfs->read()
+ * DESCRIPTION:        read from an open file
+ */
+long hfs_read(hfsfile *file, void *buf, unsigned long len)
+{
+  unsigned long *lglen, count;
+  unsigned char *ptr = buf;
+
+  f_getptrs(file, &lglen, 0, 0);
+
+  if (file->pos + len > *lglen)
+    len = *lglen - file->pos;
+
+  count = len;
+  while (count)
+    {
+      block b;
+      unsigned long bnum, offs, chunk;
+
+      bnum  = file->pos / HFS_BLOCKSZ;
+      offs  = file->pos % HFS_BLOCKSZ;
+
+      chunk = HFS_BLOCKSZ - offs;
+      if (chunk > count)
+       chunk = count;
+
+      if (f_getblock(file, bnum, &b) < 0)
+       return -1;
+
+      memcpy(ptr, b + offs, chunk);
+      ptr += chunk;
+
+      file->pos += chunk;
+      count     -= chunk;
+    }
+
+  return len;
+}
+
+/*
+ * NAME:       hfs->write()
+ * DESCRIPTION:        write to an open file
+ */
+long hfs_write(hfsfile *file, void *buf, unsigned long len)
+{
+  unsigned long *lglen, *pylen, count;
+  unsigned char *ptr = buf;
+
+  if (file->vol->flags & HFS_READONLY)
+    {
+      ERROR(EROFS, 0);
+      return -1;
+    }
+
+  f_getptrs(file, &lglen, &pylen, 0);
+
+  count = len;
+
+  /* set flag to update (at least) the modification time */
+
+  if (count)
+    {
+      file->cat.u.fil.filMdDat = d_tomtime(time(0));
+      file->flags |= HFS_UPDATE_CATREC;
+    }
+
+  while (count)
+    {
+      block b;
+      unsigned long bnum, offs, chunk;
+
+      bnum  = file->pos / HFS_BLOCKSZ;
+      offs  = file->pos % HFS_BLOCKSZ;
+
+      chunk = HFS_BLOCKSZ - offs;
+      if (chunk > count)
+       chunk = count;
+
+      if (file->pos + chunk > *pylen)
+       {
+         if (bt_space(&file->vol->ext, 1) < 0 ||
+             f_alloc(file) < 0)
+           return -1;
+       }
+#ifndef APPLE_HYB
+      /* Ignore this part as we are always writing new files to an empty disk
+        i.e. offs will always be 0 */
+
+      if (offs > 0 || chunk < HFS_BLOCKSZ)
+       {
+         if (f_getblock(file, bnum, &b) < 0)
+           return -1;
+       }
+#endif /* APPLE_HYB */
+      memcpy(b + offs, ptr, chunk);
+      ptr += chunk;
+
+      if (f_putblock(file, bnum, &b) < 0)
+       return -1;
+
+      file->pos += chunk;
+      count     -= chunk;
+
+      if (file->pos > *lglen)
+       *lglen = file->pos;
+    }
+
+  return len;
+}
+
+/*
+ * NAME:       hfs->truncate()
+ * DESCRIPTION:        truncate an open file
+ */
+int hfs_truncate(hfsfile *file, unsigned long len)
+{
+  unsigned long *lglen;
+
+  f_getptrs(file, &lglen, 0, 0);
+
+  if (*lglen > len)
+    {
+      if (file->vol->flags & HFS_READONLY)
+       {
+         ERROR(EROFS, 0);
+         return -1;
+       }
+
+      *lglen = len;
+
+      file->cat.u.fil.filMdDat = d_tomtime(time(0));
+      file->flags |= HFS_UPDATE_CATREC;
+
+      if (file->pos > len)
+       file->pos = len;
+    }
+
+  return 0;
+}
+
+/*
+ * NAME:       hfs->lseek()
+ * DESCRIPTION:        change file seek pointer
+ */
+long hfs_lseek(hfsfile *file, long offset, int from)
+{
+  unsigned long *lglen;
+  long newpos;
+
+  f_getptrs(file, &lglen, 0, 0);
+
+  switch (from)
+    {
+    case SEEK_SET:
+      newpos = offset;
+      break;
+
+    case SEEK_CUR:
+      newpos = file->pos + offset;
+      break;
+
+    case SEEK_END:
+      newpos = *lglen + offset;
+      break;
+
+    default:
+      ERROR(EINVAL, 0);
+      return -1;
+    }
+
+  if (newpos < 0)
+    newpos = 0;
+  else if (newpos > *lglen)
+    newpos = *lglen;
+
+  file->pos = newpos;
+
+  return newpos;
+}
+
+/*
+ * NAME:       hfs->close()
+ * DESCRIPTION:        close a file
+ */
+#ifdef APPLE_HYB
+/* extra args are used to set the start of the forks in the ISO volume */
+int hfs_close(hfsfile *file, long dext, long rext)
+{
+  int offset;
+#else
+int hfs_close(hfsfile *file)
+{
+#endif /* APPLE_HYB */
+  hfsvol *vol = file->vol;
+  int result = 0;
+
+  if (f_trunc(file) < 0 ||
+      f_flush(file) < 0)
+    result = -1;
+
+#ifdef APPLE_HYB
+  /* "start" of file is relative to the first available block */
+  offset = vol->hce->hfs_hdr_size + vol->hce->hfs_map_size;
+  /* update the "real" starting extent and re-flush the file */
+  if (dext)
+    file->cat.u.fil.filExtRec[0].xdrStABN = (dext - offset)/vol->lpa;
+
+  if (rext)
+    file->cat.u.fil.filRExtRec[0].xdrStABN = (rext - offset)/vol->lpa;
+
+  if (dext || rext)
+    file->flags |= HFS_UPDATE_CATREC;
+
+  if (f_flush(file) < 0)
+    result = -1;
+#endif /*APPLE_HYB */
+
+  if (file->prev)
+    file->prev->next = file->next;
+  if (file->next)
+    file->next->prev = file->prev;
+  if (file == vol->files)
+    vol->files = file->next;
+
+  FREE(file);
+
+  return result;
+}
+
+/* High-Level Catalog Routines ============================================= */
+
+/*
+ * NAME:       hfs->stat()
+ * DESCRIPTION:        return catalog information for an arbitrary path
+ */
+int hfs_stat(hfsvol *vol, char *path, hfsdirent *ent)
+{
+  CatDataRec data;
+  long parid;
+  char name[HFS_MAX_FLEN + 1];
+
+  if (v_getvol(&vol) < 0 ||
+      v_resolve(&vol, path, &data, &parid, name, 0) <= 0)
+    return -1;
+
+  r_unpackdirent(parid, name, &data, ent);
+
+  return 0;
+}
+
+/*
+ * NAME:       hfs->fstat()
+ * DESCRIPTION:        return catalog information for an open file
+ */
+int hfs_fstat(hfsfile *file, hfsdirent *ent)
+{
+  r_unpackdirent(file->parid, file->name, &file->cat, ent);
+
+  return 0;
+}
+
+/*
+ * NAME:       hfs->setattr()
+ * DESCRIPTION:        change a file's attributes
+ */
+int hfs_setattr(hfsvol *vol, char *path, hfsdirent *ent)
+{
+  CatDataRec data;
+  node n;
+
+  if (v_getvol(&vol) < 0 ||
+      v_resolve(&vol, path, &data, 0, 0, &n) <= 0)
+    return -1;
+
+  if (vol->flags & HFS_READONLY)
+    {
+      ERROR(EROFS, 0);
+      return -1;
+    }
+
+  r_packdirent(&data, ent);
+
+  if (v_putcatrec(&data, &n) < 0)
+    return -1;
+
+  return 0;
+}
+
+/*
+ * NAME:       hfs->fsetattr()
+ * DESCRIPTION:        change an open file's attributes
+ */
+int hfs_fsetattr(hfsfile *file, hfsdirent *ent)
+{
+  if (file->vol->flags & HFS_READONLY)
+    {
+      ERROR(EROFS, 0);
+      return -1;
+    }
+
+  r_packdirent(&file->cat, ent);
+
+  file->flags |= HFS_UPDATE_CATREC;
+
+  return 0;
+}
+
+/*
+ * NAME:       hfs->mkdir()
+ * DESCRIPTION:        create a new directory
+ */
+int hfs_mkdir(hfsvol *vol, char *path)
+{
+  CatDataRec data;
+  long parid;
+  char name[HFS_MAX_FLEN + 1];
+  int found;
+
+  if (v_getvol(&vol) < 0)
+    return -1;
+
+  found = v_resolve(&vol, path, &data, &parid, name, 0);
+  if (found < 0 || parid == 0)
+    return -1;
+  else if (found)
+    {
+      ERROR(EEXIST, 0);
+      return -1;
+    }
+
+  if (parid == HFS_CNID_ROOTPAR)
+    {
+      ERROR(EINVAL, 0);
+      return -1;
+    }
+
+  if (vol->flags & HFS_READONLY)
+    {
+      ERROR(EROFS, 0);
+      return -1;
+    }
+
+  if (v_newfolder(vol, parid, name) < 0)
+    return -1;
+
+  return 0;
+}
+
+/*
+ * NAME:       hfs->rmdir()
+ * DESCRIPTION:        delete an empty directory
+ */
+int hfs_rmdir(hfsvol *vol, char *path)
+{
+  CatKeyRec key;
+  CatDataRec data;
+  long parid;
+  char name[HFS_MAX_FLEN + 1];
+  unsigned char pkey[HFS_CATKEYLEN];
+
+  if (v_getvol(&vol) < 0 ||
+      v_resolve(&vol, path, &data, &parid, name, 0) <= 0)
+    return -1;
+
+  if (data.cdrType != cdrDirRec)
+    {
+      ERROR(ENOTDIR, 0);
+      return -1;
+    }
+
+  if (data.u.dir.dirVal != 0)
+    {
+      ERROR(ENOTEMPTY, 0);
+      return -1;
+    }
+
+  if (parid == HFS_CNID_ROOTPAR)
+    {
+      ERROR(EINVAL, 0);
+      return -1;
+    }
+
+  if (vol->flags & HFS_READONLY)
+    {
+      ERROR(EROFS, 0);
+      return -1;
+    }
+
+  /* delete directory record */
+
+  r_makecatkey(&key, parid, name);
+  r_packcatkey(&key, pkey, 0);
+
+  if (bt_delete(&vol->cat, pkey) < 0)
+    return -1;
+
+  /* delete thread record */
+
+  r_makecatkey(&key, data.u.dir.dirDirID, "");
+  r_packcatkey(&key, pkey, 0);
+
+  if (bt_delete(&vol->cat, pkey) < 0 ||
+      v_adjvalence(vol, parid, 1, -1) < 0)
+    return -1;
+
+  return 0;
+}
+
+/*
+ * NAME:       hfs->create()
+ * DESCRIPTION:        create a new file
+ */
+int hfs_create(hfsvol *vol, char *path, char *type, char *creator)
+{
+  CatKeyRec key;
+  CatDataRec data;
+  long id, parid;
+  char name[HFS_MAX_FLEN + 1];
+  unsigned char record[HFS_CATRECMAXLEN];
+  int found, i, reclen;
+
+  if (v_getvol(&vol) < 0)
+    return -1;
+
+  found = v_resolve(&vol, path, &data, &parid, name, 0);
+  if (found < 0 || parid == 0)
+    return -1;
+  else if (found)
+    {
+      ERROR(EEXIST, 0);
+      return -1;
+    }
+
+  if (parid == HFS_CNID_ROOTPAR)
+    {
+      ERROR(EINVAL, 0);
+      return -1;
+    }
+
+  if (vol->flags & HFS_READONLY)
+    {
+      ERROR(EROFS, 0);
+      return -1;
+    }
+
+  /* create file `name' in parent `parid' */
+
+  if (bt_space(&vol->cat, 1) < 0)
+    return -1;
+
+  id = vol->mdb.drNxtCNID++;
+  vol->flags |= HFS_UPDATE_MDB;
+
+  /* create file record */
+
+  data.cdrType   = cdrFilRec;
+  data.cdrResrv2 = 0;
+
+  data.u.fil.filFlags = 0;
+  data.u.fil.filTyp   = 0;
+
+  memset(&data.u.fil.filUsrWds, 0, sizeof(data.u.fil.filUsrWds));
+
+  data.u.fil.filUsrWds.fdType    = d_getl((unsigned char *) type);
+  data.u.fil.filUsrWds.fdCreator = d_getl((unsigned char *) creator);
+
+  data.u.fil.filFlNum  = id;
+  data.u.fil.filStBlk  = 0;
+  data.u.fil.filLgLen  = 0;
+  data.u.fil.filPyLen  = 0;
+  data.u.fil.filRStBlk = 0;
+  data.u.fil.filRLgLen = 0;
+  data.u.fil.filRPyLen = 0;
+  data.u.fil.filCrDat  = d_tomtime(time(0));
+  data.u.fil.filMdDat  = data.u.fil.filCrDat;
+  data.u.fil.filBkDat  = 0;
+
+  memset(&data.u.fil.filFndrInfo, 0, sizeof(data.u.fil.filFndrInfo));
+
+  data.u.fil.filClpSize = 0;
+
+  for (i = 0; i < 3; ++i)
+    {
+      data.u.fil.filExtRec[i].xdrStABN     = 0;
+      data.u.fil.filExtRec[i].xdrNumABlks  = 0;
+
+      data.u.fil.filRExtRec[i].xdrStABN    = 0;
+      data.u.fil.filRExtRec[i].xdrNumABlks = 0;
+    }
+
+  data.u.fil.filResrv = 0;
+
+  r_makecatkey(&key, parid, name);
+  r_packcatkey(&key, record, &reclen);
+  r_packcatdata(&data, HFS_RECDATA(record), &reclen);
+
+  if (bt_insert(&vol->cat, record, reclen) < 0 ||
+      v_adjvalence(vol, parid, 0, 1) < 0)
+    return -1;
+
+  return 0;
+}
+
+/*
+ * NAME:       hfs->delete()
+ * DESCRIPTION:        remove both forks of a file
+ */
+int hfs_delete(hfsvol *vol, char *path)
+{
+  hfsfile file;
+  CatKeyRec key;
+  unsigned char pkey[HFS_CATKEYLEN];
+  int found;
+
+  if (v_getvol(&vol) < 0 ||
+      v_resolve(&vol, path, &file.cat, &file.parid, file.name, 0) <= 0)
+    return -1;
+
+  if (file.cat.cdrType != cdrFilRec)
+    {
+      ERROR(EISDIR, 0);
+      return -1;
+    }
+
+  if (file.parid == HFS_CNID_ROOTPAR)
+    {
+      ERROR(EINVAL, 0);
+      return -1;
+    }
+
+  if (vol->flags & HFS_READONLY)
+    {
+      ERROR(EROFS, 0);
+      return -1;
+    }
+
+  /* free disk blocks */
+
+  file.vol   = vol;
+  file.flags = 0;
+
+  file.cat.u.fil.filLgLen  = 0;
+  file.cat.u.fil.filRLgLen = 0;
+
+  f_selectfork(&file, 0);
+  if (f_trunc(&file) < 0)
+    return -1;
+
+  f_selectfork(&file, 1);
+  if (f_trunc(&file) < 0)
+    return -1;
+
+  /* delete file record */
+
+  r_makecatkey(&key, file.parid, file.name);
+  r_packcatkey(&key, pkey, 0);
+
+  if (bt_delete(&vol->cat, pkey) < 0 ||
+      v_adjvalence(vol, file.parid, 0, -1) < 0)
+    return -1;
+
+  /* delete file thread, if any */
+
+  found = v_getfthread(vol, file.cat.u.fil.filFlNum, 0, 0);
+  if (found < 0)
+    return -1;
+
+  if (found)
+    {
+      r_makecatkey(&key, file.cat.u.fil.filFlNum, "");
+      r_packcatkey(&key, pkey, 0);
+
+      if (bt_delete(&vol->cat, pkey) < 0)
+       return -1;
+    }
+
+  return 0;
+}
+
+/*
+ * NAME:       hfs->rename()
+ * DESCRIPTION:        change the name of and/or move a file or directory
+ */
+int hfs_rename(hfsvol *vol, char *srcpath, char *dstpath)
+{
+  hfsvol *srcvol;
+  CatDataRec src, dst;
+  long srcid, dstid;
+  CatKeyRec key;
+  char srcname[HFS_MAX_FLEN + 1], dstname[HFS_MAX_FLEN + 1];
+  unsigned char record[HFS_CATRECMAXLEN];
+  int found, isdir, moving, reclen;
+  node n;
+
+  if (v_getvol(&vol) < 0 ||
+      v_resolve(&vol, srcpath, &src, &srcid, srcname, 0) <= 0)
+    return -1;
+
+  isdir  = (src.cdrType == cdrDirRec);
+  srcvol = vol;
+
+  found = v_resolve(&vol, dstpath, &dst, &dstid, dstname, 0);
+  if (found < 0)
+    return -1;
+
+  if (vol != srcvol)
+    {
+      ERROR(EINVAL, "can't move across volumes");
+      return -1;
+    }
+
+  if (dstid == 0)
+    {
+      ERROR(ENOENT, "bad destination path");
+      return -1;
+    }
+
+  if (found &&
+      dst.cdrType == cdrDirRec &&
+      dst.u.dir.dirDirID != src.u.dir.dirDirID)
+    {
+      dstid = dst.u.dir.dirDirID;
+      strcpy(dstname, srcname);
+
+      found = v_catsearch(vol, dstid, dstname, 0, 0, 0);
+      if (found < 0)
+       return -1;
+    }
+
+  moving = (srcid != dstid);
+
+  if (found)
+    {
+      char *ptr;
+
+      ptr = strrchr(dstpath, ':');
+      if (ptr == 0)
+       ptr = dstpath;
+      else
+       ++ptr;
+
+      if (*ptr)
+       strcpy(dstname, ptr);
+
+      if (! moving && strcmp(srcname, dstname) == 0)
+       return 0;  /* source and destination are the same */
+
+      if (moving || d_relstring(srcname, dstname))
+       {
+         ERROR(EEXIST, "can't use destination name");
+         return -1;
+       }
+    }
+
+  /* can't move anything into the root directory's parent */
+
+  if (moving && dstid == HFS_CNID_ROOTPAR)
+    {
+      ERROR(EINVAL, "can't move above root directory");
+      return -1;
+    }
+
+  if (moving && isdir)
+    {
+      long id;
+
+      /* can't move root directory anywhere */
+
+      if (src.u.dir.dirDirID == HFS_CNID_ROOTDIR)
+       {
+         ERROR(EINVAL, "can't move root directory");
+         return -1;
+       }
+
+      /* make sure we aren't trying to move a directory inside itself */
+
+      for (id = dstid; id != HFS_CNID_ROOTDIR; id = dst.u.dthd.thdParID)
+       {
+         if (id == src.u.dir.dirDirID)
+           {
+             ERROR(EINVAL, "can't move directory inside itself");
+             return -1;
+           }
+
+         if (v_getdthread(vol, id, &dst, 0) <= 0)
+           return -1;
+       }
+    }
+
+  if (vol->flags & HFS_READONLY)
+    {
+      ERROR(EROFS, 0);
+      return -1;
+    }
+
+  /* change volume name */
+
+  if (dstid == HFS_CNID_ROOTPAR)
+    {
+      if (strlen(dstname) > HFS_MAX_VLEN)
+       {
+         ERROR(ENAMETOOLONG, 0);
+         return -1;
+       }
+
+      strcpy(vol->mdb.drVN, dstname);
+      vol->flags |= HFS_UPDATE_MDB;
+    }
+
+  /* remove source record */
+
+  r_makecatkey(&key, srcid, srcname);
+  r_packcatkey(&key, record, 0);
+
+  if (bt_delete(&vol->cat, record) < 0)
+    return -1;
+
+  /* insert destination record */
+
+  r_makecatkey(&key, dstid, dstname);
+  r_packcatkey(&key, record, &reclen);
+  r_packcatdata(&src, HFS_RECDATA(record), &reclen);
+
+  if (bt_insert(&vol->cat, record, reclen) < 0)
+    return -1;
+
+  /* update thread record */
+
+  if (isdir)
+    {
+      if (v_getdthread(vol, src.u.dir.dirDirID, &dst, &n) <= 0)
+       return -1;
+
+      dst.u.dthd.thdParID = dstid;
+      strcpy(dst.u.dthd.thdCName, dstname);
+
+      if (v_putcatrec(&dst, &n) < 0)
+       return -1;
+    }
+  else
+    {
+      found = v_getfthread(vol, src.u.fil.filFlNum, &dst, &n);
+      if (found < 0)
+       return -1;
+
+      if (found)
+       {
+         dst.u.fthd.fthdParID = dstid;
+         strcpy(dst.u.fthd.fthdCName, dstname);
+
+         if (v_putcatrec(&dst, &n) < 0)
+           return -1;
+       }
+    }
+
+  /* update directory valences */
+
+  if (moving)
+    {
+      if (v_adjvalence(vol, srcid, isdir, -1) < 0 ||
+         v_adjvalence(vol, dstid, isdir,  1) < 0)
+       return -1;
+    }
+
+  return 0;
+}
+#ifdef APPLE_HYB
+/*
+ * NAME:        hfs->hfs_get_drAllocPtr()
+ * DESCRIPTION: get the current start of next allocation search 
+ */
+unsigned short
+hfs_get_drAllocPtr(hfsfile *file)
+{
+  return(file->vol->mdb.drAllocPtr);
+}
+
+/*
+ * NAME:        hfs->hfs_set_drAllocPtr()
+ * DESCRIPTION: set the current start of next allocation search 
+ */
+#ifdef PROTOTYPES
+int
+hfs_set_drAllocPtr(hfsfile *file, unsigned short drAllocPtr, int size)
+#else
+int
+hfs_set_drAllocPtr(hfsfile *file, unsigned short drAllocPtr, int size)
+#endif
+{
+  hfsvol *vol = file->vol;
+  int result = 0;
+
+  /* truncate the current fork */
+  if (f_trunc(file) < 0 ||
+      f_flush(file) < 0)
+    result = -1;
+
+  /* convert the fork size into allocation blocks */
+  size = (size + vol->mdb.drAlBlkSiz - 1)/vol->mdb.drAlBlkSiz;
+
+  /* set the start of next allocation search to be after this fork */
+  vol->mdb.drAllocPtr = drAllocPtr + size;
+
+  vol->flags |= HFS_UPDATE_MDB;
+
+  return result;
+}
+
+/*
+ * NAME:        hfs->vsetbless()
+ * DESCRIPTION: set blessed folder
+ *
+ * adapted from vsetattr() from v3.2.6
+ */
+#ifdef  PROTOTYPES
+void
+hfs_vsetbless(hfsvol *vol, unsigned long cnid)
+#else
+void
+hfs_vsetbless(hfsvol *vol, unsigned long cnid)
+#endif
+{
+  vol->mdb.drFndrInfo[0] = cnid;
+
+  vol->flags |= HFS_UPDATE_MDB;
+}
+#endif /* APPLE_HYB */
diff --git a/libhfs_iso/hfs.h b/libhfs_iso/hfs.h
new file mode 100644 (file)
index 0000000..f2c9d96
--- /dev/null
@@ -0,0 +1,208 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)hfs.h   1.4 01/11/01 joerg */
+/*
+ * hfsutils - tools for reading and writing Macintosh HFS volumes
+ * Copyright (C) 1996, 1997 Robert Leslie
+ *
+ * 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 of the License, 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.
+ */
+#ifndef HFS_H
+#define HFS_H
+
+#include <timedefs.h>
+#include <standard.h>
+
+#ifdef APPLE_HYB
+#include "hybrid.h"
+
+/* don't need device locking for mkhybrid */
+#ifndef NODEVLOCKS
+#define NODEVLOCKS
+#endif /* NODEVLOCKS */
+
+#endif /* APPLE_HYB */
+
+# define HFS_BLOCKSZ   512
+# define HFS_MAX_FLEN  31
+# define HFS_MAX_VLEN  27
+
+typedef struct _hfsvol_  hfsvol;
+typedef struct _hfsfile_ hfsfile;
+typedef struct _hfsdir_  hfsdir;
+
+typedef struct {
+  char name[HFS_MAX_VLEN + 1]; /* name of volume */
+  int flags;                   /* volume flags */
+  unsigned long totbytes;      /* total bytes on volume */
+  unsigned long freebytes;     /* free bytes on volume */
+  time_t crdate;               /* volume creation date */
+  time_t mddate;               /* last volume modification date */
+} hfsvolent;
+
+/* taken from v3.2.6 */
+typedef struct {
+  char name[HFS_MAX_FLEN + 1]; /* catalog name (MacOS Standard Roman) */
+  int flags;                   /* bit flags */
+  unsigned long cnid;          /* catalog node id (CNID) */
+  unsigned long parid;         /* CNID of parent directory */
+
+  time_t crdate;               /* date of creation */
+  time_t mddate;               /* date of last modification */
+  time_t bkdate;               /* date of last backup */
+
+  short fdflags;               /* Macintosh Finder flags */
+
+  struct {
+    signed short v;            /* Finder icon vertical coordinate */
+    signed short h;            /* horizontal coordinate */
+  } fdlocation;
+
+  union {
+    struct {
+      unsigned long dsize;     /* size of data fork */
+      unsigned long rsize;     /* size of resource fork */
+
+      char type[5];            /* file type code (plus null) */
+      char creator[5];         /* file creator code (plus null) */
+    } file;
+
+    struct {
+      unsigned short valence;  /* number of items in directory */
+
+      struct {
+       signed short top;       /* top edge of folder's rectangle */
+       signed short left;      /* left edge */
+       signed short bottom;    /* bottom edge */
+       signed short right;     /* right edge */
+      } rect;
+
+      /* mkhybrid extra */
+      signed short view;       /* Folder's view */
+
+      struct {
+       signed short v;         /* Scoll vertical position */
+       signed short h;         /* Scoll horizontal position */
+      } frscroll;
+    } dir;
+  } u;
+} hfsdirent;
+
+
+# define HFS_ISDIR             0x01
+# define HFS_ISLOCKED          0x02
+
+# define HFS_CNID_ROOTPAR      1
+# define HFS_CNID_ROOTDIR      2
+# define HFS_CNID_EXT          3
+# define HFS_CNID_CAT          4
+# define HFS_CNID_BADALLOC     5
+
+# define HFS_FNDR_ISONDESK             (1 <<  0)
+# define HFS_FNDR_COLOR                        0x0e
+# define HFS_FNDR_COLORRESERVED                (1 <<  4)
+# define HFS_FNDR_REQUIRESSWITCHLAUNCH (1 <<  5)
+# define HFS_FNDR_ISSHARED             (1 <<  6)
+# define HFS_FNDR_HASNOINITS           (1 <<  7)
+# define HFS_FNDR_HASBEENINITED                (1 <<  8)
+# define HFS_FNDR_RESERVED             (1 <<  9)
+# define HFS_FNDR_HASCUSTOMICON                (1 << 10)
+# define HFS_FNDR_ISSTATIONERY         (1 << 11)
+# define HFS_FNDR_NAMELOCKED           (1 << 12)
+# define HFS_FNDR_HASBUNDLE            (1 << 13)
+# define HFS_FNDR_ISINVISIBLE          (1 << 14)
+# define HFS_FNDR_ISALIAS              (1 << 15)
+
+extern char *hfs_error;
+/*extern unsigned char hfs_charorder[];*/
+
+#ifdef APPLE_HYB
+hfsvol *hfs_mount(hce_mem *, int, int);
+#else
+hfsvol *hfs_mount(char *, int, int);
+#endif /* APPLE_HYB */
+
+int hfs_flush(hfsvol *);
+void hfs_flushall(void);
+#ifdef APPLE_HYB
+int hfs_umount(hfsvol *, long, long);
+#else
+int hfs_umount(hfsvol *);
+#endif /* APPLE_HYB */
+void hfs_umountall(void);
+hfsvol *hfs_getvol(char *);
+void hfs_setvol(hfsvol *);
+
+int hfs_vstat(hfsvol *, hfsvolent *);
+#ifdef APPLE_HYB
+int hfs_format(hce_mem *, int, char *);
+#else
+int hfs_format(char *, int, char *);
+#endif /* APPLE_HYB */
+
+int hfs_chdir(hfsvol *, char *);
+long hfs_getcwd(hfsvol *);
+int hfs_setcwd(hfsvol *, long);
+int hfs_dirinfo(hfsvol *, long *, char *);
+
+hfsdir *hfs_opendir(hfsvol *, char *);
+int hfs_readdir(hfsdir *, hfsdirent *);
+int hfs_closedir(hfsdir *);
+
+hfsfile *hfs_open(hfsvol *, char *);
+int hfs_setfork(hfsfile *, int);
+int hfs_getfork(hfsfile *);
+long hfs_read(hfsfile *, void *, unsigned long);
+long hfs_write(hfsfile *, void *, unsigned long);
+int hfs_truncate(hfsfile *, unsigned long);
+long hfs_lseek(hfsfile *, long, int);
+#ifdef APPLE_HYB
+int hfs_close(hfsfile *, long, long);
+#else
+int hfs_close(hfsfile *);
+#endif /* APPLE_HYB */
+
+int hfs_stat(hfsvol *, char *, hfsdirent *);
+int hfs_fstat(hfsfile *, hfsdirent *);
+int hfs_setattr(hfsvol *, char *, hfsdirent *);
+int hfs_fsetattr(hfsfile *, hfsdirent *);
+
+int hfs_mkdir(hfsvol *, char *);
+int hfs_rmdir(hfsvol *, char *);
+
+int hfs_create(hfsvol *, char *, char *, char *);
+int hfs_delete(hfsvol *, char *);
+
+int hfs_rename(hfsvol *, char *, char *);
+
+int f_trunc(hfsfile *file);
+
+#ifdef APPLE_HYB
+unsigned short hfs_get_drAllocPtr(hfsfile *);
+int hfs_set_drAllocPtr(hfsfile *, unsigned short, int size);
+void hfs_vsetbless(hfsvol *, unsigned long);
+#endif /* APPLE_HYB */
+
+#endif
diff --git a/libhfs_iso/hybrid.h b/libhfs_iso/hybrid.h
new file mode 100644 (file)
index 0000000..01b83a6
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)hybrid.h        1.3 02/10/04 joerg */
+/*
+**     hybrid.h: extra info needed by libhfs and mkisofs
+**
+**     James Pearson 15/9/97
+*/
+
+#ifndef _HYBRID_H
+
+/*
+ *     The following three variables can be overridden at run time
+ *     by using the -hfs-parms option i.e. to use the following defaults
+ *     you could use: -hfs-parms CTC=2,CTC_LOOP=4,MAX_XTCSIZE=4194304
+ *     i.e. to change just MAX_XTCSIZE to 2Mb use:
+ *     -hfs-parms MAX_XTCSIZE=2097152
+ */
+
+#define        CTC     2               /* factor to increase initial Catalog file
+                                  size to prevent the file growing */
+#define CTC_LOOP 4             /* number of attemps before we give up
+                                  trying to create the volume */
+
+#define MAX_XTCSIZE 4*1024*1024 /* the maximum size of the Catalog file -
+                                  as the size of the Catalog file is linked
+                                  to the size of the volume, multi-gigabyte
+                                  volumes create very large Catalog and
+                                  Extent files - 4Mb is the size calculated
+                                  for a 1Gb volume - which is probably
+                                  overkill, but seems to be OK */
+
+#define HCE_ERROR -9999                /* dummy errno value for Catalog file
+                                  size problems */
+
+#define HFS_MAP_SIZE   16      /* size of HFS partition maps (8Kb) */
+
+typedef struct {
+  int hfs_ce_size;             /* extents/catalog size in HFS blks */
+  int hfs_hdr_size;            /* vol header size in HFS blks */
+  int hfs_dt_size;             /* Desktop file size in HFS blks */
+  int hfs_tot_size;            /* extents/catalog/dt size in HFS blks */
+  int hfs_map_size;            /* size of partition maps in HFS blks */
+  unsigned long hfs_vol_size;  /* size of volume in HFS blks */
+  unsigned char *hfs_ce;       /* mem copy of extents/catalog files */
+  unsigned char *hfs_hdr;      /* mem copy of vol header */
+  unsigned char *hfs_alt_mdb;  /* location of alternate MDB */
+  unsigned char *hfs_map;      /* location of partiton_maps */
+  int Csize;                   /* size of allocation unit (bytes) */
+  int XTCsize;                 /* def size of catalog/extents files (bytes) */
+  int max_XTCsize;             /* max size of catalog/extents files (bytes) */
+  int ctc_size;                        /* factor to increase Catalog file size */
+  char *error;                 /* HFS error message */
+} hce_mem;
+
+#define _HYBRID_H
+#endif /* _HYBRID_H */
diff --git a/libhfs_iso/internal.h b/libhfs_iso/internal.h
new file mode 100644 (file)
index 0000000..ee79b0c
--- /dev/null
@@ -0,0 +1,369 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)internal.h      1.2 01/11/01 joerg */
+/*
+ * hfsutils - tools for reading and writing Macintosh HFS volumes
+ * Copyright (C) 1996, 1997 Robert Leslie
+ *
+ * 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 of the License, 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 <timedefs.h>
+#include <standard.h>
+
+# include "hfs.h"
+
+# define ERROR(code, str)      (hfs_error = (str), errno = (code))
+
+# define SIZE(type, n)         ((size_t) (sizeof(type) * (n)))
+# define ALLOC(type, n)                ((type *) malloc(SIZE(type, n)))
+# define ALLOCX(type, n)       ((n) ? ALLOC(type, n) : (type *) 0)
+# define FREE(ptr)             {if (ptr) free((void *) ptr) ;}
+
+# define REALLOC(ptr, type, n)  \
+    ((type *) ((ptr) ? realloc(ptr, SIZE(type, n)) : malloc(SIZE(type, n))))
+# define REALLOCX(ptr, type, n)  \
+    ((n) ? REALLOC(type, n) : (FREE(ptr), (type *) 0))
+
+# define BMTST(bm, num)  \
+  (((char *) (bm))[(num) >> 3] & (0x80 >> ((num) & 0x07)))
+# define BMSET(bm, num)  \
+  (((char *) (bm))[(num) >> 3] |= (0x80 >> ((num) & 0x07)))
+# define BMCLR(bm, num)  \
+  (((char *) (bm))[(num) >> 3] &= ~(0x80 >> ((num) & 0x07)))
+
+typedef unsigned char block[HFS_BLOCKSZ];
+
+typedef signed char    Char;
+typedef unsigned char  UChar;
+typedef signed char    SignedByte;
+typedef signed short   Integer;
+typedef unsigned short UInteger;
+typedef signed long    LongInt;
+typedef unsigned long  ULongInt;
+typedef char           Str15[16];
+typedef char           Str31[32];
+typedef long           OSType;
+
+typedef struct {
+  UInteger     xdrStABN;       /* first allocation block */
+  UInteger     xdrNumABlks;    /* number of allocation blocks */
+} ExtDescriptor;
+
+typedef ExtDescriptor ExtDataRec[3];
+
+typedef struct {
+  SignedByte   xkrKeyLen;      /* key length */
+  SignedByte   xkrFkType;      /* fork type (0x00/0xff == data/resource */
+  ULongInt     xkrFNum;        /* file number */
+  UInteger     xkrFABN;        /* starting file allocation block */
+} ExtKeyRec;
+
+typedef struct {
+  SignedByte   ckrKeyLen;      /* key length */
+  SignedByte   ckrResrv1;      /* reserved */
+  ULongInt     ckrParID;       /* parent directory ID */
+  Str31                ckrCName;       /* catalog node name */
+} CatKeyRec;
+
+# define HFS_MAP1SZ  256
+# define HFS_MAPXSZ  492
+
+# define HFS_NODEREC(nd, rnum) ((nd).data + (nd).roff[rnum])
+
+# define HFS_RECKEYLEN(ptr)    (*(unsigned char *) (ptr))
+# define HFS_RECKEYSKIP(ptr)   ((1 + HFS_RECKEYLEN(ptr) + 1) & ~1)
+# define HFS_RECDATA(ptr)      ((ptr) + HFS_RECKEYSKIP(ptr))
+
+# define HFS_CATDATALEN                sizeof(CatDataRec)
+# define HFS_EXTDATALEN                sizeof(ExtDataRec)
+
+# define HFS_CATKEYLEN         sizeof(CatKeyRec)
+# define HFS_EXTKEYLEN         sizeof(ExtKeyRec)
+
+# define HFS_CATRECMAXLEN      (HFS_CATKEYLEN + HFS_CATDATALEN)
+# define HFS_EXTRECMAXLEN      (HFS_EXTKEYLEN + HFS_EXTDATALEN)
+
+# define HFS_MAXRECLEN         HFS_CATRECMAXLEN
+
+typedef struct {
+  Integer      v;              /* vertical coordinate */
+  Integer      h;              /* horizontal coordinate */
+} Point;
+
+typedef struct {
+  Integer      top;            /* top edge of rectangle */
+  Integer      left;           /* left edge */
+  Integer      bottom;         /* bottom edge */
+  Integer      right;          /* rightmost edge */
+} Rect;
+
+typedef struct {
+  Rect         frRect;         /* folder's rectangle */
+  Integer      frFlags;        /* flags */
+  Point                frLocation;     /* folder's location */
+  Integer      frView;         /* folder's view */
+} DInfo;
+
+typedef struct {
+  Point                frScroll;       /* scroll position */
+  LongInt      frOpenChain;    /* directory ID chain of open folders */
+  Integer      frUnused;       /* reserved */
+  Integer      frComment;      /* comment ID */
+  LongInt      frPutAway;      /* directory ID */
+} DXInfo;
+
+typedef struct {
+  OSType       fdType;         /* file type */
+  OSType       fdCreator;      /* file's creator */
+  Integer      fdFlags;        /* flags */
+  Point                fdLocation;     /* file's location */
+  Integer      fdFldr;         /* file's window */
+} FInfo;
+
+typedef struct {
+  Integer      fdIconID;       /* icon ID */
+  Integer      fdUnused[4];    /* reserved */
+  Integer      fdComment;      /* comment ID */
+  LongInt      fdPutAway;      /* home directory ID */
+} FXInfo;
+
+typedef struct {
+  Integer      drSigWord;      /* volume signature (0x4244 for HFS) */
+  LongInt      drCrDate;       /* date and time of volume creation */
+  LongInt      drLsMod;        /* date and time of last modification */
+  Integer      drAtrb;         /* volume attributes */
+  UInteger     drNmFls;        /* number of files in root directory */
+  UInteger     drVBMSt;        /* first block of volume bit map (always 3) */
+  UInteger     drAllocPtr;     /* start of next allocation search */
+  UInteger     drNmAlBlks;     /* number of allocation blocks in volume */
+  ULongInt     drAlBlkSiz;     /* size (in bytes) of allocation blocks */
+  ULongInt     drClpSiz;       /* default clump size */
+  UInteger     drAlBlSt;       /* first allocation block in volume */
+  LongInt      drNxtCNID;      /* next unused catalog node ID (dir/file ID) */
+  UInteger     drFreeBks;      /* number of unused allocation blocks */
+  char         drVN[28];       /* volume name (1-27 chars) */
+  LongInt      drVolBkUp;      /* date and time of last backup */
+  Integer      drVSeqNum;      /* volume backup sequence number */
+  ULongInt     drWrCnt;        /* volume write count */
+  ULongInt     drXTClpSiz;     /* clump size for extents overflow file */
+  ULongInt     drCTClpSiz;     /* clump size for catalog file */
+  UInteger     drNmRtDirs;     /* number of directories in root directory */
+  ULongInt     drFilCnt;       /* number of files in volume */
+  ULongInt     drDirCnt;       /* number of directories in volume */
+  LongInt      drFndrInfo[8];  /* information used by the Finder */
+  UInteger     drVCSize;       /* size (in blocks) of volume cache */
+  UInteger     drVBMCSize;     /* size (in blocks) of volume bitmap cache */
+  UInteger     drCtlCSize;     /* size (in blocks) of common volume cache */
+  ULongInt     drXTFlSize;     /* size (in bytes) of extents overflow file */
+  ExtDataRec   drXTExtRec;     /* first extent record for extents file */
+  ULongInt     drCTFlSize;     /* size (in bytes) of catalog file */
+  ExtDataRec   drCTExtRec;     /* first extent record for catalog file */
+} MDB;
+
+# define HFS_ATRB_BUSY         (1 <<  6)
+# define HFS_ATRB_HLOCKED      (1 <<  7)
+# define HFS_ATRB_UMOUNTED     (1 <<  8)
+# define HFS_ATRB_BBSPARED     (1 <<  9)
+# define HFS_ATRB_COPYPROT     (1 << 14)
+# define HFS_ATRB_SLOCKED      (1 << 15)
+
+typedef enum {
+  cdrDirRec  = 1,
+  cdrFilRec  = 2,
+  cdrThdRec  = 3,
+  cdrFThdRec = 4
+} CatDataType;
+
+typedef struct {
+  SignedByte   cdrType;        /* record type */
+  SignedByte   cdrResrv2;      /* reserved */
+  union {
+    struct {  /* cdrDirRec */
+      Integer  dirFlags;       /* directory flags */
+      UInteger dirVal;         /* directory valence */
+      ULongInt dirDirID;       /* directory ID */
+      LongInt  dirCrDat;       /* date and time of creation */
+      LongInt  dirMdDat;       /* date and time of last modification */
+      LongInt  dirBkDat;       /* date and time of last backup */
+      DInfo    dirUsrInfo;     /* Finder information */
+      DXInfo   dirFndrInfo;    /* additional Finder information */
+      LongInt  dirResrv[4];    /* reserved */
+    } dir;
+    struct {  /* cdrFilRec */
+      SignedByte
+               filFlags;       /* file flags */
+      SignedByte
+               filTyp;         /* file type */
+      FInfo    filUsrWds;      /* Finder information */
+      ULongInt filFlNum;       /* file ID */
+      UInteger filStBlk;       /* first alloc block of data fork */
+      ULongInt filLgLen;       /* logical EOF of data fork */
+      ULongInt filPyLen;       /* physical EOF of data fork */
+      UInteger filRStBlk;      /* first alloc block of resource fork */
+      ULongInt filRLgLen;      /* logical EOF of resource fork */
+      ULongInt filRPyLen;      /* physical EOF of resource fork */
+      LongInt  filCrDat;       /* date and time of creation */
+      LongInt  filMdDat;       /* date and time of last modification */
+      LongInt  filBkDat;       /* date and time of last backup */
+      FXInfo   filFndrInfo;    /* additional Finder information */
+      UInteger filClpSize;     /* file clump size */
+      ExtDataRec
+               filExtRec;      /* first data fork extent record */
+      ExtDataRec
+               filRExtRec;     /* first resource fork extent record */
+      LongInt  filResrv;       /* reserved */
+    } fil;
+    struct {  /* cdrThdRec */
+      LongInt  thdResrv[2];    /* reserved */
+      ULongInt thdParID;       /* parent ID for this directory */
+      Str31    thdCName;       /* name of this directory */
+    } dthd;
+    struct {  /* cdrFThdRec */
+      LongInt  fthdResrv[2];   /* reserved */
+      ULongInt fthdParID;      /* parent ID for this file */
+      Str31    fthdCName;      /* name of this file */
+    } fthd;
+  } u;
+} CatDataRec;
+
+struct _hfsfile_ {
+  struct _hfsvol_ *vol;                /* pointer to volume descriptor */
+  long parid;                  /* parent directory ID of this file */
+  char name[HFS_MAX_FLEN + 1]; /* catalog name of this file */
+  CatDataRec cat;              /* catalog information */
+  ExtDataRec ext;              /* current extent record */
+  unsigned int fabn;           /* starting file allocation block number */
+  int fork;                    /* current selected fork for I/O */
+  unsigned long pos;           /* current file seek pointer */
+  unsigned long clump;         /* file's clump size, for allocation */
+  int flags;                   /* bit flags */
+
+  struct _hfsfile_ *prev;
+  struct _hfsfile_ *next;
+};
+
+# define HFS_UPDATE_CATREC     0x01
+
+typedef struct {
+  ULongInt     ndFLink;        /* forward link */
+  ULongInt     ndBLink;        /* backward link */
+  SignedByte   ndType;         /* node type */
+  SignedByte   ndNHeight;      /* node level */
+  UInteger     ndNRecs;        /* number of records in node */
+  Integer      ndResv2;        /* reserved */
+} NodeDescriptor;
+
+# define HFS_MAXRECS   35      /* maximum based on minimum record size */
+
+typedef struct _node_ {
+  struct _btree_ *bt;          /* btree to which this node belongs */
+  unsigned long nnum;          /* node index */
+  NodeDescriptor nd;           /* node descriptor */
+  int rnum;                    /* current record index */
+  UInteger roff[HFS_MAXRECS + 1];      /* record offsets */
+  block data;                  /* raw contents of node */
+} node;
+
+enum {
+  ndIndxNode = 0x00,
+  ndHdrNode  = 0x01,
+  ndMapNode  = 0x02,
+  ndLeafNode = 0xff
+};
+
+struct _hfsdir_ {
+  struct _hfsvol_ *vol;                /* associated volume */
+  long dirid;                  /* directory ID of interest (or 0) */
+
+  node n;                      /* current B*-tree node */
+  struct _hfsvol_ *vptr;       /* current volume pointer */
+
+  struct _hfsdir_ *prev;
+  struct _hfsdir_ *next;
+};
+
+typedef struct {
+  UInteger     bthDepth;       /* current depth of tree */
+  ULongInt     bthRoot;        /* number of root node */
+  ULongInt     bthNRecs;       /* number of leaf records in tree */
+  ULongInt     bthFNode;       /* number of first leaf node */
+  ULongInt     bthLNode;       /* number of last leaf node */
+  UInteger     bthNodeSize;    /* size of a node */
+  UInteger     bthKeyLen;      /* maximum length of a key */
+  ULongInt     bthNNodes;      /* total number of nodes in tree */
+  ULongInt     bthFree;        /* number of free nodes */
+  SignedByte   bthResv[76];    /* reserved */
+} BTHdrRec;
+
+typedef struct _btree_ {
+  hfsfile f;                   /* subset file information */
+  node hdrnd;                  /* header node */
+  BTHdrRec hdr;                        /* header record */
+  char *map;                   /* usage bitmap */
+  unsigned long mapsz;         /* number of bytes in bitmap */
+  int flags;                   /* bit flags */
+
+  int (*compare)(unsigned char *, unsigned char *);
+                               /* key comparison function */
+} btree;
+
+# define HFS_UPDATE_BTHDR      0x01
+
+struct _hfsvol_ {
+  int fd;              /* volume's open file descriptor */
+  int flags;           /* bit flags */
+
+#ifdef APPLE_HYB
+  hce_mem *hce;                /* Extras needed by libhfs/mkisofs */
+#endif /* APPLE_HYB */
+
+  int pnum;            /* ordinal HFS partition number */
+  unsigned long vstart;        /* logical block offset to start of volume */
+  unsigned long vlen;  /* number of logical blocks in volume */
+  unsigned int lpa;    /* number of logical blocks per allocation block */
+
+  MDB mdb;             /* master directory block */
+  block *vbm;          /* volume bit map */
+  btree ext;           /* B*-tree control block for extents overflow file */
+  btree cat;           /* B*-tree control block for catalog file */
+  long cwd;            /* directory id of current working directory */
+
+  int refs;            /* number of external references to this volume */
+  hfsfile *files;      /* list of open files */
+  hfsdir *dirs;                /* list of open directories */
+
+  struct _hfsvol_ *prev;
+  struct _hfsvol_ *next;
+};
+
+# define HFS_READONLY          0x01
+
+# define HFS_UPDATE_MDB                0x10
+# define HFS_UPDATE_ALTMDB     0x20
+# define HFS_UPDATE_VBM                0x40
+
+extern hfsvol *hfs_mounts;
+extern hfsvol *hfs_curvol;
diff --git a/libhfs_iso/low.c b/libhfs_iso/low.c
new file mode 100644 (file)
index 0000000..94cba83
--- /dev/null
@@ -0,0 +1,529 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)low.c   1.4 04/06/17 joerg */
+/*
+ * hfsutils - tools for reading and writing Macintosh HFS volumes
+ * Copyright (C) 1996, 1997 Robert Leslie
+ *
+ * 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 of the License, 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 <mconfig.h>
+#include <strdefs.h>
+#include <stdxlib.h>
+#include <errno.h>
+#include <unixstd.h>
+#include <fctldefs.h>
+
+#include "internal.h"
+#include "data.h"
+#include "block.h"
+#include "low.h"
+#include "file.h"
+
+/*
+ * NAME:       low->lockvol()
+ * DESCRIPTION:        prevent destructive simultaneous access
+ */
+int l_lockvol(hfsvol *vol)
+{
+# ifndef NODEVLOCKS
+
+  struct flock lock;
+
+  lock.l_type   = (vol->flags & HFS_READONLY) ? F_RDLCK : F_WRLCK;
+  lock.l_start  = 0;
+  lock.l_whence = SEEK_SET;
+  lock.l_len    = 0;
+
+  if (fcntl(vol->fd, F_SETLK, &lock) < 0)
+    {
+      ERROR(errno, "unable to obtain lock for device");
+      return -1;
+    }
+
+# endif
+
+  return 0;
+}
+
+/*
+ * NAME:       low->readblock0()
+ * DESCRIPTION:        read the first sector and get bearings
+ */
+int l_readblock0(hfsvol *vol)
+{
+  block b;
+  unsigned char *ptr = b;
+  Block0 rec;
+
+  if (b_readlb(vol, 0, &b) < 0)
+    return -1;
+
+  d_fetchw(&ptr, &rec.sbSig);
+  d_fetchw(&ptr, &rec.sbBlkSize);
+  d_fetchl(&ptr, &rec.sbBlkCount);
+  d_fetchw(&ptr, &rec.sbDevType);
+  d_fetchw(&ptr, &rec.sbDevId);
+  d_fetchl(&ptr, &rec.sbData);
+  d_fetchw(&ptr, &rec.sbDrvrCount);
+  d_fetchl(&ptr, &rec.ddBlock);
+  d_fetchw(&ptr, &rec.ddSize);
+  d_fetchw(&ptr, &rec.ddType);
+
+  switch (rec.sbSig)
+    {
+    case 0x4552:  /* block device with a partition table */
+      {
+       if (rec.sbBlkSize != HFS_BLOCKSZ)
+         {
+           ERROR(EINVAL, "unsupported block size");
+           return -1;
+         }
+
+       vol->vlen = rec.sbBlkCount;
+
+       if (l_readpm(vol) < 0)
+         return -1;
+      }
+      break;
+
+    case 0x4c4b:  /* bootable floppy */
+      vol->pnum = 0;
+      break;
+
+    default:  /* non-bootable floppy or something else */
+
+      /* some miscreant media may also be partitioned;
+        we attempt to read a partition map, but ignore any failure */
+
+      if (l_readpm(vol) < 0)
+       vol->pnum = 0;
+    }
+
+  return 0;
+}
+
+/*
+ * NAME:       low->readpm()
+ * DESCRIPTION:        read the partition map and locate an HFS volume
+ */
+int l_readpm(hfsvol *vol)
+{
+  block b;
+  unsigned char *ptr;
+  Partition map;
+  unsigned long bnum;
+  int pnum;
+
+  bnum = 1;
+  pnum = vol->pnum;
+
+  for (;;)
+    {
+      if (b_readlb(vol, bnum, &b) < 0)
+       return -1;
+
+      ptr = b;
+
+      d_fetchw(&ptr, &map.pmSig);
+      d_fetchw(&ptr, &map.pmSigPad);
+      d_fetchl(&ptr, &map.pmMapBlkCnt);
+      d_fetchl(&ptr, &map.pmPyPartStart);
+      d_fetchl(&ptr, &map.pmPartBlkCnt);
+
+      memcpy(map.pmPartName, ptr, 32);
+      map.pmPartName[32] = 0;
+      ptr += 32;
+
+      memcpy(map.pmParType, ptr, 32);
+      map.pmParType[32] = 0;
+      ptr += 32;
+
+      d_fetchl(&ptr, &map.pmLgDataStart);
+      d_fetchl(&ptr, &map.pmDataCnt);
+      d_fetchl(&ptr, &map.pmPartStatus);
+      d_fetchl(&ptr, &map.pmLgBootStart);
+      d_fetchl(&ptr, &map.pmBootSize);
+      d_fetchl(&ptr, &map.pmBootAddr);
+      d_fetchl(&ptr, &map.pmBootAddr2);
+      d_fetchl(&ptr, &map.pmBootEntry);
+      d_fetchl(&ptr, &map.pmBootEntry2);
+      d_fetchl(&ptr, &map.pmBootCksum);
+
+      memcpy(map.pmProcessor, ptr, 16);
+      map.pmProcessor[16] = 0;
+      ptr += 16;
+
+      if (map.pmSig == 0x5453)
+       {
+         /* old partition map sig */
+
+         ERROR(EINVAL, "unsupported partition map signature");
+         return -1;
+       }
+
+      if (map.pmSig != 0x504d)
+       {
+         ERROR(EINVAL, "bad partition map");
+         return -1;
+       }
+
+      if (strcmp((char *) map.pmParType, "Apple_HFS") == 0 && --pnum == 0)
+       {
+         if (map.pmLgDataStart != 0)
+           {
+             ERROR(EINVAL, "unsupported start of partition logical data");
+             return -1;
+           }
+
+         vol->vstart = map.pmPyPartStart;
+         vol->vlen   = map.pmPartBlkCnt;
+
+         return 0;
+       }
+
+      if (bnum >= map.pmMapBlkCnt)
+       {
+         ERROR(EINVAL, "can't find HFS partition");
+         return -1;
+       }
+
+      ++bnum;
+    }
+}
+
+/*
+ * NAME:       low->readmdb()
+ * DESCRIPTION:        read the master directory block into memory
+ */
+int l_readmdb(hfsvol *vol)
+{
+  block b;
+  unsigned char *ptr = b;
+  MDB *mdb = &vol->mdb;
+  hfsfile *ext = &vol->ext.f;
+  hfsfile *cat = &vol->cat.f;
+  int i;
+
+  if (b_readlb(vol, 2, &b) < 0)
+    return -1;
+
+  d_fetchw(&ptr, &mdb->drSigWord);
+  d_fetchl(&ptr, &mdb->drCrDate);
+  d_fetchl(&ptr, &mdb->drLsMod);
+  d_fetchw(&ptr, &mdb->drAtrb);
+  d_fetchw(&ptr, (short *) &mdb->drNmFls);
+  d_fetchw(&ptr, (short *) &mdb->drVBMSt);
+  d_fetchw(&ptr, (short *) &mdb->drAllocPtr);
+  d_fetchw(&ptr, (short *) &mdb->drNmAlBlks);
+  d_fetchl(&ptr, (long *) &mdb->drAlBlkSiz);
+  d_fetchl(&ptr, (long *) &mdb->drClpSiz);
+  d_fetchw(&ptr, (short *) &mdb->drAlBlSt);
+  d_fetchl(&ptr, &mdb->drNxtCNID);
+  d_fetchw(&ptr, (short *) &mdb->drFreeBks);
+
+  d_fetchs(&ptr, mdb->drVN, sizeof(mdb->drVN));
+
+  if (ptr - b != 64)
+    abort();
+
+  d_fetchl(&ptr, &mdb->drVolBkUp);
+  d_fetchw(&ptr, &mdb->drVSeqNum);
+  d_fetchl(&ptr, (long *) &mdb->drWrCnt);
+  d_fetchl(&ptr, (long *) &mdb->drXTClpSiz);
+  d_fetchl(&ptr, (long *) &mdb->drCTClpSiz);
+  d_fetchw(&ptr, (short *) &mdb->drNmRtDirs);
+  d_fetchl(&ptr, (long *) &mdb->drFilCnt);
+  d_fetchl(&ptr, (long *) &mdb->drDirCnt);
+
+  for (i = 0; i < 8; ++i)
+    d_fetchl(&ptr, &mdb->drFndrInfo[i]);
+
+  if (ptr - b != 124)
+    abort();
+
+  d_fetchw(&ptr, (short *) &mdb->drVCSize);
+  d_fetchw(&ptr, (short *) &mdb->drVBMCSize);
+  d_fetchw(&ptr, (short *) &mdb->drCtlCSize);
+
+  d_fetchl(&ptr, (long *) &mdb->drXTFlSize);
+
+  for (i = 0; i < 3; ++i)
+    {
+      d_fetchw(&ptr, (short *) &mdb->drXTExtRec[i].xdrStABN);
+      d_fetchw(&ptr, (short *) &mdb->drXTExtRec[i].xdrNumABlks);
+    }
+
+  if (ptr - b != 146)
+    abort();
+
+  d_fetchl(&ptr, (long *) &mdb->drCTFlSize);
+
+  for (i = 0; i < 3; ++i)
+    {
+      d_fetchw(&ptr, (short *) &mdb->drCTExtRec[i].xdrStABN);
+      d_fetchw(&ptr, (short *) &mdb->drCTExtRec[i].xdrNumABlks);
+    }
+
+  if (ptr - b != 162)
+    abort();
+
+  vol->lpa = mdb->drAlBlkSiz / HFS_BLOCKSZ;
+
+  /* extents pseudo-file structs */
+
+  ext->vol   = vol;
+  ext->parid = 0;
+  strcpy(ext->name, "extents overflow");
+
+  ext->cat.cdrType          = cdrFilRec;
+  /* ext->cat.cdrResrv2 */
+  ext->cat.u.fil.filFlags   = 0;
+  ext->cat.u.fil.filTyp     = 0;
+  /* ext->cat.u.fil.filUsrWds */
+  ext->cat.u.fil.filFlNum   = HFS_CNID_EXT;
+  ext->cat.u.fil.filStBlk   = mdb->drXTExtRec[0].xdrStABN;
+  ext->cat.u.fil.filLgLen   = mdb->drXTFlSize;
+  ext->cat.u.fil.filPyLen   = mdb->drXTFlSize;
+  ext->cat.u.fil.filRStBlk  = 0;
+  ext->cat.u.fil.filRLgLen  = 0;
+  ext->cat.u.fil.filRPyLen  = 0;
+  ext->cat.u.fil.filCrDat   = mdb->drCrDate;
+  ext->cat.u.fil.filMdDat   = mdb->drLsMod;
+  ext->cat.u.fil.filBkDat   = 0;
+  /* ext->cat.u.fil.filFndrInfo */
+  ext->cat.u.fil.filClpSize = 0;
+
+  memcpy(ext->cat.u.fil.filExtRec, mdb->drXTExtRec, sizeof(ExtDataRec));
+  for (i = 0; i < 3; ++i)
+    {
+      ext->cat.u.fil.filRExtRec[i].xdrStABN    = 0;
+      ext->cat.u.fil.filRExtRec[i].xdrNumABlks = 0;
+    }
+  f_selectfork(ext, 0);
+
+  ext->clump = mdb->drXTClpSiz;
+  ext->flags = 0;
+
+  ext->prev = ext->next = 0;
+
+  /* catalog pseudo-file structs */
+
+  cat->vol   = vol;
+  cat->parid = 0;
+  strcpy(cat->name, "catalog");
+
+  cat->cat.cdrType          = cdrFilRec;
+  /* cat->cat.cdrResrv2 */
+  cat->cat.u.fil.filFlags   = 0;
+  cat->cat.u.fil.filTyp     = 0;
+  /* cat->cat.u.fil.filUsrWds */
+  cat->cat.u.fil.filFlNum   = HFS_CNID_CAT;
+  cat->cat.u.fil.filStBlk   = mdb->drCTExtRec[0].xdrStABN;
+  cat->cat.u.fil.filLgLen   = mdb->drCTFlSize;
+  cat->cat.u.fil.filPyLen   = mdb->drCTFlSize;
+  cat->cat.u.fil.filRStBlk  = 0;
+  cat->cat.u.fil.filRLgLen  = 0;
+  cat->cat.u.fil.filRPyLen  = 0;
+  cat->cat.u.fil.filCrDat   = mdb->drCrDate;
+  cat->cat.u.fil.filMdDat   = mdb->drLsMod;
+  cat->cat.u.fil.filBkDat   = 0;
+  /* cat->cat.u.fil.filFndrInfo */
+  cat->cat.u.fil.filClpSize = 0;
+
+  memcpy(cat->cat.u.fil.filExtRec, mdb->drCTExtRec, sizeof(ExtDataRec));
+  for (i = 0; i < 3; ++i)
+    {
+      cat->cat.u.fil.filRExtRec[i].xdrStABN    = 0;
+      cat->cat.u.fil.filRExtRec[i].xdrNumABlks = 0;
+    }
+  f_selectfork(cat, 0);
+
+  cat->clump = mdb->drCTClpSiz;
+  cat->flags = 0;
+
+  cat->prev = cat->next = 0;
+
+  return 0;
+}
+
+/*
+ * NAME:       low->writemdb()
+ * DESCRIPTION:        write the master directory block to disk
+ */
+int l_writemdb(hfsvol *vol)
+{
+  block b;
+  unsigned char *ptr = b;
+  MDB *mdb = &vol->mdb;
+  hfsfile *ext = &vol->ext.f;
+  hfsfile *cat = &vol->cat.f;
+  int i;
+
+  memset(&b, 0, sizeof(b));
+
+  mdb->drXTFlSize = ext->cat.u.fil.filPyLen;
+  mdb->drXTClpSiz = ext->clump;
+  memcpy(mdb->drXTExtRec, ext->cat.u.fil.filExtRec, sizeof(ExtDataRec));
+
+  mdb->drCTFlSize = cat->cat.u.fil.filPyLen;
+  mdb->drCTClpSiz = cat->clump;
+  memcpy(mdb->drCTExtRec, cat->cat.u.fil.filExtRec, sizeof(ExtDataRec));
+
+  d_storew(&ptr, mdb->drSigWord);
+  d_storel(&ptr, mdb->drCrDate);
+  d_storel(&ptr, mdb->drLsMod);
+  d_storew(&ptr, mdb->drAtrb);
+  d_storew(&ptr, mdb->drNmFls);
+  d_storew(&ptr, mdb->drVBMSt);
+  d_storew(&ptr, mdb->drAllocPtr);
+  d_storew(&ptr, mdb->drNmAlBlks);
+  d_storel(&ptr, mdb->drAlBlkSiz);
+  d_storel(&ptr, mdb->drClpSiz);
+  d_storew(&ptr, mdb->drAlBlSt);
+  d_storel(&ptr, mdb->drNxtCNID);
+  d_storew(&ptr, mdb->drFreeBks);
+  d_stores(&ptr, mdb->drVN, sizeof(mdb->drVN));
+
+  if (ptr - b != 64)
+    abort();
+
+  d_storel(&ptr, mdb->drVolBkUp);
+  d_storew(&ptr, mdb->drVSeqNum);
+  d_storel(&ptr, mdb->drWrCnt);
+  d_storel(&ptr, mdb->drXTClpSiz);
+  d_storel(&ptr, mdb->drCTClpSiz);
+  d_storew(&ptr, mdb->drNmRtDirs);
+  d_storel(&ptr, mdb->drFilCnt);
+  d_storel(&ptr, mdb->drDirCnt);
+
+  for (i = 0; i < 8; ++i)
+    d_storel(&ptr, mdb->drFndrInfo[i]);
+
+  if (ptr - b != 124)
+    abort();
+
+  d_storew(&ptr, mdb->drVCSize);
+  d_storew(&ptr, mdb->drVBMCSize);
+  d_storew(&ptr, mdb->drCtlCSize);
+  d_storel(&ptr, mdb->drXTFlSize);
+
+  for (i = 0; i < 3; ++i)
+    {
+      d_storew(&ptr, mdb->drXTExtRec[i].xdrStABN);
+      d_storew(&ptr, mdb->drXTExtRec[i].xdrNumABlks);
+    }
+
+  if (ptr - b != 146)
+    abort();
+
+  d_storel(&ptr, mdb->drCTFlSize);
+
+  for (i = 0; i < 3; ++i)
+    {
+      d_storew(&ptr, mdb->drCTExtRec[i].xdrStABN);
+      d_storew(&ptr, mdb->drCTExtRec[i].xdrNumABlks);
+    }
+
+  if (ptr - b != 162)
+    abort();
+
+  if (b_writelb(vol, 2, &b) < 0)
+    return -1;
+  if (vol->flags & HFS_UPDATE_ALTMDB)
+    {
+#ifdef APPLE_HYB
+      /* "write" alternative MDB to memory copy */
+      memcpy(vol->hce->hfs_alt_mdb, &b, sizeof(b));
+#else
+      if (b_writelb(vol, vol->vlen - 2, &b) < 0)
+       return -1;
+#endif /* APPLE_HYB */
+    }
+  vol->flags &= ~(HFS_UPDATE_MDB | HFS_UPDATE_ALTMDB);
+
+  return 0;
+}
+
+/*
+ * NAME:       low->readvbm()
+ * DESCRIPTION:        read the volume bit map into memory
+ */
+int l_readvbm(hfsvol *vol)
+{
+  int vbmst = vol->mdb.drVBMSt;
+  int vbmsz = (vol->mdb.drNmAlBlks + 4095) / (unsigned)4096;
+  block *bp;
+
+  if ((int)(vol->mdb.drAlBlSt - vbmst) < vbmsz)
+    {
+      ERROR(EIO, "volume bitmap collides with volume data");
+      return -1;
+    }
+
+  bp = ALLOC(block, vbmsz);
+  if (bp == 0)
+    {
+      ERROR(ENOMEM, 0);
+      return -1;
+    }
+
+  vol->vbm = bp;
+
+  while (vbmsz--)
+    {
+      if (b_readlb(vol, vbmst++, bp++) < 0)
+       {
+         FREE(vol->vbm);
+         vol->vbm = 0;
+
+         return -1;
+       }
+    }
+
+  return 0;
+}
+
+/*
+ * NAME:       low->writevbm()
+ * DESCRIPTION:        write the volume bit map to disk
+ */
+int l_writevbm(hfsvol *vol)
+{
+  int vbmst = vol->mdb.drVBMSt;
+  int vbmsz = (vol->mdb.drNmAlBlks + 4095) / (unsigned)4096;
+  block *bp = vol->vbm;
+
+  while (vbmsz--)
+    {
+      if (b_writelb(vol, vbmst++, bp++) < 0)
+       return -1;
+    }
+
+  vol->flags &= ~HFS_UPDATE_VBM;
+
+  return 0;
+}
diff --git a/libhfs_iso/low.h b/libhfs_iso/low.h
new file mode 100644 (file)
index 0000000..4434444
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)low.h   1.1 00/03/05 joerg */
+/*
+ * hfsutils - tools for reading and writing Macintosh HFS volumes
+ * Copyright (C) 1996, 1997 Robert Leslie
+ *
+ * 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 of the License, 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.
+ */
+
+typedef struct {
+  Integer      sbSig;          /* device signature (should be 0x4552) */
+  Integer      sbBlkSize;      /* block size of the device (in bytes) */
+  LongInt      sbBlkCount;     /* number of blocks on the device */
+  Integer      sbDevType;      /* reserved */
+  Integer      sbDevId;        /* reserved */
+  LongInt      sbData;         /* reserved */
+  Integer      sbDrvrCount;    /* number of driver descriptor entries */
+  LongInt      ddBlock;        /* first driver's starting block */
+  Integer      ddSize;         /* size of the driver, in 512-byte blocks */
+  Integer      ddType;         /* driver operating system type (MacOS = 1) */
+  Integer      ddPad[243];     /* additional drivers, if any */
+} Block0;
+
+typedef struct {
+  Integer      bbID;           /* boot blocks signature */
+  LongInt      bbEntry;        /* entry point to boot code */
+  Integer      bbVersion;      /* boot blocks version number */
+  Integer      bbPageFlags;    /* used internally */
+  Str15                bbSysName;      /* System filename */
+  Str15                bbShellName;    /* Finder filename */
+  Str15                bbDbg1Name;     /* debugger filename */
+  Str15                bbDbg2Name;     /* debugger filename */
+  Str15                bbScreenName;   /* name of startup screen */
+  Str15                bbHelloName;    /* name of startup program */
+  Str15                bbScrapName;    /* name of system scrap file */
+  Integer      bbCntFCBs;      /* number of FCBs to allocate */
+  Integer      bbCntEvts;      /* number of event queue elements */
+  LongInt      bb128KSHeap;    /* system heap size on 128K Mac */
+  LongInt      bb256KSHeap;    /* used internally */
+  LongInt      bbSysHeapSize;  /* system heap size on all machines */
+  Integer      filler;         /* reserved */
+  LongInt      bbSysHeapExtra; /* additional system heap space */
+  LongInt      bbSysHeapFract; /* fraction of RAM for system heap */
+} BootBlkHdr;
+
+typedef struct {
+  Integer      pmSig;          /* partition signature (0x504d or 0x5453) */
+  Integer      pmSigPad;       /* reserved */
+  LongInt      pmMapBlkCnt;    /* number of blocks in partition map */
+  LongInt      pmPyPartStart;  /* first physical block of partition */
+  LongInt      pmPartBlkCnt;   /* number of blocks in partition */
+  Char         pmPartName[33]; /* partition name */
+  Char         pmParType[33];  /* partition type */
+  /*
+   * Apple_partition_map       partition map
+   * Apple_Driver              device driver
+   * Apple_Driver43            SCSI Manager 4.3 device driver
+   * Apple_MFS                 Macintosh 64K ROM filesystem
+   * Apple_HFS                 Macintosh hierarchical filesystem
+   * Apple_Unix_SVR2           Unix filesystem
+   * Apple_PRODOS              ProDOS filesystem
+   * Apple_Free                        unused
+   * Apple_Scratch             empty
+   */
+  LongInt      pmLgDataStart;  /* first logical block of data area */
+  LongInt      pmDataCnt;      /* number of blocks in data area */
+  LongInt      pmPartStatus;   /* partition status information */
+  LongInt      pmLgBootStart;  /* first logical block of boot code */
+  LongInt      pmBootSize;     /* size of boot code, in bytes */
+  LongInt      pmBootAddr;     /* boot code load address */
+  LongInt      pmBootAddr2;    /* reserved */
+  LongInt      pmBootEntry;    /* boot code entry point */
+  LongInt      pmBootEntry2;   /* reserved */
+  LongInt      pmBootCksum;    /* boot code checksum */
+  Char         pmProcessor[17];/* processor type */
+  Integer      pmPad[188];     /* reserved */
+} Partition;
+
+int l_lockvol(hfsvol *);
+
+int l_readblock0(hfsvol *);
+int l_readpm(hfsvol *);
+
+int l_readmdb(hfsvol *);
+int l_writemdb(hfsvol *);
+
+int l_readvbm(hfsvol *);
+int l_writevbm(hfsvol *);
diff --git a/libhfs_iso/node.c b/libhfs_iso/node.c
new file mode 100644 (file)
index 0000000..8fce735
--- /dev/null
@@ -0,0 +1,473 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)node.c  1.2 02/02/10 joerg */
+/*
+ * hfsutils - tools for reading and writing Macintosh HFS volumes
+ * Copyright (C) 1996, 1997 Robert Leslie
+ *
+ * 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 of the License, 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 <mconfig.h>
+#include <stdxlib.h>
+#include <strdefs.h>
+#include <errno.h>
+
+#include "internal.h"
+#include "data.h"
+#include "btree.h"
+#include "node.h"
+
+# define NODESPACE(n)  \
+  (HFS_BLOCKSZ - (n).roff[(n).nd.ndNRecs] - 2 * ((n).nd.ndNRecs + 1))
+
+/*
+ * NAME:       node->init()
+ * DESCRIPTION:        construct an empty node
+ */
+void n_init(node *np, btree *bt, int type, int height)
+{
+  np->bt   = bt;
+  np->nnum = -1;
+
+  np->nd.ndFLink   = 0;
+  np->nd.ndBLink   = 0;
+  np->nd.ndType    = type;
+  np->nd.ndNHeight = height;
+  np->nd.ndNRecs   = 0;
+  np->nd.ndResv2   = 0;
+
+  np->rnum    = -1;
+  np->roff[0] = 0x00e;
+
+  memset(np->data, 0, sizeof(np->data));
+}
+
+/*
+ * NAME:       node->new()
+ * DESCRIPTION:        allocate a new b*-tree node
+ */
+int n_new(node *np)
+{
+  btree *bt = np->bt;
+  unsigned long num;
+
+  if (bt->hdr.bthFree == 0)
+    {
+      ERROR(EIO, "b*-tree full");
+      return -1;
+    }
+
+  num = 0;
+  while (num < bt->hdr.bthNNodes && BMTST(bt->map, num))
+    ++num;
+
+  if (num == bt->hdr.bthNNodes)
+    {
+      ERROR(EIO, "free b*-tree node not found");
+      return -1;
+    }
+
+  np->nnum = num;
+
+  BMSET(bt->map, num);
+  --bt->hdr.bthFree;
+
+  bt->flags |= HFS_UPDATE_BTHDR;
+
+  return 0;
+}
+
+/*
+ * NAME:       node->free()
+ * DESCRIPTION:        deallocate a b*-tree node
+ */
+void n_free(node *np)
+{
+  btree *bt = np->bt;
+
+  BMCLR(bt->map, np->nnum);
+  ++bt->hdr.bthFree;
+
+  bt->flags |= HFS_UPDATE_BTHDR;
+}
+
+/*
+ * NAME:       node->compact()
+ * DESCRIPTION:        clean up a node, removing deleted records
+ */
+void n_compact(node *np)
+{
+  unsigned char *ptr;
+  int offset, nrecs, i;
+
+  offset = 0x00e;
+  ptr    = np->data + offset;
+  nrecs  = 0;
+
+  for (i = 0; i < (int)np->nd.ndNRecs; ++i)
+    {
+      unsigned char *rec;
+      int reclen;
+
+      rec    = HFS_NODEREC(*np, i);
+      reclen = np->roff[i + 1] - np->roff[i];
+
+      if (HFS_RECKEYLEN(rec) > 0)
+       {
+         np->roff[nrecs++] = offset;
+         offset += reclen;
+
+         if (ptr == rec)
+           ptr += reclen;
+         else
+           {
+             while (reclen--)
+               *ptr++ = *rec++;
+           }
+       }
+    }
+
+  np->roff[nrecs] = offset;
+  np->nd.ndNRecs  = nrecs;
+}
+
+/*
+ * NAME:       node->search()
+ * DESCRIPTION:        locate a record in a node, or the record it should follow
+ */
+int n_search(node *np, unsigned char *key)
+{
+  btree *bt = np->bt;
+  int i, comp = -1;
+
+  for (i = np->nd.ndNRecs; i--; )
+    {
+      unsigned char *rec;
+
+      rec = HFS_NODEREC(*np, i);
+
+      if (HFS_RECKEYLEN(rec) == 0)
+       continue;  /* deleted record */
+
+      comp = bt->compare(rec, key);
+
+      if (comp <= 0)
+       break;
+    }
+
+  np->rnum = i;
+
+  return comp == 0;
+}
+
+/*
+ * NAME:       node->index()
+ * DESCRIPTION:        create an index record from a key and node pointer
+ */
+void n_index(btree *bt, unsigned char *key, unsigned long nnum, 
+             unsigned char *record, int *reclen)
+{
+  if (bt == &bt->f.vol->cat)
+    {
+      /* force the key length to be 0x25 */
+
+      HFS_RECKEYLEN(record) = 0x25;
+      memset(record + 1, 0, 0x25);
+      memcpy(record + 1, key + 1, HFS_RECKEYLEN(key));
+    }
+  else
+    memcpy(record, key, HFS_RECKEYSKIP(key));
+
+  d_putl(HFS_RECDATA(record), nnum);
+
+  if (reclen)
+    *reclen = HFS_RECKEYSKIP(record) + 4;
+}
+
+/*
+ * NAME:       node->split()
+ * DESCRIPTION:        divide a node into two and insert a record
+ */
+int n_split(node *left, unsigned char *record, int *reclen)
+{
+  node right;
+  int nrecs, i, mid;
+  unsigned char *rec;
+
+  right = *left;
+  right.nd.ndBLink = left->nnum;
+
+  if (n_new(&right) < 0)
+    return -1;
+
+  left->nd.ndFLink = right.nnum;
+  nrecs = left->nd.ndNRecs;
+
+  /*
+   * Ensure node split leaves enough room for new record.
+   * The size calculations used are based on the NODESPACE() macro, but
+   * I don't know what the extra 2's and 1's are needed for.
+   * John Witford <jwitford@hutch.com.au>
+   */
+  n_search(&right, record);
+  mid = nrecs/2;
+  for(;;)
+    {
+       if (right.rnum < mid)
+       {
+           if (   mid > 0
+               && (int)left->roff[mid] + *reclen + 2 > HFS_BLOCKSZ - 2 * (mid + 1))
+           {
+               --mid;
+               if (mid > 0)
+                   continue;
+           }
+       }
+       else
+       {
+           if (   mid < nrecs
+               && (int)right.roff[nrecs] - (int)right.roff[mid] + (int)left->roff[0] + *reclen + 2 > HFS_BLOCKSZ - 2 * (mid + 1))
+           {
+               ++mid;
+               if (mid < nrecs)
+                   continue;
+           }
+       }
+       break;
+    }
+
+  for (i = 0; i < nrecs; ++i)
+    {
+       if (i < mid)
+           rec = HFS_NODEREC(right, i);
+       else
+           rec = HFS_NODEREC(*left, i);
+
+       HFS_RECKEYLEN(rec) = 0;
+    }
+
+/* original code ...
+  for (i = 0; i < nrecs; ++i)
+    {
+      if (i < nrecs / 2)
+       rec = HFS_NODEREC(right, i);
+      else
+       rec = HFS_NODEREC(*left, i);
+
+      HFS_RECKEYLEN(rec) = 0;
+    }
+*/
+  n_compact(left);
+  n_compact(&right);
+
+  n_search(&right, record);
+  if (right.rnum >= 0)
+    n_insertx(&right, record, *reclen);
+  else
+    {
+      n_search(left, record);
+      n_insertx(left, record, *reclen);
+    }
+
+  /* store the new/modified nodes */
+
+  if (bt_putnode(left) < 0 ||
+      bt_putnode(&right) < 0)
+    return -1;
+
+  /* create an index record for the new node in the parent */
+
+  n_index(right.bt, HFS_NODEREC(right, 0), right.nnum, record, reclen);
+
+  /* update link pointers */
+
+  if (left->bt->hdr.bthLNode == left->nnum)
+    {
+      left->bt->hdr.bthLNode = right.nnum;
+      left->bt->flags |= HFS_UPDATE_BTHDR;
+    }
+
+  if (right.nd.ndFLink)
+    {
+      node n;
+
+      n.bt   = right.bt;
+      n.nnum = right.nd.ndFLink;
+
+      if (bt_getnode(&n) < 0)
+       return -1;
+
+      n.nd.ndBLink = right.nnum;
+
+      if (bt_putnode(&n) < 0)
+       return -1;
+    }
+
+  return 0;
+}
+
+/*
+ * NAME:       node->insertx()
+ * DESCRIPTION:        insert a record into a node (which must already have room)
+ */
+void n_insertx(node *np, unsigned char *record, int reclen)
+{
+  int rnum, i;
+  unsigned char *ptr;
+
+  rnum = np->rnum + 1;
+
+  /* push other records down to make room */
+
+  for (ptr = HFS_NODEREC(*np, np->nd.ndNRecs) + reclen;
+       ptr > HFS_NODEREC(*np, rnum) + reclen; --ptr)
+    *(ptr - 1) = *(ptr - 1 - reclen);
+
+  ++np->nd.ndNRecs;
+
+  for (i = np->nd.ndNRecs; i > rnum; --i)
+    np->roff[i] = np->roff[i - 1] + reclen;
+
+  /* write the new record */
+
+  memcpy(HFS_NODEREC(*np, rnum), record, reclen);
+}
+
+/*
+ * NAME:       node->insert()
+ * DESCRIPTION:        insert a new record into a node; return a record for parent
+ */
+int n_insert(node *np, unsigned char *record, int *reclen)
+{
+  n_compact(np);
+
+  /* check for free space */
+
+  if (np->nd.ndNRecs >= HFS_MAXRECS ||
+      *reclen + 2 > (int)NODESPACE(*np))
+    return n_split(np, record, reclen);
+
+  n_insertx(np, record, *reclen);
+  *reclen = 0;
+
+  return bt_putnode(np);
+}
+
+/*
+ * NAME:       node->merge()
+ * DESCRIPTION:        combine two nodes into a single node
+ */
+int n_merge(node *right, node *left, unsigned char *record, int *flag)
+{
+  int i, offset;
+
+  /* copy records and offsets */
+
+  memcpy(HFS_NODEREC(*left, left->nd.ndNRecs), HFS_NODEREC(*right, 0),
+        right->roff[right->nd.ndNRecs] - right->roff[0]);
+
+  offset = left->roff[left->nd.ndNRecs] - right->roff[0];
+
+  for (i = 1; i <= (int)right->nd.ndNRecs; ++i)
+    left->roff[++left->nd.ndNRecs] = offset + right->roff[i];
+
+  /* update link pointers */
+
+  left->nd.ndFLink = right->nd.ndFLink;
+
+  if (bt_putnode(left) < 0)
+    return -1;
+
+  if (right->bt->hdr.bthLNode == right->nnum)
+    {
+      right->bt->hdr.bthLNode = left->nnum;
+      right->bt->flags |= HFS_UPDATE_BTHDR;
+    }
+
+  if (right->nd.ndFLink)
+    {
+      node n;
+
+      n.bt   = right->bt;
+      n.nnum = right->nd.ndFLink;
+
+      if (bt_getnode(&n) < 0)
+       return -1;
+
+      n.nd.ndBLink = left->nnum;
+
+      if (bt_putnode(&n) < 0)
+       return -1;
+    }
+
+  n_free(right);
+
+  HFS_RECKEYLEN(record) = 0;
+  *flag = 1;
+
+  return 0;
+}
+
+/*
+ * NAME:       node->delete()
+ * DESCRIPTION:        remove a record from a node
+ */
+int n_delete(node *np, unsigned char *record, int *flag)
+{
+  node left;
+  unsigned char *rec;
+
+  rec = HFS_NODEREC(*np, np->rnum);
+
+  HFS_RECKEYLEN(rec) = 0;
+  n_compact(np);
+
+  /* see if we can merge with our left sibling */
+
+  left.bt   = np->bt;
+  left.nnum = np->nd.ndBLink;
+
+  if (left.nnum > 0)
+    {
+      if (bt_getnode(&left) < 0)
+       return -1;
+
+      if ((int)(np->nd.ndNRecs + left.nd.ndNRecs) <= HFS_MAXRECS &&
+         (int)(np->roff[np->nd.ndNRecs] - np->roff[0] +
+         2 * np->nd.ndNRecs) <= (int)NODESPACE(left))
+       return n_merge(np, &left, record, flag);
+    }
+
+  if (np->rnum == 0)
+    {
+      /* special case: first record changed; update parent record key */
+
+      n_index(np->bt, HFS_NODEREC(*np, 0), np->nnum, record, 0);
+      *flag = 1;
+    }
+
+  return bt_putnode(np);
+}
diff --git a/libhfs_iso/node.h b/libhfs_iso/node.h
new file mode 100644 (file)
index 0000000..39d3227
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)node.h  1.1 00/03/05 joerg */
+/*
+ * hfsutils - tools for reading and writing Macintosh HFS volumes
+ * Copyright (C) 1996, 1997 Robert Leslie
+ *
+ * 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 of the License, 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.
+ */
+
+void n_init(node *, btree *, int, int);
+
+int n_new(node *);
+void n_free(node *);
+
+void n_compact(node *);
+int n_search(node *, unsigned char *);
+
+void n_index(btree *, unsigned char *, unsigned long, unsigned char *, int *);
+int n_split(node *, unsigned char *, int *);
+
+void n_insertx(node *, unsigned char *, int);
+int n_insert(node *, unsigned char *, int *);
+
+int n_merge(node *, node *, unsigned char *, int *);
+int n_delete(node *, unsigned char *, int *);
diff --git a/libhfs_iso/record.c b/libhfs_iso/record.c
new file mode 100644 (file)
index 0000000..e202158
--- /dev/null
@@ -0,0 +1,551 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)record.c        1.1 00/04/26 joerg */
+/*
+ * hfsutils - tools for reading and writing Macintosh HFS volumes
+ * Copyright (C) 1996, 1997 Robert Leslie
+ *
+ * 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 of the License, 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 <mconfig.h>
+#include <stdxlib.h>
+#include <strdefs.h>
+#include <errno.h>
+
+#include "internal.h"
+#include "data.h"
+#include "record.h"
+
+/*
+ * NAME:       record->packcatkey()
+ * DESCRIPTION:        pack a catalog record key
+ */
+void r_packcatkey(CatKeyRec *key, unsigned char *pkey, int *len)
+{
+  unsigned char *start = pkey;
+
+  d_storeb(&pkey, key->ckrKeyLen);
+  d_storeb(&pkey, key->ckrResrv1);
+  d_storel(&pkey, key->ckrParID);
+  d_stores(&pkey, key->ckrCName, sizeof(key->ckrCName));
+
+  if (len)
+    *len = HFS_RECKEYSKIP(start);
+}
+
+/*
+ * NAME:       record->unpackcatkey()
+ * DESCRIPTION:        unpack a catalog record key
+ */
+void r_unpackcatkey(unsigned char *pkey, CatKeyRec *key)
+{
+  d_fetchb(&pkey, (char *) &key->ckrKeyLen);
+  d_fetchb(&pkey, (char *) &key->ckrResrv1);
+  d_fetchl(&pkey, (long *) &key->ckrParID);
+  d_fetchs(&pkey, key->ckrCName, sizeof(key->ckrCName));
+}
+
+/*
+ * NAME:       record->packextkey()
+ * DESCRIPTION:        pack an extents record key
+ */
+void r_packextkey(ExtKeyRec *key, unsigned char *pkey, int *len)
+{
+  unsigned char *start = pkey;
+
+  d_storeb(&pkey, key->xkrKeyLen);
+  d_storeb(&pkey, key->xkrFkType);
+  d_storel(&pkey, key->xkrFNum);
+  d_storew(&pkey, key->xkrFABN);
+
+  if (len)
+    *len = HFS_RECKEYSKIP(start);
+}
+
+/*
+ * NAME:       record->unpackextkey()
+ * DESCRIPTION:        unpack an extents record key
+ */
+void r_unpackextkey(unsigned char *pkey, ExtKeyRec *key)
+{
+  d_fetchb(&pkey, (char *) &key->xkrKeyLen);
+  d_fetchb(&pkey, (char *) &key->xkrFkType);
+  d_fetchl(&pkey, (long *) &key->xkrFNum);
+  d_fetchw(&pkey, (short *) &key->xkrFABN);
+}
+
+/*
+ * NAME:       record->comparecatkeys()
+ * DESCRIPTION:        compare two (packed) catalog record keys
+ */
+int r_comparecatkeys(unsigned char *pkey1, unsigned char *pkey2)
+{
+  CatKeyRec key1;
+  CatKeyRec key2;
+  int diff;
+
+  r_unpackcatkey(pkey1, &key1);
+  r_unpackcatkey(pkey2, &key2);
+
+  diff = key1.ckrParID - key2.ckrParID;
+  if (diff)
+    return diff;
+
+  return d_relstring(key1.ckrCName, key2.ckrCName);
+}
+
+/*
+ * NAME:       record->compareextkeys()
+ * DESCRIPTION:        compare two (packed) extents record keys
+ */
+int r_compareextkeys(unsigned char *pkey1, unsigned char *pkey2)
+{
+  ExtKeyRec key1;
+  ExtKeyRec key2;
+  int diff;
+
+  r_unpackextkey(pkey1, &key1);
+  r_unpackextkey(pkey2, &key2);
+
+  diff = key1.xkrFNum - key2.xkrFNum;
+  if (diff)
+    return diff;
+
+  diff = (unsigned char) key1.xkrFkType -
+         (unsigned char) key2.xkrFkType;
+  if (diff)
+    return diff;
+
+  return key1.xkrFABN - key2.xkrFABN;
+}
+
+/*
+ * NAME:       record->packcatdata()
+ * DESCRIPTION:        pack catalog record data
+ */
+void r_packcatdata(CatDataRec *data, unsigned char *pdata, int *len)
+{
+  unsigned char *start = pdata;
+  int i;
+
+  d_storeb(&pdata, data->cdrType);
+  d_storeb(&pdata, data->cdrResrv2);
+
+  switch (data->cdrType)
+    {
+    case cdrDirRec:
+      d_storew(&pdata, data->u.dir.dirFlags);
+      d_storew(&pdata, data->u.dir.dirVal);
+      d_storel(&pdata, data->u.dir.dirDirID);
+      d_storel(&pdata, data->u.dir.dirCrDat);
+      d_storel(&pdata, data->u.dir.dirMdDat);
+      d_storel(&pdata, data->u.dir.dirBkDat);
+
+      d_storew(&pdata, data->u.dir.dirUsrInfo.frRect.top);
+      d_storew(&pdata, data->u.dir.dirUsrInfo.frRect.left);
+      d_storew(&pdata, data->u.dir.dirUsrInfo.frRect.bottom);
+      d_storew(&pdata, data->u.dir.dirUsrInfo.frRect.right);
+      d_storew(&pdata, data->u.dir.dirUsrInfo.frFlags);
+      d_storew(&pdata, data->u.dir.dirUsrInfo.frLocation.v);
+      d_storew(&pdata, data->u.dir.dirUsrInfo.frLocation.h);
+      d_storew(&pdata, data->u.dir.dirUsrInfo.frView);
+
+      d_storew(&pdata, data->u.dir.dirFndrInfo.frScroll.v);
+      d_storew(&pdata, data->u.dir.dirFndrInfo.frScroll.h);
+      d_storel(&pdata, data->u.dir.dirFndrInfo.frOpenChain);
+      d_storew(&pdata, data->u.dir.dirFndrInfo.frUnused);
+      d_storew(&pdata, data->u.dir.dirFndrInfo.frComment);
+      d_storel(&pdata, data->u.dir.dirFndrInfo.frPutAway);
+
+      for (i = 0; i < 4; ++i)
+       d_storel(&pdata, data->u.dir.dirResrv[i]);
+
+      break;
+
+    case cdrFilRec:
+      d_storeb(&pdata, data->u.fil.filFlags);
+      d_storeb(&pdata, data->u.fil.filTyp);
+
+      d_storel(&pdata, data->u.fil.filUsrWds.fdType);
+      d_storel(&pdata, data->u.fil.filUsrWds.fdCreator);
+      d_storew(&pdata, data->u.fil.filUsrWds.fdFlags);
+      d_storew(&pdata, data->u.fil.filUsrWds.fdLocation.v);
+      d_storew(&pdata, data->u.fil.filUsrWds.fdLocation.h);
+      d_storew(&pdata, data->u.fil.filUsrWds.fdFldr);
+
+      d_storel(&pdata, data->u.fil.filFlNum);
+
+      d_storew(&pdata, data->u.fil.filStBlk);
+      d_storel(&pdata, data->u.fil.filLgLen);
+      d_storel(&pdata, data->u.fil.filPyLen);
+
+      d_storew(&pdata, data->u.fil.filRStBlk);
+      d_storel(&pdata, data->u.fil.filRLgLen);
+      d_storel(&pdata, data->u.fil.filRPyLen);
+
+      d_storel(&pdata, data->u.fil.filCrDat);
+      d_storel(&pdata, data->u.fil.filMdDat);
+      d_storel(&pdata, data->u.fil.filBkDat);
+
+      d_storew(&pdata, data->u.fil.filFndrInfo.fdIconID);
+      for (i = 0; i < 4; ++i)
+       d_storew(&pdata, data->u.fil.filFndrInfo.fdUnused[i]);
+      d_storew(&pdata, data->u.fil.filFndrInfo.fdComment);
+      d_storel(&pdata, data->u.fil.filFndrInfo.fdPutAway);
+
+      d_storew(&pdata, data->u.fil.filClpSize);
+
+      for (i = 0; i < 3; ++i)
+       {
+         d_storew(&pdata, data->u.fil.filExtRec[i].xdrStABN);
+         d_storew(&pdata, data->u.fil.filExtRec[i].xdrNumABlks);
+       }
+
+      for (i = 0; i < 3; ++i)
+       {
+         d_storew(&pdata, data->u.fil.filRExtRec[i].xdrStABN);
+         d_storew(&pdata, data->u.fil.filRExtRec[i].xdrNumABlks);
+       }
+
+      d_storel(&pdata, data->u.fil.filResrv);
+      break;
+
+    case cdrThdRec:
+      for (i = 0; i < 2; ++i)
+       d_storel(&pdata, data->u.dthd.thdResrv[i]);
+
+      d_storel(&pdata, data->u.dthd.thdParID);
+      d_stores(&pdata, data->u.dthd.thdCName, sizeof(data->u.dthd.thdCName));
+      break;
+
+    case cdrFThdRec:
+      for (i = 0; i < 2; ++i)
+       d_storel(&pdata, data->u.fthd.fthdResrv[i]);
+
+      d_storel(&pdata, data->u.fthd.fthdParID);
+      d_stores(&pdata, data->u.fthd.fthdCName, sizeof(data->u.fthd.fthdCName));
+      break;
+
+    default:
+      abort();
+    }
+
+  if (len)
+    *len += pdata - start;
+}
+
+/*
+ * NAME:       record->unpackcatdata()
+ * DESCRIPTION:        unpack catalog record data
+ */
+void r_unpackcatdata(unsigned char *pdata, CatDataRec *data)
+{
+  int i;
+
+  d_fetchb(&pdata, (char *) &data->cdrType);
+  d_fetchb(&pdata, (char *) &data->cdrResrv2);
+
+  switch (data->cdrType)
+    {
+    case cdrDirRec:
+      d_fetchw(&pdata, &data->u.dir.dirFlags);
+      d_fetchw(&pdata, (short *) &data->u.dir.dirVal);
+      d_fetchl(&pdata, (long *) &data->u.dir.dirDirID);
+      d_fetchl(&pdata, &data->u.dir.dirCrDat);
+      d_fetchl(&pdata, &data->u.dir.dirMdDat);
+      d_fetchl(&pdata, &data->u.dir.dirBkDat);
+
+      d_fetchw(&pdata, &data->u.dir.dirUsrInfo.frRect.top);
+      d_fetchw(&pdata, &data->u.dir.dirUsrInfo.frRect.left);
+      d_fetchw(&pdata, &data->u.dir.dirUsrInfo.frRect.bottom);
+      d_fetchw(&pdata, &data->u.dir.dirUsrInfo.frRect.right);
+      d_fetchw(&pdata, &data->u.dir.dirUsrInfo.frFlags);
+      d_fetchw(&pdata, &data->u.dir.dirUsrInfo.frLocation.v);
+      d_fetchw(&pdata, &data->u.dir.dirUsrInfo.frLocation.h);
+      d_fetchw(&pdata, &data->u.dir.dirUsrInfo.frView);
+
+      d_fetchw(&pdata, &data->u.dir.dirFndrInfo.frScroll.v);
+      d_fetchw(&pdata, &data->u.dir.dirFndrInfo.frScroll.h);
+      d_fetchl(&pdata, &data->u.dir.dirFndrInfo.frOpenChain);
+      d_fetchw(&pdata, &data->u.dir.dirFndrInfo.frUnused);
+      d_fetchw(&pdata, &data->u.dir.dirFndrInfo.frComment);
+      d_fetchl(&pdata, &data->u.dir.dirFndrInfo.frPutAway);
+
+      for (i = 0; i < 4; ++i)
+       d_fetchl(&pdata, &data->u.dir.dirResrv[i]);
+
+      break;
+
+    case cdrFilRec:
+      d_fetchb(&pdata, (char *) &data->u.fil.filFlags);
+      d_fetchb(&pdata, (char *) &data->u.fil.filTyp);
+
+      d_fetchl(&pdata, &data->u.fil.filUsrWds.fdType);
+      d_fetchl(&pdata, &data->u.fil.filUsrWds.fdCreator);
+      d_fetchw(&pdata, &data->u.fil.filUsrWds.fdFlags);
+      d_fetchw(&pdata, &data->u.fil.filUsrWds.fdLocation.v);
+      d_fetchw(&pdata, &data->u.fil.filUsrWds.fdLocation.h);
+      d_fetchw(&pdata, &data->u.fil.filUsrWds.fdFldr);
+
+      d_fetchl(&pdata, (long *) &data->u.fil.filFlNum);
+
+      d_fetchw(&pdata, (short *) &data->u.fil.filStBlk);
+      d_fetchl(&pdata, (long *) &data->u.fil.filLgLen);
+      d_fetchl(&pdata, (long *) &data->u.fil.filPyLen);
+
+      d_fetchw(&pdata, (short *) &data->u.fil.filRStBlk);
+      d_fetchl(&pdata, (long *) &data->u.fil.filRLgLen);
+      d_fetchl(&pdata, (long *) &data->u.fil.filRPyLen);
+
+      d_fetchl(&pdata, &data->u.fil.filCrDat);
+      d_fetchl(&pdata, &data->u.fil.filMdDat);
+      d_fetchl(&pdata, &data->u.fil.filBkDat);
+
+      d_fetchw(&pdata, &data->u.fil.filFndrInfo.fdIconID);
+      for (i = 0; i < 4; ++i)
+       d_fetchw(&pdata, &data->u.fil.filFndrInfo.fdUnused[i]);
+      d_fetchw(&pdata, &data->u.fil.filFndrInfo.fdComment);
+      d_fetchl(&pdata, &data->u.fil.filFndrInfo.fdPutAway);
+
+      d_fetchw(&pdata, (short *) &data->u.fil.filClpSize);
+
+      for (i = 0; i < 3; ++i)
+       {
+         d_fetchw(&pdata, (short *) &data->u.fil.filExtRec[i].xdrStABN);
+         d_fetchw(&pdata, (short *) &data->u.fil.filExtRec[i].xdrNumABlks);
+       }
+
+      for (i = 0; i < 3; ++i)
+       {
+         d_fetchw(&pdata, (short *) &data->u.fil.filRExtRec[i].xdrStABN);
+         d_fetchw(&pdata, (short *) &data->u.fil.filRExtRec[i].xdrNumABlks);
+       }
+
+      d_fetchl(&pdata, &data->u.fil.filResrv);
+      break;
+
+    case cdrThdRec:
+      for (i = 0; i < 2; ++i)
+       d_fetchl(&pdata, &data->u.dthd.thdResrv[i]);
+
+      d_fetchl(&pdata, (long *) &data->u.dthd.thdParID);
+      d_fetchs(&pdata, data->u.dthd.thdCName, sizeof(data->u.dthd.thdCName));
+      break;
+
+    case cdrFThdRec:
+      for (i = 0; i < 2; ++i)
+       d_fetchl(&pdata, &data->u.fthd.fthdResrv[i]);
+
+      d_fetchl(&pdata, (long *) &data->u.fthd.fthdParID);
+      d_fetchs(&pdata, data->u.fthd.fthdCName, sizeof(data->u.fthd.fthdCName));
+      break;
+
+    default:
+      abort();
+    }
+}
+
+/*
+ * NAME:       record->packextdata()
+ * DESCRIPTION:        pack extent record data
+ */
+void r_packextdata(ExtDataRec *data, unsigned char *pdata, int *len)
+{
+  unsigned char *start = pdata;
+  int i;
+
+  for (i = 0; i < 3; ++i)
+    {
+      d_storew(&pdata, (*data)[i].xdrStABN);
+      d_storew(&pdata, (*data)[i].xdrNumABlks);
+    }
+
+  if (len)
+    *len += pdata - start;
+}
+
+/*
+ * NAME:       record->unpackextdata()
+ * DESCRIPTION:        unpack extent record data
+ */
+void r_unpackextdata(unsigned char *pdata, ExtDataRec *data)
+{
+  int i;
+
+  for (i = 0; i < 3; ++i)
+    {
+      d_fetchw(&pdata, (short *) &(*data)[i].xdrStABN);
+      d_fetchw(&pdata, (short *) &(*data)[i].xdrNumABlks);
+    }
+}
+
+/*
+ * NAME:       record->makecatkey()
+ * DESCRIPTION:        construct a catalog record key
+ */
+void r_makecatkey(CatKeyRec *key, long parid, char *name)
+{
+  int len;
+
+  len = strlen(name) + 1;
+
+  key->ckrKeyLen = 0x05 + len + (len & 1);
+  key->ckrResrv1 = 0;
+  key->ckrParID  = parid;
+
+  strcpy(key->ckrCName, name);
+}
+
+/*
+ * NAME:       record->makeextkey()
+ * DESCRIPTION:        construct an extents record key
+ */
+void r_makeextkey(ExtKeyRec *key, int ffork, long fnum, unsigned int fabn)
+{
+  key->xkrKeyLen = 0x07;
+  key->xkrFkType = ffork;
+  key->xkrFNum   = fnum;
+  key->xkrFABN   = fabn;
+}
+
+/*
+ * NAME:       record->unpackdirent()
+ * DESCRIPTION:        unpack catalog information into hfsdirent structure
+ *
+ * Taken fron v3.2.6
+ */
+void r_unpackdirent(long parid, char *name, CatDataRec *data, hfsdirent *ent)
+{
+  strcpy(ent->name, name);
+  ent->parid = parid;
+
+  switch (data->cdrType)
+    {
+    case cdrDirRec:
+      ent->flags = HFS_ISDIR;
+      ent->cnid  = data->u.dir.dirDirID;
+
+      ent->crdate = d_toutime(data->u.dir.dirCrDat);
+      ent->mddate = d_toutime(data->u.dir.dirMdDat);
+      ent->bkdate = d_toutime(data->u.dir.dirBkDat);
+
+      ent->fdflags      = data->u.dir.dirUsrInfo.frFlags;
+      ent->fdlocation.v = data->u.dir.dirUsrInfo.frLocation.v;
+      ent->fdlocation.h = data->u.dir.dirUsrInfo.frLocation.h;
+
+      ent->u.dir.valence = data->u.dir.dirVal;
+
+      ent->u.dir.rect.top    = data->u.dir.dirUsrInfo.frRect.top;
+      ent->u.dir.rect.left   = data->u.dir.dirUsrInfo.frRect.left;
+      ent->u.dir.rect.bottom = data->u.dir.dirUsrInfo.frRect.bottom;
+      ent->u.dir.rect.right  = data->u.dir.dirUsrInfo.frRect.right;
+
+      /* mkhybrid extra */
+      ent->u.dir.frscroll.v  = data->u.dir.dirFndrInfo.frScroll.v;
+      ent->u.dir.frscroll.h  = data->u.dir.dirFndrInfo.frScroll.h;
+      ent->u.dir.view       = data->u.dir.dirUsrInfo.frView;
+
+      break;
+
+    case cdrFilRec:
+      ent->flags = (data->u.fil.filFlags & (1 << 0)) ? HFS_ISLOCKED : 0;
+      ent->cnid  = data->u.fil.filFlNum;
+
+      ent->crdate = d_toutime(data->u.fil.filCrDat);
+      ent->mddate = d_toutime(data->u.fil.filMdDat);
+      ent->bkdate = d_toutime(data->u.fil.filBkDat);
+
+      ent->fdflags      = data->u.fil.filUsrWds.fdFlags;
+      ent->fdlocation.v = data->u.fil.filUsrWds.fdLocation.v;
+      ent->fdlocation.h = data->u.fil.filUsrWds.fdLocation.h;
+
+      ent->u.file.dsize = data->u.fil.filLgLen;
+      ent->u.file.rsize = data->u.fil.filRLgLen;
+
+      d_putl((unsigned char *) ent->u.file.type,
+             data->u.fil.filUsrWds.fdType);
+      d_putl((unsigned char *) ent->u.file.creator,
+            data->u.fil.filUsrWds.fdCreator);
+
+      ent->u.file.type[4] = ent->u.file.creator[4] = 0;
+
+      break;
+    }
+}
+
+/*
+ * NAME:       record->packdirent()
+ * DESCRIPTION:        make changes to a catalog record
+ *
+ * Taken fron v3.2.6
+ */
+void r_packdirent(CatDataRec *data, hfsdirent *ent)
+{
+  switch (data->cdrType)
+    {
+    case cdrDirRec:
+      data->u.dir.dirCrDat = d_tomtime(ent->crdate);
+      data->u.dir.dirMdDat = d_tomtime(ent->mddate);
+      data->u.dir.dirBkDat = d_tomtime(ent->bkdate);
+
+      data->u.dir.dirUsrInfo.frFlags      = ent->fdflags;
+      data->u.dir.dirUsrInfo.frLocation.v = ent->fdlocation.v;
+      data->u.dir.dirUsrInfo.frLocation.h = ent->fdlocation.h;
+
+      data->u.dir.dirUsrInfo.frRect.top    = ent->u.dir.rect.top;
+      data->u.dir.dirUsrInfo.frRect.left   = ent->u.dir.rect.left;
+      data->u.dir.dirUsrInfo.frRect.bottom = ent->u.dir.rect.bottom;
+      data->u.dir.dirUsrInfo.frRect.right  = ent->u.dir.rect.right;
+
+      /* mkhybrid extra */
+      data->u.dir.dirFndrInfo.frScroll.v   = ent->u.dir.frscroll.v;
+      data->u.dir.dirFndrInfo.frScroll.h   = ent->u.dir.frscroll.h;
+      data->u.dir.dirUsrInfo.frView       = ent->u.dir.view;
+
+      break;
+
+    case cdrFilRec:
+      if (ent->flags & HFS_ISLOCKED)
+       data->u.fil.filFlags |=  (1 << 0);
+      else
+       data->u.fil.filFlags &= ~(1 << 0);
+
+      data->u.fil.filCrDat = d_tomtime(ent->crdate);
+      data->u.fil.filMdDat = d_tomtime(ent->mddate);
+      data->u.fil.filBkDat = d_tomtime(ent->bkdate);
+
+      data->u.fil.filUsrWds.fdFlags      = ent->fdflags;
+      data->u.fil.filUsrWds.fdLocation.v = ent->fdlocation.v;
+      data->u.fil.filUsrWds.fdLocation.h = ent->fdlocation.h;
+
+      data->u.fil.filUsrWds.fdType =
+       d_getl((unsigned char *) ent->u.file.type);
+      data->u.fil.filUsrWds.fdCreator =
+       d_getl((unsigned char *) ent->u.file.creator);
+
+      break;
+    }
+}
diff --git a/libhfs_iso/record.h b/libhfs_iso/record.h
new file mode 100644 (file)
index 0000000..90934eb
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)record.h        1.1 00/03/05 joerg */
+/*
+ * hfsutils - tools for reading and writing Macintosh HFS volumes
+ * Copyright (C) 1996, 1997 Robert Leslie
+ *
+ * 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 of the License, 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.
+ */
+
+void r_packcatkey(CatKeyRec *, unsigned char *, int *);
+void r_unpackcatkey(unsigned char *, CatKeyRec *);
+
+void r_packextkey(ExtKeyRec *, unsigned char *, int *);
+void r_unpackextkey(unsigned char *, ExtKeyRec *);
+
+int r_comparecatkeys(unsigned char *, unsigned char *);
+int r_compareextkeys(unsigned char *, unsigned char *);
+
+void r_packcatdata(CatDataRec *, unsigned char *, int *);
+void r_unpackcatdata(unsigned char *, CatDataRec *);
+
+void r_packextdata(ExtDataRec *, unsigned char *, int *);
+void r_unpackextdata(unsigned char *, ExtDataRec *);
+
+void r_makecatkey(CatKeyRec *, long, char *);
+void r_makeextkey(ExtKeyRec *, int, long, unsigned int);
+
+void r_unpackdirent(long, char *, CatDataRec *, hfsdirent *);
+void r_packdirent(CatDataRec *, hfsdirent *);
diff --git a/libhfs_iso/volume.c b/libhfs_iso/volume.c
new file mode 100644 (file)
index 0000000..b352735
--- /dev/null
@@ -0,0 +1,741 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)volume.c        1.4 04/06/17 joerg */
+/*
+ * hfsutils - tools for reading and writing Macintosh HFS volumes
+ * Copyright (C) 1996, 1997 Robert Leslie
+ *
+ * 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 of the License, 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 <mconfig.h>
+#include <stdxlib.h>
+#include <strdefs.h>
+#include <errno.h>
+
+#include "internal.h"
+#include "data.h"
+#include "low.h"
+#include "btree.h"
+#include "record.h"
+#include "volume.h"
+
+static void    markexts(block *vbm, ExtDataRec *exts);
+
+
+/*
+ * NAME:       vol->catsearch()
+ * DESCRIPTION:        search catalog tree
+ */
+int v_catsearch(hfsvol *vol, long parid, char *name, CatDataRec *data, 
+                char *cname, node *np)
+{
+  CatKeyRec key;
+  unsigned char pkey[HFS_CATKEYLEN];
+  node n;
+  unsigned char *ptr;
+  int found;
+
+  if (np == 0)
+    np = &n;
+
+  r_makecatkey(&key, parid, name);
+  r_packcatkey(&key, pkey, 0);
+
+  found = bt_search(&vol->cat, pkey, np);
+  if (found <= 0)
+    return found;
+
+  ptr = HFS_NODEREC(*np, np->rnum);
+
+  if (cname)
+    {
+      r_unpackcatkey(ptr, &key);
+      strcpy(cname, key.ckrCName);
+    }
+
+  if (data)
+    r_unpackcatdata(HFS_RECDATA(ptr), data);
+
+  return 1;
+}
+
+/*
+ * NAME:       vol->extsearch()
+ * DESCRIPTION:        search extents tree
+ */
+int v_extsearch(hfsfile *file, unsigned int fabn, ExtDataRec *data, node *np)
+{
+  ExtKeyRec key;
+  ExtDataRec extsave;
+  unsigned int fabnsave;
+  unsigned char pkey[HFS_EXTKEYLEN];
+  node n;
+  unsigned char *ptr;
+  int found;
+
+  if (np == 0)
+    np = &n;
+
+  r_makeextkey(&key, file->fork, file->cat.u.fil.filFlNum, fabn);
+  r_packextkey(&key, pkey, 0);
+
+  /* in case bt_search() clobbers these */
+
+  memcpy(&extsave, &file->ext, sizeof(ExtDataRec));
+  fabnsave = file->fabn;
+
+  found = bt_search(&file->vol->ext, pkey, np);
+
+  memcpy(&file->ext, &extsave, sizeof(ExtDataRec));
+  file->fabn = fabnsave;
+
+  if (found <= 0)
+    return found;
+
+  if (data)
+    {
+      ptr = HFS_NODEREC(*np, np->rnum);
+      r_unpackextdata(HFS_RECDATA(ptr), data);
+    }
+
+  return 1;
+}
+
+/*
+ * NAME:       vol->getthread()
+ * DESCRIPTION:        retrieve catalog thread information for a file or directory
+ */
+int v_getthread(hfsvol *vol, long id, CatDataRec *thread, node *np, int type)
+{
+  CatDataRec rec;
+  int found;
+
+  if (thread == 0)
+    thread = &rec;
+
+  found = v_catsearch(vol, id, "", thread, 0, np);
+  if (found <= 0)
+    return found;
+
+  if (thread->cdrType != type)
+    {
+      ERROR(EIO, "bad thread record");
+      return -1;
+    }
+
+  return 1;
+}
+
+/*
+ * NAME:       vol->putcatrec()
+ * DESCRIPTION:        store catalog information
+ */
+int v_putcatrec(CatDataRec *data, node *np)
+{
+  unsigned char pdata[HFS_CATDATALEN], *ptr;
+  int len = 0;
+
+  r_packcatdata(data, pdata, &len);
+
+  ptr = HFS_NODEREC(*np, np->rnum);
+  memcpy(HFS_RECDATA(ptr), pdata, len);
+
+  return bt_putnode(np);
+}
+
+/*
+ * NAME:       vol->putextrec()
+ * DESCRIPTION:        store extent information
+ */
+int v_putextrec(ExtDataRec *data, node *np)
+{
+  unsigned char pdata[HFS_EXTDATALEN], *ptr;
+  int len = 0;
+
+  r_packextdata(data, pdata, &len);
+
+  ptr = HFS_NODEREC(*np, np->rnum);
+  memcpy(HFS_RECDATA(ptr), pdata, len);
+
+  return bt_putnode(np);
+}
+
+/*
+ * NAME:       vol->allocblocks()
+ * DESCRIPTION:        allocate a contiguous range of blocks
+ */
+int v_allocblocks(hfsvol *vol, ExtDescriptor *blocks)
+{
+  unsigned int request, found, foundat, start, end, pt;
+  block *vbm;
+  int wrap = 0;
+
+  if (vol->mdb.drFreeBks == 0)
+    {
+      ERROR(ENOSPC, "volume full");
+      return -1;
+    }
+
+  request = blocks->xdrNumABlks;
+  found   = 0;
+  foundat = 0;
+  start   = vol->mdb.drAllocPtr;
+  end     = vol->mdb.drNmAlBlks;
+  pt      = start;
+  vbm     = vol->vbm;
+
+  if (request == 0)
+    abort();
+
+  for (;;)
+    {
+      unsigned int mark;
+
+      /* skip blocks in use */
+
+      while (pt < end && BMTST(vbm, pt))
+       ++pt;
+
+      if (wrap && pt >= start)
+       break;
+
+      /* count blocks not in use */
+
+      mark = pt;
+      while (pt < end && pt - mark < request && ! BMTST(vbm, pt))
+       ++pt;
+
+      if (pt - mark > found)
+       {
+         found   = pt - mark;
+         foundat = mark;
+       }
+
+      if (pt == end)
+       pt = 0, wrap = 1;
+
+      if (found == request)
+       break;
+    }
+
+  if (found == 0 || found > vol->mdb.drFreeBks)
+    {
+      ERROR(EIO, "bad volume bitmap or free block count");
+      return -1;
+    }
+
+  blocks->xdrStABN    = foundat;
+  blocks->xdrNumABlks = found;
+
+  vol->mdb.drAllocPtr = pt;
+  vol->mdb.drFreeBks -= found;
+
+  for (pt = foundat; pt < foundat + found; ++pt)
+    BMSET(vbm, pt);
+
+  vol->flags |= HFS_UPDATE_MDB | HFS_UPDATE_VBM;
+
+  return 0;
+}
+
+/*
+ * NAME:       vol->freeblocks()
+ * DESCRIPTION:        deallocate a contiguous range of blocks
+ */
+void v_freeblocks(hfsvol *vol, ExtDescriptor *blocks)
+{
+  unsigned int start, len, pt;
+  block *vbm;
+
+  start = blocks->xdrStABN;
+  len   = blocks->xdrNumABlks;
+  vbm   = vol->vbm;
+
+  vol->mdb.drFreeBks += len;
+
+  for (pt = start; pt < start + len; ++pt)
+    BMCLR(vbm, pt);
+
+  vol->flags |= HFS_UPDATE_MDB | HFS_UPDATE_VBM;
+}
+
+/*
+ * NAME:       vol->resolve()
+ * DESCRIPTION:        translate a pathname; return catalog information
+ */
+int v_resolve(hfsvol **vol, char *path, CatDataRec *data, long *parid, 
+              char *fname, node *np)
+{
+  long dirid;
+  char name[HFS_MAX_FLEN + 1], *nptr;
+  int found;
+
+  if (*path == 0)
+    {
+      ERROR(ENOENT, "empty path");
+      return -1;
+    }
+
+  if (parid)
+    *parid = 0;
+
+  nptr = strchr(path, ':');
+
+  if (*path == ':' || nptr == 0)
+    {
+      dirid = (*vol)->cwd;  /* relative path */
+
+      if (*path == ':')
+       ++path;
+
+      if (*path == 0)
+       {
+         found = v_getdthread(*vol, dirid, data, 0);
+         if (found <= 0)
+           return found;
+
+         if (parid)
+           *parid = data->u.dthd.thdParID;
+
+         return v_catsearch(*vol, data->u.dthd.thdParID,
+                            data->u.dthd.thdCName, data, fname, np);
+       }
+    }
+  else
+    {
+      hfsvol *check;
+
+      dirid = HFS_CNID_ROOTPAR;  /* absolute path */
+
+      if (nptr - path > HFS_MAX_VLEN)
+       {
+         ERROR(ENAMETOOLONG, 0);
+         return -1;
+       }
+
+      strncpy(name, path, nptr - path);
+      name[nptr - path] = 0;
+
+      for (check = hfs_mounts; check; check = check->next)
+       {
+         if (d_relstring(check->mdb.drVN, name) == 0)
+           {
+             *vol = check;
+             break;
+           }
+       }
+    }
+
+  for (;;)
+    {
+      while (*path == ':')
+       {
+         ++path;
+
+         found = v_getdthread(*vol, dirid, data, 0);
+         if (found <= 0)
+           return found;
+
+         dirid = data->u.dthd.thdParID;
+       }
+
+      if (*path == 0)
+       {
+         found = v_getdthread(*vol, dirid, data, 0);
+         if (found <= 0)
+           return found;
+
+         if (parid)
+           *parid = data->u.dthd.thdParID;
+
+         return v_catsearch(*vol, data->u.dthd.thdParID,
+                            data->u.dthd.thdCName, data, fname, np);
+       }
+
+      nptr = name;
+      while (nptr < name + sizeof(name) - 1 && *path && *path != ':')
+       *nptr++ = *path++;
+
+      if (*path && *path != ':')
+       {
+         ERROR(ENAMETOOLONG, 0);
+         return -1;
+       }
+
+      *nptr = 0;
+      if (*path == ':')
+       ++path;
+
+      if (parid)
+       *parid = dirid;
+
+      found = v_catsearch(*vol, dirid, name, data, fname, np);
+      if (found < 0)
+       return -1;
+
+      if (found == 0)
+       {
+         if (*path && parid)
+           *parid = 0;
+
+         if (*path == 0 && fname)
+           strcpy(fname, name);
+
+         return 0;
+       }
+
+      switch (data->cdrType)
+       {
+       case cdrDirRec:
+         if (*path == 0)
+           return 1;
+
+         dirid = data->u.dir.dirDirID;
+         break;
+
+       case cdrFilRec:
+         if (*path == 0)
+           return 1;
+
+         ERROR(ENOTDIR, "invalid pathname");
+         return -1;
+
+       default:
+         ERROR(EIO, "unexpected catalog record");
+         return -1;
+       }
+    }
+}
+
+/*
+ * NAME:       vol->destruct()
+ * DESCRIPTION:        free memory consumed by a volume descriptor
+ */
+void v_destruct(hfsvol *vol)
+{
+  FREE(vol->vbm);
+
+  FREE(vol->ext.map);
+  FREE(vol->cat.map);
+
+  FREE(vol);
+}
+
+/*
+ * NAME:       vol->getvol()
+ * DESCRIPTION:        validate a volume reference
+ */
+int v_getvol(hfsvol **vol)
+{
+  if (*vol == 0)
+    {
+      if (hfs_curvol == 0)
+       {
+         ERROR(EINVAL, "no volume is current");
+         return -1;
+       }
+
+      *vol = hfs_curvol;
+    }
+
+  return 0;
+}
+
+/*
+ * NAME:       vol->flush()
+ * DESCRIPTION:        flush all pending changes (B*-tree, MDB, VBM) to disk
+ */
+int v_flush(hfsvol *vol, int umounting)
+{
+  if (! (vol->flags & HFS_READONLY))
+    {
+      if ((vol->ext.flags & HFS_UPDATE_BTHDR) &&
+         bt_writehdr(&vol->ext) < 0)
+       return -1;
+
+      if ((vol->cat.flags & HFS_UPDATE_BTHDR) &&
+         bt_writehdr(&vol->cat) < 0)
+       return -1;
+
+      if ((vol->flags & HFS_UPDATE_VBM) &&
+         l_writevbm(vol) < 0)
+       return -1;
+
+      if (umounting &&
+         ! (vol->mdb.drAtrb & HFS_ATRB_UMOUNTED))
+       {
+         vol->mdb.drAtrb |= HFS_ATRB_UMOUNTED;
+         vol->flags |= HFS_UPDATE_MDB;
+       }
+
+      if ((vol->flags & (HFS_UPDATE_MDB | HFS_UPDATE_ALTMDB)) &&
+         l_writemdb(vol) < 0)
+       return -1;
+    }
+
+  return 0;
+}
+
+/*
+ * NAME:       vol->adjvalence()
+ * DESCRIPTION:        update a volume's valence counts
+ */
+int v_adjvalence(hfsvol *vol, long parid, int isdir, int adj)
+{
+  node n;
+  CatDataRec data;
+
+  if (isdir)
+    vol->mdb.drDirCnt += adj;
+  else
+    vol->mdb.drFilCnt += adj;
+
+  vol->flags |= HFS_UPDATE_MDB;
+
+  if (parid == HFS_CNID_ROOTDIR)
+    {
+      if (isdir)
+       vol->mdb.drNmRtDirs += adj;
+      else
+       vol->mdb.drNmFls    += adj;
+    }
+  else if (parid == HFS_CNID_ROOTPAR)
+    return 0;
+
+  if (v_getdthread(vol, parid, &data, 0) <= 0 ||
+      v_catsearch(vol, data.u.dthd.thdParID, data.u.dthd.thdCName,
+                 &data, 0, &n) <= 0 ||
+      data.cdrType != cdrDirRec)
+    {
+      ERROR(EIO, "can't find parent directory");
+      return -1;
+    }
+
+  data.u.dir.dirVal  += adj;
+  data.u.dir.dirMdDat = d_tomtime(time(0));
+
+  return v_putcatrec(&data, &n);
+}
+
+/*
+ * NAME:       vol->newfolder()
+ * DESCRIPTION:        create a new HFS folder
+ */
+int v_newfolder(hfsvol *vol, long parid, char *name)
+{
+  CatKeyRec key;
+  CatDataRec data;
+  long id;
+  unsigned char record[HFS_CATRECMAXLEN];
+  int i, reclen;
+
+  if (bt_space(&vol->cat, 2) < 0)
+    return -1;
+
+  id = vol->mdb.drNxtCNID++;
+  vol->flags |= HFS_UPDATE_MDB;
+
+  /* create directory record */
+
+  data.cdrType   = cdrDirRec;
+  data.cdrResrv2 = 0;
+
+  data.u.dir.dirFlags = 0;
+  data.u.dir.dirVal   = 0;
+  data.u.dir.dirDirID = id;
+  data.u.dir.dirCrDat = d_tomtime(time(0));
+  data.u.dir.dirMdDat = data.u.dir.dirCrDat;
+  data.u.dir.dirBkDat = 0;
+
+  memset(&data.u.dir.dirUsrInfo,  0, sizeof(data.u.dir.dirUsrInfo));
+  memset(&data.u.dir.dirFndrInfo, 0, sizeof(data.u.dir.dirFndrInfo));
+  for (i = 0; i < 4; ++i)
+    data.u.dir.dirResrv[i] = 0;
+
+  r_makecatkey(&key, parid, name);
+  r_packcatkey(&key, record, &reclen);
+  r_packcatdata(&data, HFS_RECDATA(record), &reclen);
+
+  if (bt_insert(&vol->cat, record, reclen) < 0)
+    return -1;
+
+  /* create thread record */
+
+  data.cdrType   = cdrThdRec;
+  data.cdrResrv2 = 0;
+
+  data.u.dthd.thdResrv[0] = 0;
+  data.u.dthd.thdResrv[1] = 0;
+  data.u.dthd.thdParID    = parid;
+  strcpy(data.u.dthd.thdCName, name);
+
+  r_makecatkey(&key, id, "");
+  r_packcatkey(&key, record, &reclen);
+  r_packcatdata(&data, HFS_RECDATA(record), &reclen);
+
+  if (bt_insert(&vol->cat, record, reclen) < 0 ||
+      v_adjvalence(vol, parid, 1, 1) < 0)
+    return -1;
+
+  return 0;
+}
+
+/*
+ * NAME:       markexts()
+ * DESCRIPTION:        set bits from an extent record in the volume bitmap
+ */
+static
+void markexts(block *vbm, ExtDataRec *exts)
+{
+  int i;
+  unsigned int start, len;
+
+  for (i = 0; i < 3; ++i)
+    {
+      for (start = (*exts)[i].xdrStABN,
+            len = (*exts)[i].xdrNumABlks; len--; ++start)
+       BMSET(vbm, start);
+    }
+}
+
+/*
+ * NAME:       vol->scavenge()
+ * DESCRIPTION:        safeguard blocks in the volume bitmap
+ */
+int v_scavenge(hfsvol *vol)
+{
+  block *vbm = vol->vbm;
+  node n;
+  unsigned int pt, blks;
+
+  if (vbm == 0)
+    return 0;
+
+  markexts(vbm, &vol->mdb.drXTExtRec);
+  markexts(vbm, &vol->mdb.drCTExtRec);
+
+  vol->flags |= HFS_UPDATE_VBM;
+
+  /* scavenge the extents overflow file */
+
+  n.bt   = &vol->ext;
+  n.nnum = vol->ext.hdr.bthFNode;
+
+  if (n.nnum > 0)
+    {
+      if (bt_getnode(&n) < 0)
+       return -1;
+
+      n.rnum = 0;
+
+      for (;;)
+       {
+         ExtDataRec data;
+         unsigned char *ptr;
+
+         while (n.rnum >= (int)n.nd.ndNRecs)
+           {
+             n.nnum = n.nd.ndFLink;
+             if (n.nnum == 0)
+               break;
+
+             if (bt_getnode(&n) < 0)
+               return -1;
+
+             n.rnum = 0;
+           }
+
+         if (n.nnum == 0)
+           break;
+
+         ptr = HFS_NODEREC(n, n.rnum);
+         r_unpackextdata(HFS_RECDATA(ptr), &data);
+
+         markexts(vbm, &data);
+
+         ++n.rnum;
+       }
+    }
+
+  /* scavenge the catalog file */
+
+  n.bt   = &vol->cat;
+  n.nnum = vol->cat.hdr.bthFNode;
+
+  if (n.nnum > 0)
+    {
+      if (bt_getnode(&n) < 0)
+       return -1;
+
+      n.rnum = 0;
+
+      for (;;)
+       {
+         CatDataRec data;
+         unsigned char *ptr;
+
+         while (n.rnum >= (int)n.nd.ndNRecs)
+           {
+             n.nnum = n.nd.ndFLink;
+             if (n.nnum == 0)
+               break;
+
+             if (bt_getnode(&n) < 0)
+               return -1;
+
+             n.rnum = 0;
+           }
+
+         if (n.nnum == 0)
+           break;
+
+         ptr = HFS_NODEREC(n, n.rnum);
+         r_unpackcatdata(HFS_RECDATA(ptr), &data);
+
+         if (data.cdrType == cdrFilRec)
+           {
+             markexts(vbm, &data.u.fil.filExtRec);
+             markexts(vbm, &data.u.fil.filRExtRec);
+           }
+
+         ++n.rnum;
+       }
+    }
+
+  for (blks = 0, pt = vol->mdb.drNmAlBlks; pt--; )
+    {
+      if (! BMTST(vbm, pt))
+       ++blks;
+    }
+
+  if (vol->mdb.drFreeBks != blks)
+    {
+      vol->mdb.drFreeBks = blks;
+      vol->flags |= HFS_UPDATE_MDB;
+    }
+
+  return 0;
+}
diff --git a/libhfs_iso/volume.h b/libhfs_iso/volume.h
new file mode 100644 (file)
index 0000000..2cc6005
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)volume.h        1.1 00/03/05 joerg */
+/*
+ * hfsutils - tools for reading and writing Macintosh HFS volumes
+ * Copyright (C) 1996, 1997 Robert Leslie
+ *
+ * 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 of the License, 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.
+ */
+
+int v_catsearch(hfsvol *, long, char *, CatDataRec *, char *, node *);
+int v_extsearch(hfsfile *, unsigned int, ExtDataRec *, node *);
+
+int v_getthread(hfsvol *, long, CatDataRec *, node *, int);
+
+# define v_getdthread(vol, id, thread, np)  \
+    v_getthread(vol, id, thread, np, cdrThdRec)
+# define v_getfthread(vol, id, thread, np)  \
+    v_getthread(vol, id, thread, np, cdrFThdRec)
+
+int v_putcatrec(CatDataRec *, node *);
+int v_putextrec(ExtDataRec *, node *);
+
+int v_allocblocks(hfsvol *, ExtDescriptor *);
+void v_freeblocks(hfsvol *, ExtDescriptor *);
+
+int v_resolve(hfsvol **, char *, CatDataRec *, long *, char *, node *);
+
+void v_destruct(hfsvol *);
+int v_getvol(hfsvol **);
+int v_flush(hfsvol *, int);
+
+int v_adjvalence(hfsvol *, long, int, int);
+int v_newfolder(hfsvol *, long, char *);
+
+int v_scavenge(hfsvol *);
diff --git a/libparanoia/CMakeLists.txt b/libparanoia/CMakeLists.txt
new file mode 100644 (file)
index 0000000..4319496
--- /dev/null
@@ -0,0 +1,6 @@
+PROJECT (LIBparanoia C)
+INCLUDE_DIRECTORIES(../include ${CMAKE_BINARY_DIR} ../wodim ${CMAKE_BINARY_DIR}/include)
+ADD_DEFINITIONS(-DHAVE_CONFIG_H)
+SET(LIBparanoia_SRCS gap.c isort.c overlap.c p_block.c paranoia.c pmalloc.c)
+
+ADD_LIBRARY (paranoia STATIC ${LIBparanoia_SRCS})
diff --git a/libparanoia/README.interface b/libparanoia/README.interface
new file mode 100644 (file)
index 0000000..a7a44b4
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * Exports (libparanoia) cdda_paranoia.h
+ */
+cdrom_paranoia *paranoia_init  __PR((void * d, int nsectors));
+void           paranoia_modeset __PR((cdrom_paranoia * p, int mode));
+long           paranoia_seek   __PR((cdrom_paranoia * p, long seek, int mode));
+Int16_t                *paranoia_read  __PR((cdrom_paranoia * p, void (*callback) (long, int)));
+Int16_t                *paranoia_read_limited __PR((cdrom_paranoia * p, void (*callback) (long, int), int maxretries));
+void           paranoia_free   __PR((cdrom_paranoia * p));
+void           paranoia_overlapset __PR((cdrom_paranoia * p, long overlap));
+
+/*
+ * Exports ?? (libparanoia) overlap.h
+ */
+extern void    paranoia_resetall       __PR((cdrom_paranoia * p));
+extern void    paranoia_resetcache     __PR((cdrom_paranoia * p));
+
+Supported:
+
+PARANOIA_MODE_VERIFY
+PARANOIA_MODE_OVERLAP
+PARANOIA_MODE_NEVERSKIP
+
+Unsupported:
+
+PARANOIA_MODE_FRAGMENT
+PARANOIA_MODE_SCRATCH
+PARANOIA_MODE_REPAIR
+
+
+
+/*
+ * Imports (global Code)
+ */
+cdda_disc_firstsector  (cdrom_drive *d)                -> long sector
+cdda_disc_lastsector   (cdrom_drive *d)                -> long sector
+cdda_read              (cdrom_drive *d, void *buffer, long beginsector, long sectors)  -> long sectors
+cdda_sector_gettrack   (cdrom_drive *d,long sector)    -> int trackno
+cdda_track_audiop      (cdrom_drive *d,int track)      -> int ???  /* Is audiotrack */
+cdda_track_firstsector (cdrom_drive *d,int track)      -> long sector
+cdda_track_lastsector  (cdrom_drive *d,int track)      -> long sector
+cdda_tracks            (cdrom_drive *d)                -> int tracks
+
+callback               (long inpos, int function)
+
+/*
+ * Imports (libc)
+ */
+calloc
+free
+malloc
+realloc
+
+memcmp
+memcpy
+memmove
+memset
+
+qsort
+
+/*--------------------------------------------------------------------------*/
+usalp = usal_open();
+bufsize = usal_bufsize(usalp, CDR_BUF_SIZE);
+nsecs = bufsize / SEC_SIZE;
+
+cdp = paranoia_init(usalp, nsecs);
+# paranoia_modeset(cdp, mode);
+# paranoia_overlapset(cdp, overlap);
+
+while (not ready) {
+       bp = paranoia_read(cdp, NULL);
+       write(f, bp, SEC_SISE);
+}
+
+paranoia_free(cdp);
diff --git a/libparanoia/README.paranoia b/libparanoia/README.paranoia
new file mode 100644 (file)
index 0000000..4864c32
--- /dev/null
@@ -0,0 +1,83 @@
+# @(#)README.paranoia  1.1 97/04/04 J. Schilling from Monty (xiphmont@mit.edu)
+README.paranoia
+
+Paranoia II:
+(c) Monty
+xiphmont@mit.edu
+
+Hi there.
+
+All CDROM drives are not created equal.  You're probably using this
+patch because yours is a little less equal than others-- or maybe you
+just keep your CD collection in a box of full of gravel.  Jewel cases
+are for wimps; you know what I'm talking about.
+
+This patch adds extra-robust interframe syncronization, code to detect
+scratches (and hold sync across the scratch) and finally routines to
+filter out scratches as best possible.  These are all handled
+automatically by fairly modular code.
+
+1) extra interframe syncronization -------------------------------------
+
+Some CD drives can read audio data from an exact starting point to an
+exact ending point flawlessly; these are rare.  A larger number of
+drives read from only an approximately correct starting point, but do
+manage to get all the data in-tact from wherever they manage to begin
+the read.  Stock cdda2wav is coded with this in mind.
+
+More drives, especially IDE-like and recent ATAPI drives, suffer from
+framing misalignments within atomic multi-sector read operations.
+Cdda2wav is also set, by default, to read 75 sectors at a time from
+ATAPI drives, which Linux's IDE driver breaks into multiple 8 sector
+reads to conserve kernel memory.  Both of these things will break
+cdda2wav; the symptoms include cracks or pops within the read sample.
+
+The "Paranoia" patch will verify the alignment of *every* byte read by
+cdda2wav.  The goal is data integrity, not performance: a minimum 50%
+speed hit will result from the patch, likely more if your CDROM
+suffers from the framing bugs the patch corrects.  
+
+2) scratch detection and tolerance ------------------------------------
+
+Because overlap syncronization requires matching exact, perfect sample
+sections, scratched CDs typically cause normal cdda2wav to bail when
+overlap syncronization is turned on.  The second part of the
+"Paranoia" patch ignores scratches in the read bitstream and
+syncronizes using the data that can still be "trusted".  This step
+also collects first-pass scratch detection information used by the
+third section of the patch.
+
+Expect performance to drop through the floor on a badly scratched CD;
+the code can no longer use a simple case of exact matching for speedy
+correlation.  Maintaining solid sync across a scratch is processor
+bound; later I'll add speedier algorithms for correlation than the
+brute force method currently used.  Scratch detection imposes little
+additional overhead on a non-scratched CD.
+
+3) scratch repair -----------------------------------------------------
+
+Scratches are an irrevocable loss of data.  Still, it's usually
+possible to reconstruct a sample closer to the original data than the
+raw hissing, fluttering and crackling that severe scratches in the CD
+surface produce.
+
+Scratch filtering is the 'hard part' of this patch.  It needs to do
+two things; first, find the 'pops' that escaped detection in section 2
+of the patch and secondly fill in the gaps.  Both are acheived using
+delta (slew) averaging and forward and backward linear predictive
+interpolation (with IIR filters) to fill in known gaps as well as look
+for 'problem values' in stretches of sample known to be scratched.
+
+THE SCRATCH DETECTION IS NOT PERFECT.  Nor is the repair perfect,
+although it is easier than detecting scratches reliably.  Both are
+cases of coming arbitrarily close to perfection; Paranoia is designed
+with light to moderate damage in mind, but will still recover a
+listenable sample from heavy damage.  
+
+Paranoia still has quite a bit of room for improvement in the scratch
+repair code... If cdda2wav + Paranoia is not doing an acceptable job
+on CDs that you just gotta have, drop me a line; I didn't want to sink
+months into a project I wasn't certain anyone would ever use :-)
+
+Monty
+
diff --git a/libparanoia/cdda_paranoia.h b/libparanoia/cdda_paranoia.h
new file mode 100644 (file)
index 0000000..24a2411
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)cdda_paranoia.h 1.20 04/02/20 J. Schilling from cdparanoia-III-alpha9.8 */
+/*
+ *     Modifications to make the code portable Copyright (c) 2002 J. Schilling
+ */
+/*
+ * CopyPolicy: GNU Public License 2 applies
+ * Copyright (C) by Monty (xiphmont@mit.edu)
+ *
+ */
+
+#ifndef        _CDROM_PARANOIA_H
+#define        _CDROM_PARANOIA_H
+
+#ifndef _MCONFIG_H
+#include <mconfig.h>
+#endif
+#ifndef _UTYPES_H
+#include <utypes.h>
+#endif
+
+#ifndef        __GNUC__
+#define        inline
+#endif
+
+#define        CD_FRAMESIZE_RAW                2352
+#define        CD_FRAMEWORDS                   (CD_FRAMESIZE_RAW/2)
+
+/*
+ * Second parameter of the callback function
+ */
+#define        PARANOIA_CB_READ                 0      /* Read off adjust ??? */
+#define        PARANOIA_CB_VERIFY               1      /* Verifying jitter */
+#define        PARANOIA_CB_FIXUP_EDGE           2      /* Fixed edge jitter */
+#define        PARANOIA_CB_FIXUP_ATOM           3      /* Fixed atom jitter */
+#define        PARANOIA_CB_SCRATCH              4      /* Unsupported */
+#define        PARANOIA_CB_REPAIR               5      /* Unsupported */
+#define        PARANOIA_CB_SKIP                 6      /* Skip exhausted retry */
+#define        PARANOIA_CB_DRIFT                7      /* Drift detected */
+#define        PARANOIA_CB_BACKOFF              8      /* Unsupported */
+#define        PARANOIA_CB_OVERLAP              9      /* Dyn Overlap adjust */
+#define        PARANOIA_CB_FIXUP_DROPPED       10      /* Fixed dropped bytes */
+#define        PARANOIA_CB_FIXUP_DUPED         11      /* Fixed duplicate bytes */
+#define        PARANOIA_CB_READERR             12      /* Hard read error */
+
+/*
+ * Cdparanoia modes to be set with paranoia_modeset()
+ */
+#define        PARANOIA_MODE_FULL               0xFF
+#define        PARANOIA_MODE_DISABLE            0
+
+#define        PARANOIA_MODE_VERIFY             1      /* Verify data integrity in overlap area */
+#define        PARANOIA_MODE_FRAGMENT           2      /* unsupported */
+#define        PARANOIA_MODE_OVERLAP            4      /* Perform overlapped reads */
+#define        PARANOIA_MODE_SCRATCH            8      /* unsupported */
+#define        PARANOIA_MODE_REPAIR            16      /* unsupported */
+#define        PARANOIA_MODE_NEVERSKIP         32      /* Do not skip failed reads (retry maxretries) */
+
+
+#ifndef        CDP_COMPILE
+typedef        void    cdrom_paranoia;
+#endif
+
+/*
+ * The interface from libcdparanoia to the high level caller
+ */
+extern cdrom_paranoia  *paranoia_init(void * d, int nsectors);
+extern void    paranoia_dynoverlapset(cdrom_paranoia * p, int minoverlap, 
+                                                                                         int maxoverlap);
+extern void    paranoia_modeset(cdrom_paranoia * p, int mode);
+extern long    paranoia_seek(cdrom_paranoia * p, long seek, int mode);
+extern Int16_t *paranoia_read(cdrom_paranoia * p, void (*callback) (long, int));
+extern Int16_t *paranoia_read_limited(cdrom_paranoia * p, 
+                                                                                                 void (*callback) (long, int), 
+                                                                                                 int maxretries);
+extern void    paranoia_free(cdrom_paranoia * p);
+extern void    paranoia_overlapset(cdrom_paranoia * p, long overlap);
+
+#ifndef        HAVE_MEMMOVE
+#define        memmove(dst, src, size)         movebytes((src), (dst), (size))
+#endif
+
+
+/*
+ * The callback interface from libparanoia to the CD-ROM interface
+ */
+extern long    cdda_disc_firstsector(void *d);         /* -> long sector */
+extern long    cdda_disc_lastsector(void *d);          /* -> long sector */
+/* -> long sectors */
+extern long    cdda_read(void *d, void *buffer, long beginsector, long sectors);       
+extern int     cdda_sector_gettrack(void *d, long sector);     /* -> int trackno */
+extern int     cdda_track_audiop(void *d, int track);  /* -> int Is audiotrack */
+extern long    cdda_track_firstsector(void *d, int track);     /* -> long sector */
+extern long    cdda_track_lastsector(void *d, int track);      /* -> long sector */
+extern int     cdda_tracks(void *d);           /* -> int tracks */
+
+#endif /* _CDROM_PARANOIA_H */
diff --git a/libparanoia/gap.c b/libparanoia/gap.c
new file mode 100644 (file)
index 0000000..6bb1b92
--- /dev/null
@@ -0,0 +1,244 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)gap.c   1.12 04/02/18 J. Schilling from cdparanoia-III-alpha9.8 */
+/*
+ *     Modifications to make the code portable Copyright (c) 2002 J. Schilling
+ */
+/*
+ * CopyPolicy: GNU Public License 2 applies
+ * Copyright (C) by Monty (xiphmont@mit.edu)
+ *
+ * Gapa analysis support code for paranoia
+ *
+ */
+
+#include <mconfig.h>
+#include <standard.h>
+#include <utypes.h>
+#include <strdefs.h>
+#include "p_block.h"
+#include "cdda_paranoia.h"
+#include "gap.h"
+
+long i_paranoia_overlap_r(Int16_t * buffA, Int16_t * buffB, long offsetA, 
+                                                                 long offsetB);
+long i_paranoia_overlap_f(Int16_t * buffA, Int16_t * buffB, long offsetA, 
+                                                                 long offsetB, long sizeA, long sizeB);
+int i_stutter_or_gap(Int16_t * A, Int16_t * B, long offA, long offB, long gap);
+void i_analyze_rift_f(Int16_t * A, Int16_t * B, 
+                                                   long sizeA, long sizeB, 
+                                                        long aoffset, long boffset, 
+                                                        long *matchA, long *matchB, long *matchC);
+void i_analyze_rift_r(Int16_t * A, Int16_t * B,
+                      long sizeA, long sizeB,
+                      long aoffset, long boffset,
+                      long *matchA, long *matchB, long *matchC);
+void analyze_rift_silence_f(Int16_t * A, Int16_t * B,
+                            long sizeA, long sizeB,
+                            long aoffset, long boffset,
+                            long *matchA, long *matchB);
+
+/*
+ * Gap analysis code
+ */
+long i_paranoia_overlap_r(Int16_t *buffA, Int16_t *buffB, long offsetA, 
+                          long offsetB)
+{
+       long            beginA = offsetA;
+       long            beginB = offsetB;
+
+       for (; beginA >= 0 && beginB >= 0; beginA--, beginB--)
+               if (buffA[beginA] != buffB[beginB])
+                       break;
+       beginA++;
+       beginB++;
+
+       return (offsetA - beginA);
+}
+
+long i_paranoia_overlap_f(Int16_t *buffA, Int16_t *buffB, long offsetA, 
+                          long offsetB, long sizeA, long sizeB)
+{
+       long            endA = offsetA;
+       long            endB = offsetB;
+
+       for (; endA < sizeA && endB < sizeB; endA++, endB++)
+               if (buffA[endA] != buffB[endB])
+                       break;
+
+       return (endA - offsetA);
+}
+
+int i_stutter_or_gap(Int16_t *A, Int16_t *B, long offA, long offB, long gap)
+{
+       long            a1 = offA;
+       long            b1 = offB;
+
+       if (a1 < 0) {
+               b1 -= a1;
+               gap += a1;
+               a1 = 0;
+       }
+       return (memcmp(A + a1, B + b1, gap * 2));
+}
+
+/*
+ * riftv is the first value into the rift -> or <-
+ */
+void i_analyze_rift_f(Int16_t *A, Int16_t *B, long sizeA, long sizeB,
+                      long aoffset, long boffset, long *matchA, long *matchB, 
+                      long *matchC)
+{
+
+       long            apast = sizeA - aoffset;
+       long            bpast = sizeB - boffset;
+       long            i;
+
+       *matchA = 0, *matchB = 0, *matchC = 0;
+
+       /*
+        * Look for three possible matches... (A) Ariftv->B,
+        * (B) Briftv->A and (c) AB->AB.
+        */
+       for (i = 0; ; i++) {
+               if (i < bpast)  /* A */
+                       if (i_paranoia_overlap_f(A, B, aoffset, boffset + i, sizeA, sizeB) >= MIN_WORDS_RIFT) {
+                               *matchA = i;
+                               break;
+                       }
+               if (i < apast) {        /* B */
+                       if (i_paranoia_overlap_f(A, B, aoffset + i, boffset, sizeA, sizeB) >= MIN_WORDS_RIFT) {
+                               *matchB = i;
+                               break;
+                       }
+                       if (i < bpast)  /* C */
+                               if (i_paranoia_overlap_f(A, B, aoffset + i, boffset + i, sizeA, sizeB) >= MIN_WORDS_RIFT) {
+                                       *matchC = i;
+                                       break;
+                               }
+               } else if (i >= bpast)
+                       break;
+
+       }
+
+       if (*matchA == 0 && *matchB == 0 && *matchC == 0)
+               return;
+
+       if (*matchC)
+               return;
+       if (*matchA) {
+               if (i_stutter_or_gap(A, B, aoffset - *matchA, boffset, *matchA))
+                       return;
+               *matchB = -*matchA;     /* signify we need to remove n bytes */
+                                       /* from B */
+               *matchA = 0;
+               return;
+       } else {
+               if (i_stutter_or_gap(B, A, boffset - *matchB, aoffset, *matchB))
+                       return;
+               *matchA = -*matchB;
+               *matchB = 0;
+               return;
+       }
+}
+
+/*
+ * riftv must be first even val of rift moving back
+ */
+void i_analyze_rift_r(Int16_t *A, Int16_t *B, long sizeA, long sizeB, 
+                      long aoffset, long boffset, long *matchA, long *matchB, 
+                      long *matchC)
+{
+
+       long            apast = aoffset + 1;
+       long            bpast = boffset + 1;
+       long            i;
+
+       *matchA = 0, *matchB = 0, *matchC = 0;
+
+       /*
+        * Look for three possible matches... (A) Ariftv->B, (B) Briftv->A and
+        * (c) AB->AB.
+        */
+       for (i = 0; ; i++) {
+               if (i < bpast)  /* A */
+                       if (i_paranoia_overlap_r(A, B, aoffset, boffset - i) >= MIN_WORDS_RIFT) {
+                               *matchA = i;
+                               break;
+                       }
+               if (i < apast) {        /* B */
+                       if (i_paranoia_overlap_r(A, B, aoffset - i, boffset) >= MIN_WORDS_RIFT) {
+                               *matchB = i;
+                               break;
+                       }
+                       if (i < bpast)  /* C */
+                               if (i_paranoia_overlap_r(A, B, aoffset - i, boffset - i) >= MIN_WORDS_RIFT) {
+                                       *matchC = i;
+                                       break;
+                               }
+               } else if (i >= bpast)
+                       break;
+
+       }
+
+       if (*matchA == 0 && *matchB == 0 && *matchC == 0)
+               return;
+
+       if (*matchC)
+               return;
+
+       if (*matchA) {
+               if (i_stutter_or_gap(A, B, aoffset + 1, boffset - *matchA + 1, *matchA))
+                       return;
+               *matchB = -*matchA;     /* signify we need to remove n bytes */
+                                       /* from B */
+               *matchA = 0;
+               return;
+       } else {
+               if (i_stutter_or_gap(B, A, boffset + 1, aoffset - *matchB + 1, *matchB))
+                       return;
+               *matchA = -*matchB;
+               *matchB = 0;
+               return;
+       }
+}
+
+void analyze_rift_silence_f(Int16_t *A, Int16_t *B, long sizeA, long sizeB, 
+                            long aoffset, long boffset, long *matchA, 
+                            long *matchB)
+{
+       *matchA = -1;
+       *matchB = -1;
+
+       sizeA = min(sizeA, aoffset + MIN_WORDS_RIFT);
+       sizeB = min(sizeB, boffset + MIN_WORDS_RIFT);
+
+       aoffset++;
+       boffset++;
+
+       while (aoffset < sizeA) {
+               if (A[aoffset] != A[aoffset - 1]) {
+                       *matchA = 0;
+                       break;
+               }
+               aoffset++;
+       }
+
+       while (boffset < sizeB) {
+               if (B[boffset] != B[boffset - 1]) {
+                       *matchB = 0;
+                       break;
+               }
+               boffset++;
+       }
+}
diff --git a/libparanoia/gap.h b/libparanoia/gap.h
new file mode 100644 (file)
index 0000000..f772ae3
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)gap.h   1.10 04/02/18 J. Schilling from cdparanoia-III-alpha9.8 */
+/*
+ *     Modifications to make the code portable Copyright (c) 2002 J. Schilling
+ */
+/*
+ * CopyPolicy: GNU Public License 2 applies
+ * Copyright (C) by Monty (xiphmont@mit.edu)
+ */
+
+#ifndef        _GAP_H_
+#define        _GAP_H_
+
+extern long    i_paranoia_overlap_r(Int16_t * buffA, Int16_t * buffB,
+                                                                                       long offsetA, long offsetB);
+extern long    i_paranoia_overlap_f(Int16_t * buffA, Int16_t * buffB,
+                                                                                       long offsetA, long offsetB,
+                                                                                       long sizeA, long sizeB);
+extern int     i_stutter_or_gap(Int16_t * A, Int16_t * B,
+                                                                         long offA, long offB,
+                                                                         long gap);
+extern void    i_analyze_rift_f(Int16_t * A, Int16_t * B,
+                                                                         long sizeA, long sizeB,
+                                                                         long aoffset, long boffset,
+                                                                         long *matchA, long *matchB, long *matchC);
+extern void    i_analyze_rift_r(Int16_t * A, Int16_t * B,
+                                                                         long sizeA, long sizeB,
+                                                                         long aoffset, long boffset,
+                                                                         long *matchA, long *matchB, long *matchC);
+extern void    analyze_rift_silence_f(Int16_t * A, Int16_t * B,
+                                                                                         long sizeA, long sizeB,
+                                                                                         long aoffset, long boffset,
+                                                                                         long *matchA, long *matchB);
+
+#endif
diff --git a/libparanoia/isort.c b/libparanoia/isort.c
new file mode 100644 (file)
index 0000000..a3d38ad
--- /dev/null
@@ -0,0 +1,159 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)isort.c 1.14 04/02/20 J. Schilling from cdparanoia-III-alpha9.8 */
+/*
+ *     Modifications to make the code portable Copyright (c) 2002 J. Schilling
+ */
+/*
+ * CopyPolicy: GNU Public License 2 applies
+ * Copyright (C) by Monty (xiphmont@mit.edu)
+ *
+ * sorted vector abstraction for paranoia
+ *
+ */
+
+/*
+ * Old isort got a bit complex.  This re-constrains complexity to
+ * give a go at speed through a more alpha-6-like mechanism.
+ */
+
+#include <mconfig.h>
+#include <stdxlib.h>
+#include <standard.h>
+#include <utypes.h>
+#include <strdefs.h>
+#include "p_block.h"
+#include "isort.h"
+#include "pmalloc.h"
+
+sort_info *sort_alloc(long size);
+void sort_unsortall(sort_info * i);
+void sort_free(sort_info * i);
+void sort_sort(sort_info * i, long sortlo, long sorthi);
+void sort_setup(sort_info * i, Int16_t * vector, long *abspos, long size, 
+                                        long sortlo, long sorthi);
+sort_link *sort_getmatch(sort_info * i, long post, long overlap, int value);
+sort_link *sort_nextmatch(sort_info * i, sort_link * prev);
+
+
+sort_info *sort_alloc(long size)
+{
+       sort_info       *ret = _pcalloc(1, sizeof (sort_info));
+
+       ret->vector = NULL;
+       ret->sortbegin = -1;
+       ret->size = -1;
+       ret->maxsize = size;
+
+       ret->head = _pcalloc(65536, sizeof (sort_link *));
+       ret->bucketusage = _pmalloc(65536 * sizeof (long));
+       ret->revindex = _pcalloc(size, sizeof (sort_link));
+       ret->lastbucket = 0;
+
+       return (ret);
+}
+
+void sort_unsortall(sort_info *i)
+{
+       if (i->lastbucket > 2000) {     /* a guess */
+               memset(i->head, 0, 65536 * sizeof (sort_link *));
+       } else {
+               long    b;
+
+               for (b = 0; b < i->lastbucket; b++)
+                       i->head[i->bucketusage[b]] = NULL;
+       }
+
+       i->lastbucket = 0;
+       i->sortbegin = -1;
+}
+
+void sort_free(sort_info *i)
+{
+       _pfree(i->revindex);
+       _pfree(i->head);
+       _pfree(i->bucketusage);
+       _pfree(i);
+}
+
+void sort_sort(sort_info *i, long sortlo, long sorthi)
+{
+       long    j;
+
+       for (j = sorthi - 1; j >= sortlo; j--) {
+               sort_link       **hv = i->head + i->vector[j] + 32768;
+               sort_link        *l = i->revindex + j;
+
+               if (*hv == NULL) {
+                       i->bucketusage[i->lastbucket] = i->vector[j] + 32768;
+                       i->lastbucket++;
+               }
+               l->next = *hv;
+               *hv = l;
+       }
+       i->sortbegin = 0;
+}
+
+/*
+ * size *must* be less than i->maxsize
+ */
+void sort_setup(sort_info *i, Int16_t *vector, long *abspos, long size, 
+                long sortlo, long sorthi)
+{
+       if (i->sortbegin != -1)
+               sort_unsortall(i);
+
+       i->vector = vector;
+       i->size = size;
+       i->abspos = abspos;
+
+       i->lo = min(size, max(sortlo - *abspos, 0));
+       i->hi = max(0, min(sorthi - *abspos, size));
+}
+
+sort_link *sort_getmatch(sort_info *i, long post, long overlap, int value)
+{
+       sort_link       *ret;
+
+       if (i->sortbegin == -1)
+               sort_sort(i, i->lo, i->hi);
+       /*
+        * Now we reuse lo and hi
+        */
+       post = max(0, min(i->size, post));
+       i->val = value + 32768;
+       i->lo = max(0, post - overlap);         /* absolute position */
+       i->hi = min(i->size, post + overlap);   /* absolute position */
+
+       ret = i->head[i->val];
+       while (ret) {
+               if (ipos(i, ret) < i->lo) {
+                       ret = ret->next;
+               } else {
+                       if (ipos(i, ret) >= i->hi)
+                               ret = NULL;
+                       break;
+               }
+       }
+/*     i->head[i->val]=ret; */
+       return (ret);
+}
+
+sort_link *sort_nextmatch(sort_info *i, sort_link *prev)
+{
+       sort_link       *ret = prev->next;
+
+       if (!ret || ipos(i, ret) >= i->hi)
+               return (NULL);
+       return (ret);
+}
diff --git a/libparanoia/isort.h b/libparanoia/isort.h
new file mode 100644 (file)
index 0000000..1b6661c
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)isort.h 1.10 04/02/18 J. Schilling from cdparanoia-III-alpha9.8 */
+/*
+ *     Modifications to make the code portable Copyright (c) 2002 J. Schilling
+ */
+/*
+ * CopyPolicy: GNU Public License 2 applies
+ * Copyright (C) by Monty (xiphmont@mit.edu)
+ */
+
+#ifndef        _ISORT_H_
+#define        _ISORT_H_
+
+typedef struct sort_link {
+       struct sort_link *next;
+} sort_link;
+
+typedef struct sort_info {
+       Int16_t         *vector;        /* vector */
+                                       /* vec storage doesn't belong to us */
+
+       long            *abspos;        /* pointer for side effects */
+       long            size;           /* vector size */
+
+       long            maxsize;        /* maximum vector size */
+
+       long            sortbegin;      /* range of contiguous sorted area */
+       long            lo;
+       long            hi;             /* current post, overlap range */
+       int             val;            /* ...and val */
+
+       /*
+        * sort structs
+        */
+       sort_link       **head;         /* sort buckets (65536) */
+
+       long            *bucketusage;   /* of used buckets (65536) */
+       long            lastbucket;
+       sort_link       *revindex;
+
+} sort_info;
+
+extern sort_info       *sort_alloc(long size);
+extern void            sort_unsortall(sort_info * i);
+extern void            sort_setup(sort_info * i, Int16_t * vector, long *abspos, 
+                                                                 long size, long sortlo, long sorthi);
+extern void            sort_free(sort_info * i);
+extern sort_link       *sort_getmatch(sort_info * i, long post, long overlap, 
+                                                                                       int value);
+extern sort_link       *sort_nextmatch(sort_info * i, sort_link * prev);
+
+#define        is(i)           ((i)->size)
+#define        ib(i)           (*(i)->abspos)
+#define        ie(i)           ((i)->size + *(i)->abspos)
+#define        iv(i)           ((i)->vector)
+#define        ipos(i, l)      ((l) - (i)->revindex)
+
+#endif
diff --git a/libparanoia/overlap.c b/libparanoia/overlap.c
new file mode 100644 (file)
index 0000000..6f15baf
--- /dev/null
@@ -0,0 +1,228 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)overlap.c       1.11 04/02/20 J. Schilling from cdparanoia-III-alpha9.8 */
+/*
+ *     Modifications to make the code portable Copyright (c) 2002 J. Schilling
+ */
+/*
+ * CopyPolicy: GNU Public License 2 applies
+ * Copyright (C) by Monty (xiphmont@mit.edu)
+ *
+ * Statistic code and cache management for overlap settings
+ *
+ */
+
+#include <mconfig.h>
+#include <stdxlib.h>
+#include <standard.h>
+#include <utypes.h>
+#include "p_block.h"
+#include "cdda_paranoia.h"
+#include "overlap.h"
+#include "isort.h"
+
+void paranoia_resetcache(cdrom_paranoia *p);
+void paranoia_resetall(cdrom_paranoia *p);
+void i_paranoia_trim(cdrom_paranoia *p, long beginword, long endword);
+void offset_adjust_settings(cdrom_paranoia *p, void (*callback)(long, int));
+void offset_add_value(cdrom_paranoia *p, offsets *o, long value, 
+                                                        void (*callback)(long, int));
+
+/*
+ * Internal cache management
+ */
+void paranoia_resetcache(cdrom_paranoia *p)
+{
+       c_block         *c = c_first(p);
+       v_fragment      *v;
+
+       while (c) {
+               free_c_block(c);
+               c = c_first(p);
+       }
+
+       v = v_first(p);
+       while (v) {
+               free_v_fragment(v);
+               v = v_first(p);
+       }
+}
+
+void paranoia_resetall(cdrom_paranoia *p)
+{
+       p->root.returnedlimit = 0;
+       p->dyndrift = 0;
+       p->root.lastsector = 0;
+
+       if (p->root.vector) {
+               i_cblock_destructor(p->root.vector);
+               p->root.vector = NULL;
+       }
+       paranoia_resetcache(p);
+}
+
+void i_paranoia_trim(cdrom_paranoia *p, long beginword, long endword)
+{
+       root_block      *root = &(p->root);
+
+       if (root->vector != NULL) {
+               long    target = beginword - p->maxdynoverlap;
+               long    rbegin = cb(root->vector);
+               long    rend = ce(root->vector);
+
+               if (rbegin > beginword)
+                       goto rootfree;
+
+               if (rbegin + p->maxdynoverlap < beginword) {
+                       if (target + MIN_WORDS_OVERLAP > rend)
+                               goto rootfree;
+
+                       {
+                               long    offset = target - rbegin;
+
+                               c_removef(root->vector, offset);
+                       }
+               } {
+                       c_block *c = c_first(p);
+
+                       while (c) {
+                               c_block *next = c_next(c);
+
+                               if (ce(c) < beginword - p->maxdynoverlap)
+                                       free_c_block(c);
+                               c = next;
+                       }
+               }
+
+       }
+       return;
+
+rootfree:
+
+       i_cblock_destructor(root->vector);
+       root->vector = NULL;
+       root->returnedlimit = -1;
+       root->lastsector = 0;
+
+}
+
+/*
+ * Statistical and heuristic[al? :-] management
+ */
+void offset_adjust_settings(cdrom_paranoia *p, void (*callback)(long, int))
+{
+       if (p->stage2.offpoints >= 10) {
+               /*
+                * drift: look at the average offset value.  If it's over one
+                * sector, frob it.  We just want a little hysteresis [sp?]
+                */
+               long    av = (p->stage2.offpoints ? p->stage2.offaccum / p->stage2.offpoints : 0);
+
+               if (abs(av) > p->dynoverlap / 4) {
+                       av = (av / MIN_SECTOR_EPSILON) * MIN_SECTOR_EPSILON;
+
+                       if (callback)
+                               (*callback) (ce(p->root.vector), PARANOIA_CB_DRIFT);
+                       p->dyndrift += av;
+
+                       /*
+                        * Adjust all the values in the cache otherwise we get
+                        * a (potentially unstable) feedback loop
+                        */
+                       {
+                               c_block         *c = c_first(p);
+                               v_fragment      *v = v_first(p);
+
+                               while (v && v->one) {
+                                       /*
+                                        * safeguard beginning bounds case with
+                                        * a hammer
+                                        */
+                                       if (fb(v) < av || cb(v->one) < av) {
+                                               v->one = NULL;
+                                       } else {
+                                               fb(v) -= av;
+                                       }
+                                       v = v_next(v);
+                               }
+                               while (c) {
+                                       long    adj = min(av, cb(c));
+
+                                       c_set(c, cb(c) - adj);
+                                       c = c_next(c);
+                               }
+                       }
+
+                       p->stage2.offaccum = 0;
+                       p->stage2.offmin = 0;
+                       p->stage2.offmax = 0;
+                       p->stage2.offpoints = 0;
+                       p->stage2.newpoints = 0;
+                       p->stage2.offdiff = 0;
+               }
+       }
+       if (p->stage1.offpoints >= 10) {
+               /*
+                * dynoverlap: we arbitrarily set it to 4x the running
+                * difference value, unless min/max are more
+                */
+               p->dynoverlap = (p->stage1.offpoints ? p->stage1.offdiff /
+                       p->stage1.offpoints * 3 : CD_FRAMEWORDS);
+
+               if (p->dynoverlap < -p->stage1.offmin * 1.5)
+                       p->dynoverlap = -p->stage1.offmin * 1.5;
+
+               if (p->dynoverlap < p->stage1.offmax * 1.5)
+                       p->dynoverlap = p->stage1.offmax * 1.5;
+
+               if (p->dynoverlap < p->mindynoverlap)
+                       p->dynoverlap = p->mindynoverlap;
+               if (p->dynoverlap > p->maxdynoverlap)
+                       p->dynoverlap = p->maxdynoverlap;
+
+               if (callback)
+                       (*callback) (p->dynoverlap, PARANOIA_CB_OVERLAP);
+
+               if (p->stage1.offpoints > 600) {
+                       /*
+                        * bit of a bug; this routine is called too often
+                        * due to the overlap mesh alg we use in stage 1
+                        */
+                       p->stage1.offpoints /= 1.2;
+                       p->stage1.offaccum /= 1.2;
+                       p->stage1.offdiff /= 1.2;
+               }
+               p->stage1.offmin = 0;
+               p->stage1.offmax = 0;
+               p->stage1.newpoints = 0;
+       }
+}
+
+void offset_add_value(cdrom_paranoia *p, offsets *o, long value, 
+                      void (*callback)(long, int))
+{
+       if (o->offpoints != -1) {
+
+               o->offdiff += abs(value);
+               o->offpoints++;
+               o->newpoints++;
+               o->offaccum += value;
+               if (value < o->offmin)
+                       o->offmin = value;
+               if (value > o->offmax)
+                       o->offmax = value;
+
+               if (o->newpoints >= 10)
+                       offset_adjust_settings(p, callback);
+       }
+}
diff --git a/libparanoia/overlap.h b/libparanoia/overlap.h
new file mode 100644 (file)
index 0000000..44db6e2
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)overlap.h       1.7 04/02/18 J. Schilling from cdparanoia-III-alpha9.8 */
+/*
+ *     Modifications to make the code portable Copyright (c) 2002 J. Schilling
+ */
+/*
+ * CopyPolicy: GNU Public License 2 applies
+ * Copyright (C) by Monty (xiphmont@mit.edu)
+ */
+
+#ifndef        _OVERLAP_H_
+#define        _OVERLAP_H_
+
+extern void    paranoia_resetcache(cdrom_paranoia *p);
+extern void    paranoia_resetall(cdrom_paranoia *p);
+extern void    i_paranoia_trim(cdrom_paranoia *p, long beginword, long endword);
+extern void    offset_adjust_settings(cdrom_paranoia *p,
+                                                                                                 void (*callback) (long, int));
+extern void    offset_add_value(cdrom_paranoia *p, offsets *o, long value,
+                                                                                 void (*callback) (long, int));
+
+#endif
diff --git a/libparanoia/overlapdef.txt b/libparanoia/overlapdef.txt
new file mode 100644 (file)
index 0000000..3aff6cf
--- /dev/null
@@ -0,0 +1,20 @@
+# @(#)overlapdef.txt   1.1 98/08/19 J. Schilling from Monty (xiphmont@mit.edu)
+
+  0          70    100
+A |----------|-----|
+B      |-----|---------|
+       0     40        100
+
+offset=-30
+begin=30
+end=100
+
+  0          70    100
+A |----------|-----|
+B      |-----|---------|
+       50    90        150
+
+offset=20
+begin=30
+end=100
+
diff --git a/libparanoia/p_block.c b/libparanoia/p_block.c
new file mode 100644 (file)
index 0000000..e37334b
--- /dev/null
@@ -0,0 +1,474 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)p_block.c       1.19 04/02/23 J. Schilling from cdparanoia-III-alpha9.8 */
+/*
+ *     Modifications to make the code portable Copyright (c) 2002 J. Schilling
+ */
+#include <mconfig.h>
+#include <stdxlib.h>
+#include <standard.h>
+#include <utypes.h>
+#include <strdefs.h>
+#include "p_block.h"
+#include "cdda_paranoia.h"
+#include "pmalloc.h"
+
+linked_list    *new_list(void *(*newp) (void), void (*freep) (void *));
+linked_element *add_elem(linked_list *l, void *elem);
+linked_element *new_elem(linked_list *list);
+void                           free_elem(linked_element *e, int free_ptr);
+void                           free_list(linked_list *list, int free_ptr);
+void                           *get_elem(linked_element *e);
+linked_list    *copy_list(linked_list *list);
+static c_block *i_cblock_constructor(void);
+void                           i_cblock_destructor(c_block *c);
+c_block                        *new_c_block(cdrom_paranoia *p);
+void                           free_c_block(c_block *c);
+static v_fragment *i_vfragment_constructor(void);
+static void    i_v_fragment_destructor(v_fragment *v);
+v_fragment             *new_v_fragment(cdrom_paranoia *p, c_block *one, long begin, 
+                                                                                long end, int last);
+void                           free_v_fragment(v_fragment *v);
+c_block                        *c_first(cdrom_paranoia *p);
+c_block                        *c_last(cdrom_paranoia *p);
+c_block                        *c_next(c_block *c);
+c_block                        *c_prev(c_block *c);
+v_fragment             *v_first(cdrom_paranoia *p);
+v_fragment             *v_last(cdrom_paranoia *p);
+v_fragment             *v_next(v_fragment *v);
+v_fragment             *v_prev(v_fragment *v);
+void                           recover_cache(cdrom_paranoia *p);
+Int16_t                        *v_buffer(v_fragment *v);
+c_block                        *c_alloc(Int16_t *vector, long begin, long size);
+void                           c_set(c_block *v, long begin);
+void                           c_remove(c_block *v, long cutpos, long cutsize);
+void                           c_overwrite(c_block *v, long pos, Int16_t *b, long size);
+void                           c_append(c_block *v, Int16_t *vector, long size);
+void                           c_removef(c_block *v, long cut);
+void                           i_paranoia_firstlast(cdrom_paranoia *p);
+cdrom_paranoia *paranoia_init(void *d, int nsectors);
+
+
+linked_list *new_list(void *(*newp)(void), void (*freep)(void *))
+{
+       linked_list     *ret = _pcalloc(1, sizeof (linked_list));
+
+       ret->new_poly = newp;
+       ret->free_poly = freep;
+       return (ret);
+}
+
+linked_element *add_elem(linked_list *l, void *elem)
+{
+
+       linked_element  *ret = _pcalloc(1, sizeof (linked_element));
+
+       ret->stamp = l->current++;
+       ret->ptr = elem;
+       ret->list = l;
+
+       if (l->head)
+               l->head->prev = ret;
+       else
+               l->tail = ret;
+       ret->next = l->head;
+       ret->prev = NULL;
+       l->head = ret;
+       l->active++;
+
+       return (ret);
+}
+
+linked_element *new_elem(linked_list *list)
+{
+       void            *new = list->new_poly();
+
+       return (add_elem(list, new));
+}
+
+void free_elem(linked_element *e, int free_ptr)
+{
+       linked_list     *l = e->list;
+
+       if (free_ptr)
+               l->free_poly(e->ptr);
+
+       if (e == l->head)
+               l->head = e->next;
+       if (e == l->tail)
+               l->tail = e->prev;
+
+       if (e->prev)
+               e->prev->next = e->next;
+       if (e->next)
+               e->next->prev = e->prev;
+
+       l->active--;
+       _pfree(e);
+}
+
+void free_list(linked_list *list, int free_ptr)
+{
+       while (list->head)
+               free_elem(list->head, free_ptr);
+       _pfree(list);
+}
+
+void *get_elem(linked_element *e)
+{
+       return (e->ptr);
+}
+
+linked_list *copy_list(linked_list *list)
+{
+       linked_list     *new = new_list(list->new_poly, list->free_poly);
+       linked_element  *i = list->tail;
+
+       while (i) {
+               add_elem(new, i->ptr);
+               i = i->prev;
+       }
+       return (new);
+}
+
+/**** C_block stuff ******************************************************/
+
+#define        vp_cblock_constructor_func ((void*(*)(void))i_cblock_constructor)
+static c_block *i_cblock_constructor()
+{
+       c_block         *ret = _pcalloc(1, sizeof (c_block));
+
+       return (ret);
+}
+
+#define        vp_cblock_destructor_func ((void(*)(void*))i_cblock_destructor)
+void i_cblock_destructor(c_block *c)
+{
+       if (c) {
+               if (c->vector)
+                       _pfree(c->vector);
+               if (c->flags)
+                       _pfree(c->flags);
+               c->e = NULL;
+               _pfree(c);
+       }
+}
+
+c_block *new_c_block(cdrom_paranoia *p)
+{
+       linked_element  *e = new_elem(p->cache);
+       c_block         *c = e->ptr;
+
+       c->e = e;
+       c->p = p;
+       return (c);
+}
+
+void free_c_block(c_block *c)
+{
+       /*
+        * also rid ourselves of v_fragments that reference this block
+        */
+       v_fragment              *v = v_first(c->p);
+
+       while (v) {
+               v_fragment      *next = v_next(v);
+
+               if (v->one == c)
+                       free_v_fragment(v);
+               v = next;
+       }
+
+       free_elem(c->e, 1);
+}
+
+#define        vp_vfragment_constructor_func ((void*(*)(void))i_vfragment_constructor)
+static v_fragment *i_vfragment_constructor()
+{
+       v_fragment      *ret = _pcalloc(1, sizeof (v_fragment));
+
+       return (ret);
+}
+
+#define        vp_v_fragment_destructor_func ((void(*)(void*))i_v_fragment_destructor)
+static void i_v_fragment_destructor(v_fragment *v)
+{
+       _pfree(v);
+}
+
+v_fragment *new_v_fragment(cdrom_paranoia *p, c_block *one, long begin, 
+                           long end, int last)
+{
+       linked_element  *e = new_elem(p->fragments);
+       v_fragment      *b = e->ptr;
+
+       b->e = e;
+       b->p = p;
+
+       b->one = one;
+       b->begin = begin;
+       b->vector = one->vector + begin - one->begin;
+       b->size = end - begin;
+       b->lastsector = last;
+
+       return (b);
+}
+
+void free_v_fragment(v_fragment *v)
+{
+       free_elem(v->e, 1);
+}
+
+c_block *c_first(cdrom_paranoia *p)
+{
+       if (p->cache->head)
+               return (p->cache->head->ptr);
+       return (NULL);
+}
+
+c_block* c_last(cdrom_paranoia *p)
+{
+       if (p->cache->tail)
+               return (p->cache->tail->ptr);
+       return (NULL);
+}
+
+c_block *c_next(c_block *c)
+{
+       if (c->e->next)
+               return (c->e->next->ptr);
+       return (NULL);
+}
+
+c_block *c_prev(c_block *c)
+{
+       if (c->e->prev)
+               return (c->e->prev->ptr);
+       return (NULL);
+}
+
+v_fragment *v_first(cdrom_paranoia *p)
+{
+       if (p->fragments->head) {
+               return (p->fragments->head->ptr);
+       }
+       return (NULL);
+}
+
+v_fragment *v_last(cdrom_paranoia *p)
+{
+       if (p->fragments->tail)
+               return (p->fragments->tail->ptr);
+       return (NULL);
+}
+
+v_fragment *v_next(v_fragment *v)
+{
+       if (v->e->next)
+               return (v->e->next->ptr);
+       return (NULL);
+}
+
+v_fragment *v_prev(v_fragment *v)
+{
+       if (v->e->prev)
+               return (v->e->prev->ptr);
+       return (NULL);
+}
+
+void recover_cache(cdrom_paranoia *p)
+{
+       linked_list     *l = p->cache;
+
+       /*
+        * Are we at/over our allowed cache size?
+        */
+       while (l->active > p->cache_limit) {
+               /*
+                * cull from the tail of the list
+                */
+               free_c_block(c_last(p));
+       }
+
+}
+
+Int16_t *v_buffer(v_fragment *v)
+{
+       if (!v->one)
+               return (NULL);
+       if (!cv(v->one))
+               return (NULL);
+       return (v->vector);
+}
+
+/*
+ * alloc a c_block not on a cache list
+ */
+c_block *c_alloc(Int16_t *vector, long begin, long size)
+{
+       c_block         *c = _pcalloc(1, sizeof (c_block));
+
+       c->vector = vector;
+       c->begin = begin;
+       c->size = size;
+       return (c);
+}
+
+void c_set(c_block *v, long begin)
+{
+       v->begin = begin;
+}
+
+/*
+ * pos here is vector position from zero
+ */
+void c_insert(c_block *v, long pos, Int16_t *b, long size)
+{
+       int             vs = cs(v);
+
+       if (pos < 0 || pos > vs)
+               return;
+
+       if (v->vector)
+               v->vector = _prealloc(v->vector, sizeof (Int16_t) * (size + vs));
+       else
+               v->vector = _pmalloc(sizeof (Int16_t) * size);
+
+       if (pos < vs)
+               memmove(v->vector + pos + size, v->vector + pos,
+                       (vs - pos) * sizeof (Int16_t));
+       memcpy(v->vector + pos, b, size * sizeof (Int16_t));
+
+       v->size += size;
+}
+
+void c_remove(c_block *v, long cutpos, long cutsize)
+{
+       int             vs = cs(v);
+
+       if (cutpos < 0 || cutpos > vs)
+               return;
+       if (cutpos + cutsize > vs)
+               cutsize = vs - cutpos;
+       if (cutsize < 0)
+               cutsize = vs - cutpos;
+       if (cutsize < 1)
+               return;
+
+       memmove(v->vector + cutpos, v->vector + cutpos + cutsize,
+               (vs - cutpos - cutsize) * sizeof (Int16_t));
+
+       v->size -= cutsize;
+}
+
+void c_overwrite(c_block *v, long pos, Int16_t *b, long size)
+{
+       int             vs = cs(v);
+
+       if (pos < 0)
+               return;
+       if (pos + size > vs)
+               size = vs - pos;
+
+       memcpy(v->vector + pos, b, size * sizeof (Int16_t));
+}
+
+void c_append(c_block *v, Int16_t *vector, long size)
+{
+       int             vs = cs(v);
+
+       /*
+        * update the vector
+        */
+       if (v->vector)
+               v->vector = _prealloc(v->vector, sizeof (Int16_t) * (size + vs));
+       else
+               v->vector = _pmalloc(sizeof (Int16_t) * size);
+       memcpy(v->vector + vs, vector, sizeof (Int16_t) * size);
+
+       v->size += size;
+}
+
+void c_removef(c_block *v, long cut)
+{
+       c_remove(v, 0, cut);
+       v->begin += cut;
+}
+
+
+
+/*
+ * Initialization
+ */
+void i_paranoia_firstlast(cdrom_paranoia *p)
+{
+       int     i;
+       void    *d = p->d;
+
+       p->current_lastsector = -1;
+       for (i = cdda_sector_gettrack(d, p->cursor); i < cdda_tracks(d); i++)
+               if (!cdda_track_audiop(d, i))
+                       p->current_lastsector = cdda_track_lastsector(d, i - 1);
+       if (p->current_lastsector == -1)
+               p->current_lastsector = cdda_disc_lastsector(d);
+
+       p->current_firstsector = -1;
+       for (i = cdda_sector_gettrack(d, p->cursor); i > 0; i--)
+               if (!cdda_track_audiop(d, i))
+                       p->current_firstsector = cdda_track_firstsector(d, i + 1);
+       if (p->current_firstsector == -1)
+               p->current_firstsector = cdda_disc_firstsector(d);
+
+}
+
+cdrom_paranoia *paranoia_init(void *d, int nsectors)
+{
+       cdrom_paranoia  *p = _pcalloc(1, sizeof (cdrom_paranoia));
+
+       p->cache = new_list(vp_cblock_constructor_func,
+                               vp_cblock_destructor_func);
+
+       p->fragments = new_list(vp_vfragment_constructor_func,
+                               vp_v_fragment_destructor_func);
+
+       p->nsectors  = nsectors;
+       p->readahead = 150;
+       p->sortcache = sort_alloc(p->readahead * CD_FRAMEWORDS);
+       p->d = d;
+       p->mindynoverlap = MIN_SECTOR_EPSILON;
+       p->maxdynoverlap = MAX_SECTOR_OVERLAP * CD_FRAMEWORDS;
+       p->maxdynoverlap = (nsectors - 1) * CD_FRAMEWORDS;
+       p->dynoverlap = MAX_SECTOR_OVERLAP * CD_FRAMEWORDS;
+       p->cache_limit = JIGGLE_MODULO;
+       p->enable = PARANOIA_MODE_FULL;
+       p->cursor = cdda_disc_firstsector(d);
+       p->lastread = -1000000;
+
+       /*
+        * One last one... in case data and audio tracks are mixed...
+        */
+       i_paranoia_firstlast(p);
+
+       return (p);
+}
+
+void paranoia_dynoverlapset(cdrom_paranoia *p, int minoverlap, int maxoverlap)
+{
+       if (minoverlap >= 0)
+               p->mindynoverlap = minoverlap;
+       if (maxoverlap > minoverlap)
+               p->maxdynoverlap = maxoverlap;
+
+       if (p->maxdynoverlap < p->mindynoverlap)
+               p->maxdynoverlap = p->mindynoverlap;
+}
diff --git a/libparanoia/p_block.h b/libparanoia/p_block.h
new file mode 100644 (file)
index 0000000..418c193
--- /dev/null
@@ -0,0 +1,210 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)p_block.h       1.16 04/02/20 J. Schilling from cdparanoia-III-alpha9.8 */
+/*
+ *     Modifications to make the code portable Copyright (c) 2002 J. Schilling
+ */
+/*
+ * CopyPolicy: GNU Public License 2 applies
+ * Copyright (C) by Monty (xiphmont@mit.edu)
+ */
+
+#ifndef        _p_block_h_
+#define        _p_block_h_
+
+#define        MIN_WORDS_OVERLAP         64    /* 16 bit words */
+#define        MIN_WORDS_SEARCH          64    /* 16 bit words */
+#define        MIN_WORDS_RIFT            16    /* 16 bit words */
+#define        MAX_SECTOR_OVERLAP        32    /* sectors */
+#define        MIN_SECTOR_EPSILON       128    /* words */
+#define        MIN_SECTOR_BACKUP         16    /* sectors */
+#define        JIGGLE_MODULO             15    /* sectors */
+#define        MIN_SILENCE_BOUNDARY    1024    /* 16 bit words */
+
+#define        min(x, y) ((x) > (y)?(y):(x))
+#define        max(x, y) ((x) < (y)?(y):(x))
+
+#include "isort.h"
+
+typedef struct linked_list {
+       /* linked list */
+       struct linked_element   *head;
+       struct linked_element   *tail;
+
+       void                    *(*new_poly)(void);
+       void                    (*free_poly)(void *poly);
+       long                    current;
+       long                    active;
+
+} linked_list;
+
+typedef struct linked_element {
+       void                    *ptr;
+       struct linked_element   *prev;
+       struct linked_element   *next;
+
+       struct linked_list      *list;
+       int                     stamp;
+} linked_element;
+
+extern linked_list     *new_list(void *(*newp) (void),
+                                                                                void (*freep) (void *));
+extern linked_element  *new_elem(linked_list *list);
+extern linked_element  *add_elem(linked_list *list, void *elem);
+extern void            free_list(linked_list *list, int free_ptr);     /* unlink or free */
+extern void            free_elem(linked_element *e, int free_ptr);     /* unlink or free */
+extern void            *get_elem(linked_element *e);
+extern linked_list     *copy_list(linked_list *list);  /* shallow; doesn't copy */
+                                                                       /* contained structures */
+
+typedef struct c_block {
+       /* The buffer */
+       Int16_t         *vector;
+       long            begin;
+       long            size;
+
+       /* auxiliary support structures */
+       unsigned char   *flags;
+                               /*
+                                * 1    known boundaries in read data
+                                * 2    known blanked data
+                                * 4    matched sample
+                                * 8    reserved
+                                * 16   reserved
+                                * 32   reserved
+                                * 64   reserved
+                                * 128  reserved
+                                */
+
+       /* end of session cases */
+       long            lastsector;
+       struct cdrom_paranoia   *p;
+       struct linked_element   *e;
+} c_block;
+
+extern void    free_c_block(c_block *c);
+extern void    i_cblock_destructor(c_block *c);
+extern c_block *new_c_block(struct cdrom_paranoia *p);
+
+typedef struct v_fragment {
+       c_block         *one;
+
+       long            begin;
+       long            size;
+       Int16_t         *vector;
+
+       /* end of session cases */
+       long            lastsector;
+
+       /* linked list */
+       struct cdrom_paranoia   *p;
+       struct linked_element   *e;
+
+} v_fragment;
+
+extern void    free_v_fragment(v_fragment *c);
+extern v_fragment *new_v_fragment(struct cdrom_paranoia *p, c_block *one,
+                                                                                        long begin, long end,
+                                                                                        int lastsector);
+extern Int16_t *v_buffer(v_fragment *v);
+
+extern c_block *c_first(struct cdrom_paranoia *p);
+extern c_block *c_last(struct cdrom_paranoia *p);
+extern c_block *c_next(c_block *c);
+extern c_block *c_prev(c_block *c);
+
+extern v_fragment *v_first(struct cdrom_paranoia *p);
+extern v_fragment *v_last(struct cdrom_paranoia *p);
+extern v_fragment *v_next(v_fragment *v);
+extern v_fragment *v_prev(v_fragment *v);
+
+typedef struct root_block {
+       long            returnedlimit;
+       long            lastsector;
+       struct cdrom_paranoia   *p;
+
+       c_block         *vector;        /* doesn't use any sorting */
+       int             silenceflag;
+       long            silencebegin;
+} root_block;
+
+typedef struct offsets {
+       long    offpoints;
+       long    newpoints;
+       long    offaccum;
+       long    offdiff;
+       long    offmin;
+       long    offmax;
+
+} offsets;
+
+typedef struct cdrom_paranoia {
+       void            *d;             /* A pointer to the driver interface */
+       int             nsectors;       /* # of sectors that fit into DMA buf */
+
+       root_block      root;           /* verified/reconstructed cached data */
+       linked_list     *cache;         /* our data as read from the cdrom */
+       long            cache_limit;
+       linked_list     *fragments;     /* fragments of blocks that have been */
+                                       /* 'verified' */
+       sort_info       *sortcache;
+
+       int             readahead;      /* sectors of readahead in each readop */
+       int             jitter;
+       long            lastread;
+
+       int             enable;
+       long            cursor;
+       long            current_lastsector;
+       long            current_firstsector;
+
+       /* statistics for drift/overlap */
+       struct offsets  stage1;
+       struct offsets  stage2;
+
+       long            mindynoverlap;
+       long            maxdynoverlap;
+       long            dynoverlap;
+       long            dyndrift;
+
+       /* statistics for verification */
+
+} cdrom_paranoia;
+
+extern c_block *c_alloc(Int16_t *vector, long begin, long size);
+extern void    c_set(c_block *v, long begin);
+extern void    c_insert(c_block *v, long pos, Int16_t *b, long size);
+extern void    c_remove(c_block *v, long cutpos, long cutsize);
+extern void    c_overwrite(c_block *v, long pos, Int16_t *b, long size);
+extern void    c_append(c_block *v, Int16_t *vector, long size);
+extern void    c_removef(c_block *v, long cut);
+
+#define        ce(v)   ((v)->begin + (v)->size)
+#define        cb(v)   ((v)->begin)
+#define        cs(v)   ((v)->size)
+
+/*
+ * pos here is vector position from zero
+ */
+extern void    recover_cache(cdrom_paranoia *p);
+extern void    i_paranoia_firstlast(cdrom_paranoia *p);
+
+#define        cv(c)   ((c)->vector)
+
+#define        fe(f)   ((f)->begin + (f)->size)
+#define        fb(f)   ((f)->begin)
+#define        fs(f)   ((f)->size)
+#define        fv(f)   (v_buffer(f))
+
+#define        CDP_COMPILE
+#endif
diff --git a/libparanoia/paranoia.c b/libparanoia/paranoia.c
new file mode 100644 (file)
index 0000000..56a7be4
--- /dev/null
@@ -0,0 +1,1741 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)paranoia.c      1.33 04/08/17 J. Schilling from cdparanoia-III-alpha9.8 */
+/*
+ *     Modifications to make the code portable Copyright (c) 2002 J. Schilling
+ */
+/*
+ * CopyPolicy: GNU Public License 2 applies
+ * Copyright (C) by Monty (xiphmont@mit.edu)
+ *
+ * Toplevel file for the paranoia abstraction over the cdda lib
+ *
+ */
+
+/* immediate todo:: */
+/* Allow disabling of root fixups? */
+
+/*
+ * Dupe bytes are creeping into cases that require greater overlap
+ * than a single fragment can provide.  We need to check against a
+ * larger area* (+/-32 sectors of root?) to better eliminate
+ *  dupes. Of course this leads to other problems... Is it actually a
+ *  practically solvable problem?
+ */
+/* Bimodal overlap distributions break us. */
+/* scratch detection/tolerance not implemented yet */
+
+/*
+ * Da new shtick: verification now a two-step assymetric process.
+ *
+ * A single 'verified/reconstructed' data segment cache, and then the
+ * multiple fragment cache
+ *
+ * verify a newly read block against previous blocks; do it only this
+ * once. We maintain a list of 'verified sections' from these matches.
+ *
+ * We then glom these verified areas into a new data buffer.
+ * Defragmentation fixups are allowed here alone.
+ *
+ * We also now track where read boundaries actually happened; do not
+ * verify across matching boundaries.
+ */
+
+/*
+ * Silence.  "It's BAAAAAAaaack."
+ *
+ * audio is now treated as great continents of values floating on a
+ * mantle of molten silence.  Silence is not handled by basic
+ * verification at all; we simply anchor sections of nonzero audio to a
+ * position and fill in everything else as silence.  We also note the
+ * audio that interfaces with silence; an edge must be 'wet'.
+ */
+
+#include <mconfig.h>
+#include <allocax.h>
+#include <stdxlib.h>
+#include <unixstd.h>
+#include <standard.h>
+#include <utypes.h>
+#include <stdio.h>
+#include <strdefs.h>
+#include "p_block.h"
+#include "cdda_paranoia.h"
+#include "overlap.h"
+#include "gap.h"
+#include "isort.h"
+#include "pmalloc.h"
+
+/*
+ * used by: i_iterate_stage2() / i_stage2_each()
+ */
+typedef struct sync_result {
+       long            offset;
+       long            begin;
+       long            end;
+} sync_result;
+
+static inline long re(root_block *root);
+static inline long rb(root_block *root);
+static inline long rs(root_block *root);
+static inline Int16_t *rv(root_block *root);
+static inline long i_paranoia_overlap(Int16_t *buffA, Int16_t *buffB,
+                                      long offsetA, long offsetB,
+                                      long sizeA, long sizeB,
+                                      long *ret_begin, long *ret_end);
+static inline long i_paranoia_overlap2(Int16_t *buffA, Int16_t *buffB,
+                                       Uchar *flagsA, Uchar *flagsB,
+                                       long offsetA, long offsetB,
+                                       long sizeA, long sizeB,
+                                       long *ret_begin, long *ret_end);
+static inline long do_const_sync(c_block *A,
+                                 sort_info *B, Uchar *flagB,
+                                 long posA, long posB,
+                                 long *begin, long *end, long *offset);
+static inline long try_sort_sync(cdrom_paranoia *p,
+                                 sort_info *A, Uchar *Aflags,
+                                 c_block *B,
+                                 long post, long *begin, long *end,
+                                 long *offset, void (*callback) (long, int));
+static inline void stage1_matched(c_block *old, c_block *new,
+                                  long matchbegin, long matchend, 
+                                                                                        long matchoffset, 
+                                                                                        void (*callback) (long, int));
+static long i_iterate_stage1(cdrom_paranoia *p, c_block *old, c_block *new,
+                             void (*callback) (long, int));
+static long i_stage1(cdrom_paranoia *p, c_block *new, 
+                                                       void (*callback) (long, int));
+static long i_iterate_stage2(cdrom_paranoia *p, v_fragment *v, sync_result *r, 
+                                                                         void (*callback)(long, int));
+static void i_silence_test(root_block *root);
+static long i_silence_match(root_block *root, v_fragment *v,
+                            void (*callback) (long, int));
+static long i_stage2_each(root_block *root, v_fragment *v,
+                          void (*callback) (long, int));
+static int i_init_root(root_block *root, v_fragment *v, 
+                       long begin, void (*callback)(long, int));
+static int vsort(const void *a, const void *b);
+static int i_stage2(cdrom_paranoia *p, long beginword, long endword, 
+                                                 void (*callback)(long, int));
+static void i_end_case(cdrom_paranoia *p, long endword, 
+                       void (*callback)(long, int));
+static void verify_skip_case(cdrom_paranoia *p, 
+                             void (*callback)(long, int));
+void paranoia_free(cdrom_paranoia *p);
+void paranoia_modeset(cdrom_paranoia *p, int enable);
+long paranoia_seek(cdrom_paranoia *p, long seek, int mode);
+c_block *i_read_c_block(cdrom_paranoia *p, long beginword, long endword, 
+                                                               void (*callback)(long,int));
+Int16_t *paranoia_read(cdrom_paranoia *p, void (*callback)(long, int));
+Int16_t *paranoia_read_limited(cdrom_paranoia *p, void (*callback)(long, int),
+                               int max_retries);
+void paranoia_overlapset(cdrom_paranoia *p, long overlap);
+
+
+static inline long re(root_block *root)
+{
+       if (!root)
+               return (-1);
+       if (!root->vector)
+               return (-1);
+       return (ce(root->vector));
+}
+
+static inline long rb(root_block *root)
+{
+       if (!root)
+               return (-1);
+       if (!root->vector)
+               return (-1);
+       return (cb(root->vector));
+}
+
+static inline long rs(root_block *root)
+{
+       if (!root)
+               return (-1);
+       if (!root->vector)
+               return (-1);
+       return (cs(root->vector));
+}
+
+static inline Int16_t *rv(root_block *root)
+{
+       if (!root)
+               return (NULL);
+       if (!root->vector)
+               return (NULL);
+       return (cv(root->vector));
+}
+
+#define        rc(r)   ((r)->vector)
+
+/*
+ * matching and analysis code
+ */
+static inline long
+i_paranoia_overlap(Int16_t *buffA, Int16_t *buffB, long offsetA, long offsetB, 
+                   long sizeA, long sizeB, long *ret_begin, long *ret_end)
+{
+       long    beginA = offsetA;
+       long    endA = offsetA;
+       long    beginB = offsetB;
+       long    endB = offsetB;
+
+       for (; beginA >= 0 && beginB >= 0; beginA--, beginB--)
+               if (buffA[beginA] != buffB[beginB])
+                       break;
+       beginA++;
+       beginB++;
+
+       for (; endA < sizeA && endB < sizeB; endA++, endB++)
+               if (buffA[endA] != buffB[endB])
+                       break;
+
+       if (ret_begin)
+               *ret_begin = beginA;
+       if (ret_end)
+               *ret_end = endA;
+       return (endA - beginA);
+}
+
+static inline long
+i_paranoia_overlap2(Int16_t *buffA, Int16_t *buffB, Uchar *flagsA, 
+                    Uchar *flagsB, long offsetA, long offsetB, long sizeA, 
+                    long sizeB, long *ret_begin, long *ret_end)
+{
+       long            beginA = offsetA;
+       long            endA = offsetA;
+       long            beginB = offsetB;
+       long            endB = offsetB;
+
+       for (; beginA >= 0 && beginB >= 0; beginA--, beginB--) {
+               if (buffA[beginA] != buffB[beginB])
+                       break;
+               /*
+                * don't allow matching across matching sector boundaries
+                */
+               if ((flagsA[beginA] & flagsB[beginB] & 1)) {
+                       beginA--;
+                       beginB--;
+                       break;
+               }
+               /*
+                * don't allow matching through known missing data
+                */
+               if ((flagsA[beginA] & 2) || (flagsB[beginB] & 2))
+                       break;
+       }
+       beginA++;
+       beginB++;
+
+       for (; endA < sizeA && endB < sizeB; endA++, endB++) {
+               if (buffA[endA] != buffB[endB])
+                       break;
+               /*
+                * don't allow matching across matching sector boundaries
+                */
+               if ((flagsA[endA] & flagsB[endB] & 1) && endA != beginA) {
+                       break;
+               }
+               /*
+                * don't allow matching through known missing data
+                */
+               if ((flagsA[endA] & 2) || (flagsB[endB] & 2))
+                       break;
+       }
+
+       if (ret_begin)
+               *ret_begin = beginA;
+       if (ret_end)
+               *ret_end = endA;
+       return (endA - beginA);
+}
+
+/* Top level of the first stage matcher */
+
+/*
+ * We match each analysis point of new to the preexisting blocks
+ * recursively.  We can also optionally maintain a list of fragments of
+ * the preexisting block that didn't match anything, and match them back
+ * afterward.
+ */
+#define        OVERLAP_ADJ     (MIN_WORDS_OVERLAP/2-1)
+
+static inline long
+do_const_sync(c_block *A, sort_info *B, Uchar *flagB, long posA, long posB, 
+              long *begin, long *end, long *offset)
+{
+       Uchar           *flagA = A->flags;
+       long            ret = 0;
+
+       if (flagB == NULL)
+               ret = i_paranoia_overlap(cv(A), iv(B), posA, posB,
+                       cs(A), is(B), begin, end);
+       else if ((flagB[posB] & 2) == 0)
+               ret = i_paranoia_overlap2(cv(A), iv(B), flagA, flagB, posA, posB, cs(A),
+                       is(B), begin, end);
+
+       if (ret > MIN_WORDS_SEARCH) {
+               *offset = (posA + cb(A)) - (posB + ib(B));
+               *begin += cb(A);
+               *end += cb(A);
+               return (ret);
+       }
+       return (0);
+}
+
+/*
+ * post is w.r.t. B.  in stage one, we post from old.  In stage 2 we
+ * post from root. Begin, end, offset count from B's frame of
+ * reference
+ */
+static inline long
+try_sort_sync(cdrom_paranoia *p, sort_info *A, Uchar *Aflags, c_block *B, 
+              long post, long *begin, long *end, long *offset,
+              void (*callback)(long, int))
+{
+
+       long            dynoverlap = p->dynoverlap;
+       sort_link       *ptr = NULL;
+       Uchar           *Bflags = B->flags;
+
+       /*
+        * block flag matches 0x02 (unmatchable)
+        */
+       if (Bflags == NULL || (Bflags[post - cb(B)] & 2) == 0) {
+               /*
+                * always try absolute offset zero first!
+                */
+               {
+                       long            zeropos = post - ib(A);
+
+                       if (zeropos >= 0 && zeropos < is(A)) {
+                               if (cv(B)[post - cb(B)] == iv(A)[zeropos]) {
+                                       if (do_const_sync(B, A, Aflags,
+                                                       post - cb(B), zeropos,
+                                                       begin, end, offset)) {
+
+                                               offset_add_value(p, &(p->stage1), *offset, callback);
+
+                                               return (1);
+                                       }
+                               }
+                       }
+               }
+       } else
+               return (0);
+
+       ptr = sort_getmatch(A, post - ib(A), dynoverlap, cv(B)[post - cb(B)]);
+
+       while (ptr) {
+
+               if (do_const_sync(B, A, Aflags,
+                               post - cb(B), ipos(A, ptr),
+                               begin, end, offset)) {
+                       offset_add_value(p, &(p->stage1), *offset, callback);
+                       return (1);
+               }
+               ptr = sort_nextmatch(A, ptr);
+       }
+
+       *begin = -1;
+       *end = -1;
+       *offset = -1;
+       return (0);
+}
+
+static inline void
+stage1_matched(c_block *old, c_block *new, long matchbegin, long matchend, 
+               long matchoffset, void (*callback)(long, int))
+{
+       long            i;
+       long            oldadjbegin = matchbegin - cb(old);
+       long            oldadjend = matchend - cb(old);
+       long            newadjbegin = matchbegin - matchoffset - cb(new);
+       long            newadjend = matchend - matchoffset - cb(new);
+
+       if (matchbegin - matchoffset <= cb(new) ||
+               matchbegin <= cb(old) ||
+               (new->flags[newadjbegin] & 1) ||
+               (old->flags[oldadjbegin] & 1)) {
+               if (matchoffset)
+                       if (callback)
+                               (*callback) (matchbegin, PARANOIA_CB_FIXUP_EDGE);
+       } else if (callback)
+               (*callback) (matchbegin, PARANOIA_CB_FIXUP_ATOM);
+
+       if (matchend - matchoffset >= ce(new) ||
+               (new->flags[newadjend] & 1) ||
+               matchend >= ce(old) ||
+               (old->flags[oldadjend] & 1)) {
+               if (matchoffset)
+                       if (callback)
+                               (*callback) (matchend, PARANOIA_CB_FIXUP_EDGE);
+       } else if (callback)
+               (*callback) (matchend, PARANOIA_CB_FIXUP_ATOM);
+
+       /*
+        * Mark the verification flags.  Don't mark the first or last OVERLAP/2
+        * elements so that overlapping fragments have to overlap by OVERLAP to
+        * actually merge. We also remove elements from the sort such that
+        * later sorts do not have to sift through already matched data
+        */
+       newadjbegin += OVERLAP_ADJ;
+       newadjend -= OVERLAP_ADJ;
+       for (i = newadjbegin; i < newadjend; i++)
+               new->flags[i] |= 4;     /* mark verified */
+
+       oldadjbegin += OVERLAP_ADJ;
+       oldadjend -= OVERLAP_ADJ;
+       for (i = oldadjbegin; i < oldadjend; i++)
+               old->flags[i] |= 4;     /* mark verified */
+
+}
+
+#define        CB_NULL         (void (*)(long, int))0
+
+static long 
+i_iterate_stage1(cdrom_paranoia *p, c_block *old, c_block *new, 
+                 void (*callback)(long, int))
+{
+
+       long            matchbegin = -1;
+       long            matchend = -1;
+       long            matchoffset;
+
+       /*
+        * we no longer try to spread the stage one search area by dynoverlap
+        */
+       long            searchend = min(ce(old), ce(new));
+       long            searchbegin = max(cb(old), cb(new));
+       long            searchsize = searchend - searchbegin;
+       sort_info       *i = p->sortcache;
+       long            ret = 0;
+       long            j;
+
+       long            tried = 0;
+       long            matched = 0;
+
+       if (searchsize <= 0)
+               return (0);
+
+       /*
+        * match return values are in terms of the new vector, not old
+        */
+       for (j = searchbegin; j < searchend; j += 23) {
+               if ((new->flags[j - cb(new)] & 6) == 0) {
+                       tried++;
+                       if (try_sort_sync(p, i, new->flags, old, j, &matchbegin, &matchend, &matchoffset,
+                                       callback) == 1) {
+
+                               matched += matchend - matchbegin;
+
+                               /*
+                                * purely cosmetic: if we're matching zeros,
+                                * don't use the callback because they will
+                                * appear to be all skewed
+                                */
+                               {
+                                       long            jj = matchbegin - cb(old);
+                                       long            end = matchend - cb(old);
+
+                                       for (; jj < end; jj++)
+                                               if (cv(old)[jj] != 0)
+                                                       break;
+                                       if (jj < end) {
+                                               stage1_matched(old, new, matchbegin, matchend, matchoffset, callback);
+                                       } else {
+                                               stage1_matched(old, new, matchbegin, matchend, matchoffset, CB_NULL);
+                                       }
+                               }
+                               ret++;
+                               if (matchend - 1 > j)
+                                       j = matchend - 1;
+                       }
+               }
+       }
+#ifdef NOISY
+       fprintf(stderr, "iterate_stage1: search area=%ld[%ld-%ld] tried=%ld matched=%ld spans=%ld\n",
+               searchsize, searchbegin, searchend, tried, matched, ret);
+#endif
+
+       return (ret);
+}
+
+static long 
+i_stage1(cdrom_paranoia *p, c_block *new, void (*callback)(long, int))
+{
+
+       long            size = cs(new);
+       c_block         *ptr = c_last(p);
+       int             ret = 0;
+       long            begin = 0;
+       long            end;
+
+       if (ptr)
+               sort_setup(p->sortcache, cv(new), &cb(new), cs(new),
+                       cb(new), ce(new));
+
+       while (ptr && ptr != new) {
+
+               if (callback)
+                       (*callback) (cb(new), PARANOIA_CB_VERIFY);
+               i_iterate_stage1(p, ptr, new, callback);
+
+               ptr = c_prev(ptr);
+       }
+
+       /*
+        * parse the verified areas of new into v_fragments
+        */
+       begin = 0;
+       while (begin < size) {
+               for (; begin < size; begin++)
+                       if (new->flags[begin] & 4)
+                               break;
+               for (end = begin; end < size; end++)
+                       if ((new->flags[end] & 4) == 0)
+                               break;
+               if (begin >= size)
+                       break;
+
+               ret++;
+
+               new_v_fragment(p, new, cb(new) + max(0, begin - OVERLAP_ADJ),
+                       cb(new) + min(size, end + OVERLAP_ADJ),
+                       (end + OVERLAP_ADJ >= size && new->lastsector));
+
+               begin = end;
+       }
+
+       return (ret);
+}
+
+/*
+ * reconcile v_fragments to root buffer.  Free if matched, fragment/fixup root
+ * if necessary
+ *
+ * do *not* match using zero posts
+ */
+static long 
+i_iterate_stage2(cdrom_paranoia *p, v_fragment *v, sync_result *r, 
+                 void (*callback)(long, int))
+{
+       root_block      *root = &(p->root);
+       long            matchbegin = -1;
+       long            matchend = -1;
+       long            offset;
+       long            fbv;
+       long            fev;
+
+#ifdef NOISY
+       fprintf(stderr, "Stage 2 search: fbv=%ld fev=%ld\n", fb(v), fe(v));
+#endif
+
+       if (min(fe(v) + p->dynoverlap, re(root)) -
+               max(fb(v) - p->dynoverlap, rb(root)) <= 0)
+               return (0);
+
+       if (callback)
+               (*callback) (fb(v), PARANOIA_CB_VERIFY);
+
+       /*
+        * just a bit of v; determine the correct area
+        */
+       fbv = max(fb(v), rb(root) - p->dynoverlap);
+
+       /*
+        * we want to avoid zeroes
+        */
+       while (fbv < fe(v) && fv(v)[fbv - fb(v)] == 0)
+               fbv++;
+       if (fbv == fe(v))
+               return (0);
+       fev = min(min(fbv + 256, re(root) + p->dynoverlap), fe(v));
+
+       {
+               /*
+                * spread the search area a bit.  We post from root, so
+                * containment must strictly adhere to root
+                */
+               long            searchend = min(fev + p->dynoverlap, re(root));
+               long            searchbegin = max(fbv - p->dynoverlap, rb(root));
+               sort_info       *i = p->sortcache;
+               long            j;
+
+               sort_setup(i, fv(v), &fb(v), fs(v), fbv, fev);
+               for (j = searchbegin; j < searchend; j += 23) {
+                       while (j < searchend && rv(root)[j - rb(root)] == 0)
+                               j++;
+                       if (j == searchend)
+                               break;
+
+                       if (try_sort_sync(p, i, (Uchar *)0, rc(root), j,
+                                       &matchbegin, &matchend, &offset, callback)) {
+
+                               r->begin = matchbegin;
+                               r->end = matchend;
+                               r->offset = -offset;
+                               if (offset)
+                                       if (callback)
+                                               (*callback) (r->begin, PARANOIA_CB_FIXUP_EDGE);
+                               return (1);
+                       }
+               }
+       }
+       return (0);
+}
+
+/*
+ * simple test for a root vector that ends in silence
+ */
+static void i_silence_test(root_block *root)
+{
+       Int16_t         *vec = rv(root);
+       long            end = re(root) - rb(root) - 1;
+       long            j;
+
+       for (j = end - 1; j >= 0; j--)
+               if (vec[j] != 0)
+                       break;
+       if (j < 0 || end - j > MIN_SILENCE_BOUNDARY) {
+               if (j < 0)
+                       j = 0;
+               root->silenceflag = 1;
+               root->silencebegin = rb(root) + j;
+               if (root->silencebegin < root->returnedlimit)
+                       root->silencebegin = root->returnedlimit;
+       }
+}
+
+/*
+ * match into silence vectors at offset zero if at all possible.  This
+ * also must be called with vectors in ascending begin order in case
+ * there are nonzero islands
+ */
+static long
+i_silence_match(root_block *root, v_fragment *v, void (*callback)(long, int))
+{
+
+       cdrom_paranoia  *p = v->p;
+       Int16_t *vec = fv(v);
+       long            end = fs(v);
+       long            begin;
+       long            j;
+
+       /*
+        * does this vector begin wet?
+        */
+       if (end < MIN_SILENCE_BOUNDARY)
+               return (0);
+       for (j = 0; j < end; j++)
+               if (vec[j] != 0)
+                       break;
+       if (j < MIN_SILENCE_BOUNDARY)
+               return (0);
+       j += fb(v);
+
+       /*
+        * is the new silent section ahead of the end of the old
+        * by < p->dynoverlap?
+        */
+       if (fb(v) >= re(root) && fb(v) - p->dynoverlap < re(root)) {
+               /*
+                * extend the zeroed area of root
+                * XXX dynarrays are not needed here.
+                */
+               long            addto = fb(v) + MIN_SILENCE_BOUNDARY - re(root);
+/*             Int16_t         avec[addto];*/
+#ifdef HAVE_ALLOCA
+               Int16_t         *avec = alloca(addto * sizeof (Int16_t));
+#else
+               Int16_t         *avec = _pmalloc(addto * sizeof (Int16_t));
+#endif
+
+               memset(avec, 0, sizeof (avec));
+               c_append(rc(root), avec, addto);
+#ifndef        HAVE_ALLOCA
+               _pfree(avec);
+#endif
+       }
+       /*
+        * do we have an 'effortless' overlap?
+        */
+       begin = max(fb(v), root->silencebegin);
+       end = min(j, re(root));
+
+       if (begin < end) {
+               /*
+                * don't use it unless it will extend...
+                */
+               if (fe(v) > re(root)) {
+                       long            voff = begin - fb(v);
+
+                       c_remove(rc(root), begin - rb(root), -1);
+                       c_append(rc(root), vec + voff, fs(v) - voff);
+               }
+               offset_add_value(p, &p->stage2, 0, callback);
+
+       } else {
+               if (j < begin) {
+                       /*
+                        * OK, we'll have to force it a bit as the root is
+                        * jittered forward
+                        */
+                       long            voff = j - fb(v);
+
+                       /*
+                        * don't use it unless it will extend...
+                        */
+                       if (begin + fs(v) - voff > re(root)) {
+                               c_remove(rc(root), root->silencebegin - rb(root), -1);
+                               c_append(rc(root), vec + voff, fs(v) - voff);
+                       }
+                       offset_add_value(p, &p->stage2, end - begin, callback);
+               } else
+                       return (0);
+       }
+
+       /*
+        * test the new root vector for ending in silence
+        */
+       root->silenceflag = 0;
+       i_silence_test(root);
+
+       if (v->lastsector)
+               root->lastsector = 1;
+       free_v_fragment(v);
+       return (1);
+}
+
+static long
+i_stage2_each(root_block *root, v_fragment *v, void (*callback)(long, int))
+{
+
+       cdrom_paranoia *p = v->p;
+       long            dynoverlap = p->dynoverlap / 2 * 2;
+
+       if (!v || !v->one)
+               return (0);
+
+       if (!rv(root)) {
+               return (0);
+       } else {
+               sync_result     r;
+
+               if (i_iterate_stage2(p, v, &r, callback)) {
+
+                       long            begin = r.begin - rb(root);
+                       long            end = r.end - rb(root);
+                       long            offset = r.begin + r.offset - fb(v) - begin;
+                       long            temp;
+                       c_block         *l = NULL;
+
+                       /*
+                        * we have a match! We don't rematch off rift, we chase
+                        * the match all the way to both extremes doing rift
+                        * analysis.
+                        */
+#ifdef NOISY
+                       fprintf(stderr, "Stage 2 match\n");
+#endif
+
+                       /*
+                        * chase backward
+                        * note that we don't extend back right now, only
+                        * forward.
+                        */
+                       while ((begin + offset > 0 && begin > 0)) {
+                               long            matchA = 0,
+                                               matchB = 0,
+                                               matchC = 0;
+                               long            beginL = begin + offset;
+
+                               if (l == NULL) {
+                                       Int16_t *buff = _pmalloc(fs(v) * sizeof (Int16_t));
+
+                                       l = c_alloc(buff, fb(v), fs(v));
+                                       memcpy(buff, fv(v), fs(v) * sizeof (Int16_t));
+                               }
+                               i_analyze_rift_r(rv(root), cv(l),
+                                       rs(root), cs(l),
+                                       begin - 1, beginL - 1,
+                                       &matchA, &matchB, &matchC);
+
+#ifdef NOISY
+                               fprintf(stderr, "matching rootR: matchA:%ld matchB:%ld matchC:%ld\n",
+                                       matchA, matchB, matchC);
+#endif
+
+                               if (matchA) {
+                                       /*
+                                        * a problem with root
+                                        */
+                                       if (matchA > 0) {
+                                               /*
+                                                * dropped bytes; add back from v
+                                                */
+                                               if (callback)
+                                                       (*callback) (begin + rb(root) - 1, PARANOIA_CB_FIXUP_DROPPED);
+                                               if (rb(root) + begin < p->root.returnedlimit)
+                                                       break;
+                                               else {
+                                                       c_insert(rc(root), begin, cv(l) + beginL - matchA,
+                                                               matchA);
+                                                       offset -= matchA;
+                                                       begin += matchA;
+                                                       end += matchA;
+                                               }
+                                       } else {
+                                               /*
+                                                * duplicate bytes; drop from root
+                                                */
+                                               if (callback)
+                                                       (*callback) (begin + rb(root) - 1, PARANOIA_CB_FIXUP_DUPED);
+                                               if (rb(root) + begin + matchA < p->root.returnedlimit)
+                                                       break;
+                                               else {
+                                                       c_remove(rc(root), begin + matchA, -matchA);
+                                                       offset -= matchA;
+                                                       begin += matchA;
+                                                       end += matchA;
+                                               }
+                                       }
+                               } else if (matchB) {
+                                       /*
+                                        * a problem with the fragment
+                                        */
+                                       if (matchB > 0) {
+                                               /*
+                                                * dropped bytes
+                                                */
+                                               if (callback)
+                                                       (*callback) (begin + rb(root) - 1, PARANOIA_CB_FIXUP_DROPPED);
+                                               c_insert(l, beginL, rv(root) + begin - matchB,
+                                                       matchB);
+                                               offset += matchB;
+                                       } else {
+                                               /*
+                                                * duplicate bytes
+                                                */
+                                               if (callback)
+                                                       (*callback) (begin + rb(root) - 1, PARANOIA_CB_FIXUP_DUPED);
+                                               c_remove(l, beginL + matchB, -matchB);
+                                               offset += matchB;
+                                       }
+                               } else if (matchC) {
+                                       /*
+                                        * Uhh... problem with both
+                                        * Set 'disagree' flags in root
+                                        */
+                                       if (rb(root) + begin - matchC < p->root.returnedlimit)
+                                               break;
+                                       c_overwrite(rc(root), begin - matchC,
+                                               cv(l) + beginL - matchC, matchC);
+
+                               } else {
+                                       /*
+                                        * do we have a mismatch due to silence
+                                        * beginning/end case?
+                                        * in the 'chase back' case, we don't
+                                        * do anything.
+                                        * Did not determine nature of
+                                        * difficulty... report and bail
+                                        */
+                                       /* RRR(*callback)(post,PARANOIA_CB_XXX); */
+                                       break;
+                               }
+                               /*
+                                * not the most efficient way, but it will do
+                                * for now
+                                */
+                               beginL = begin + offset;
+                               i_paranoia_overlap(rv(root), cv(l),
+                                       begin, beginL,
+                                       rs(root), cs(l),
+                                       &begin, &end);
+                       }
+
+                       /*
+                        * chase forward
+                        */
+                       temp = l ? cs(l) : fs(v);
+                       while (end + offset < temp && end < rs(root)) {
+                               long    matchA = 0,
+                                       matchB = 0,
+                                       matchC = 0;
+                               long    beginL = begin + offset;
+                               long    endL = end + offset;
+
+                               if (l == NULL) {
+                                       Int16_t *buff = _pmalloc(fs(v) * sizeof (Int16_t));
+
+                                       l = c_alloc(buff, fb(v), fs(v));
+                                       memcpy(buff, fv(v), fs(v) * sizeof (Int16_t));
+                               }
+                               i_analyze_rift_f(rv(root), cv(l),
+                                       rs(root), cs(l),
+                                       end, endL,
+                                       &matchA, &matchB, &matchC);
+
+#ifdef NOISY
+                               fprintf(stderr, "matching rootF: matchA:%ld matchB:%ld matchC:%ld\n",
+                                       matchA, matchB, matchC);
+#endif
+
+                               if (matchA) {
+                                       /*
+                                        * a problem with root
+                                        */
+                                       if (matchA > 0) {
+                                               /*
+                                                * dropped bytes; add back from v
+                                                */
+                                               if (callback)
+                                                       (*callback) (end + rb(root), PARANOIA_CB_FIXUP_DROPPED);
+                                               if (end + rb(root) < p->root.returnedlimit)
+                                                       break;
+                                               c_insert(rc(root), end, cv(l) + endL, matchA);
+                                       } else {
+                                               /*
+                                                * duplicate bytes; drop from root
+                                                */
+                                               if (callback)
+                                                       (*callback) (end + rb(root), PARANOIA_CB_FIXUP_DUPED);
+                                               if (end + rb(root) < p->root.returnedlimit)
+                                                       break;
+                                               c_remove(rc(root), end, -matchA);
+                                       }
+                               } else if (matchB) {
+                                       /*
+                                        * a problem with the fragment
+                                        */
+                                       if (matchB > 0) {
+                                               /*
+                                                * dropped bytes
+                                                */
+                                               if (callback)
+                                                       (*callback) (end + rb(root), PARANOIA_CB_FIXUP_DROPPED);
+                                               c_insert(l, endL, rv(root) + end, matchB);
+                                       } else {
+                                               /*
+                                                * duplicate bytes
+                                                */
+                                               if (callback)
+                                                       (*callback) (end + rb(root), PARANOIA_CB_FIXUP_DUPED);
+                                               c_remove(l, endL, -matchB);
+                                       }
+                               } else if (matchC) {
+                                       /*
+                                        * Uhh... problem with both
+                                        * Set 'disagree' flags in root
+                                        */
+                                       if (end + rb(root) < p->root.returnedlimit)
+                                               break;
+                                       c_overwrite(rc(root), end, cv(l) + endL, matchC);
+                               } else {
+                                       analyze_rift_silence_f(rv(root), cv(l),
+                                               rs(root), cs(l),
+                                               end, endL,
+                                               &matchA, &matchB);
+                                       if (matchA) {
+                                               /*
+                                                * silence in root
+                                                * Can only do this if we haven't
+                                                * already returned data
+                                                */
+                                               if (end + rb(root) >= p->root.returnedlimit) {
+                                                       c_remove(rc(root), end, -1);
+                                               }
+                                       } else if (matchB) {
+                                               /*
+                                                * silence in fragment; lose it
+                                                */
+                                               if (l)
+                                                       i_cblock_destructor(l);
+                                               free_v_fragment(v);
+                                               return (1);
+
+                                       } else {
+                                               /*
+                                                * Could not determine nature of
+                                                * difficulty... report and bail
+                                                */
+                                               /* RRR(*callback)(post,PARANOIA_CB_XXX); */
+                                       }
+                                       break;
+                               }
+                               /*
+                                * not the most efficient way, but it will do for now
+                                */
+                               i_paranoia_overlap(rv(root), cv(l),
+                                       begin, beginL,
+                                       rs(root), cs(l),
+                                       (long *)0, &end);
+                       }
+
+                       /*
+                        * if this extends our range, let's glom
+                        */
+                       {
+                               long    sizeA = rs(root);
+                               long    sizeB;
+                               long    vecbegin;
+                               Int16_t *vector;
+
+                               if (l) {
+                                       sizeB = cs(l);
+                                       vector = cv(l);
+                                       vecbegin = cb(l);
+                               } else {
+                                       sizeB = fs(v);
+                                       vector = fv(v);
+                                       vecbegin = fb(v);
+                               }
+
+                               if (sizeB - offset > sizeA || v->lastsector) {
+                                       if (v->lastsector) {
+                                               root->lastsector = 1;
+                                       }
+                                       if (end < sizeA)
+                                               c_remove(rc(root), end, -1);
+
+                                       if (sizeB - offset - end)
+                                               c_append(rc(root), vector + end + offset,
+                                                       sizeB - offset - end);
+
+                                       i_silence_test(root);
+
+                                       /*
+                                        * add offset into dynoverlap stats
+                                        */
+                                       offset_add_value(p, &p->stage2, offset + vecbegin - rb(root), callback);
+                               }
+                       }
+                       if (l)
+                               i_cblock_destructor(l);
+                       free_v_fragment(v);
+                       return (1);
+
+               } else {
+                       /*
+                        * D'oh.  No match.  What to do with the fragment?
+                        */
+                       if (fe(v) + dynoverlap < re(root) && !root->silenceflag) {
+                               /*
+                                * It *should* have matched.  No good; free it.
+                                */
+                               free_v_fragment(v);
+                       }
+                       /*
+                        * otherwise, we likely want this for an upcoming match
+                        * we don't free the sort info (if it was collected)
+                        */
+                       return (0);
+
+               }
+       }
+}
+
+static int
+i_init_root(root_block *root, v_fragment *v, long begin, 
+            void (*callback)(long, int))
+{
+       if (fb(v) <= begin && fe(v) > begin) {
+
+               root->lastsector = v->lastsector;
+               root->returnedlimit = begin;
+
+               if (rv(root)) {
+                       i_cblock_destructor(rc(root));
+                       rc(root) = NULL;
+               }
+               {
+                       Int16_t         *buff = _pmalloc(fs(v) * sizeof (Int16_t));
+
+                       memcpy(buff, fv(v), fs(v) * sizeof (Int16_t));
+                       root->vector = c_alloc(buff, fb(v), fs(v));
+               }
+               i_silence_test(root);
+
+               return (1);
+       } else
+               return (0);
+}
+
+static int vsort(const void *a, const void *b)
+{
+       return ((*(v_fragment **) a)->begin - (*(v_fragment **) b)->begin);
+}
+
+static int
+i_stage2(cdrom_paranoia *p, long beginword, long endword, 
+         void (*callback)(long, int))
+{
+
+       int             flag = 1;
+       int             ret = 0;
+       root_block      *root = &(p->root);
+
+#ifdef NOISY
+       fprintf(stderr, "Fragments:%ld\n", p->fragments->active);
+       fflush(stderr);
+#endif
+
+       /*
+        * even when the 'silence flag' is lit, we try to do non-silence
+        * matching in the event that there are still audio vectors with
+        * content to be sunk before the silence
+        */
+       while (flag) {
+               /*
+                * loop through all the current fragments
+                */
+               v_fragment      *first = v_first(p);
+               long            active = p->fragments->active,
+                               count = 0;
+#ifdef HAVE_DYN_ARRAYS
+               v_fragment      *list[active];
+#else
+               v_fragment      **list = _pmalloc(active * sizeof (v_fragment *));
+#endif
+
+               while (first) {
+                       v_fragment      *next = v_next(first);
+
+                       list[count++] = first;
+                       first = next;
+               }
+
+               flag = 0;
+               if (count) {
+                       /*
+                        * sorted in ascending order of beginning
+                        */
+                       qsort(list, active, sizeof (v_fragment *), vsort);
+
+                       /*
+                        * we try a nonzero based match even if in silent mode
+                        * in the case that there are still cached vectors to
+                        * sink behind continent->ocean boundary
+                        */
+                       for (count = 0; count < active; count++) {
+                               first = list[count];
+                               if (first->one) {
+                                       if (rv(root) == NULL) {
+                                               if (i_init_root(&(p->root), first, beginword, callback)) {
+                                                       free_v_fragment(first);
+                                                       flag = 1;
+                                                       ret++;
+                                               }
+                                       } else {
+                                               if (i_stage2_each(root, first, callback)) {
+                                                       ret++;
+                                                       flag = 1;
+                                               }
+                                       }
+                               }
+                       }
+
+                       /*
+                        * silence handling
+                        */
+                       if (!flag && p->root.silenceflag) {
+                               for (count = 0; count < active; count++) {
+                                       first = list[count];
+                                       if (first->one) {
+                                               if (rv(root) != NULL) {
+                                                       if (i_silence_match(root, first, callback)) {
+                                                               ret++;
+                                                               flag = 1;
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+               }
+#ifndef        HAVE_DYN_ARRAYS
+               _pfree(list);
+#endif
+       }
+       return (ret);
+}
+
+static void
+i_end_case(cdrom_paranoia *p, long endword, void (*callback)(long, int))
+{
+
+       root_block      *root = &p->root;
+
+       /*
+        * have an 'end' flag; if we've just read in the last sector in a
+        * session, set the flag.  If we verify to the end of a fragment
+        * which has the end flag set, we're done (set a done flag).
+        * Pad zeroes to the end of the read
+        */
+       if (root->lastsector == 0)
+               return;
+       if (endword < re(root))
+               return;
+
+       {
+               long            addto = endword - re(root);
+               char            *temp = _pcalloc(addto, sizeof (char) * 2);
+
+               c_append(rc(root), (void *) temp, addto);
+               _pfree(temp);
+
+               /*
+                * trash da cache
+                */
+               paranoia_resetcache(p);
+
+       }
+}
+
+/*
+ * We want to add a sector. Look through the caches for something that
+ * spans.  Also look at the flags on the c_block... if this is an
+ * obliterated sector, get a bit of a chunk past the obliteration.
+ *
+ * Not terribly smart right now, actually.  We can probably find
+ * *some* match with a cache block somewhere.  Take it and continue it
+ * through the skip
+ */
+static void
+verify_skip_case(cdrom_paranoia *p, void (*callback)(long, int))
+{
+
+       root_block      *root = &(p->root);
+       c_block         *graft = NULL;
+       int             vflag = 0;
+       int             gend = 0;
+       long            post;
+
+#ifdef NOISY
+       fprintf(stderr, "\nskipping\n");
+#endif
+
+       if (rv(root) == NULL) {
+               post = 0;
+       } else {
+               post = re(root);
+       }
+       if (post == -1)
+               post = 0;
+
+       if (callback)
+               (*callback) (post, PARANOIA_CB_SKIP);
+
+       if (p->enable & PARANOIA_MODE_NEVERSKIP)
+               return;
+
+       /*
+        * We want to add a sector.  Look for a c_block that spans,
+        * preferrably a verified area
+        */
+       {
+               c_block         *c = c_first(p);
+
+               while (c) {
+                       long            cbegin = cb(c);
+                       long            cend = ce(c);
+
+                       if (cbegin <= post && cend > post) {
+                               long            vend = post;
+
+                               if (c->flags[post - cbegin] & 4) {
+                                       /*
+                                        * verified area!
+                                        */
+                                       while (vend < cend && (c->flags[vend - cbegin] & 4))
+                                               vend++;
+                                       if (!vflag || vend > vflag) {
+                                               graft = c;
+                                               gend = vend;
+                                       }
+                                       vflag = 1;
+                               } else {
+                                       /*
+                                        * not a verified area
+                                        */
+                                       if (!vflag) {
+                                               while (vend < cend && (c->flags[vend - cbegin] & 4) == 0)
+                                                       vend++;
+                                               if (graft == NULL || gend > vend) {
+                                                       /*
+                                                        * smallest unverified area
+                                                        */
+                                                       graft = c;
+                                                       gend = vend;
+                                               }
+                                       }
+                               }
+                       }
+                       c = c_next(c);
+               }
+
+               if (graft) {
+                       long            cbegin = cb(graft);
+                       long            cend = ce(graft);
+
+                       while (gend < cend && (graft->flags[gend - cbegin] & 4))
+                               gend++;
+                       gend = min(gend + OVERLAP_ADJ, cend);
+
+                       if (rv(root) == NULL) {
+                               Int16_t *buff = _pmalloc(cs(graft));
+
+                               memcpy(buff, cv(graft), cs(graft));
+                               rc(root) = c_alloc(buff, cb(graft), cs(graft));
+                       } else {
+                               c_append(rc(root), cv(graft) + post - cbegin,
+                                       gend - post);
+                       }
+
+                       root->returnedlimit = re(root);
+                       return;
+               }
+       }
+
+       /*
+        * No?  Fine.  Great.  Write in some zeroes :-P
+        */
+       {
+               void    *temp = _pcalloc(CD_FRAMESIZE_RAW, sizeof (Int16_t));
+
+               if (rv(root) == NULL) {
+                       rc(root) = c_alloc(temp, post, CD_FRAMESIZE_RAW);
+               } else {
+                       c_append(rc(root), temp, CD_FRAMESIZE_RAW);
+                       _pfree(temp);
+               }
+               root->returnedlimit = re(root);
+       }
+}
+
+/*
+ * toplevel
+ */
+void paranoia_free(cdrom_paranoia *p)
+{
+       paranoia_resetall(p);
+       sort_free(p->sortcache);
+       _pfree(p);
+}
+
+void paranoia_modeset(cdrom_paranoia *p, int enable)
+{
+       p->enable = enable;
+}
+
+long paranoia_seek(cdrom_paranoia *p, long seek, int mode)
+{
+       long    sector;
+       long    ret;
+
+       switch (mode) {
+       case SEEK_SET:
+               sector = seek;
+               break;
+       case SEEK_END:
+               sector = cdda_disc_lastsector(p->d) + seek;
+               break;
+       default:
+               sector = p->cursor + seek;
+               break;
+       }
+
+       if (cdda_sector_gettrack(p->d, sector) == -1)
+               return (-1);
+
+       i_cblock_destructor(p->root.vector);
+       p->root.vector = NULL;
+       p->root.lastsector = 0;
+       p->root.returnedlimit = 0;
+
+       ret = p->cursor;
+       p->cursor = sector;
+
+       i_paranoia_firstlast(p);
+
+       /*
+        * Evil hack to fix pregap patch for NEC drives! To be rooted out in a10
+        */
+       p->current_firstsector = sector;
+
+       return (ret);
+}
+
+/*
+ * returns last block read, -1 on error
+ */
+c_block *i_read_c_block(cdrom_paranoia *p, long beginword, long endword, 
+                        void (*callback)(long, int))
+{
+       /*
+        * why do it this way?  We need to read lots of sectors to kludge
+        * around stupid read ahead buffers on cheap drives, as well as avoid
+        * expensive back-seeking. We also want to 'jiggle' the start address
+        * to try to break borderline drives more noticeably (and make broken
+        * drives with unaddressable sectors behave more often).
+        */
+       long            readat;
+       long            firstread;
+       long            totaltoread = p->readahead;
+       long            sectatonce = p->nsectors;
+       long            driftcomp = (float) p->dyndrift / CD_FRAMEWORDS + .5;
+       c_block         *new = NULL;
+       root_block      *root = &p->root;
+       Int16_t         *buffer = NULL;
+       void            *bufbase = NULL;
+       Uchar           *flags = NULL;
+       long            sofar;
+       long            dynoverlap = (p->dynoverlap + CD_FRAMEWORDS - 1) / CD_FRAMEWORDS;
+       long            anyflag = 0;
+       int             reduce = 0;
+static int             pagesize = -1;
+#define        valign(x, a)    (((char *)(x)) + ((a) - 1 - ((((UIntptr_t)(x))-1)%(a))))
+
+       /*
+        * What is the first sector to read?  want some pre-buffer if we're not
+        * at the extreme beginning of the disc
+        */
+       if (p->enable & (PARANOIA_MODE_VERIFY | PARANOIA_MODE_OVERLAP)) {
+
+               /*
+                * we want to jitter the read alignment boundary
+                */
+               long    target;
+
+               if (rv(root) == NULL || rb(root) > beginword)
+                       target = p->cursor - dynoverlap;
+               else
+                       target = re(root) / (CD_FRAMEWORDS) - dynoverlap;
+
+               if (target + MIN_SECTOR_BACKUP > p->lastread && target <= p->lastread)
+                       target = p->lastread - MIN_SECTOR_BACKUP;
+
+               /*
+                * we want to jitter the read alignment boundary, as some
+                * drives, beginning from a specific point, will tend to
+                * lose bytes between sectors in the same place.  Also, as
+                * our vectors are being made up of multiple reads, we want
+                * the overlap boundaries to move....
+                */
+               readat = (target & (~((long) JIGGLE_MODULO - 1))) + p->jitter;
+               if (readat > target)
+                       readat -= JIGGLE_MODULO;
+               p->jitter++;
+               if (p->jitter >= JIGGLE_MODULO)
+                       p->jitter = 0;
+
+       } else {
+               readat = p->cursor;
+       }
+
+       readat += driftcomp;
+
+       if (p->enable & (PARANOIA_MODE_OVERLAP | PARANOIA_MODE_VERIFY)) {
+               flags = _pcalloc(totaltoread * CD_FRAMEWORDS, 1);
+               new = new_c_block(p);
+               recover_cache(p);
+       } else {
+               /*
+                * in the case of root it's just the buffer
+                */
+               paranoia_resetall(p);
+               new = new_c_block(p);
+       }
+
+       /*
+        * Do not use valloc() as valloc() in glibc is buggy and returns memory
+        * that cannot be passed to free().
+        */
+       if (pagesize < 0) {
+               pagesize = getpagesize();
+               if (pagesize < 0)
+                       pagesize = 4096;        /* Just a guess */
+       }
+       reduce = pagesize / CD_FRAMESIZE_RAW;
+       bufbase = _pmalloc(totaltoread * CD_FRAMESIZE_RAW + pagesize);
+       buffer = (Int16_t *)valign(bufbase, pagesize);
+       sofar = 0;
+       firstread = -1;
+
+       /*
+        * actual read loop
+        */
+       while (sofar < totaltoread) {
+               long    secread = sectatonce;
+               long    adjread = readat;
+               long    thisread;
+
+               /*
+                * don't under/overflow the audio session
+                */
+               if (adjread < p->current_firstsector) {
+                       secread -= p->current_firstsector - adjread;
+                       adjread = p->current_firstsector;
+               }
+               if (adjread + secread - 1 > p->current_lastsector)
+                       secread = p->current_lastsector - adjread + 1;
+
+               if (sofar + secread > totaltoread)
+                       secread = totaltoread - sofar;
+
+               /*
+                * If we are inside the buffer, the transfers are no longer
+                * page aligned. Reduce the transfer size to avoid problems.
+                * Such problems are definitely known to appear on FreeBSD.
+                */
+               if ((sofar > 0) && (secread > (sectatonce - reduce)))
+                       secread = sectatonce - reduce;
+
+               if (secread > 0) {
+
+                       if (firstread < 0)
+                               firstread = adjread;
+                       if ((thisread = cdda_read(p->d, buffer + sofar * CD_FRAMEWORDS, adjread,
+                                               secread)) < secread) {
+
+                               if (thisread < 0)
+                                       thisread = 0;
+
+                               /*
+                                * Uhhh... right.  Make something up. But
+                                * don't make us seek backward!
+                                */
+                               if (callback)
+                                       (*callback) ((adjread + thisread) * CD_FRAMEWORDS, PARANOIA_CB_READERR);
+                               memset(buffer + (sofar + thisread) * CD_FRAMEWORDS, 0,
+                                       CD_FRAMESIZE_RAW * (secread - thisread));
+                               if (flags)
+                                       memset(flags + (sofar + thisread) * CD_FRAMEWORDS, 2,
+                                               CD_FRAMEWORDS * (secread - thisread));
+                       }
+                       if (thisread != 0)
+                               anyflag = 1;
+
+                       if (flags && sofar != 0) {
+                               /*
+                                * Don't verify across overlaps that are too
+                                * close to one another
+                                */
+                               int     i = 0;
+
+                               for (i = -MIN_WORDS_OVERLAP / 2; i < MIN_WORDS_OVERLAP / 2; i++)
+                                       flags[sofar * CD_FRAMEWORDS + i] |= 1;
+                       }
+                       p->lastread = adjread + secread;
+
+                       if (adjread + secread - 1 == p->current_lastsector)
+                               new->lastsector = -1;
+
+                       if (callback)
+                               (*callback) ((adjread + secread - 1) * CD_FRAMEWORDS, PARANOIA_CB_READ);
+
+                       sofar += secread;
+                       readat = adjread + secread;
+               } else if (readat < p->current_firstsector) {
+                       readat += sectatonce;
+                                               /*
+                                                * due to being before the
+                                                * readable area
+                                                */
+               } else {
+                       break;  /* due to being past the readable area */
+               }
+       }
+
+       if (anyflag) {
+               new->vector = _pmalloc(totaltoread * CD_FRAMESIZE_RAW);
+               memcpy(new->vector, buffer, totaltoread * CD_FRAMESIZE_RAW);
+               _pfree(bufbase);
+
+               new->begin = firstread * CD_FRAMEWORDS - p->dyndrift;
+               new->size = sofar * CD_FRAMEWORDS;
+               new->flags = flags;
+       } else {
+               if (new)
+                       free_c_block(new);
+               if (bufbase)
+                       _pfree(bufbase);
+               if (flags)
+                       _pfree(flags);
+               new = NULL;
+               bufbase = NULL;
+               flags = NULL;
+       }
+       return (new);
+}
+
+/*
+ * The returned buffer is *not* to be freed by the caller.  It will
+ * persist only until the next call to paranoia_read() for this p
+ */
+Int16_t *paranoia_read(cdrom_paranoia *p, void (*callback)(long, int))
+{
+       return (paranoia_read_limited(p, callback, 20));
+}
+
+/*
+ * I added max_retry functionality this way in order to avoid breaking any
+ * old apps using the nerw libs.  cdparanoia 9.8 will need the updated libs,
+ * but nothing else will require it.
+ */
+Int16_t *paranoia_read_limited(cdrom_paranoia *p, void (*callback)(long, int),
+                               int max_retries)
+{
+       long            beginword = p->cursor * (CD_FRAMEWORDS);
+       long            endword = beginword + CD_FRAMEWORDS;
+       long            retry_count = 0;
+       long            lastend = -2;
+       root_block      *root = &p->root;
+
+       if (beginword > p->root.returnedlimit)
+               p->root.returnedlimit = beginword;
+       lastend = re(root);
+
+       /*
+        * First, is the sector we want already in the root?
+        */
+       while (rv(root) == NULL ||
+               rb(root) > beginword ||
+               (re(root) < endword + p->maxdynoverlap &&
+                       p->enable & (PARANOIA_MODE_VERIFY | PARANOIA_MODE_OVERLAP)) ||
+               re(root) < endword) {
+
+               /*
+                * Nope; we need to build or extend the root verified range
+                */
+               if (p->enable & (PARANOIA_MODE_VERIFY | PARANOIA_MODE_OVERLAP)) {
+                       i_paranoia_trim(p, beginword, endword);
+                       recover_cache(p);
+                       if (rb(root) != -1 && p->root.lastsector)
+                               i_end_case(p, endword + p->maxdynoverlap,
+                                       callback);
+                       else
+                               i_stage2(p, beginword,
+                                       endword + p->maxdynoverlap,
+                                       callback);
+               } else
+                       i_end_case(p, endword + p->maxdynoverlap,
+                               callback);      /* only trips if we're already */
+                                               /* done */
+
+               if (!(rb(root) == -1 || rb(root) > beginword ||
+                               re(root) < endword + p->maxdynoverlap))
+                       break;
+
+               /*
+                * Hmm, need more.  Read another block
+                */
+               {
+                       c_block *new = i_read_c_block(p, beginword, endword, callback);
+
+                       if (new) {
+                               if (p->enable & (PARANOIA_MODE_OVERLAP | PARANOIA_MODE_VERIFY)) {
+
+                                       if (p->enable & PARANOIA_MODE_VERIFY)
+                                               i_stage1(p, new, callback);
+                                       else {
+                                               /*
+                                                * just make v_fragments from the
+                                                * boundary information.
+                                                */
+                                               long    begin = 0,
+                                                       end = 0;
+
+                                               while (begin < cs(new)) {
+                                                       while (end < cs(new) && (new->flags[begin] & 1))
+                                                               begin++;
+                                                       end = begin + 1;
+                                                       while (end < cs(new) && (new->flags[end] & 1) == 0)
+                                                               end++;
+                                                       {
+                                                               new_v_fragment(p, new, begin + cb(new),
+                                                                       end + cb(new),
+                                                                       (new->lastsector && cb(new) + end == ce(new)));
+                                                       }
+                                                       begin = end;
+                                               }
+                                       }
+
+                               } else {
+
+                                       if (p->root.vector)
+                                               i_cblock_destructor(p->root.vector);
+                                       free_elem(new->e, 0);
+                                       p->root.vector = new;
+
+                                       i_end_case(p, endword + p->maxdynoverlap,
+                                               callback);
+
+                               }
+                       }
+               }
+
+               /*
+                * Are we doing lots of retries?  **********************
+                *
+                * Check unaddressable sectors first.  There's no backoff
+                * here; jiggle and minimum backseek handle that for us
+                */
+               if (rb(root) != -1 && lastend + 588 < re(root)) {
+                       /*
+                        * If we've not grown half a sector
+                        */
+                       lastend = re(root);
+                       retry_count = 0;
+               } else {
+                       /*
+                        * increase overlap or bail
+                        */
+                       retry_count++;
+
+                       /*
+                        * The better way to do this is to look at how many
+                        * actual matches we're getting and what kind of gap
+                        */
+                       if (retry_count % 5 == 0) {
+                               if (p->dynoverlap == p->maxdynoverlap ||
+                                               retry_count == max_retries) {
+                                       verify_skip_case(p, callback);
+                                       retry_count = 0;
+                               } else {
+                                       if (p->stage1.offpoints != -1) {        /* hack */
+                                               p->dynoverlap *= 1.5;
+                                               if (p->dynoverlap > p->maxdynoverlap)
+                                                       p->dynoverlap = p->maxdynoverlap;
+                                               if (callback)
+                                                       (*callback) (p->dynoverlap, PARANOIA_CB_OVERLAP);
+                                       }
+                               }
+                       }
+               }
+       }
+       p->cursor++;
+
+       return (rv(root) + (beginword - rb(root)));
+}
+
+/*
+ * a temporary hack
+ */
+void paranoia_overlapset(cdrom_paranoia *p, long overlap)
+{
+       p->dynoverlap = overlap * CD_FRAMEWORDS;
+       p->stage1.offpoints = -1;
+}
diff --git a/libparanoia/pmalloc.c b/libparanoia/pmalloc.c
new file mode 100644 (file)
index 0000000..65dee97
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)pmalloc.c       1.3 04/05/15 Copyright 2004 J. Schilling */
+/*
+ *     Paranoia malloc() functions
+ *
+ *     Copyright (c) 2004 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <mconfig.h>
+#include <stdxlib.h>
+#include <standard.h>
+#include <schily.h>
+#include "pmalloc.h"
+
+#ifdef PM_ADD_DEBUG
+static int madd = 8192;
+static int cadd = 8192;
+static int radd = 8192;
+#else
+static int madd = 0;
+/*static int cadd = 0;*/
+static int radd = 0;
+#endif
+
+void _pfree(void *ptr)
+{
+       free(ptr);
+}
+
+void *_pmalloc(size_t size)
+{
+       void    *p;
+
+       p = malloc(size + madd);
+       if (p == NULL)
+               raisecond("NO MEM", 0L);
+       return (p);
+}
+
+void *_pcalloc(size_t nelem, size_t elsize)
+{
+       void    *p;
+#ifdef PM_ADD_DEBUG
+       size_t  n = nelem * elsize;
+
+       n += cadd;
+       p = calloc(1, n);
+#else
+       p = calloc(nelem, elsize);
+#endif
+       if (p == NULL)
+               raisecond("NO MEM", 0L);
+       return (p);
+}
+
+void *_prealloc(void *ptr, size_t size)
+{
+       void    *p;
+
+       p = realloc(ptr, size + radd);
+       if (p == NULL)
+               raisecond("NO MEM", 0L);
+       return (p);
+}
diff --git a/libparanoia/pmalloc.h b/libparanoia/pmalloc.h
new file mode 100644 (file)
index 0000000..f64ad2f
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)pmalloc.h       1.1 04/02/20 Copyright 2004 J. Schilling */
+/*
+ *     Paranoia malloc() functions
+ *
+ *     Copyright (c) 2004 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef        _PMALLOC_H
+#define        _PMALLOC_H
+
+extern void    _pfree(void *ptr);
+extern void    *_pmalloc(size_t size);
+extern void    *_pcalloc(size_t nelem, size_t elsize);
+extern void    *_prealloc(void *ptr, size_t size);
+
+#endif /* _PMALLOC_H */
diff --git a/librols/CMakeLists.txt b/librols/CMakeLists.txt
new file mode 100644 (file)
index 0000000..9aabc7c
--- /dev/null
@@ -0,0 +1,7 @@
+PROJECT (LIBROLS C)
+INCLUDE_DIRECTORIES(../include ../libhfs_iso ${CMAKE_BINARY_DIR} ../wodim ${CMAKE_BINARY_DIR}/include)
+
+SET(LIBROLS_SRCS  astoi.c astoll.c astoull.c breakline.c cmpbytes.c comerr.c error.c fexec.c fillbytes.c getargs.c getav0.c getdomainname.c geterrno.c gethostid.c gethostname.c getpagesize.c handlecond.c movebytes.c raisecond.c rename.c saveargs.c seterrno.c spawn.c strcatl.c strdup.c streql.c swabbytes.c usleep.c stdio/cvmod.c stdio/dat.c stdio/fcons.c stdio/fdown.c stdio/fdup.c stdio/ffileread.c stdio/ffilewrite.c stdio/fgetline.c stdio/file_raise.c stdio/fileclose.c stdio/fileluopen.c stdio/filemopen.c stdio/fileopen.c  stdio/filepos.c stdio/fileread.c stdio/filereopen.c stdio/fileseek.c stdio/filesize.c stdio/filestat.c stdio/filewrite.c stdio/flag.c stdio/flush.c stdio/fpipe.c stdio/niread.c stdio/niwrite.c stdio/nixread.c stdio/nixwrite.c stdio/openfd.c stdio/peekc.c default.c)
+
+ADD_LIBRARY (rols STATIC ${CMAKE_CURRENT_SOURCE_DIR}/../include/xconfig.h  ${CMAKE_CURRENT_SOURCE_DIR}/../include/align.h ${LIBROLS_SRCS})
+
diff --git a/librols/astoi.c b/librols/astoi.c
new file mode 100644 (file)
index 0000000..94c14a3
--- /dev/null
@@ -0,0 +1,151 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)astoi.c 1.8 03/06/15 Copyright 1985, 1995-2003 J. Schilling */
+/*
+ *     astoi() converts a string to int
+ *     astol() converts a string to long
+ *
+ *     Leading tabs and spaces are ignored.
+ *     Both return pointer to the first char that has not been used.
+ *     Caller must check if this means a bad conversion.
+ *
+ *     leading "+" is ignored
+ *     leading "0"  makes conversion octal (base 8)
+ *     leading "0x" makes conversion hex   (base 16)
+ *
+ *     Copyright (c) 1985, 1995-2003 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <standard.h>
+#include <schily.h>
+
+#define        is_space(c)      ((c) == ' ' || (c) == '\t')
+#define        is_digit(c)      ((c) >= '0' && (c) <= '9')
+#define        is_hex(c)       (\
+                       ((c) >= 'a' && (c) <= 'f') || \
+                       ((c) >= 'A' && (c) <= 'F'))
+
+#define        to_lower(c)     (((c) >= 'A' && (c) <= 'Z') ? (c) - 'A'+'a' : (c))
+
+#ifdef notdef
+EXPORT int
+atoi(s)
+       char    *s;
+{
+       long    l;
+
+       (void) astol(s, &l);
+       return ((int) l);
+}
+
+EXPORT long
+atol(s)
+       char    *s;
+{
+       long    l;
+
+       (void) astol(s, &l);
+       return (l);
+}
+#endif
+
+EXPORT char *
+astoi(s, i)
+       const char *s;
+       int *i;
+{
+       long l;
+       char *ret;
+
+       ret = astol(s, &l);
+       *i = l;
+       return (ret);
+}
+
+EXPORT char *
+astol(s, l)
+       register const char *s;
+       long *l;
+{
+       return (astolb(s, l, 0));
+}
+
+EXPORT char *
+astolb(s, l, base)
+       register const char *s;
+       long *l;
+       register int base;
+{
+       int neg = 0;
+       register long ret = 0L;
+       register int digit;
+       register char c;
+
+       while (is_space(*s))
+               s++;
+
+       if (*s == '+') {
+               s++;
+       } else if (*s == '-') {
+               s++;
+               neg++;
+       }
+
+       if (base == 0) {
+               if (*s == '0') {
+                       base = 8;
+                       s++;
+                       if (*s == 'x' || *s == 'X') {
+                               s++;
+                               base = 16;
+                       }
+               } else {
+                       base = 10;
+               }
+       }
+       for (; (c = *s) != 0; s++) {
+
+               if (is_digit(c)) {
+                       digit = c - '0';
+               } else if (is_hex(c)) {
+                       digit = to_lower(c) - 'a' + 10;
+               } else {
+                       break;
+               }
+
+               if (digit < base) {
+                       ret *= base;
+                       ret += digit;
+               } else {
+                       break;
+               }
+       }
+       if (neg)
+               ret = -ret;
+       *l = ret;
+       return ((char *)s);
+}
diff --git a/librols/astoll.c b/librols/astoll.c
new file mode 100644 (file)
index 0000000..1e35808
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)astoll.c        1.3 03/06/15 Copyright 1985, 2000-2003 J. Schilling */
+/*
+ *     astoll() converts a string to long long
+ *
+ *     Leading tabs and spaces are ignored.
+ *     Both return pointer to the first char that has not been used.
+ *     Caller must check if this means a bad conversion.
+ *
+ *     leading "+" is ignored
+ *     leading "0"  makes conversion octal (base 8)
+ *     leading "0x" makes conversion hex   (base 16)
+ *
+ *     Llong is silently reverted to long if the compiler does not
+ *     support long long.
+ *
+ *     Copyright (c) 1985, 2000-2003 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <mconfig.h>
+#include <standard.h>
+#include <utypes.h>
+#include <schily.h>
+
+#define        is_space(c)      ((c) == ' ' || (c) == '\t')
+#define        is_digit(c)      ((c) >= '0' && (c) <= '9')
+#define        is_hex(c)       (\
+                       ((c) >= 'a' && (c) <= 'f') || \
+                       ((c) >= 'A' && (c) <= 'F'))
+
+#define        to_lower(c)     (((c) >= 'A' && (c) <= 'Z') ? (c) - 'A'+'a' : (c))
+
+char *
+astoll(s, l)
+       register const char *s;
+       Llong *l;
+{
+       return (astollb(s, l, 0));
+}
+
+char *
+astollb(s, l, base)
+       register const char *s;
+       Llong *l;
+       register int base;
+{
+       int neg = 0;
+       register Llong ret = (Llong)0;
+       register int digit;
+       register char c;
+
+       while (is_space(*s))
+               s++;
+
+       if (*s == '+') {
+               s++;
+       } else if (*s == '-') {
+               s++;
+               neg++;
+       }
+
+       if (base == 0) {
+               if (*s == '0') {
+                       base = 8;
+                       s++;
+                       if (*s == 'x' || *s == 'X') {
+                               s++;
+                               base = 16;
+                       }
+               } else {
+                       base = 10;
+               }
+       }
+       for (; (c = *s) != 0; s++) {
+
+               if (is_digit(c)) {
+                       digit = c - '0';
+               } else if (is_hex(c)) {
+                       digit = to_lower(c) - 'a' + 10;
+               } else {
+                       break;
+               }
+
+               if (digit < base) {
+                       ret *= base;
+                       ret += digit;
+               } else {
+                       break;
+               }
+       }
+       if (neg)
+               ret = -ret;
+       *l = ret;
+       return ((char *)s);
+}
diff --git a/librols/astoull.c b/librols/astoull.c
new file mode 100644 (file)
index 0000000..6ab6920
--- /dev/null
@@ -0,0 +1,182 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)astoll.c        1.3 03/06/15 Copyright 1985, 2000-2005 J. Schilling */
+/*
+ *     astoll() converts a string to long long
+ *
+ *     Leading tabs and spaces are ignored.
+ *     Both return pointer to the first char that has not been used.
+ *     Caller must check if this means a bad conversion.
+ *
+ *     leading "+" is ignored
+ *     leading "0"  makes conversion octal (base 8)
+ *     leading "0x" makes conversion hex   (base 16)
+ *
+ *     Llong is silently reverted to long if the compiler does not
+ *     support long long.
+ *
+ *     Copyright (c) 1985, 2000-2005 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <mconfig.h>
+#include <standard.h>
+#include <utypes.h>
+#include <schily.h>
+#include <errno.h>
+#ifndef        HAVE_ERRNO_DEF
+extern int     errno;
+#endif
+
+#define        is_space(c)      ((c) == ' ' || (c) == '\t')
+#define        is_digit(c)      ((c) >= '0' && (c) <= '9')
+#define        is_hex(c)       (\
+                       ((c) >= 'a' && (c) <= 'f') || \
+                       ((c) >= 'A' && (c) <= 'F'))
+
+#define        is_lower(c)     ((c) >= 'a' && (c) <= 'z')
+#define        is_upper(c)     ((c) >= 'A' && (c) <= 'Z')
+#define        to_lower(c)     (((c) >= 'A' && (c) <= 'Z') ? (c) - 'A'+'a' : (c))
+
+#if    ('i' + 1) < 'j'
+#define        BASE_MAX        ('i' - 'a' + 10 + 1)    /* This is EBCDIC */
+#else
+#define        BASE_MAX        ('z' - 'a' + 10 + 1)    /* This is ASCII */
+#endif
+
+
+
+EXPORT char *astoull   __PR((const char *s, Ullong *l));
+EXPORT char *astoullb  __PR((const char *s, Ullong *l, int base));
+
+EXPORT char *
+astoull(s, l)
+       register const char *s;
+       Ullong *l;
+{
+       return (astoullb(s, l, 0));
+}
+
+EXPORT char *
+astoullb(s, l, base)
+       register const char *s;
+       Ullong *l;
+       register int base;
+{
+#ifdef DO_SIGNED
+       int neg = 0;
+#endif
+       register Ullong ret = (Ullong)0;
+               Ullong maxmult;
+       register int digit;
+       register char c;
+
+       if (base > BASE_MAX || base == 1 || base < 0) {
+               errno = EINVAL;
+               return ((char *)s);
+       }
+
+       while (is_space(*s))
+               s++;
+
+       if (*s == '+') {
+               s++;
+       } else if (*s == '-') {
+#ifndef        DO_SIGNED
+               errno = EINVAL;
+               return ((char *)s);
+#else
+               s++;
+               neg++;
+#endif
+       }
+
+       if (base == 0) {
+               if (*s == '0') {
+                       base = 8;
+                       s++;
+                       if (*s == 'x' || *s == 'X') {
+                               s++;
+                               base = 16;
+                       }
+               } else {
+                       base = 10;
+               }
+       }
+       maxmult = TYPE_MAXVAL(Ullong) / base;
+       for (; (c = *s) != 0; s++) {
+
+               if (is_digit(c)) {
+                       digit = c - '0';
+#ifdef OLD
+               } else if (is_hex(c)) {
+                       digit = to_lower(c) - 'a' + 10;
+#else
+               } else if (is_lower(c)) {
+                       digit = c - 'a' + 10;
+               } else if (is_upper(c)) {
+                       digit = c - 'A' + 10;
+#endif
+               } else {
+                       break;
+               }
+
+               if (digit < base) {
+                       if (ret > maxmult)
+                               goto overflow;
+                       ret *= base;
+                       if (TYPE_MAXVAL(Ullong) - ret < digit)
+                               goto overflow;
+                       ret += digit;
+               } else {
+                       break;
+               }
+       }
+#ifdef DO_SIGNED
+       if (neg)
+               ret = -ret;
+#endif
+       *l = ret;
+       return ((char *)s);
+overflow:
+       for (; (c = *s) != 0; s++) {
+
+               if (is_digit(c)) {
+                       digit = c - '0';
+               } else if (is_lower(c)) {
+                       digit = c - 'a' + 10;
+               } else if (is_upper(c)) {
+                       digit = c - 'A' + 10;
+               } else {
+                       break;
+               }
+               if (digit >= base)
+                       break;
+       }
+       *l = TYPE_MAXVAL(Ullong);
+       errno = ERANGE;
+       return ((char *)s);
+}
diff --git a/librols/breakline.c b/librols/breakline.c
new file mode 100644 (file)
index 0000000..fe0ab9a
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)breakline.c     1.10 04/09/25 Copyright 1985, 1995-2003 J. Schilling */
+/*
+ *     break a line pointed to by *buf into fields
+ *     returns the number of tokens, the line was broken into (>= 1)
+ *
+ *     delim is the delimiter to break at
+ *     array[0 .. found-1] point to strings from broken line
+ *     array[found ... len] point to '\0'
+ *     len is the size of the array
+ *
+ *     Copyright (c) 1985, 1995-2003 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <mconfig.h>
+#include <standard.h>
+#include <schily.h>
+
+#ifdef PROTOTYPES
+EXPORT int
+breakline(char *buf,
+               register char delim,
+               register char *array[],
+               register int len)
+#else
+EXPORT int
+breakline(buf, delim, array, len)
+               char    *buf;
+       register char   delim;
+       register char   *array[];
+       register int    len;
+#endif
+{
+       register char   *bp = buf;
+       register char   *dp;
+       register int    i;
+       register int    found;
+
+       for (i = 0, found = 1; i < len; i++) {
+               for (dp = bp; *dp != '\0' && *dp != delim; dp++)
+                       /* LINTED */
+                       ;
+
+               array[i] = bp;
+               if (*dp == delim) {
+                       *dp++ = '\0';
+                       found++;
+               }
+               bp = dp;
+       }
+       return (found);
+}
diff --git a/librols/cmpbytes.c b/librols/cmpbytes.c
new file mode 100644 (file)
index 0000000..360635f
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)cmpbytes.c      1.15 03/06/15 Copyright 1988, 1995-2003 J. Schilling */
+/*
+ *     compare data
+ *
+ *     Copyright (c) 1988, 1995-2003 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <standard.h>
+#include <align.h>
+#include <schily.h>
+
+#define        DO8(a)  a; a; a; a; a; a; a; a;
+
+EXPORT int
+cmpbytes(fromp, top, cnt)
+       const void      *fromp;
+       const void      *top;
+       int             cnt;
+{
+       register const char     *from   = (char *)fromp;
+       register const char     *to     = (char *)top;
+       register int            n;
+       register int            i;
+
+       /*
+        * If we change cnt to be unsigned, check for == instead of <=
+        */
+       if ((n = cnt) <= 0)
+               return (cnt);
+
+       /*
+        * Compare byte-wise until properly aligned for a long pointer.
+        */
+       i = sizeof (long) - 1;
+       while (--n >= 0 && --i >= 0 && !l2aligned(from, to)) {
+               if (*to++ != *from++)
+                       goto cdiff;
+       }
+       n++;
+
+       if (n >= (int)(8 * sizeof (long))) {
+               if (l2aligned(from, to)) {
+                       register const long *froml = (const long *)from;
+                       register const long *tol   = (const long *)to;
+                       register int rem = n % (8 * sizeof (long));
+
+                       n /= (8 * sizeof (long));
+                       do {
+                               DO8(
+                                       if (*tol++ != *froml++)
+                                               break;
+                               );
+                       } while (--n > 0);
+
+                       if (n > 0) {
+                               --froml;
+                               --tol;
+                               to = (const char *)tol;
+                               from = (const char *)froml;
+                               goto ldiff;
+                       }
+                       to = (const char *)tol;
+                       from = (const char *)froml;
+                       n = rem;
+               }
+
+               if (n >= 8) {
+                       n -= 8;
+                       do {
+                               DO8(
+                                       if (*to++ != *from++)
+                                               goto cdiff;
+                               );
+                       } while ((n -= 8) >= 0);
+                       n += 8;
+               }
+               if (n > 0) do {
+                       if (*to++ != *from++)
+                               goto cdiff;
+               } while (--n > 0);
+               return (cnt);
+       }
+       if (n > 0) do {
+               if (*to++ != *from++)
+                       goto cdiff;
+       } while (--n > 0);
+       return (cnt);
+ldiff:
+       n = sizeof (long);
+       do {
+               if (*to++ != *from++)
+                       goto cdiff;
+       } while (--n > 0);
+cdiff:
+       return (--from - (char *)fromp);
+}
diff --git a/librols/comerr.c b/librols/comerr.c
new file mode 100644 (file)
index 0000000..7100fef
--- /dev/null
@@ -0,0 +1,268 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)comerr.c        1.29 03/06/15 Copyright 1985-1989, 1995-2003 J. Schilling */
+/*
+ *     Routines for printing command errors
+ *
+ *     Copyright (c) 1985-1989, 1995-2003 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <mconfig.h>
+#include <unixstd.h>           /* include <sys/types.h> try to get size_t */
+#include <stdio.h>             /* Try again for size_t */
+#include <stdxlib.h>           /* Try again for size_t */
+#include <standard.h>
+#include <vadefs.h>
+#include <strdefs.h>
+#include <schily.h>
+#include <errno.h>
+#ifndef        HAVE_STRERROR
+extern char    *sys_errlist[];
+extern int     sys_nerr;
+#endif
+
+EXPORT int     on_comerr       __PR((void (*fun)(int, void *), void *arg));
+EXPORT void    comerr          __PR((const char *, ...));
+EXPORT void    comerrno        __PR((int, const char *, ...));
+EXPORT int     errmsg          __PR((const char *, ...));
+EXPORT int     errmsgno        __PR((int, const char *, ...));
+LOCAL  int     _comerr         __PR((int, int, const char *, va_list));
+EXPORT void    comexit         __PR((int));
+EXPORT char    *errmsgstr      __PR((int));
+
+typedef        struct ex {
+       struct ex *next;
+       void    (*func) __PR((int, void *));
+       void    *arg;
+} ex_t;
+
+LOCAL  ex_t    *exfuncs;
+
+EXPORT int
+on_comerr(func, arg)
+       void    (*func) __PR((int, void *));
+       void    *arg;
+{
+       ex_t    *fp;
+
+       fp = malloc(sizeof (*fp));
+       if (fp == NULL)
+               return (-1);
+
+       fp->func = func;
+       fp->arg  = arg;
+       fp->next = exfuncs;
+       exfuncs = fp;
+       return (0);
+}
+
+/* VARARGS1 */
+#ifdef PROTOTYPES
+EXPORT void
+comerr(const char *msg, ...)
+#else
+EXPORT void
+comerr(msg, va_alist)
+       char    *msg;
+       va_dcl
+#endif
+{
+       va_list args;
+
+#ifdef PROTOTYPES
+       va_start(args, msg);
+#else
+       va_start(args);
+#endif
+       (void) _comerr(TRUE, geterrno(), msg, args);
+       /* NOTREACHED */
+       va_end(args);
+}
+
+/* VARARGS2 */
+#ifdef PROTOTYPES
+EXPORT void
+comerrno(int err, const char *msg, ...)
+#else
+EXPORT void
+comerrno(err, msg, va_alist)
+       int     err;
+       char    *msg;
+       va_dcl
+#endif
+{
+       va_list args;
+
+#ifdef PROTOTYPES
+       va_start(args, msg);
+#else
+       va_start(args);
+#endif
+       (void) _comerr(TRUE, err, msg, args);
+       /* NOTREACHED */
+       va_end(args);
+}
+
+/* VARARGS1 */
+#ifdef PROTOTYPES
+EXPORT int
+errmsg(const char *msg, ...)
+#else
+EXPORT int
+errmsg(msg, va_alist)
+       char    *msg;
+       va_dcl
+#endif
+{
+       va_list args;
+       int     ret;
+
+#ifdef PROTOTYPES
+       va_start(args, msg);
+#else
+       va_start(args);
+#endif
+       ret = _comerr(FALSE, geterrno(), msg, args);
+       va_end(args);
+       return (ret);
+}
+
+/* VARARGS2 */
+#ifdef PROTOTYPES
+EXPORT int
+errmsgno(int err, const char *msg, ...)
+#else
+EXPORT int
+errmsgno(err, msg, va_alist)
+       int     err;
+       char    *msg;
+       va_dcl
+#endif
+{
+       va_list args;
+       int     ret;
+
+#ifdef PROTOTYPES
+       va_start(args, msg);
+#else
+       va_start(args);
+#endif
+       ret = _comerr(FALSE, err, msg, args);
+       va_end(args);
+       return (ret);
+}
+
+#ifdef __BEOS__
+       /*
+        * On BeOS errno is a big negative number (0x80000000 + small number).
+        * We assume that small negative numbers are safe to be used as special
+        * values that prevent printing the errno text.
+        *
+        * We tried to use #if EIO < 0 but this does not work because EIO is
+        * defined to a enum. ENODEV may work as ENODEV is defined to a number
+        * directly.
+        */
+#define        silent_schily_error(e)          ((e) < 0 && (e) >= -1024)
+#else
+       /*
+        * On UNIX errno is a small non-negative number, so we assume that
+        * negative values cannot be a valid errno and don't print the error
+        * string in this case. However the value may still be used as exit()
+        * code if 'exflg' is set.
+        */
+#define        silent_schily_error(e)          ((e) < 0)
+#endif
+LOCAL int
+_comerr(exflg, err, msg, args)
+       int             exflg;
+       int             err;
+       const char      *msg;
+       va_list         args;
+{
+       char    errbuf[20];
+       char    *errnam;
+       char    *prognam = get_progname();
+
+       if (silent_schily_error(err)) {
+               fprintf(stderr, "%s: ", prognam);
+               vfprintf(stderr, msg, args);
+       } else {
+               errnam = errmsgstr(err);
+               if (errnam == NULL) {
+                       (void) snprintf(errbuf, sizeof (errbuf),
+                                               "Error %d", err);
+                       errnam = errbuf;
+               }
+               fprintf(stderr, "%s: %s. ", prognam, errnam);
+               vfprintf(stderr, msg, args);
+       }
+       if (exflg) {
+               comexit(err);
+               /* NOTREACHED */
+       }
+       return (err);
+}
+
+EXPORT void
+comexit(err)
+       int     err;
+{
+       while (exfuncs) {
+               (*exfuncs->func)(err, exfuncs->arg);
+               exfuncs = exfuncs->next;
+       }
+       exit(err);
+       /* NOTREACHED */
+}
+
+EXPORT char *
+errmsgstr(err)
+       int     err;
+{
+#ifdef HAVE_STRERROR
+       /*
+        * POSIX compliance may look strange...
+        */
+       int     errsav = geterrno();
+       char    *ret;
+
+       seterrno(0);
+       ret = strerror(err);
+       err = geterrno();
+       seterrno(errsav);
+
+       if (ret == NULL || err)
+               return (NULL);
+       return (ret);
+#else
+       if (err < 0 || err >= sys_nerr) {
+               return (NULL);
+       } else {
+               return (sys_errlist[err]);
+       }
+#endif
+}
diff --git a/librols/default.c b/librols/default.c
new file mode 100644 (file)
index 0000000..10878c3
--- /dev/null
@@ -0,0 +1,179 @@
+/* 
+ * Copyright 2006 Eduard Bloch 
+ *
+ * Uses my config parser code and small wrappers to provide the old interface.
+ *
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <mconfig.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+
+enum parstate {
+       KEYBEGINSEARCH,
+       KEYCOMPARE,
+       EQSIGNSEARCH,
+       VALBEGINSEARCH,
+       LASTCHARSEARCH
+};
+
+#define GETVAL_BUF_LEN 512
+#define isUspace(x) isspace( (int) (unsigned char) x)
+
+static FILE *glob_cfg_ptr = NULL;
+
+/*
+ * Warning, uses static line buffer, not reentrant. NULL returned if the key isn't found.
+ */
+static char *get_value(FILE *srcfile, const char *key, int dorewind) {
+       static char linebuf[GETVAL_BUF_LEN];
+
+       if(!srcfile)
+               return ((char *) NULL);
+
+       if(dorewind)
+               rewind(srcfile);
+
+       if(!key)
+               return NULL;
+
+next_line:
+       while(fgets(linebuf, sizeof(linebuf)-1, srcfile)) {
+               int i;
+               int keybeg=0;
+               int s=KEYBEGINSEARCH;
+               char *ret=NULL;
+               int lastchar=0;
+
+               /* simple state machine, char position moved by the states (or not),
+                * state change is done by the state (or not) */
+               for( i=0 ; i<sizeof(linebuf) ; ) {
+                       /* printf("key: %s, %s, s: %d\n", key,  linebuf, s); */
+                       switch(s) {
+                               case(KEYBEGINSEARCH):
+                                       {
+                                               if(isUspace(linebuf[i]))
+                                                       i++;
+                                               else if(linebuf[i] == '#' || linebuf[i]=='\0')
+                                                       goto next_line;
+                                               else {
+                                                       s=KEYCOMPARE;
+                                                       keybeg=i;
+                                               }
+                                       }
+                                       break;
+                               case(KEYCOMPARE): /* compare the key */
+                                       {
+                                               if(key[i-keybeg]=='\0') 
+                                                       /* end of key, next state decides what to do on this position */
+                                                       s=EQSIGNSEARCH;
+                                               else {
+                                                       if(linebuf[i-keybeg]!=key[i-keybeg])
+                                                               goto next_line;
+                                                       else
+                                                               i++;
+                                               }
+                                       }
+                                       break;
+                               case(EQSIGNSEARCH): /* skip whitespace, stop on =, break on anything else */
+                                       {
+                                               if(isUspace(linebuf[i]))
+                                                       i++;
+                                               else if(linebuf[i]=='=') {
+                                                       s=VALBEGINSEARCH;
+                                                       i++;
+                                               }
+                                               else
+                                                       goto next_line;
+                                       }
+                                       break;
+                               case(VALBEGINSEARCH):
+                                       {
+                                               if(isUspace(linebuf[i]))
+                                                       i++;
+                                               else {
+                                                       /* possible at EOF */
+                                                       if(linebuf[i] == '\0')
+                                                               return NULL;
+
+                                                       lastchar=i-1; /* lastchar can be a space, see below */
+                                                       ret= & linebuf[i];
+                                                       s=LASTCHARSEARCH;
+                                               }
+                                       }
+                                       break;
+                               case(LASTCHARSEARCH):
+                                       {
+                                               if(linebuf[i]) {
+                                                       if(!isUspace(linebuf[i]))
+                                                               lastchar=i;
+                                               }
+                                               else { /* got string end, terminate after the last seen char */
+                                                       if(linebuf+lastchar < ret) /* no non-space found */
+                                                               return NULL;
+                                                       linebuf[lastchar+1]='\0';
+                                                       return ret;
+                                               }
+                                               i++;
+                                       }
+                                       break;
+                       }
+               }
+       }
+       return NULL;
+}
+
+int cfg_open(const char *name)
+{
+       if(glob_cfg_ptr) {
+               fclose(glob_cfg_ptr);
+               glob_cfg_ptr=NULL;
+       }
+       if(!name) {
+               glob_cfg_ptr=NULL;
+               return 0;
+       }
+       glob_cfg_ptr = fopen(name, "r");
+       return (glob_cfg_ptr ? 0 : -1);
+}
+
+int cfg_close()
+{
+       int r;
+       if(!glob_cfg_ptr)
+               return 0;
+       r=fclose(glob_cfg_ptr);
+       glob_cfg_ptr=NULL;
+       return r;
+}
+
+void cfg_restart()
+{
+       get_value(glob_cfg_ptr, NULL, 1);
+}
+
+char *cfg_get(const char *key)
+{
+       return get_value(glob_cfg_ptr, key, 1);
+}
+
+char *cfg_get_next(const char *key)
+{
+       return get_value(glob_cfg_ptr, key, 0);
+}
diff --git a/librols/error.c b/librols/error.c
new file mode 100644 (file)
index 0000000..d0f1e12
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)error.c 1.13 03/06/15 Copyright 1985, 1989, 1995-2003 J. Schilling */
+/*
+ *     fprintf() on standard error stdio stream
+ *
+ *     Copyright (c) 1985, 1989, 1995-2003 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <mconfig.h>
+#include <stdio.h>
+#include <standard.h>
+#include <vadefs.h>
+#include <schily.h>
+
+/* VARARGS1 */
+#ifdef PROTOTYPES
+EXPORT int
+schily_error(const char *fmt, ...)
+#else
+EXPORT int
+schily_error(fmt, va_alist)
+       char    *fmt;
+       va_dcl
+#endif
+{
+       va_list args;
+       int     ret;
+
+#ifdef PROTOTYPES
+       va_start(args, fmt);
+#else
+       va_start(args);
+#endif
+       ret = vfprintf(stderr, fmt, args);
+       va_end(args);
+       return (ret);
+}
diff --git a/librols/fexec.c b/librols/fexec.c
new file mode 100644 (file)
index 0000000..9136402
--- /dev/null
@@ -0,0 +1,421 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)fexec.c 1.24 04/06/06 Copyright 1985, 1995-2004 J. Schilling */
+/*
+ *     Execute a program with stdio redirection
+ *
+ *     Copyright (c) 1985, 1995-2004 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <mconfig.h>
+#include <stdio.h>
+#include <standard.h>
+#define        rols_fexecl     __nothing_1_    /* prototype in schily.h is wrong */
+#define        rols_fexecle    __nothing_2_    /* prototype in schily.h is wrong */
+#include <schily.h>
+#undef rols_fexecl
+#undef rols_fexecle
+       int rols_fexecl  __PR((const char *, FILE *, FILE *, FILE *, ...));
+       int rols_fexecle __PR((const char *, FILE *, FILE *, FILE *, ...));
+#include <unixstd.h>
+#include <stdxlib.h>
+#include <strdefs.h>
+#include <vadefs.h>
+
+#ifdef JOS
+#      include <error.h>
+#else
+#      include <errno.h>
+#endif
+#include <fctldefs.h>
+#include <dirdefs.h>
+#include <maxpath.h>
+
+#define        MAX_F_ARGS      16
+
+extern char **environ;
+
+LOCAL void      fdcopy __PR((int, int));
+LOCAL void      fdmove __PR((int, int));
+LOCAL const char *chkname __PR((const char *, const char *));
+LOCAL const char *getpath __PR((char * const *));
+
+#ifdef PROTOTYPES
+EXPORT int
+rols_fexecl(const char *name, FILE *in, FILE *out, FILE *err, ...)
+#else
+EXPORT int
+rols_fexecl(name, in, out, err, va_alist)
+       char    *name;
+       FILE    *in;
+       FILE    *out;
+       FILE    *err;
+       va_dcl
+#endif
+{
+       va_list args;
+       int     ac = 0;
+       char    *xav[MAX_F_ARGS];
+       char    **av;
+       char    **pav;
+       char    *p;
+       int     ret;
+
+#ifdef PROTOTYPES
+       va_start(args, err);
+#else
+       va_start(args);
+#endif
+       while (va_arg(args, char *) != NULL)
+               ac++;
+       va_end(args);
+
+       if (ac < MAX_F_ARGS) {
+               pav = av = xav;
+       } else {
+               pav = av = (char **)malloc((ac+1)*sizeof (char *));
+               if (av == 0)
+                       return (-1);
+       }
+
+#ifdef PROTOTYPES
+       va_start(args, err);
+#else
+       va_start(args);
+#endif
+       do {
+               p = va_arg(args, char *);
+               *pav++ = p;
+       } while (p != NULL);
+       va_end(args);
+
+       ret = rols_fexecv(name, in, out, err, ac, av);
+       if (av != xav)
+               free(av);
+       return (ret);
+}
+
+#ifdef PROTOTYPES
+EXPORT int
+rols_fexecle(const char *name, FILE *in, FILE *out, FILE *err, ...)
+#else
+EXPORT int
+rols_fexecle(name, in, out, err, va_alist)
+       char    *name;
+       FILE    *in;
+       FILE    *out;
+       FILE    *err;
+       va_dcl
+#endif
+{
+       va_list args;
+       int     ac = 0;
+       char    *xav[MAX_F_ARGS];
+       char    **av;
+       char    **pav;
+       char    *p;
+       char    **env;
+       int     ret;
+
+#ifdef PROTOTYPES
+       va_start(args, err);
+#else
+       va_start(args);
+#endif
+       while (va_arg(args, char *) != NULL)
+               ac++;
+       env = va_arg(args, char **);
+       va_end(args);
+
+       if (ac < MAX_F_ARGS) {
+               pav = av = xav;
+       } else {
+               pav = av = (char **)malloc((ac+1)*sizeof (char *));
+               if (av == 0)
+                       return (-1);
+       }
+
+#ifdef PROTOTYPES
+       va_start(args, err);
+#else
+       va_start(args);
+#endif
+       do {
+               p = va_arg(args, char *);
+               *pav++ = p;
+       } while (p != NULL);
+       va_end(args);
+
+       ret = rols_fexecve(name, in, out, err, av, env);
+       if (av != xav)
+               free(av);
+       return (ret);
+}
+
+EXPORT int
+rols_fexecv(name, in, out, err, ac, av)
+       const char *name;
+       FILE *in, *out, *err;
+       int ac;
+       char *av[];
+{
+       av[ac] = NULL;                  /*  force list to be null terminated */
+       return (rols_fexecve(name, in, out, err, av, environ));
+}
+
+EXPORT int
+rols_fexecve(name, in, out, err, av, env)
+       const char *name;
+       FILE *in, *out, *err;
+       char * const av[], * const env[];
+{
+       char    nbuf[MAXPATHNAME+1];
+       char    *np;
+       const char *path;
+       int     ret;
+       int     fin;
+       int     fout;
+       int     ferr;
+#ifndef        JOS
+       int     o[3];
+       int     f[3];
+       int     errsav;
+
+       o[0] = o[1] = o[2] = f[0] = f[1] = f[2] = 0;
+#endif
+
+       fflush(out);
+       fflush(err);
+       fin  = fdown(in);
+       fout = fdown(out);
+       ferr = fdown(err);
+#ifdef JOS
+
+       /*
+        * If name contains a pathdelimiter ('/' on unix)
+        * or name is too long ...
+        * try exec without path search.
+        */
+       if (find('/', name) || strlen(name) > MAXFILENAME) {
+               ret = exec_env(name, fin, fout, ferr, av, env);
+
+       } else if ((path = getpath(env)) == NULL) {
+               ret = exec_env(name, fin, fout, ferr, av, env);
+               if ((ret == ENOFILE) && strlen(name) <= (sizeof (nbuf) - 6)) {
+                       strcatl(nbuf, "/bin/", name, (char *)NULL);
+                       ret = exec_env(nbuf, fin, fout, ferr, av, env);
+                       if (ret == EMISSDIR)
+                               ret = ENOFILE;
+               }
+       } else {
+               int     nlen = strlen(name);
+
+               for (;;) {
+                       np = nbuf;
+                       /*
+                        * JOS always uses ':' as PATH Environ separator
+                        */
+                       while (*path != ':' && *path != '\0' &&
+                               np < &nbuf[MAXPATHNAME-nlen-2]) {
+
+                               *np++ = *path++;
+                       }
+                       *np = '\0';
+                       if (*nbuf == '\0')
+                               strcatl(nbuf, name, (char *)NULL);
+                       else
+                               strcatl(nbuf, nbuf, "/", name, (char *)NULL);
+                       ret = exec_env(nbuf, fin, fout, ferr, av, env);
+                       if (ret == EMISSDIR)
+                               ret = ENOFILE;
+                       if (ret != ENOFILE || *path == '\0')
+                               break;
+                       path++;
+               }
+       }
+       return (ret);
+
+#else  /* JOS */
+
+       if (fin != 0) {
+               f[0] = fcntl(0, F_GETFD, 0);
+               o[0] = dup(0);
+               fcntl(o[0], F_SETFD, 1);
+               fdcopy(fin, 0);
+       }
+       if (fout != 1) {
+               f[1] = fcntl(1, F_GETFD, 0);
+               o[1] = dup(1);
+               fcntl(o[1], F_SETFD, 1);
+               fdcopy(fout, 1);
+       }
+       if (ferr != 2) {
+               f[2] = fcntl(2, F_GETFD, 0);
+               o[2] = dup(2);
+               fcntl(o[2], F_SETFD, 1);
+               fdcopy(ferr, 2);
+       }
+       if (fin != 0)
+               close(fin);
+       if (fout != 1)
+               close(fout);
+       if (ferr != 2)
+               close(ferr);
+
+       /*
+        * If name contains a pathdelimiter ('/' on unix)
+        * or name is too long ...
+        * try exec without path search.
+        */
+#ifdef FOUND_MAXFILENAME
+       if (strchr(name, '/') || strlen(name) > (unsigned)MAXFILENAME) {
+#else
+       if (strchr(name, '/')) {
+#endif
+               ret = execve(name, av, env);
+
+       } else if ((path = getpath(env)) == NULL) {
+               ret = execve(name, av, env);
+               if ((geterrno() == ENOENT) && strlen(name) <= (sizeof (nbuf) - 6)) {
+                       strcatl(nbuf, "/bin/", name, (char *)NULL);
+                       ret = execve(nbuf, av, env);
+               }
+       } else {
+               int     nlen = strlen(name);
+
+               for (;;) {
+                       np = nbuf;
+                       while (*path != PATH_ENV_DELIM && *path != '\0' &&
+                               np < &nbuf[MAXPATHNAME-nlen-2]) {
+
+                               *np++ = *path++;
+                       }
+                       *np = '\0';
+                       if (*nbuf == '\0')
+                               strcatl(nbuf, name, (char *)NULL);
+                       else
+                               strcatl(nbuf, nbuf, "/", name, (char *)NULL);
+                       ret = execve(nbuf, av, env);
+                       if (geterrno() != ENOENT || *path == '\0')
+                               break;
+                       path++;
+               }
+       }
+       errsav = geterrno();
+                       /* reestablish old files */
+       if (ferr != 2) {
+               fdmove(2, ferr);
+               fdmove(o[2], 2);
+               if (f[2] == 0)
+                       fcntl(2, F_SETFD, 0);
+       }
+       if (fout != 1) {
+               fdmove(1, fout);
+               fdmove(o[1], 1);
+               if (f[1] == 0)
+                       fcntl(1, F_SETFD, 0);
+       }
+       if (fin != 0) {
+               fdmove(0, fin);
+               fdmove(o[0], 0);
+               if (f[0] == 0)
+                       fcntl(0, F_SETFD, 0);
+       }
+       seterrno(errsav);
+       return (ret);
+
+#endif /* JOS */
+}
+
+#ifndef        JOS
+
+LOCAL void
+fdcopy(fd1, fd2)
+       int     fd1;
+       int     fd2;
+{
+       close(fd2);
+       fcntl(fd1, F_DUPFD, fd2);
+}
+
+LOCAL void
+fdmove(fd1, fd2)
+       int     fd1;
+       int     fd2;
+{
+       fdcopy(fd1, fd2);
+       close(fd1);
+}
+
+#endif
+
+/*----------------------------------------------------------------------------
+|
+|      get PATH from env
+|
++----------------------------------------------------------------------------*/
+
+LOCAL const char *
+getpath(env)
+       char    * const *env;
+{
+       char * const *p = env;
+       const char *p2;
+
+       if (p != NULL) {
+               while (*p != NULL) {
+                       if ((p2 = chkname("PATH", *p)) != NULL)
+                               return (p2);
+                       p++;
+               }
+       }
+       return (NULL);
+}
+
+
+/*----------------------------------------------------------------------------
+|
+| Check if name is in environment.
+| Return pointer to value name is found.
+|
++----------------------------------------------------------------------------*/
+
+LOCAL const char *
+chkname(name, ev)
+       const char      *name;
+       const char      *ev;
+{
+       for (;;) {
+               if (*name != *ev) {
+                       if (*ev == '=' && *name == '\0')
+                               return (++ev);
+                       return (NULL);
+               }
+               name++;
+               ev++;
+       }
+}
diff --git a/librols/fillbytes.c b/librols/fillbytes.c
new file mode 100644 (file)
index 0000000..8d500e9
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)fillbytes.c     1.13 03/06/15 Copyright 1987, 1995-2003 J. Schilling */
+/*
+ *     fill memory with data
+ *
+ *     Copyright (c) 1987, 1995-2003 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <standard.h>
+#include <align.h>
+#include <schily.h>
+
+#define        DO8(a)  a; a; a; a; a; a; a; a;
+
+#define        cval    ((char) lval)
+
+#ifdef PROTOTYPES
+EXPORT char *
+fillbytes(void *tov, int cnt, char val)
+#else
+EXPORT char *
+fillbytes(tov, cnt, val)
+       void    *tov;
+       int     cnt;
+       char    val;
+#endif
+{
+       register char   *to = (char *)tov;
+       register int    n;
+       register long   lval;
+
+       /*
+        * If we change cnt to be unsigned, check for == instead of <=
+        */
+       if ((n = cnt) <= 0)
+               return (to);
+
+       lval = val & 0xFF;
+
+       /*
+        * Assign byte-wise until properly aligned for a long pointer.
+        */
+       while (--n >= 0 && !laligned(to)) {
+               *to++ = cval;
+       }
+       n++;
+
+       if (n >= (int)(8 * sizeof (long))) {
+               register int rem = n % (8 * sizeof (long));
+
+               lval |= (lval<<8);
+               lval |= (lval<<16);
+#if SIZE_LONG > SIZE_INT
+               lval |= (lval<<32);
+#endif
+
+               n /= (8 * sizeof (long));
+               {
+                       register long *tol = (long *)to;
+
+                       do {
+                               DO8 (*tol++ = lval);
+                       } while (--n > 0);
+
+                       to = (char *)tol;
+               }
+               n = rem;
+
+               if (n >= 8) {
+                       n -= 8;
+                       do {
+                               DO8 (*to++ = cval);
+                       } while ((n -= 8) >= 0);
+                       n += 8;
+               }
+               if (n > 0) do {
+                       *to++ = cval;
+               } while (--n > 0);
+               return (to);
+       }
+       if (n > 0) do {
+               *to++ = cval;
+       } while (--n > 0);
+       return (to);
+}
diff --git a/librols/findbytes.c b/librols/findbytes.c
new file mode 100644 (file)
index 0000000..0b56597
--- /dev/null
@@ -0,0 +1,164 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)findbytes.c     1.2 03/06/15 Copyright 2000-2003 J. Schilling */
+/*
+ *     Find a byte with specific value in memory.
+ *
+ *     Copyright (c) 2000-2003 J. Schilling
+ *
+ *     Based on a strlen() idea from Torbjorn Granlund (tege@sics.se) and
+ *     Dan Sahlin (dan@sics.se) and the memchr() suggestion
+ *     from Dick Karpinski (dick@cca.ucsf.edu).
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <mconfig.h>
+#include <stdxlib.h>
+#include <utypes.h>
+#include <align.h>
+#include <standard.h>
+#include <strdefs.h>
+#include <schily.h>
+
+#ifdef PROTOTYPES
+EXPORT char *
+findbytes(const void *vp, int cnt, char val)
+#else
+EXPORT char *
+findbytes(vp, cnt, val)
+               const   void    *vp;
+       register        int     cnt;
+                       char    val;
+#endif
+{
+       register        Uchar   uval = (Uchar)val;
+       register const  Uchar   *cp  = (Uchar *)vp;
+       register const  Ulong   *lp;
+       register        Ulong   lval;
+       register        Ulong   lmask;
+       register        Ulong   magic_mask;
+
+       /*
+        * Test byte-wise until cp is properly aligned for a long pointer.
+        */
+       while (--cnt >= 0 && !laligned(cp)) {
+               if (*cp++ == uval)
+                       return ((char *)--cp);
+       }
+       cnt++;
+
+       /*
+        * The magic mask is a long word where all carry bits a clear.
+        * This are bits 8, 16, 24 ...
+        * In addition, the top bit is not set (e.g bit 31 or 63). The magic
+        * mask will look this way:
+        *
+        * bits:  01111110 11111110 ... 11111110 11111111
+        * bytes: AAAAAAAA BBBBBBBB ... CCCCCCCC DDDDDDDD
+        *
+        * If we add anything to this magic number, no carry bit will change if
+        * it is the first carry bit left to a 0 byte. Adding anything != 0
+        * to the magic number will just turn the carry bit left to the byte
+        * but does not propagate any further.
+        */
+#if SIZE_LONG == 4
+       magic_mask = 0x7EFEFEFFL;
+#else
+#if SIZE_LONG == 8
+       magic_mask = 0x7EFEFEFEFEFEFEFFL;
+#else
+       /*
+        * #error will not work for all compilers (e.g. sunos4)
+        * The following line will abort compilation on all compilers
+        * if none of the above is defines. And that's  what we want.
+        */
+       error   SIZE_LONG has unknown value
+#endif
+#endif
+
+       lmask = val & 0xFF;
+       lmask |= lmask << 8;
+       lmask |= lmask << 16;
+#if SIZE_LONG > 4
+       lmask |= lmask << 32;
+#endif
+#if SIZE_LONG > 8
+       error   SIZE_LONG has unknown value
+#endif
+       for (lp = (const Ulong *)cp; cnt >= sizeof (long); cnt -= sizeof (long)) {
+               /*
+                * We are not looking for 0 bytes so we need to xor with the
+                * long mask of repeated bytes. If any of the bytes matches our
+                * wanted char, we will create a 0 byte in the current long.
+                * But how will we find if at least one byte in a long is zero?
+                *
+                * If we add 'magic_mask' and any of the holes in the magic
+                * mask do not change, we most likely found a 0 byte in the
+                * long word. It is only a most likely match because if bits
+                * 24..30 (ot bits 56..62) are 0 but bit 31 (or bit 63) is set
+                * we will believe that we found a match but there is none.
+                * This will happen if there is 0x80nnnnnn / 0x80nnnnnnnnnnnnnn
+                */
+               lval = (*lp++ ^ lmask);            /* create 0 byte on match */
+               lval = (lval + magic_mask) ^ ~lval; /* set bits unchanged by +*/
+               if ((lval & ~magic_mask) != 0) {   /* a magic hole was set   */
+                       /*
+                        * If any of the hole bits did not change by addition,
+                        * we most likely had a match.
+                        * If this was a correct match, find the matching byte.
+                        */
+                       cp = (const Uchar *)(lp - 1);
+
+                       if (cp[0] == uval)
+                               return ((char *)cp);
+                       if (cp[1] == uval)
+                               return ((char *)&cp[1]);
+                       if (cp[2] == uval)
+                               return ((char *)&cp[2]);
+                       if (cp[3] == uval)
+                               return ((char *)&cp[3]);
+#if SIZE_LONG > 4
+                       if (cp[4] == uval)
+                               return ((char *)&cp[4]);
+                       if (cp[5] == uval)
+                               return ((char *)&cp[5]);
+                       if (cp[6] == uval)
+                               return ((char *)&cp[6]);
+                       if (cp[7] == uval)
+                               return ((char *)&cp[7]);
+#endif
+#if SIZE_LONG > 8
+                       error   SIZE_LONG has unknown value
+#endif
+               }
+       }
+
+       for (cp = (const Uchar *)lp; --cnt >= 0; ) {
+               if (*cp++ == uval)
+                       return ((char *)--cp);
+       }
+       return ((char *)NULL);
+}
diff --git a/librols/getargs.c b/librols/getargs.c
new file mode 100644 (file)
index 0000000..76f1a88
--- /dev/null
@@ -0,0 +1,838 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)getargs.c       2.37 04/09/25 Copyright 1985, 1988, 1994-2003 J. Schilling */
+#define        NEW
+/*
+ *     Copyright (c) 1985, 1988, 1994-2003 J. Schilling
+ *
+ *     1.3.88   Start implementation of release 2
+ */
+/*
+ *     Parse arguments on a command line.
+ *     Format string type specifier (appearing directly after flag name):
+ *             ''      BOOL
+ *             '!'     BOOL with size modifier +++ NEU +++ (XXX nicht fertig)
+ *             '*'     string
+ *             '?'     char
+ *             '#'     number
+ *             '&'     call function
+ *             '+'     inctype                 +++ NEU +++
+ *
+ *     The '#' and '+' types may have size modifiers added:
+ *             'c'/'C' char
+ *             's'/'S' short
+ *             'i'/'I' int     (default)
+ *             'l'/'L' long
+ *             'll'/'LL' long long
+ *
+ *     The format string 'f* ' may be used to disallow -ffoo for f*
+ *
+ *     XXX This is currently only implemented for the '*' format
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/* LINTLIBRARY */
+#include <mconfig.h>
+#include <standard.h>
+#include <utypes.h>
+#include <getargs.h>
+#include <vadefs.h>
+#include <strdefs.h>
+#include <schily.h>
+#include <ctype.h>
+
+#define        NOARGS            0     /* No more args                 */
+#define        NOTAFLAG          1     /* Not a flag type argument     */
+#define        BADFLAG         (-1)    /* Not a valid flag argument    */
+#define        BADFMT          (-2)    /* Error in format string       */
+#define        NOTAFILE        (-3)    /* Seems to be a flag type arg  */
+
+
+       int     _getargs __PR((int *, char *const **, const char *,
+                                                       BOOL, va_list));
+LOCAL  int     dofile __PR((int *, char *const **, const char **));
+LOCAL  int     doflag __PR((int *, char *const **, const char *,
+                                               const char *, BOOL, va_list));
+LOCAL  int     dosflags __PR((const char *, const char *, BOOL, va_list));
+LOCAL  int     checkfmt __PR((const char *));
+LOCAL  int     checkeql __PR((const char *));
+
+LOCAL  va_list va_dummy;
+
+LOCAL  char    fmtspecs[] = "#?*&+";
+/*LOCAL        char    fmtspecs[] = "#?*&+!";*/
+
+#define        isfmtspec(c)            (strchr(fmtspecs, c) != NULL)
+
+/*---------------------------------------------------------------------------
+|
+|      get flags until a non flag type argument is reached
+|
++---------------------------------------------------------------------------*/
+/* VARARGS3 */
+#ifdef PROTOTYPES
+EXPORT int
+getargs(int *pac, char *const **pav, const char *fmt, ...)
+#else
+EXPORT int
+getargs(pac, pav, fmt, va_alist)
+       int     *pac;
+       char    **pav[];
+       char    *fmt;
+       va_dcl
+#endif
+{
+       va_list args;
+       int     ret;
+
+#ifdef PROTOTYPES
+       va_start(args, fmt);
+#else
+       va_start(args);
+#endif
+       ret = _getargs(pac, pav, fmt, TRUE, args);
+       va_end(args);
+       return (ret);
+}
+
+
+/*---------------------------------------------------------------------------
+|
+|      get all flags on the command line, do not stop on files
+|
++---------------------------------------------------------------------------*/
+/* VARARGS3 */
+#ifdef PROTOTYPES
+EXPORT int
+getallargs(int *pac, char *const **pav, const char *fmt, ...)
+#else
+EXPORT int
+getallargs(pac, pav, fmt, va_alist)
+       int     *pac;
+       char    **pav[];
+       char    *fmt;
+       va_dcl
+#endif
+{
+       va_list args;
+       int     ret;
+
+#ifdef PROTOTYPES
+       va_start(args, fmt);
+#else
+       va_start(args);
+#endif
+       for (; ; (*pac)--, (*pav)++) {
+               if ((ret = _getargs(pac, pav, fmt, TRUE, args)) != NOTAFLAG)
+                       break;
+       }
+       va_end(args);
+       return (ret);
+}
+
+
+/*---------------------------------------------------------------------------
+|
+|      get next non flag type argument (i.e. a file)
+|
++---------------------------------------------------------------------------*/
+EXPORT int
+getfiles(pac, pav, fmt)
+       int             *pac;
+       char *const     *pav[];
+       const char      *fmt;
+{
+       return (_getargs(pac, pav, fmt, FALSE, va_dummy));
+}
+
+
+/*---------------------------------------------------------------------------
+|
+|      check args until the next non flag type argmument is reached
+|      *pac is decremented, *pav is incremented so that the
+|      non flag type argument is at *pav[0]
+|
+|      return code:
+|              NOARGS          no more args
+|              NOTAFLAG        not a flag type argument
+|              BADFLAG         a non-matching flag type argument
+|              BADFMT          bad syntax in format string
+|
+|
++---------------------------------------------------------------------------*/
+/*LOCAL*/ int
+_getargs(pac, pav, fmt, setargs, args)
+       register int            *pac;
+       register char   *const  **pav;
+               const char      *fmt;
+               BOOL            setargs;
+               va_list         args;
+{
+       const   char    *argp;
+               int     ret;
+
+
+       for (; *pac > 0; (*pac)--, (*pav)++) {
+               argp = **pav;
+
+               ret = dofile(pac, pav, &argp);
+
+               if (ret != NOTAFILE)
+                       return (ret);
+
+               ret = doflag(pac, pav, argp, fmt, setargs, args);
+
+               if (ret != NOTAFLAG)
+                       return (ret);
+       }
+       return (NOARGS);
+}
+
+
+/*---------------------------------------------------------------------------
+|
+| check if *pargp is a file type argument
+|
++---------------------------------------------------------------------------*/
+LOCAL int
+dofile(pac, pav, pargp)
+       register int            *pac;
+       register char *const    **pav;
+               const char      **pargp;
+{
+       register const char     *argp = *pargp;
+
+
+       if (argp[0] == '-') {
+               /*
+                * "-"  is a special non flag type argument
+                *      that usually means take stdin instead of a named file
+                */
+               if (argp[1] == '\0')
+                       return (NOTAFLAG);
+               /*
+                * "--" is a prefix to take the next argument
+                *      as non flag type argument
+                * NOTE: Posix requires "--" to indicate the end of the
+                *       flags on the command line. But we are currently not
+                *       Posix.
+                */
+               if (argp[1] == '-' && argp[2] == '\0') {
+                       if (--(*pac) > 0) {
+                               (*pav)++;
+                               return (NOTAFLAG);
+                       } else {
+                               return (NOARGS);
+                       }
+               }
+       }
+
+       /*
+        * now check if it may be flag type argument
+        * flag type arguments begin with a '-', a '+' or contain a '='
+        * i.e. -flag +flag or flag=
+        */
+       if (argp[0] != '-' && argp[0] != '+' && (!checkeql(argp)))
+               return (NOTAFLAG);
+
+       return (NOTAFILE);
+}
+
+
+/*---------------------------------------------------------------------------
+|
+|      compare argp with the format string
+|      if a match is found store the result a la scanf in one of the
+|      arguments pointed to in the va_list
+|
+|      If setargs is FALSE, only check arguments for getfiles()
+|      in this case, va_list may be a dummy arg.
+|
++---------------------------------------------------------------------------*/
+LOCAL int
+doflag(pac, pav, argp, fmt, setargs, oargs)
+               int             *pac;
+               char    *const  **pav;
+       register const char     *argp;
+       register const char     *fmt;
+               BOOL            setargs;
+               va_list         oargs;
+{
+       char    argstr[2];
+       long    val;
+       Llong   llval;
+       int     singlecharflag  = 0;
+       BOOL    isspec;
+       BOOL    hasdash         = FALSE;
+       BOOL    doubledash      = FALSE;
+       BOOL    haseql          = checkeql(argp);
+       const char      *sargp;
+       const char      *sfmt   = fmt;
+       va_list args;
+       char    *const  *spav   = *pav;
+       int             spac    = *pac;
+       void            *curarg = (void *)0;
+
+       /*
+        * flags beginning with '-' don't have to include the '-' in
+        * the format string.
+        * flags beginning with '+' have to include it in the format string.
+        */
+       if (argp[0] == '-') {
+               argp++;
+               hasdash = TRUE;
+               /*
+                * Implement legacy support for --longopt
+                * If we find a double dash, we do not look for combinations
+                * of boolean single char flags.
+                */
+               if (argp[0] == '-') {
+                       argp++;
+                       doubledash = TRUE;
+                       /*
+                        * Allow -- only for long options.
+                        */
+                       if (argp[1] == '\0') {
+                               return (BADFLAG);
+                       }
+               }
+       }
+       sargp = argp;
+
+       /*
+        * Initialize 'args' to the start of the argument list.
+        * I don't know any portable way to copy an arbitrary
+        * C object so I use a system-specific routine
+        * (probably a macro) from stdarg.h.  (Remember that
+        * if va_list is an array, 'args' will be a pointer
+        * and '&args' won't be what I would need for memcpy.)
+        * It is a system requirement for SVr4 compatibility
+        * to be able to do this assgignement. If your system
+        * defines va_list to be an array but does not define
+        * va_copy() you are lost.
+        * This is needed to make sure, that 'oargs' will not
+        * be clobbered.
+        */
+       va_copy(args, oargs);
+
+       if (setargs)
+               curarg = va_arg(args, void *);
+
+       /*
+        * check if the first flag in format string is a singlechar flag
+        */
+       if (fmt[1] == ',' || fmt[1] == '+' || fmt[1] == '\0')
+               singlecharflag++;
+       /*
+        * check the whole format string for a match
+        */
+       for (;;) {
+               for (; *fmt; fmt++, argp++) {
+                       if (*fmt == '\\') {
+                               /*
+                                * Allow "#?*&+" to appear inside a flag.
+                                * NOTE: they must be escaped by '\\' only
+                                *       inside the the format string.
+                                */
+                               fmt++;
+                               isspec = FALSE;
+                       } else {
+                               isspec = isfmtspec(*fmt);
+                       }
+                       /*
+                        * If isspec is TRUE, the arg beeing checked starts
+                        * like a valid flag. Argp now points to the rest.
+                        */
+                       if (isspec) {
+                               /*
+                                * If *argp is '+' and we are on the
+                                * beginning of the arg that is currently
+                                * checked, this cannot be an inc type flag.
+                                */
+                               if (*argp == '+' && argp == sargp)
+                                       continue;
+                               /*
+                                * skip over to arg of flag
+                                */
+                               if (*argp == '=') {
+                                       argp++;
+                               } else if (*argp != '\0' && haseql) {
+                                       /*
+                                        * Flag and arg are not separated by a
+                                        * space.
+                                        * Check here for:
+                                        * xxxxx=yyyyy  match on '&'
+                                        * Checked before:
+                                        * abc=yyyyy    match on 'abc&'
+                                        *              or       'abc*'
+                                        *              or       'abc#'
+                                        * We come here if 'argp' starts with
+                                        * the same sequence as a valid flag
+                                        * and contains an equal sign.
+                                        * We have tested before if the text
+                                        * before 'argp' matches exactly.
+                                        * At this point we have no exact match
+                                        * and we only allow to match
+                                        * the special pattern '&'.
+                                        * We need this e.g. for 'make'.
+                                        * We allow any flag type argument to
+                                        * match the format string "&" to set
+                                        * up a function that handles all odd
+                                        * stuff that getargs will not grok.
+                                        * In addition, to allow getargs to be
+                                        * used for CPP type flags we allow to
+                                        * match -Dabc=xyz on 'D&'. Note that
+                                        * Dabc=xyz will not match 'D&'.
+                                        */
+                                       if ((!hasdash && argp != sargp) || *fmt != '&')
+                                               goto nextarg;
+                               }
+
+                               /*
+                                * The format string 'f* ' may be used
+                                * to disallow -ffoo for f*
+                                *
+                                * XXX This is currently only implemented for
+                                * XXX the '*' format
+                                */
+                               if (!haseql && *argp != '\0' && fmt[0] == '*' && fmt[1] == ' ')
+                                       goto nextarg;
+                               /*
+                                * *arpp == '\0' || !haseql
+                                * We come here if 'argp' starts with
+                                * the same sequence as a valid flag.
+                                * This will match on the following args:
+                                * -farg        match on 'f*'
+                                * -f12         match on 'f#'
+                                * +12          match on '+#'
+                                * -12          match on '#'
+                                * and all args that are separated from
+                                * their flags.
+                                * In the switch statement below, we check
+                                * if the text after 'argp' (if *argp != 0) or
+                                * the next arg is a valid arg for this flag.
+                                */
+                               break;
+                       } else if (*fmt == *argp) {
+                               if (argp[1] == '\0' &&
+                                   (fmt[1] == '\0' || fmt[1] == ',')) {
+
+                                       if (setargs)
+                                               *((int *)curarg) = TRUE;
+
+
+                                       return (checkfmt(fmt)); /* XXX */
+                               }
+                       } else {
+                               /*
+                                * skip over to next format identifier
+                                * & reset arg pointer
+                                */
+                       nextarg:
+                               while (*fmt != ',' && *fmt != '\0') {
+                                       /* function has extra arg on stack */
+                                       if (*fmt == '&' && setargs)
+                                               curarg = va_arg(args, void *);
+                                       fmt++;
+                               }
+                               argp = sargp;
+                               break;
+                       }
+               }
+               switch (*fmt) {
+
+               case '\0':
+                       /*
+                        * Boolean type has been tested before.
+                        */
+                       if (singlecharflag && !doubledash &&
+                           (val = dosflags(sargp, sfmt, setargs, oargs)) !=
+                                                               BADFLAG)
+                               return (val);
+
+
+                       return (BADFLAG);
+
+               case ',':
+                       fmt++;
+                       if (fmt[1] == ',' || fmt[1] == '+' || fmt[1] == '\0')
+                               singlecharflag++;
+                       if (setargs)
+                               curarg = va_arg(args, void *);
+                       continue;
+
+               case '*':
+                       if (*argp == '\0') {
+                               if (*pac > 1) {
+                                       (*pac)--;
+                                       (*pav)++;
+                                       argp = **pav;
+                               } else {
+                                       return (BADFLAG);
+                               }
+                       }
+                       if (fmt[1] == ' ')      /* To disallow -ffoo for f* */
+                               fmt++;
+                       if (setargs)
+                               *((const char **)curarg) = argp;
+
+
+                       return (checkfmt(fmt));
+
+               case '?':
+                       /*
+                        * If more than one char arg, it
+                        * cannot be a character argument.
+                        */
+                       if (argp[1] != '\0')
+                               goto nextchance;
+                       if (setargs)
+                               *((char *)curarg) = *argp;
+
+
+                       return (checkfmt(fmt));
+
+               case '+':
+                       /*
+                        * inc type is similar to boolean,
+                        * there is no arg in argp to convert.
+                        */
+                       if (*argp != '\0')
+                               goto nextchance;
+                       /*
+                        * If *fmt is '+' and we are on the beginning
+                        * of the format desciptor that is currently
+                        * checked, this cannot be an inc type flag.
+                        */
+                       if (fmt == sfmt || fmt[-1] == ',')
+                               goto nextchance;
+
+                       if (fmt[1] == 'l' || fmt[1] == 'L') {
+                               if (fmt[2] == 'l' || fmt[2] == 'L') {
+                                       if (setargs)
+                                               *((Llong *)curarg) += 1;
+                                       fmt += 2;
+                               } else {
+                                       if (setargs)
+                                               *((long *)curarg) += 1;
+                                       fmt++;
+                               }
+                       } else if (fmt[1] == 's' || fmt[1] == 'S') {
+                               if (setargs)
+                                       *((short *)curarg) += 1;
+                               fmt++;
+                       } else if (fmt[1] == 'c' || fmt[1] == 'C') {
+                               if (setargs)
+                                       *((char *)curarg) += 1;
+                               fmt++;
+                       } else {
+                               if (fmt[1] == 'i' || fmt[1] == 'I')
+                                       fmt++;
+                               if (setargs)
+                                       *((int *)curarg) += 1;
+                       }
+
+                       argstr[0] = *fmt;
+                       argstr[1] = '\0';
+
+                       return (checkfmt(fmt));
+
+               case '#':
+                       if (*argp == '\0') {
+                               if (*pac > 1) {
+                                       (*pac)--;
+                                       (*pav)++;
+                                       argp = **pav;
+                               } else {
+                                       return (BADFLAG);
+                               }
+                       }
+                       if (*astoll(argp, &llval) != '\0') {
+                               /*
+                                * arg is not a valid number!
+                                * go to next format in the format string
+                                * and check if arg matches any other type
+                                * in the format specs.
+                                */
+                       nextchance:
+                               while (*fmt != ',' && *fmt != '\0') {
+                                       if (*fmt == '&' && setargs)
+                                               curarg = va_arg(args, void *);
+                                       fmt++;
+                               }
+                               argp = sargp;
+                               *pac = spac;
+                               *pav = spav;
+                               continue;
+                       }
+                       val = (long)llval;
+                       if (fmt[1] == 'l' || fmt[1] == 'L') {
+                               if (fmt[2] == 'l' || fmt[2] == 'L') {
+                                       if (setargs)
+                                               *((Llong *)curarg) = llval;
+                                       fmt += 2;
+                               } else {
+                                       if (setargs)
+                                               *((long *)curarg) = val;
+                                       fmt++;
+                               }
+                       } else if (fmt[1] == 's' || fmt[1] == 'S') {
+                               if (setargs)
+                                       *((short *)curarg) = (short)val;
+                               fmt++;
+                       } else if (fmt[1] == 'c' || fmt[1] == 'C') {
+                               if (setargs)
+                                       *((char *)curarg) = (char)val;
+                               fmt++;
+                       } else {
+                               if (fmt[1] == 'i' || fmt[1] == 'I')
+                                       fmt++;
+                               if (setargs)
+                                       *((int *)curarg) = (int)val;
+                       }
+                       argstr[0] = *fmt;
+                       argstr[1] = '\0';
+
+                       return (checkfmt(fmt));
+
+               case '&':
+                       if (*argp == '\0') {
+                               if (*pac > 1) {
+                                       (*pac)--;
+                                       (*pav)++;
+                                       argp = **pav;
+                               } else {
+                                       return (BADFLAG);
+                               }
+                       }
+
+                       if ((val = checkfmt(fmt)) != NOTAFLAG)
+                               return (val);
+
+                       if (setargs) {
+                               int     ret;
+                               void    *funarg = va_arg(args, void *);
+
+                               ret = ((*(getargfun)curarg) (argp, funarg));
+                               if (ret != NOTAFILE)
+                                       return (ret);
+                               fmt++;
+                       } else {
+                               return (val);
+                       }
+                       /*
+                        * Called function returns NOTAFILE: try next format.
+                        */
+               }
+       }
+}
+
+
+/*---------------------------------------------------------------------------
+|
+|      parse args for combined single char flags
+|
++---------------------------------------------------------------------------*/
+typedef struct {
+       void    *curarg;        /* The pointer to the arg to modify      */
+       short   count;          /* The number of times a sc flag appears */
+       char    c;              /* The single char flag character        */
+       char    type;           /* The type of the single char flag      */
+} sflags;
+
+LOCAL int
+dosflags(argp, fmt, setargs, oargs)
+       register const char     *argp;
+       register const char     *fmt;
+               BOOL            setargs;
+               va_list         oargs;
+{
+#define        MAXSF   32
+               sflags  sf[MAXSF];
+               va_list args;
+       register sflags *rsf    = sf;
+       register int    nsf     = 0;
+       register const char *p  = argp;
+       register int    i;
+       register void   *curarg = (void *)0;
+               char    type;
+
+       /*
+        * Initialize 'args' to the start of the argument list.
+        * I don't know any portable way to copy an arbitrary
+        * C object so I use a system-specific routine
+        * (probably a macro) from stdarg.h.  (Remember that
+        * if va_list is an array, 'args' will be a pointer
+        * and '&args' won't be what I would need for memcpy.)
+        * It is a system requirement for SVr4 compatibility
+        * to be able to do this assgignement. If your system
+        * defines va_list to be an array but does not define
+        * va_copy() you are lost.
+        * This is needed to make sure, that 'oargs' will not
+        * be clobbered.
+        */
+       va_copy(args, oargs);
+
+       if (setargs)
+               curarg = va_arg(args, void *);
+
+       while (*p) {
+               for (i = 0; i < nsf; i++) {
+                       if (rsf[i].c == *p)
+                               break;
+               }
+               if (i >= MAXSF)
+                       return (BADFLAG);
+               if (i == nsf) {
+                       rsf[i].curarg = (void *)0;
+                       rsf[i].count = 0;
+                       rsf[i].c = *p;
+                       rsf[i].type = (char)-1;
+                       nsf++;
+               }
+               rsf[i].count++;
+               p++;
+       }
+
+       while (*fmt) {
+               if (!isfmtspec(*fmt) &&
+                   (fmt[1] == ',' || fmt[1] == '+' || fmt[1] == '\0') &&
+                   strchr(argp, *fmt)) {
+                       for (i = 0; i < nsf; i++) {
+                               if (rsf[i].c == *fmt) {
+                                       if (fmt[1] == '+') {
+                                               fmt++;
+                                               if (fmt[1] == ',' ||
+                                                   fmt[1] == '\0') {
+                                                       rsf[i].type = 'i';
+                                               } else if ((fmt[1] == 'l' ||
+                                                           fmt[1] == 'L') &&
+                                                           (fmt[2] == 'l' ||
+                                                           fmt[2] == 'L')) {
+                                                       /*
+                                                        * Type 'Q'uad (ll)
+                                                        */
+                                                       rsf[i].type = 'Q';
+                                                       fmt++;
+                                               } else {
+                                                       /*
+                                                        * Type 'l','i','s','c'
+                                                        */
+                                                       rsf[i].type = fmt[1];
+                                               }
+                                       } else {
+                                               /*
+                                                * ',' or '\0' for BOOL
+                                                */
+                                               rsf[i].type = fmt[1];
+                                       }
+                                       rsf[i].curarg = curarg;
+                                       break;
+                               }
+                       }
+               }
+               while (*fmt != ',' && *fmt != '\0') {
+                       /* function has extra arg on stack */
+                       if (*fmt == '&' && setargs)
+                               curarg = va_arg(args, void *);
+                       fmt++;
+               }
+               if (*fmt != '\0')
+                       fmt++;
+
+               if (setargs)
+                       curarg = va_arg(args, void *);
+       }
+       for (i = 0; i < nsf; i++) {
+               type = rsf[i].type;
+               if (type == (char)-1) {
+                       return (BADFLAG);
+               }
+               if (rsf[i].curarg) {
+                       if (type == ',' || type == '\0') {
+                               *((int *)rsf[i].curarg) = TRUE;
+                       } else if (type == 'i' || type == 'I') {
+                               *((int *)rsf[i].curarg) += rsf[i].count;
+                       } else if (type == 'l' || type == 'L') {
+                               *((long *)rsf[i].curarg) += rsf[i].count;
+                       } else if (type == 'Q') {
+                               *((Llong *)rsf[i].curarg) += rsf[i].count;
+                       } else if (type == 's' || type == 'S') {
+                               *((short *)rsf[i].curarg) += rsf[i].count;
+                       } else if (type == 'c' || type == 'C') {
+                               *((char *)rsf[i].curarg) += rsf[i].count;
+                       } else {
+                               return (BADFLAG);
+                       }
+               }
+       }
+       return (NOTAFLAG);
+}
+
+/*---------------------------------------------------------------------------
+|
+|      If the next format character is a comma or the string delimiter,
+|      there are no invalid format specifiers. Return success.
+|      Otherwise raise the getarg_bad_format condition.
+|
++---------------------------------------------------------------------------*/
+LOCAL int
+checkfmt(fmt)
+       const char      *fmt;
+{
+       char    c;
+
+       c = *(++fmt);   /* non constant expression */
+
+
+       if (c == ',' || c == '\0') {
+               return (NOTAFLAG);
+       } else {
+               raisecond("getarg_bad_format", (long)fmt);
+               return (BADFMT);
+       }
+}
+
+/*---------------------------------------------------------------------------
+|
+|      Parse the string as long as valid characters can be found.
+|      Valid flag identifiers are chosen from the set of
+|      alphanumeric characters, '-' and '_'.
+|      If the next character is an equal sign the string
+|      contains a valid flag identifier.
+|
++---------------------------------------------------------------------------*/
+LOCAL int
+checkeql(str)
+       register const char *str;
+{
+       register unsigned char c;
+
+       for (c = (unsigned char)*str;
+                               isalnum(c) || c == '_' || c == '-'; c = *str++)
+               /* LINTED */
+               ;
+       return (c == '=');
+}
diff --git a/librols/getav0.c b/librols/getav0.c
new file mode 100644 (file)
index 0000000..3b7e2f4
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)getav0.c        1.16 04/05/09 Copyright 1985, 1995-2004 J. Schilling */
+/*
+ *     Get arg vector by scanning the stack
+ *
+ *     Copyright (c) 1985, 1995-2004 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <mconfig.h>
+#include <sigblk.h>
+#include <avoffset.h>
+#include <standard.h>
+#include <schily.h>
+
+#if    !defined(AV_OFFSET) || !defined(FP_INDIR)
+#      ifdef   HAVE_SCANSTACK
+#      undef   HAVE_SCANSTACK
+#      endif
+#endif
+
+#ifdef HAVE_SCANSTACK
+
+#include <stkframe.h>
+
+#define        is_even(p)      ((((long)(p)) & 1) == 0)
+#define        even(p)         (((long)(p)) & ~1L)
+#ifdef __future__
+#define        even(p)         (((long)(p)) - 1) /* will this work with 64 bit ?? */
+#endif
+
+EXPORT char    **getmainfp     __PR((void));
+EXPORT char    **getavp        __PR((void));
+EXPORT char    *getav0         __PR((void));
+
+
+EXPORT char **
+getmainfp()
+{
+       register struct frame *fp;
+               char    **av;
+#if    FP_INDIR > 0
+       register int    i = 0;
+#endif
+
+       /*
+        * As the SCO OpenServer C-Compiler has a bug that may cause
+        * the first function call to getfp() been done before the
+        * new stack frame is created, we call getfp() twice.
+        */
+       (void) getfp();
+       fp = (struct frame *)getfp();
+       if (fp == NULL)
+               return (NULL);
+
+       while (fp->fr_savfp) {
+               if (fp->fr_savpc == NULL)
+                       break;
+
+               if (!is_even(fp->fr_savfp)) {
+                       fp = (struct frame *)even(fp->fr_savfp);
+                       if (fp == NULL)
+                               break;
+                       fp = (struct frame *)((SIGBLK *)fp)->sb_savfp;
+                       continue;
+               }
+               fp = (struct frame *)fp->fr_savfp;
+
+#if    FP_INDIR > 0
+               i++;
+#endif
+       }
+
+#if    FP_INDIR > 0
+       i -= FP_INDIR;
+       fp = (struct frame *)getfp();
+       if (fp == NULL)
+               return (NULL);
+
+       while (fp->fr_savfp) {
+               if (fp->fr_savpc == NULL)
+                       break;
+
+               if (!is_even(fp->fr_savfp)) {
+                       fp = (struct frame *)even(fp->fr_savfp);
+                       if (fp == NULL)
+                               break;
+                       fp = (struct frame *)((SIGBLK *)fp)->sb_savfp;
+                       continue;
+               }
+               fp = (struct frame *)fp->fr_savfp;
+
+               if (--i <= 0)
+                       break;
+       }
+#endif
+
+       av = (char **)fp;
+       return (av);
+}
+
+EXPORT char **
+getavp()
+{
+       register struct frame *fp;
+               char    **av;
+
+       fp = (struct frame *)getmainfp();
+       if (fp == NULL)
+               return (NULL);
+
+       av = (char **)(((char *)fp) + AV_OFFSET);       /* aus avoffset.h */
+                                                       /* -> avoffset.c  */
+       return (av);
+}
+
+EXPORT char *
+getav0()
+{
+       return (getavp()[0]);
+}
+
+#else
+
+EXPORT char *
+getav0()
+{
+       return ("???");
+}
+
+#endif /* HAVE_SCANSTACK */
diff --git a/librols/getdomainname.c b/librols/getdomainname.c
new file mode 100644 (file)
index 0000000..8338770
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)getdomainname.c 1.16 03/06/15 Copyright 1995-2003 J. Schilling */
+/*
+ *     Copyright (c) 1995-2003 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <mconfig.h>
+#include <standard.h>
+#include <stdxlib.h>
+#ifdef HAVE_SYS_SYSTEMINFO_H
+#include <sys/systeminfo.h>
+#endif
+#include <libport.h>
+
+#ifndef        HAVE_GETDOMAINNAME
+EXPORT int     getdomainname   __PR((char *name, int namelen));
+#endif
+
+
+/*#undef       HAVE_GETDOMAINNAME*/
+/*#undef       SI_SRPC_DOMAIN*/
+
+#if    !defined(HAVE_GETDOMAINNAME) && defined(SI_SRPC_DOMAIN)
+#define        FUNC_GETDOMAINNAME
+
+EXPORT int
+getdomainname(name, namelen)
+       char    *name;
+       int     namelen;
+{
+       if (sysinfo(SI_SRPC_DOMAIN, name, namelen) < 0)
+               return (-1);
+       return (0);
+}
+#endif
+
+#if    !defined(HAVE_GETDOMAINNAME) && !defined(FUNC_GETDOMAINNAME)
+#define        FUNC_GETDOMAINNAME
+
+#include <stdio.h>
+#include <strdefs.h>
+#include <schily.h>
+
+EXPORT int
+getdomainname(name, namelen)
+       char    *name;
+       int     namelen;
+{
+       FILE    *f;
+       char    name1[1024];
+       char    *p;
+       char    *p2;
+
+       name[0] = '\0';
+
+       f = fileopen("/etc/resolv.conf", "r");
+
+       if (f == NULL)
+               return (-1);
+
+       while (rols_fgetline(f, name1, sizeof (name1)) >= 0) {
+               if ((p = strchr(name1, '#')) != NULL)
+                       *p = '\0';
+
+               /*
+                * Skip leading whitespace.
+                */
+               p = name1;
+               while (*p != '\0' && (*p == ' ' || *p == '\t'))
+                       p++;
+
+               if (strncmp(p, "domain", 6) == 0) {
+                       p += 6;
+                       while (*p != '\0' && (*p == ' ' || *p == '\t'))
+                               p++;
+                       if ((p2 = strchr(p, ' ')) != NULL)
+                               *p2 = '\0';
+                       if ((p2 = strchr(p, '\t')) != NULL)
+                               *p2 = '\0';
+
+                       strncpy(name, p, namelen);
+
+                       fclose(f);
+                       return (0);
+               }
+       }
+       fclose(f);
+       return (0);
+}
+#endif
diff --git a/librols/geterrno.c b/librols/geterrno.c
new file mode 100644 (file)
index 0000000..8e60e78
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)geterrno.c      1.9 03/06/15 Copyright 1985, 1995-2003 J. Schilling */
+/*
+ *     Get error number
+ *
+ *     Copyright (c) 1985, 1995-2003 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <errno.h>
+#include <standard.h>
+#include <schily.h>
+
+#ifndef        HAVE_ERRNO_DEF
+extern int     errno;
+#endif
+
+#ifdef geterrno
+#undef geterrno
+#endif
+
+EXPORT int
+geterrno()
+
+{
+       return (errno);
+}
diff --git a/librols/gethostid.c b/librols/gethostid.c
new file mode 100644 (file)
index 0000000..1b4fe02
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)gethostid.c     1.15 03/06/15 Copyright 1995-2003 J. Schilling */
+/*
+ *     Copyright (c) 1995-2003 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <mconfig.h>
+#include <standard.h>
+#include <stdxlib.h>
+#include <utypes.h>
+#ifdef HAVE_SYS_SYSTEMINFO_H
+#include <sys/systeminfo.h>
+#endif
+#include <libport.h>
+
+#ifndef        HAVE_GETHOSTID
+EXPORT long    gethostid       __PR((void));
+#endif
+
+
+#if    !defined(HAVE_GETHOSTID)
+
+#if    defined(SI_HW_SERIAL)
+
+EXPORT long
+gethostid()
+{
+       long    id;
+
+       char    hbuf[257];
+       sysinfo(SI_HW_SERIAL, hbuf, sizeof (hbuf));
+       id = atoi(hbuf);
+       return (id);
+}
+#else
+
+#include <errno.h>
+EXPORT long
+gethostid()
+{
+       long    id = -1L;
+
+#ifdef ENOSYS
+       seterrno(ENOSYS);
+#else
+       seterrno(EINVAL);
+#endif
+       return (id);
+}
+#endif
+
+#endif
diff --git a/librols/gethostname.c b/librols/gethostname.c
new file mode 100644 (file)
index 0000000..483ee7f
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)gethostname.c   1.15 03/10/04 Copyright 1995 J. Schilling */
+/*
+ *     Copyright (c) 1995 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <mconfig.h>
+#include <standard.h>
+#include <stdxlib.h>
+#ifdef HAVE_SYS_SYSTEMINFO_H
+#include <sys/systeminfo.h>
+#endif
+#include <libport.h>
+
+#ifndef        HAVE_GETHOSTNAME
+EXPORT int     gethostname     __PR((char *name, int namelen));
+
+
+#ifdef SI_HOSTNAME
+
+EXPORT int
+gethostname(name, namelen)
+       char    *name;
+       int     namelen;
+{
+       if (sysinfo(SI_HOSTNAME, name, namelen) < 0)
+               return (-1);
+       return (0);
+}
+#else
+
+#if    defined(HAVE_UNAME) && defined(HAVE_SYS_UTSNAME_H)
+#include <sys/utsname.h>
+#include <strdefs.h>
+
+EXPORT int
+gethostname(name, namelen)
+       char    *name;
+       int     namelen;
+{
+       struct utsname  uts;
+
+       if (uname(&uts) < 0)
+               return (-1);
+
+       strncpy(name, uts.nodename, namelen);
+       return (0);
+}
+#endif
+
+#endif
+
+#endif /* HAVE_GETHOSTNAME */
diff --git a/librols/getpagesize.c b/librols/getpagesize.c
new file mode 100644 (file)
index 0000000..8a98edd
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)getpagesize.c   1.1 01/11/28 Copyright 2001 J. Schilling */
+/*
+ *     Copyright (c) 2001 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <mconfig.h>
+
+#ifndef        HAVE_GETPAGESIZE
+
+#include <unixstd.h>
+#include <standard.h>
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+#include <libport.h>
+
+#ifdef HAVE_OS_H
+#include <OS.h>                /* BeOS for B_PAGE_SIZE */
+#endif
+
+int getpagesize(void)
+{
+#ifdef _SC_PAGESIZE
+       return sysconf(_SC_PAGESIZE);
+#else
+# ifdef PAGESIZE               /* Traditional UNIX page size from param.h */
+       return PAGESIZE;
+# else
+
+#  ifdef B_PAGE_SIZE           /* BeOS page size from OS.h */
+       return B_PAGE_SIZE;
+#  else
+       return 512;
+#  endif
+# endif
+#endif
+}
+
+#endif /* HAVE_GETPAGESIZE */
diff --git a/librols/handlecond.c b/librols/handlecond.c
new file mode 100644 (file)
index 0000000..06668b8
--- /dev/null
@@ -0,0 +1,287 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)handlecond.c    1.22 04/05/09 Copyright 1985-2004 J. Schilling */
+/*
+ *     setup/clear a condition handler for a software signal
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/*
+ *     A procedure frame is marked to have handlers if the
+ *     previous freme pointer for this procedure is odd.
+ *     The even base value, in this case actually points to a SIGBLK which
+ *     holds the saved "real" frame pointer.
+ *     The SIGBLK mentioned above may me the start of a chain of SIGBLK's,
+ *     containing different handlers.
+ *
+ *     This will work on processors which support a frame pointer chain
+ *     on the stack.
+ *     On a processor which doesn't support this I think of a method
+ *     where handlecond() has an own chain of frames, holding chains of
+ *     SIGBLK's.
+ *     In this case, a parameter has to be added to handlecond() and
+ *     unhandlecond(). This parameter will be an opaque cookie which is zero
+ *     on the first call to handlecond() in a procedure.
+ *     A new cookie will be returned by handlecond() which must be used on
+ *     each subsequent call to handlecond() and unhandlecond() in the same
+ *     procedure.
+ *
+ *     Copyright (c) 1985-2004 J. Schilling
+ */
+#include <mconfig.h>
+#include <sigblk.h>
+#include <standard.h>
+#include <stdxlib.h>
+#include <strdefs.h>
+#include <avoffset.h>
+#include <utypes.h>
+#include <schily.h>
+
+#if    !defined(AV_OFFSET) || !defined(FP_INDIR)
+#      ifdef   HAVE_SCANSTACK
+#      undef   HAVE_SCANSTACK
+#      endif
+#endif
+
+#ifdef HAVE_SCANSTACK
+#include <stkframe.h>
+#else
+extern SIGBLK  *__roothandle;
+#endif /* HAVE_SCANSTACK */
+
+#define        is_even(p)      ((((long)(p)) & 1) == 0)
+#define        even(p)         (((long)(p)) & ~1L)
+#if defined(__sun) && defined(__i386)
+/*
+ * Solaris x86 has a broken frame.h which defines the frame ptr to int.
+ */
+#define        odd(p)          (((Intptr_t)(p)) | 1)
+#else
+#define        odd(p)          (void *)(((Intptr_t)(p)) | 1)
+#endif
+
+#ifdef __future__
+#define        even(p)         (((long)(p)) - 1) /* will this work with 64 bit ?? */
+#endif
+
+EXPORT void    starthandlecond __PR((SIGBLK *sp));
+
+#ifdef PROTOTYPES
+EXPORT void
+handlecond(const char  *signame,
+               register SIGBLK *sp,
+               int             (*func)(const char *, long, long),
+               long            arg1)
+#else
+EXPORT void
+handlecond(signame, sp, func, arg1)
+               char    *signame;
+       register SIGBLK *sp;
+               BOOL    (*func)();
+               long    arg1;
+#endif
+{
+       register SIGBLK *this;
+       register SIGBLK *last = (SIGBLK *)NULL;
+#ifdef HAVE_SCANSTACK
+       struct frame    *fp   = (struct frame *)NULL;
+#endif
+               int     slen;
+
+       if (signame == NULL || (slen = strlen(signame)) == 0) {
+               raisecond("handle_bad_name", (long)signame);
+               abort();
+       }
+
+#ifdef HAVE_SCANSTACK
+       fp = (struct frame *)getfp();
+       fp = (struct frame *)fp->fr_savfp;      /* point to frame of caller */
+       if (is_even(fp->fr_savfp)) {
+               /*
+                * Easy case: no handlers yet
+                * save real framepointer in sp->sb_savfp
+                */
+               sp->sb_savfp   = (long **)fp->fr_savfp;
+               this = (SIGBLK *)NULL;
+       } else {
+               this = (SIGBLK *)even(fp->fr_savfp);
+       }
+#else
+       this = __roothandle;
+#endif
+
+       for (; this; this = this->sb_signext) {
+               if (this == sp) {
+                       /*
+                        * If a SIGBLK is reused, the name must not change.
+                        */
+                       if (this->sb_signame != NULL &&
+                           !streql(this->sb_signame, signame)) {
+                               raisecond("handle_reused_block", (long)signame);
+                               abort();
+                       }
+                       sp->sb_sigfun = func;
+                       sp->sb_sigarg = arg1;
+                       return;
+               }
+               if (this->sb_signame != NULL &&
+                   streql(this->sb_signame, signame)) {
+                       if (last == (SIGBLK *)NULL) {
+                               /*
+                                * 'this' is the first entry in chain
+                                */
+                               if (this->sb_signext == (SIGBLK *)NULL) {
+                                       /*
+                                        * only 'this' entry is in chain, copy
+                                        * saved real frame pointer into new sp
+                                        */
+                                       sp->sb_savfp = this->sb_savfp;
+                               } else {
+#ifdef HAVE_SCANSTACK
+                                       /*
+                                        * make second entry first link in chain
+                                        */
+                                       this->sb_signext->sb_savfp =
+                                                               this->sb_savfp;
+                                       fp->fr_savfp = odd(this->sb_signext);
+#else
+                                       /*
+                                        * Cannot happen if scanning the stack
+                                        * is not possible...
+                                        */
+                                       raisecond("handle_is_empty", (long)0);
+                                       abort();
+#endif
+                               }
+                               continue;       /* don't trash 'last' ptr */
+                       } else {
+                               last->sb_signext = this->sb_signext;
+                       }
+               }
+               last = this;
+       }
+       sp->sb_signext = (SIGBLK *)NULL;
+       sp->sb_signame = signame;
+       sp->sb_siglen  = slen;
+       sp->sb_sigfun  = func;
+       sp->sb_sigarg  = arg1;
+       /*
+        * If there is a chain append to end of the chain, else make it first
+        */
+       if (last)
+               last->sb_signext = sp;
+#ifdef HAVE_SCANSTACK
+       else
+               fp->fr_savfp = odd(sp);
+#else
+       /*
+        * Cannot happen if scanning the stack is not possible...
+        */
+       else {
+               raisecond("handle_is_empty", (long)0);
+               abort();
+       }
+#endif
+}
+
+EXPORT void
+starthandlecond(sp)
+       register SIGBLK *sp;
+{
+#ifdef HAVE_SCANSTACK
+       struct frame    *fp = NULL;
+
+       /*
+        * As the SCO OpenServer C-Compiler has a bug that may cause
+        * the first function call to getfp() been done before the
+        * new stack frame is created, we call getfp() twice.
+        */
+       (void) getfp();
+#endif
+
+       sp->sb_signext = (SIGBLK *)NULL;
+       sp->sb_signame = NULL;
+       sp->sb_siglen  = 0;
+       sp->sb_sigfun  = (handlefunc_t)NULL;
+       sp->sb_sigarg  = 0;
+
+#ifdef HAVE_SCANSTACK
+       fp = (struct frame *)getfp();
+       fp = (struct frame *)fp->fr_savfp;      /* point to frame of caller */
+
+       if (is_even(fp->fr_savfp)) {
+               /*
+                * Easy case: no handlers yet
+                * save real framepointer in sp
+                */
+               sp->sb_savfp = (long **)fp->fr_savfp;
+               fp->fr_savfp = odd(sp);
+       } else {
+               raisecond("handle_not_empty", (long)0);
+               abort();
+       }
+#else
+       sp->sb_savfp    = (long **)__roothandle;
+       __roothandle    = sp;
+#endif
+}
+
+EXPORT void
+unhandlecond(sp)
+       register SIGBLK *sp;
+{
+#ifdef HAVE_SCANSTACK
+       register struct frame   *fp;
+       register SIGBLK         *sps;
+
+       /*
+        * As the SCO OpenServer C-Compiler has a bug that may cause
+        * the first function call to getfp() been done before the
+        * new stack frame is created, we call getfp() twice.
+        */
+       (void) getfp();
+       fp = (struct frame *)getfp();
+       fp = (struct frame *)fp->fr_savfp;      /* point to frame of caller */
+
+       if (!is_even(fp->fr_savfp)) {                   /* if handlers      */
+               sps = (SIGBLK *)even(fp->fr_savfp);     /* point to SIGBLK  */
+                                                       /* real framepointer */
+#if defined(__sun) && defined(__i386)
+               fp->fr_savfp = (intptr_t)sps->sb_savfp;
+#else
+               fp->fr_savfp = (struct frame *)sps->sb_savfp;
+#endif
+       }
+#else
+       if (__roothandle == NULL) {
+               raisecond("handle_is_empty", (long)0);
+               abort();
+       }
+       /*
+        * Pop top level handler chain.
+        */
+       __roothandle = (SIGBLK *)__roothandle->sb_savfp;
+#endif
+}
diff --git a/librols/movebytes.c b/librols/movebytes.c
new file mode 100644 (file)
index 0000000..3724c99
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)movebytes.c     1.13 03/06/15 Copyright 1985, 1989, 1995-2003 J. Schilling */
+/*
+ *     move data
+ *
+ *     Copyright (c) 1985, 1989, 1995-2003 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <standard.h>
+#include <align.h>
+#include <schily.h>
+
+#define        DO8(a)  a; a; a; a; a; a; a; a;
+
+EXPORT char *
+movebytes(fromv, tov, cnt)
+       const void      *fromv;
+       void            *tov;
+       int             cnt;
+{
+       register const char     *from   = fromv;
+       register char           *to     = tov;
+       register int            n;
+
+       /*
+        * If we change cnt to be unsigned, check for == instead of <=
+        */
+       if ((n = cnt) <= 0)
+               return (to);
+
+       if (from >= to) {
+               /*
+                * source is on higher adresses than destination:
+                *      move bytes forwards
+                */
+               if (n >= (int)(8 * sizeof (long))) {
+                       if (l2aligned(from, to)) {
+                               register const long *froml = (const long *)from;
+                               register long *tol = (long *)to;
+                               register int rem = n % (8 * sizeof (long));
+
+                               n /= (8 * sizeof (long));
+                               do {
+                                       DO8 (*tol++ = *froml++);
+                               } while (--n > 0);
+
+                               from = (const char *)froml;
+                               to = (char *)tol;
+                               n = rem;
+                       }
+
+                       if (n >= 8) {
+                               n -= 8;
+                               do {
+                                       DO8 (*to++ = *from++);
+                               } while ((n -= 8) >= 0);
+                               n += 8;
+                       }
+
+                       if (n > 0) do {
+                               *to++ = *from++;
+                       } while (--n > 0);
+                       return (to);
+               }
+               if (n > 0) do {
+                       *to++ = *from++;
+               } while (--n > 0);
+               return (to);
+       } else {
+               char *ep;
+
+               /*
+                * source is on lower adresses than destination:
+                *      move bytes backwards
+                */
+               to += n;
+               from += n;
+               ep = to;
+               if (n >= (int)(8 * sizeof (long))) {
+                       if (l2aligned(from, to)) {
+                               register const long *froml = (const long *)from;
+                               register long *tol = (long *)to;
+                               register int rem = n % (8 * sizeof (long));
+
+                               n /= (8 * sizeof (long));
+                               do {
+                                       DO8 (*--tol = *--froml);
+                               } while (--n > 0);
+
+                               from = (const char *)froml;
+                               to = (char *)tol;
+                               n = rem;
+                       }
+                       if (n >= 8) {
+                               n -= 8;
+                               do {
+                                       DO8 (*--to = *--from);
+                               } while ((n -= 8) >= 0);
+                               n += 8;
+                       }
+                       if (n > 0) do {
+                               *--to = *--from;
+                       } while (--n > 0);
+                       return (ep);
+               }
+               if (n > 0) do {
+                       *--to = *--from;
+               } while (--n > 0);
+               return (ep);
+       }
+}
diff --git a/librols/raisecond.c b/librols/raisecond.c
new file mode 100644 (file)
index 0000000..01cef9c
--- /dev/null
@@ -0,0 +1,179 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)raisecond.c     1.18 04/05/09 Copyright 1985, 1989, 1995-2004 J. Schilling */
+/*
+ *     raise a condition (software signal)
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/*
+ *     Check for installed condition handlers.
+ *     If a handler is found, the function is called with the appropriate args.
+ *     If no handler is found or no handler signals success,
+ *     the program will be aborted.
+ *
+ *     Copyright (c) 1985, 1989, 1995-2004 J. Schilling
+ */
+#include <mconfig.h>
+#include <stdio.h>
+#include <standard.h>
+#include <sigblk.h>
+#include <unixstd.h>
+#include <stdxlib.h>
+#include <strdefs.h>
+#include <avoffset.h>
+#include <schily.h>
+
+#if    !defined(AV_OFFSET) || !defined(FP_INDIR)
+#      ifdef   HAVE_SCANSTACK
+#      undef   HAVE_SCANSTACK
+#      endif
+#endif
+
+/*
+ * Macros to print to stderr without stdio, to avoid screwing up.
+ */
+#ifndef        STDERR_FILENO
+#define        STDERR_FILENO   2
+#endif
+#define        eprints(a)      do { int ret; ret = write(STDERR_FILENO, (a), sizeof (a)-1); } while (0)
+#define        eprintl(a)      do { int ret; ret = write(STDERR_FILENO, (a), strlen(a)); } while (0)
+
+#define        is_even(p)      ((((long)(p)) & 1) == 0)
+#define        even(p)         (((long)(p)) & ~1L)
+#ifdef __future__
+#define        even(p)         (((long)(p)) - 1) /* will this work with 64 bit ?? */
+#endif
+
+
+LOCAL  void raiseabort  __PR((const char *));
+
+#ifdef HAVE_SCANSTACK
+#include <stkframe.h>
+#define        next_frame(vp)  do {                                                \
+                               if (((struct frame *)(vp))->fr_savfp == 0) { \
+                                       vp = (void *)0;                     \
+                                       break;                              \
+                               }                                           \
+                               if (((struct frame *)(vp))->fr_savpc == 0) { \
+                                       vp = (void *)0;                     \
+                                       break;                              \
+                               }                                           \
+                               vp =                                        \
+                                   (void *)((struct frame *)(vp))->fr_savfp; \
+                       } while (vp != NULL && is_even(vp));                \
+                       vp = (struct frame *)even(vp);
+#else
+EXPORT SIGBLK  *__roothandle;
+
+#define        next_frame(vp)  vp = (((SIGBLK *)(vp))->sb_savfp);
+#endif
+
+LOCAL  BOOL framehandle __PR((SIGBLK *, const char *, const char *, long));
+
+/*
+ *     Loop through the chain of procedure frames on the stack.
+ *
+ *     Frame pointers normally have even values.
+ *     Frame pointers of procedures with an installed handler are marked odd.
+ *     The even base value, in this case actually points to a SIGBLK which
+ *     holds the saved "real" frame pointer.
+ *     The SIGBLK mentioned above may me the start of a chain of SIGBLK's,
+ *     containing different handlers.
+ */
+EXPORT void
+raisecond(signame, arg2)
+       const char      *signame;
+       long            arg2;
+{
+       register void   *vp = NULL;
+
+#ifdef HAVE_SCANSTACK
+       /*
+        * As the SCO OpenServer C-Compiler has a bug that may cause
+        * the first function call to getfp() been done before the
+        * new stack frame is created, we call getfp() twice.
+        */
+       (void) getfp();
+       vp = getfp();
+       next_frame(vp);
+#else
+       vp = __roothandle;
+#endif
+
+       while (vp) {
+               if (framehandle((SIGBLK *)vp, signame, signame, arg2))
+                       return;
+               else if (framehandle((SIGBLK *)vp, "any_other", signame, arg2))
+                       return;
+#ifdef HAVE_SCANSTACK
+               vp = (struct frame *)((SIGBLK *)vp)->sb_savfp;
+#endif
+               next_frame(vp);
+       }
+       /*
+        * No matching handler that signals success found.
+        * Print error message and abort.
+        */
+       raiseabort(signame);
+       /* NOTREACHED */
+}
+
+/*
+ *     Loop through the handler chain for a procedure frame.
+ *
+ *     If no handler with matching name is found, return FALSE,
+ *     otherwise the first handler with matching name is called.
+ *     The return value in the latter case depends on the called function.
+ */
+LOCAL BOOL
+framehandle(sp, handlename, signame, arg2)
+       register SIGBLK *sp;
+       const char      *handlename;
+       const char      *signame;
+       long            arg2;
+{
+       for (; sp; sp = sp->sb_signext) {
+               if (sp->sb_signame != NULL &&
+                   streql(sp->sb_signame, handlename)) {
+                       if (sp->sb_sigfun == NULL) {    /* deactivated */
+                               return (FALSE);
+                       } else {
+                               return (*sp->sb_sigfun)(signame,
+                                                       sp->sb_sigarg, arg2);
+                       }
+               }
+       }
+       return (FALSE);
+}
+
+LOCAL void
+raiseabort(signame)
+       const   char    *signame;
+{
+       eprints("Condition not caught: "); eprintl(signame); eprints(".\n");
+       abort();
+       /* NOTREACHED */
+}
diff --git a/librols/rename.c b/librols/rename.c
new file mode 100644 (file)
index 0000000..dca60ea
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)rename.c        1.6 04/09/04 Copyright 1998-2003 J. Schilling */
+/*
+ *     rename() for old systems that don't have it.
+ *
+ *     Copyright (c) 1998-2003 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#define        rename  __nothing__
+#include <mconfig.h>
+
+#ifndef        HAVE_RENAME
+
+#include <stdio.h>     /* XXX not OK but needed for js_xx() in schily.h */
+#include <unixstd.h>
+#include <strdefs.h>
+#include <statdefs.h>
+#include <maxpath.h>
+#include <standard.h>
+#include <utypes.h>
+#include <schily.h>
+#include <errno.h>
+#undef rename
+#include <libport.h>
+
+#ifndef        MAXPATHNAME
+#define        MAXPATHNAME     1024
+#endif
+
+#if    MAXPATHNAME < 1024
+#undef MAXPATHNAME
+#define        MAXPATHNAME     1024
+#endif
+
+#define        MAXNAME MAXPATHNAME
+
+#define        FILEDESC struct stat
+
+#ifndef        HAVE_LSTAT
+#define        lstat   stat
+#endif
+
+EXPORT int
+rename(old, new)
+       const char      *old;
+       const char      *new;
+{
+       char    nname[MAXNAME];
+       char    bakname[MAXNAME];
+       char    strpid[32];
+       int     strplen;
+       BOOL    savpresent = FALSE;
+       BOOL    newpresent = FALSE;
+       int     serrno;
+       FILEDESC ostat;
+       FILEDESC xstat;
+
+       serrno = geterrno();
+
+       if (lstat(old, &ostat) < 0)
+               return (-1);
+
+       if (lstat(new, &xstat) >= 0) {
+               newpresent = TRUE;
+               if (ostat.st_dev == xstat.st_dev &&
+                   ostat.st_ino == xstat.st_ino)
+                       return (0);             /* old == new we are done */
+       }
+
+       strplen = snprintf(strpid, sizeof (strpid), ".%lld",
+                                                       (Llong)getpid());
+
+       if (strlen(new) <= (MAXNAME-strplen) ||
+           strchr(&new[MAXNAME-strplen], '/') == NULL) {
+               /*
+                * Save old version of file 'new'.
+                */
+               strncpy(nname, new, MAXNAME-strplen);
+               nname[MAXNAME-strplen] = '\0';
+               snprintf(bakname, sizeof (bakname), "%s%s", nname, strpid);
+               unlink(bakname);
+               if (link(new, bakname) >= 0)
+                       savpresent = TRUE;
+       }
+
+       if (newpresent) {
+               if (rmdir(new) < 0) {
+                       if (geterrno() == ENOTDIR) {
+                               if (unlink(new) < 0)
+                                       return (-1);
+                       } else {
+                               return (-1);
+                       }
+               }
+       }
+
+       /*
+        * Now add 'new' name to 'old'.
+        */
+       if (link(old, new) < 0) {
+               serrno = geterrno();
+               /*
+                * Make sure not to loose old version of 'new'.
+                */
+               if (savpresent) {
+                       unlink(new);
+                       link(bakname, new);
+                       unlink(bakname);
+               }
+               seterrno(serrno);
+               return (-1);
+       }
+       if (unlink(old) < 0)
+               return (-1);
+       unlink(bakname);                /* Fails in most cases...       */
+       seterrno(serrno);               /* ...so restore errno          */
+       return (0);
+}
+#endif /* HAVE_RENAME */
diff --git a/librols/saveargs.c b/librols/saveargs.c
new file mode 100644 (file)
index 0000000..c3a0b3c
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)saveargs.c      1.11 03/07/13 Copyright 1995-2003 J. Schilling */
+/*
+ *     save argc, argv for command error printing routines
+ *
+ *     Copyright (c) 1995-2003 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <mconfig.h>
+#include <standard.h>
+#include <strdefs.h>
+#include <stdxlib.h>
+#include <avoffset.h>
+#include <schily.h>
+
+#if    !defined(AV_OFFSET) || !defined(FP_INDIR)
+#      ifdef   HAVE_SCANSTACK
+#      undef   HAVE_SCANSTACK
+#      endif
+#endif
+
+static int     ac_saved;
+static char    **av_saved;
+static char    *av0_saved;
+static char    *progname_saved;
+
+static char    av0_sp[32];     /* av0 space, avoid malloc() in most cases */
+static char    prn_sp[32];     /* name space, avoid malloc() in most cases */
+static char    dfl_str[] = "?";
+
+EXPORT void
+save_args(ac, av)
+       int     ac;
+       char    *av[];
+{
+       int     slen;
+
+       ac_saved = ac;
+       av_saved = av;
+
+       if (av0_saved && av0_saved != av0_sp)
+               free(av0_saved);
+
+       slen = strlen(av[0]) + 1;
+
+       if (slen <= (int)sizeof (av0_sp))
+               av0_saved = av0_sp;
+       else
+               av0_saved = malloc(slen);
+
+       if (av0_saved)
+               strcpy(av0_saved, av[0]);
+}
+
+EXPORT int
+saved_ac()
+{
+       return (ac_saved);
+}
+
+EXPORT char **
+saved_av()
+{
+       return (av_saved);
+}
+
+EXPORT char *
+saved_av0()
+{
+       return (av0_saved);
+}
+
+EXPORT void
+set_progname(name)
+       const char      *name;
+{
+       int     slen;
+
+       if (progname_saved && progname_saved != prn_sp)
+               free(progname_saved);
+
+       slen = strlen(name) + 1;
+
+       if (slen <= sizeof (prn_sp))
+               progname_saved = prn_sp;
+       else
+               progname_saved = malloc(slen);
+
+       if (progname_saved)
+               strcpy(progname_saved, name);
+}
+
+EXPORT char *
+get_progname()
+{
+#ifdef HAVE_SCANSTACK
+       char    *progname;
+#endif
+
+       if (progname_saved)
+               return (progname_saved);
+       if (av0_saved)
+               return (av0_saved);
+#ifdef HAVE_SCANSTACK
+       progname = getav0();            /* scan stack to get argv[0] */
+       if (progname)
+               return (progname);
+#endif
+       return (dfl_str);
+}
diff --git a/librols/seterrno.c b/librols/seterrno.c
new file mode 100644 (file)
index 0000000..39c2c81
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)seterrno.c      1.8 03/06/15 Copyright 1985, 1995-2003 J. Schilling */
+/*
+ *     Set error number
+ *
+ *     Copyright (c) 1985, 1995-2003 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <standard.h>
+#include <errno.h>
+#include <schily.h>
+
+#ifndef        HAVE_ERRNO_DEF
+extern int     errno;
+#endif
+
+#ifdef seterrno
+#undef seterrno
+#endif
+
+EXPORT int
+seterrno(err)
+       int     err;
+{
+       int     old = errno;
+
+       errno = err;
+       return (old);
+}
diff --git a/librols/snprintf.c b/librols/snprintf.c
new file mode 100644 (file)
index 0000000..87b7364
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)snprintf.c      1.9 04/05/09 Copyright 1985, 1996-2004 J. Schilling */
+/*
+ *     Copyright (c) 1985, 1996-2004 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#define        snprintf __nothing__    /* prototype may be wrong (e.g. IRIX) */
+#include <mconfig.h>
+#include <unixstd.h>           /* include <sys/types.h> try to get size_t */
+#include <stdio.h>             /* Try again for size_t */
+#include <stdxlib.h>           /* Try again for size_t */
+#include <vadefs.h>
+#include <standard.h>
+#include <schily.h>
+#undef snprintf
+
+EXPORT int snprintf __PR((char *, size_t maxcnt, const char *, ...));
+
+typedef struct {
+       char    *ptr;
+       int     count;
+} *BUF, _BUF;
+
+#ifdef PROTOTYPES
+static void _cput(char c, long l)
+#else
+static void _cput(c, l)
+       char    c;
+       long    l;
+#endif
+{
+       register BUF    bp = (BUF)l;
+
+       if (--bp->count > 0) {
+               *bp->ptr++ = c;
+       } else {
+               /*
+                * Make sure that there will never be a negative overflow.
+                */
+               bp->count++;
+       }
+}
+
+/* VARARGS2 */
+#ifdef PROTOTYPES
+EXPORT int
+snprintf(char *buf, size_t maxcnt, const char *form, ...)
+#else
+EXPORT int
+snprintf(buf, maxcnt, form, va_alist)
+       char    *buf;
+       unsigned maxcnt;
+       char    *form;
+       va_dcl
+#endif
+{
+       va_list args;
+       int     cnt;
+       _BUF    bb;
+
+       bb.ptr = buf;
+       bb.count = maxcnt;
+
+#ifdef PROTOTYPES
+       va_start(args, form);
+#else
+       va_start(args);
+#endif
+       cnt = format(_cput, (long)&bb, form,  args);
+       va_end(args);
+       if (maxcnt > 0)
+               *(bb.ptr) = '\0';
+       if (bb.count < 0)
+               return (-1);
+
+       return (cnt);
+}
diff --git a/librols/spawn.c b/librols/spawn.c
new file mode 100644 (file)
index 0000000..011e92f
--- /dev/null
@@ -0,0 +1,170 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)spawn.c 1.17 04/09/25 Copyright 1985, 1989, 1995-2003 J. Schilling */
+/*
+ *     Spawn another process/ wait for child process
+ *
+ *     Copyright (c) 1985, 1989, 1995-2003 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <mconfig.h>
+#include <stdio.h>
+#include <standard.h>
+#define        fspawnl __nothing__     /* prototype in schily.h is wrong */
+#define        spawnl  __nothing__     /* prototype in schily.h is wrong */
+#include <schily.h>
+#undef fspawnl
+#undef spawnl
+#include <unixstd.h>
+#include <stdxlib.h>
+#include <vadefs.h>
+#include <waitdefs.h>
+#include <errno.h>
+
+#define        MAX_F_ARGS      16
+
+EXPORT int     fspawnl __PR((FILE *, FILE *, FILE *, ...));
+
+EXPORT int
+fspawnv(in, out, err, argc, argv)
+       FILE    *in;
+       FILE    *out;
+       FILE    *err;
+       int     argc;
+       char    * const argv[];
+{
+       int     pid;
+
+       if ((pid = fspawnv_nowait(in, out, err, argv[0], argc, argv)) < 0)
+               return (pid);
+
+       return (wait_chld(pid));
+}
+
+/* VARARGS3 */
+#ifdef PROTOTYPES
+EXPORT int
+fspawnl(FILE *in, FILE *out, FILE *err, ...)
+#else
+EXPORT int
+fspawnl(in, out, err, va_alist)
+       FILE    *in;
+       FILE    *out;
+       FILE    *err;
+       va_dcl
+#endif
+{
+       va_list args;
+       int     ac = 0;
+       char    *xav[MAX_F_ARGS];
+       char    **av;
+       char    **pav;
+       char    *p;
+       int     ret;
+
+#ifdef PROTOTYPES
+       va_start(args, err);
+#else
+       va_start(args);
+#endif
+       while (va_arg(args, char *) != NULL)
+               ac++;
+       va_end(args);
+
+       if (ac < MAX_F_ARGS) {
+               pav = av = xav;
+       } else {
+               pav = av = (char **)malloc((ac+1)*sizeof (char *));
+               if (av == 0)
+                       return (-1);
+       }
+
+#ifdef PROTOTYPES
+       va_start(args, err);
+#else
+       va_start(args);
+#endif
+       do {
+               p = va_arg(args, char *);
+               *pav++ = p;
+       } while (p != NULL);
+       va_end(args);
+
+       ret =  fspawnv(in, out, err, ac, av);
+       if (av != xav)
+               free(av);
+       return (ret);
+}
+
+EXPORT int
+fspawnv_nowait(in, out, err, name, argc, argv)
+       FILE            *in;
+       FILE            *out;
+       FILE            *err;
+       const char      *name;
+       int             argc;
+       char            * const argv[];
+{
+       int     pid = -1;       /* Initialization needed to make GCC happy */
+       int     i;
+
+       for (i = 1; i < 64; i *= 2) {
+               if ((pid = fork()) >= 0)
+                       break;
+               sleep(i);
+       }
+       if (pid != 0)
+               return (pid);
+                               /*
+                                * silly: fexecv must set av[ac] = NULL
+                                * so we have to cast argv tp (char **)
+                                */
+       rols_fexecv(name, in, out, err, argc, (char **)argv);
+       exit(geterrno());
+       /* NOTREACHED */
+}
+
+EXPORT int
+wait_chld(pid)
+       int     pid;
+{
+       int     died;
+       WAIT_T  status;
+
+       do {
+               do {
+                       died = wait(&status);
+               } while (died < 0 && geterrno() == EINTR);
+               if (died < 0)
+                       return (died);
+       } while (died != pid);
+
+       if (WCOREDUMP(status))
+               unlink("core");
+
+       return (WEXITSTATUS(status));
+}
diff --git a/librols/stdio/cvmod.c b/librols/stdio/cvmod.c
new file mode 100644 (file)
index 0000000..a825c42
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)cvmod.c 2.9 04/08/08 Copyright 1986, 1995-2003 J. Schilling */
+/*
+ *     Copyright (c) 1986, 1995-2003 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "schilyio.h"
+
+#ifndef        O_BINARY
+#define        O_BINARY        0
+#endif
+#ifndef        O_LARGEFILE
+#define        O_LARGEFILE     0
+#endif
+
+EXPORT int
+_cvmod(mode, omode, flag)
+       const char      *mode;
+       int             *omode;
+       int             *flag;
+{
+       while (*mode) {
+               switch (*mode) {
+
+               case 'r':   *omode |= O_RDONLY; *flag |= FI_READ;       break;
+               case 'w':   *omode |= O_WRONLY; *flag |= FI_WRITE;      break;
+               case 'e':   *omode |= O_EXCL;                           break;
+               case 'c':   *omode |= O_CREAT;  *flag |= FI_CREATE;     break;
+               case 't':   *omode |= O_TRUNC;  *flag |= FI_TRUNC;      break;
+               case 'a':   *omode |= O_APPEND; *flag |= FI_APPEND;     break;
+               case 'u':                       *flag |= FI_UNBUF;      break;
+                       /* dummy on UNIX */
+               case 'b':   *omode |= O_BINARY; *flag |= FI_BINARY;     break;
+                       /*
+                        * XXX do we need this ?
+                        * XXX May this be a problem?
+                        */
+               case 'l':   *omode |= O_LARGEFILE;                      break;
+               default:    raisecond(_badmode, 0L);
+                           return (0);
+               }
+               mode++;
+       }
+       if (*flag & FI_READ && *flag & FI_WRITE) {
+               *omode &= ~(O_RDONLY|O_WRONLY);
+               *omode |= O_RDWR;
+       }
+       return (1);
+}
diff --git a/librols/stdio/dat.c b/librols/stdio/dat.c
new file mode 100644 (file)
index 0000000..cda63cf
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)dat.c   1.3 03/06/15 Copyright 1986, 1996-2003 J. Schilling */
+/*
+ *     Copyright (c) 1986, 1996-2003 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+char   _badfile[]      = "bad_file";
+char   _badmode[]      = "bad_file_mode";
+char   _badop[]        = "bad_file_op";
diff --git a/librols/stdio/fcons.c b/librols/stdio/fcons.c
new file mode 100644 (file)
index 0000000..1630248
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)fcons.c 2.17 04/08/08 Copyright 1986, 1995-2003 J. Schilling */
+/*
+ *     Copyright (c) 1986, 1995-2003  J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "schilyio.h"
+
+/*
+ * Note that because of a definition in schilyio.h we are using fseeko()/ftello()
+ * instead of fseek()/ftell() if available.
+ */
+
+LOCAL  char    *fmtab[] = {
+                       "",     /* 0    FI_NONE                         */
+                       "r",    /* 1    FI_READ                         */
+                       "w",    /* 2    FI_WRITE                **1)    */
+                       "r+",   /* 3    FI_READ  | FI_WRITE             */
+                       "b",    /* 4    FI_NONE  | FI_BINARY            */
+                       "rb",   /* 5    FI_READ  | FI_BINARY            */
+                       "wb",   /* 6    FI_WRITE | FI_BINARY    **1)    */
+                       "r+b",  /* 7    FI_READ  | FI_WRITE | FI_BINARY */
+
+/* + FI_APPEND */      "",     /* 0    FI_NONE                         */
+/* ...         */      "r",    /* 1    FI_READ                         */
+                       "a",    /* 2    FI_WRITE                **1)    */
+                       "a+",   /* 3    FI_READ  | FI_WRITE             */
+                       "b",    /* 4    FI_NONE  | FI_BINARY            */
+                       "rb",   /* 5    FI_READ  | FI_BINARY            */
+                       "ab",   /* 6    FI_WRITE | FI_BINARY    **1)    */
+                       "a+b",  /* 7    FI_READ  | FI_WRITE | FI_BINARY */
+               };
+/*
+ * NOTES:
+ *     1)      fdopen() guarantees not to create/trunc files in this case
+ *
+ *     "w"     will create/trunc files with fopen()
+ *     "a"     will create files with fopen()
+ */
+
+
+EXPORT FILE *
+_fcons(fd, f, flag)
+       register FILE   *fd;
+               int     f;
+               int     flag;
+{
+       int     my_gflag = _io_glflag;
+
+       if (fd == (FILE *)NULL)
+               fd = fdopen(f,
+                       fmtab[flag&(FI_READ|FI_WRITE|FI_BINARY | FI_APPEND)]);
+
+       if (fd != (FILE *)NULL) {
+               if (flag & FI_APPEND) {
+                       (void) fseek(fd, (off_t)0, SEEK_END);
+               }
+               if (flag & FI_UNBUF) {
+                       setbuf(fd, NULL);
+                       my_gflag |= _IOUNBUF;
+               }
+               set_my_flag(fd, my_gflag); /* must clear it if fd is reused */
+               return (fd);
+       }
+       if (flag & FI_CLOSE)
+               close(f);
+
+       return ((FILE *) NULL);
+}
diff --git a/librols/stdio/fdown.c b/librols/stdio/fdown.c
new file mode 100644 (file)
index 0000000..375530f
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)fdown.c 1.10 04/08/08 Copyright 1986, 1995-2003 J. Schilling */
+/*
+ *     Copyright (c) 1986, 1995-2003 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "schilyio.h"
+
+EXPORT int
+fdown(f)
+       register FILE *f;
+{
+       down(f);
+       return (fileno(f));
+}
diff --git a/librols/stdio/fdup.c b/librols/stdio/fdup.c
new file mode 100644 (file)
index 0000000..cdb180d
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)fdup.c  1.14 04/08/08 Copyright 1986, 1995-2003 J. Schilling */
+/*
+ *     Copyright (c) 1986, 1995-2003 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "schilyio.h"
+
+/*
+ * Note that because of a definition in schilyio.h we are using fseeko()/ftello()
+ * instead of fseek()/ftell() if available.
+ */
+
+EXPORT FILE *
+fdup(f)
+       register FILE  *f;
+{
+       int  newfd;
+
+       down(f);
+       if ((newfd = dup(fileno(f))) < 0)
+               return ((FILE *) NULL);
+
+       lseek(newfd, ftell(f), SEEK_SET);
+       return (_fcons((FILE *)0, newfd, (FI_READ | FI_WRITE | FI_CLOSE)));
+}
diff --git a/librols/stdio/ffileread.c b/librols/stdio/ffileread.c
new file mode 100644 (file)
index 0000000..cbf8276
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)ffileread.c     1.10 04/09/25 Copyright 1986, 1996-2003 J. Schilling */
+/*
+ *     Copyright (c) 1986, 1996-2003 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "schilyio.h"
+#include <errno.h>
+
+EXPORT int
+ffileread(f, buf, len)
+       register FILE   *f;
+       void    *buf;
+       int     len;
+{
+       register int    fd;
+       register int    ret;
+
+       down2(f, _IOREAD, _IORW);
+       fd = fileno(f);
+
+       while ((ret = read(fd, buf, len)) < 0 && geterrno() == EINTR)
+               /* LINTED */
+               ;
+       return (ret);
+}
diff --git a/librols/stdio/ffilewrite.c b/librols/stdio/ffilewrite.c
new file mode 100644 (file)
index 0000000..61f6635
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)ffilewrite.c    1.6 04/08/08 Copyright 1986 J. Schilling */
+/*
+ *     Copyright (c) 1986 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "schilyio.h"
+
+EXPORT int
+ffilewrite(f, buf, len)
+       register FILE   *f;
+       void    *buf;
+       int     len;
+{
+       down2(f, _IORWT, _IORW);
+
+       return (write(fileno(f), (char *)buf, len));
+}
diff --git a/librols/stdio/fgetline.c b/librols/stdio/fgetline.c
new file mode 100644 (file)
index 0000000..910e0e6
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)fgetline.c      1.8 04/09/25 Copyright 1986, 1996-2003 J. Schilling */
+/*
+ *     Copyright (c) 1986, 1996-2003 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "schilyio.h"
+
+/*
+ * XXX should we check if HAVE_USG_STDIO is defined and
+ * XXX use something line memccpy to speed things up ???
+ */
+
+EXPORT int
+rols_fgetline(f, buf, len)
+       register        FILE    *f;
+                       char    *buf;
+       register        int     len;
+{
+       register int    c       = '\0';
+       register char   *bp     = buf;
+       register int    nl      = '\n';
+
+       down2(f, _IOREAD, _IORW);
+
+       for (;;) {
+               if ((c = getc(f)) < 0)
+                       break;
+               if (c == nl)
+                       break;
+               if (--len > 0) {
+                       *bp++ = (char)c;
+               } else {
+                       /*
+                        * Read up to end of line
+                        */
+                       while ((c = getc(f)) >= 0 && c != nl)
+                               /* LINTED */
+                               ;
+                       break;
+               }
+       }
+       *bp = '\0';
+       /*
+        * If buffer is empty and we hit EOF, return EOF
+        */
+       if (c < 0 && bp == buf)
+               return (c);
+
+       return (bp - buf);
+}
+
+EXPORT int
+rols_getline(buf, len)
+       char    *buf;
+       int     len;
+{
+       return (rols_fgetline(stdin, buf, len));
+}
diff --git a/librols/stdio/file_raise.c b/librols/stdio/file_raise.c
new file mode 100644 (file)
index 0000000..5605c8e
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)file_raise.c    1.8 04/08/08 Copyright 1986, 1995-2003 J. Schilling */
+/*
+ *     Copyright (c) 1986, 1995-2003 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "schilyio.h"
+
+EXPORT void
+file_raise(f, flg)
+       register FILE *f;
+       int flg;
+{
+       int     oflag;
+extern int     _io_glflag;
+
+       if (f == (FILE *)NULL) {
+               if (flg)
+                       _io_glflag &= ~_IONORAISE;
+               else
+                       _io_glflag |= _IONORAISE;
+               return;
+       }
+       down(f);
+
+       oflag = my_flag(f);
+
+       if (flg)
+               oflag &= ~_IONORAISE;
+       else
+               oflag |= _IONORAISE;
+
+       set_my_flag(f, oflag);
+}
diff --git a/librols/stdio/fileclose.c b/librols/stdio/fileclose.c
new file mode 100644 (file)
index 0000000..ce78958
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)fileclose.c     1.7 04/08/08 Copyright 1986 J. Schilling */
+/*
+ *     Copyright (c) 1988 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "schilyio.h"
+
+EXPORT int
+fileclose(f)
+       FILE    *f;
+{
+       down(f);
+       return (fclose(f));
+}
diff --git a/librols/stdio/fileluopen.c b/librols/stdio/fileluopen.c
new file mode 100644 (file)
index 0000000..f178d8a
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)fileluopen.c    1.17 04/08/08 Copyright 1986, 1995-2003 J. Schilling */
+/*
+ *     Copyright (c) 1986, 1995-2003 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "schilyio.h"
+
+/*
+ * Note that because of a definition in schilyio.h we are using fseeko()/ftello()
+ * instead of fseek()/ftell() if available.
+ */
+
+#ifndef        O_NDELAY                /* This is undefined on BeOS :-( */
+#define        O_NDELAY        0
+#endif
+#ifndef        O_CREAT
+#define        O_CREAT         0
+#endif
+#ifndef        O_TRUNC
+#define        O_TRUNC         0
+#endif
+#ifndef        O_EXCL
+#define        O_EXCL          0
+#endif
+
+/*
+ *     fileluopen - open a stream for lun
+ */
+EXPORT FILE *
+fileluopen(f, mode)
+       int             f;
+       const char      *mode;
+{
+       int     omode = 0;
+       int     flag = 0;
+
+       if (!_cvmod(mode, &omode, &flag))
+               return ((FILE *) NULL);
+
+       if (omode & (O_NDELAY|O_CREAT|O_TRUNC|O_EXCL)) {
+               raisecond(_badmode, 0L);
+               return ((FILE *) NULL);
+       }
+
+#ifdef F_GETFD
+       if (fcntl(f, F_GETFD, 0) < 0) {
+               raisecond(_badfile, 0L);
+               return ((FILE *) NULL);
+       }
+#endif
+
+#ifdef O_APPEND
+       if (omode & O_APPEND)
+               lseek(f, (off_t)0, SEEK_END);
+#endif
+
+       return (_fcons((FILE *)0, f, flag));
+}
diff --git a/librols/stdio/filemopen.c b/librols/stdio/filemopen.c
new file mode 100644 (file)
index 0000000..b8b7482
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)filemopen.c     1.4 05/08/18 Copyright 1986, 1995-2005 J. Schilling */
+/*
+ *     Copyright (c) 1986, 1995-2005 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "schilyio.h"
+
+EXPORT FILE *
+#ifdef PROTOTYPES
+filemopen(const char *name, const char *mode, mode_t cmode)
+#else
+filemopen(name, mode, cmode)
+       const char      *name;
+       const char      *mode;
+       mode_t          cmode;
+#endif
+{
+       int     ret;
+       int     omode = 0;
+       int     flag = 0;
+
+       if (!_cvmod(mode, &omode, &flag))
+               return ((FILE *) NULL);
+
+       if ((ret = open(name, omode, cmode)) < 0)
+               return ((FILE *) NULL);
+
+       return (_fcons((FILE *)0, ret, flag | FI_CLOSE));
+}
diff --git a/librols/stdio/fileopen.c b/librols/stdio/fileopen.c
new file mode 100644 (file)
index 0000000..4b5e9a8
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)fileopen.c      1.11 05/08/18 Copyright 1986, 1995-2005 J. Schilling */
+/*
+ *     Copyright (c) 1986, 1995-2005 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "schilyio.h"
+
+EXPORT FILE *
+fileopen(name, mode)
+       const char      *name;
+       const char      *mode;
+{
+       int     ret;
+       int     omode = 0;
+       int     flag = 0;
+
+       if (!_cvmod(mode, &omode, &flag))
+               return ((FILE *) NULL);
+
+       if ((ret = _openfd(name, omode)) < 0)
+               return ((FILE *) NULL);
+
+       return (_fcons((FILE *)0, ret, flag | FI_CLOSE));
+}
diff --git a/librols/stdio/filepos.c b/librols/stdio/filepos.c
new file mode 100644 (file)
index 0000000..37f9166
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)filepos.c       1.10 04/08/08 Copyright 1986, 1996-2003 J. Schilling */
+/*
+ *     Copyright (c) 1986, 1996-2003 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "schilyio.h"
+
+/*
+ * Note that because of a definition in schilyio.h we are using fseeko()/ftello()
+ * instead of fseek()/ftell() if available.
+ */
+
+EXPORT off_t
+filepos(f)
+       register FILE   *f;
+{
+       down(f);
+       return (ftell(f));
+}
diff --git a/librols/stdio/fileread.c b/librols/stdio/fileread.c
new file mode 100644 (file)
index 0000000..2550f31
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)fileread.c      1.14 04/08/08 Copyright 1986, 1995-2003 J. Schilling */
+/*
+ *     Copyright (c) 1986, 1995-2003 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "schilyio.h"
+
+static char    _readerr[]      = "file_read_err";
+
+#ifdef HAVE_USG_STDIO
+
+EXPORT int
+fileread(f, buf, len)
+       register FILE   *f;
+       void    *buf;
+       int     len;
+{
+       int     cnt;
+       register int    n;
+
+       down2(f, _IOREAD, _IORW);
+
+       if (f->_flag & _IONBF) {
+               cnt = _niread(fileno(f), buf, len);
+               if (cnt < 0) {
+                       f->_flag |= _IOERR;
+                       if (!(my_flag(f) & _IONORAISE))
+                               raisecond(_readerr, 0L);
+               }
+               if (cnt == 0 && len)
+                       f->_flag |= _IOEOF;
+               return (cnt);
+       }
+       cnt = 0;
+       while (len > 0) {
+               if (f->_cnt <= 0) {
+                       if (usg_filbuf(f) == EOF)
+                               break;
+                       f->_cnt++;
+                       f->_ptr--;
+               }
+               n = f->_cnt >= len ? len : f->_cnt;
+               buf = (void *)movebytes(f->_ptr, buf, n);
+               f->_ptr += n;
+               f->_cnt -= n;
+               cnt += n;
+               len -= n;
+       }
+       if (!ferror(f))
+               return (cnt);
+       if (!(my_flag(f) & _IONORAISE))
+               raisecond(_readerr, 0L);
+       return (-1);
+}
+
+#else
+
+EXPORT int
+fileread(f, buf, len)
+       register FILE   *f;
+       void    *buf;
+       int     len;
+{
+       int     cnt;
+
+       down2(f, _IOREAD, _IORW);
+
+       if (my_flag(f) & _IOUNBUF)
+               return (_niread(fileno(f), buf, len));
+       cnt = fread(buf, 1, len, f);
+
+       if (!ferror(f))
+               return (cnt);
+       if (!(my_flag(f) & _IONORAISE))
+               raisecond(_readerr, 0L);
+       return (-1);
+}
+
+#endif /* HAVE_USG_STDIO */
diff --git a/librols/stdio/filereopen.c b/librols/stdio/filereopen.c
new file mode 100644 (file)
index 0000000..537edfc
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)filereopen.c    1.15 04/08/08 Copyright 1986, 1995 J. Schilling */
+/*
+ *     open new file on old stream
+ *
+ *     Copyright (c) 1986, 1995 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "schilyio.h"
+
+/*
+ * Note that because of a definition in schilyio.h we are using fseeko()/ftello()
+ * instead of fseek()/ftell() if available.
+ */
+
+LOCAL  char    *fmtab[] = {
+                       "",     /* 0    FI_NONE                         */
+                       "r",    /* 1    FI_READ                         */
+                       "r+",   /* 2    FI_WRITE                **1)    */
+                       "r+",   /* 3    FI_READ  | FI_WRITE             */
+                       "b",    /* 4    FI_NONE  | FI_BINARY            */
+                       "rb",   /* 5    FI_READ  | FI_BINARY            */
+                       "r+b",  /* 6    FI_WRITE | FI_BINARY    **1)    */
+                       "r+b",  /* 7    FI_READ  | FI_WRITE | FI_BINARY */
+
+/* + FI_APPEND */      "",     /* 0    FI_NONE                         */
+/* ...         */      "r",    /* 1    FI_READ                         */
+                       "a",    /* 2    FI_WRITE                **1)    */
+                       "a+",   /* 3    FI_READ  | FI_WRITE             */
+                       "b",    /* 4    FI_NONE  | FI_BINARY            */
+                       "rb",   /* 5    FI_READ  | FI_BINARY            */
+                       "ab",   /* 6    FI_WRITE | FI_BINARY    **1)    */
+                       "a+b",  /* 7    FI_READ  | FI_WRITE | FI_BINARY */
+               };
+/*
+ * NOTES:
+ *     1)      there is no fopen() mode that opens for writing
+ *             without creating/truncating at the same time.
+ *
+ *     "w"     will create/trunc files with fopen()
+ *     "a"     will create files with fopen()
+ */
+
+EXPORT FILE *
+filereopen(name, mode, fp)
+       const char      *name;
+       const char      *mode;
+       FILE            *fp;
+{
+       int     ret;
+       int     omode = 0;
+       int     flag = 0;
+
+       if (!_cvmod(mode, &omode, &flag))
+               return ((FILE *) NULL);
+
+       /*
+        * create/truncate file if necessary
+        */
+       if ((ret = _openfd(name, omode)) < 0)
+               return ((FILE *) NULL);
+       close(ret);
+
+       fp = freopen(name,
+               fmtab[flag & (FI_READ | FI_WRITE | FI_BINARY | FI_APPEND)], fp);
+
+       if (fp != (FILE *) NULL) {
+               set_my_flag(fp, 0); /* must clear it if fp is reused */
+
+               if (flag & FI_APPEND) {
+                       (void) fseek(fp, (off_t)0, SEEK_END);
+               }
+               if (flag & FI_UNBUF) {
+                       setbuf(fp, NULL);
+                       add_my_flag(fp, _IOUNBUF);
+               }
+       }
+       return (fp);
+}
diff --git a/librols/stdio/fileseek.c b/librols/stdio/fileseek.c
new file mode 100644 (file)
index 0000000..6ea0b17
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)fileseek.c      1.12 04/08/08 Copyright 1986, 1996-2003 J. Schilling */
+/*
+ *     Copyright (c) 1986, 1996-2003 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "schilyio.h"
+
+/*
+ * Note that because of a definition in schilyio.h we are using fseeko()/ftello()
+ * instead of fseek()/ftell() if available.
+ */
+
+static char    _seekerr[]      = "file_seek_err";
+
+EXPORT int
+fileseek(f, pos)
+       register FILE   *f;
+       off_t   pos;
+{
+       int     ret;
+
+       down(f);
+       ret = fseek(f, pos, SEEK_SET);
+       if (ret < 0 && !(my_flag(f) & _IONORAISE))
+               raisecond(_seekerr, 0L);
+       return (ret);
+}
diff --git a/librols/stdio/filesize.c b/librols/stdio/filesize.c
new file mode 100644 (file)
index 0000000..cecb52b
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)filesize.c      1.13 04/08/08 Copyright 1986, 1995-2003 J. Schilling */
+/*
+ *     Copyright (c) 1986, 1995-2003 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "schilyio.h"
+#include <statdefs.h>
+
+EXPORT off_t
+filesize(f)
+       register FILE   *f;
+{
+       struct stat buf;
+
+       down(f);
+       if (fstat(fileno(f), &buf) < 0) {
+               raisecond("filesize", 0L);
+               return (-1);
+       }
+       return (buf.st_size);
+}
diff --git a/librols/stdio/filestat.c b/librols/stdio/filestat.c
new file mode 100644 (file)
index 0000000..f9ba8db
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)filestat.c      1.9 04/08/08 Copyright 1985 J. Schilling */
+/*
+ *     Copyright (c) 1985 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "schilyio.h"
+#include <statdefs.h>
+
+EXPORT int
+filestat(f, stbuf)
+       FILE            *f;
+       struct stat     *stbuf;
+{
+       down(f);
+       return (fstat(fileno(f), stbuf));
+}
diff --git a/librols/stdio/filewrite.c b/librols/stdio/filewrite.c
new file mode 100644 (file)
index 0000000..dd3603f
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)filewrite.c     1.14 04/08/08 Copyright 1986, 1995-2003 J. Schilling */
+/*
+ *     Copyright (c) 1986, 1995-2003 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "schilyio.h"
+
+static char    _writeerr[]     = "file_write_err";
+
+#ifdef HAVE_USG_STDIO
+
+EXPORT int
+filewrite(f, vbuf, len)
+       register FILE   *f;
+       void    *vbuf;
+       int     len;
+{
+       register int    n;
+       int     cnt;
+       char            *buf = vbuf;
+
+       down2(f, _IOWRT, _IORW);
+
+       if (f->_flag & _IONBF) {
+               cnt = write(fileno(f), buf, len);
+               if (cnt < 0) {
+                       f->_flag |= _IOERR;
+                       if (!(my_flag(f) & _IONORAISE))
+                               raisecond(_writeerr, 0L);
+               }
+               return (cnt);
+       }
+       cnt = 0;
+       while (len > 0) {
+               if (f->_cnt <= 0) {
+                       if (usg_flsbuf((unsigned char) *buf++, f) == EOF)
+                               break;
+                       cnt++;
+                       if (--len == 0)
+                               break;
+               }
+               if ((n = f->_cnt >= len ? len : f->_cnt) > 0) {
+                       f->_ptr = (unsigned char *)movebytes(buf, f->_ptr, n);
+                       buf += n;
+                       f->_cnt -= n;
+                       cnt += n;
+                       len -= n;
+               }
+       }
+       if (!ferror(f))
+               return (cnt);
+       if (!(my_flag(f) & _IONORAISE))
+       raisecond(_writeerr, 0L);
+       return (-1);
+}
+
+#else
+
+EXPORT int
+filewrite(f, vbuf, len)
+       register FILE   *f;
+       void    *vbuf;
+       int     len;
+{
+       int     cnt;
+       char            *buf = vbuf;
+
+       down2(f, _IOWRT, _IORW);
+
+       if (my_flag(f) & _IOUNBUF)
+               return (write(fileno(f), buf, len));
+       cnt = fwrite(buf, 1, len, f);
+
+       if (!ferror(f))
+               return (cnt);
+       if (!(my_flag(f) & _IONORAISE))
+       raisecond(_writeerr, 0L);
+       return (-1);
+}
+
+#endif /* HAVE_USG_STDIO */
diff --git a/librols/stdio/flag.c b/librols/stdio/flag.c
new file mode 100644 (file)
index 0000000..a9571c6
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)flag.c  2.10 05/06/12 Copyright 1986-2003 J. Schilling */
+/*
+ *     Copyright (c) 1986-2003 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "schilyio.h"
+#include <stdxlib.h>
+
+#ifdef DO_MYFLAG
+
+#define        FL_INIT 10
+
+EXPORT int     _io_glflag;             /* global default flag */
+LOCAL  int     _fl_inc = 10;           /* increment for expanding flag struct */
+EXPORT int     _fl_max = FL_INIT;      /* max fd currently in _io_myfl */
+LOCAL  _io_fl  _io_smyfl[FL_INIT];     /* initial static space */
+EXPORT _io_fl  *_io_myfl = _io_smyfl;  /* init to static space */
+
+LOCAL int _more_flags  __PR((FILE *));
+
+LOCAL int
+_more_flags(fp)
+       FILE    *fp;
+{
+       register int    f = fileno(fp);
+       register int    n = _fl_max;
+       register _io_fl *np;
+
+       while (n <= f)
+               n += _fl_inc;
+
+       if (_io_myfl == _io_smyfl) {
+               np = (_io_fl *) malloc(n * sizeof (*np));
+               fillbytes(np, n * sizeof (*np), '\0');
+               movebytes(_io_smyfl, np, sizeof (_io_smyfl)/sizeof (*np));
+       } else {
+               np = (_io_fl *) realloc(_io_myfl, n * sizeof (*np));
+               if (np)
+                       fillbytes(&np[_fl_max], (n-_fl_max)*sizeof (*np), '\0');
+       }
+       if (np) {
+               _io_myfl = np;
+               _fl_max = n;
+               return (_io_get_my_flag(fp));
+       } else {
+               return (_IONORAISE);
+       }
+}
+
+EXPORT int
+_io_get_my_flag(fp)
+       register FILE   *fp;
+{
+       register int    f = fileno(fp);
+       register _io_fl *fl;
+
+       if (f >= _fl_max)
+               return (_more_flags(fp));
+
+       fl = &_io_myfl[f];
+
+       if (fl->fl_io == 0 || fl->fl_io == fp)
+               return (fl->fl_flags);
+
+       while (fl && fl->fl_io != fp)
+               fl = fl->fl_next;
+
+       if (fl == 0)
+               return (0);
+
+       return (fl->fl_flags);
+}
+
+EXPORT void
+_io_set_my_flag(fp, flag)
+       FILE    *fp;
+       int     flag;
+{
+       register int    f = fileno(fp);
+       register _io_fl *fl;
+       register _io_fl *fl2;
+
+       if (f >= _fl_max)
+               (void) _more_flags(fp);
+
+       fl = &_io_myfl[f];
+
+       if (fl->fl_io != (FILE *)0) {
+               fl2 = fl;
+
+               while (fl && fl->fl_io != fp)
+                       fl = fl->fl_next;
+               if (fl == 0) {
+                       if ((fl = (_io_fl *) malloc(sizeof (*fl))) == 0)
+                               return;
+                       fl->fl_next = fl2->fl_next;
+                       fl2->fl_next = fl;
+               }
+       }
+       fl->fl_io = fp;
+       fl->fl_flags = flag;
+}
+
+EXPORT void
+_io_add_my_flag(fp, flag)
+       FILE    *fp;
+       int     flag;
+{
+       int     oflag = _io_get_my_flag(fp);
+
+       oflag |= flag;
+
+       _io_set_my_flag(fp, oflag);
+}
+
+#endif /* DO_MYFLAG */
diff --git a/librols/stdio/flush.c b/librols/stdio/flush.c
new file mode 100644 (file)
index 0000000..9d9f2fa
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)flush.c 1.7 04/08/08 Copyright 1986 J. Schilling */
+/*
+ *     Copyright (c) 1986 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "schilyio.h"
+
+EXPORT int
+flush()
+{
+       return (fflush(stdout));
+}
diff --git a/librols/stdio/fpipe.c b/librols/stdio/fpipe.c
new file mode 100644 (file)
index 0000000..72f3ee9
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)fpipe.c 1.12 04/08/08 Copyright 1986, 1995-2003 J. Schilling */
+/*
+ *     Copyright (c) 1986, 1995-2003 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "schilyio.h"
+
+EXPORT int
+fpipe(pipef)
+       FILE *pipef[];
+{
+       int filedes[2];
+
+       if (pipe(filedes) < 0)
+               return (0);
+
+       if ((pipef[0] = _fcons((FILE *)0,
+                               filedes[0], FI_READ|FI_CLOSE)) != (FILE *)0) {
+               if ((pipef[1] = _fcons((FILE *)0,
+                               filedes[1], FI_WRITE|FI_CLOSE)) != (FILE *)0) {
+                       return (1);
+               }
+               fclose(pipef[0]);
+       }
+       close(filedes[1]);
+       return (0);
+}
diff --git a/librols/stdio/niread.c b/librols/stdio/niread.c
new file mode 100644 (file)
index 0000000..2f025fa
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)niread.c        1.12 04/08/08 Copyright 1986, 1996-2003 J. Schilling */
+/*
+ *     Non interruptable read
+ *
+ *     Copyright (c) 1986, 1996-2003 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "schilyio.h"
+#include <errno.h>
+
+EXPORT int
+_niread(f, buf, count)
+       int     f;
+       void    *buf;
+       int     count;
+{
+       int     ret;
+       int     oerrno = geterrno();
+
+       while ((ret = read(f, buf, count)) < 0 && geterrno() == EINTR) {
+               /*
+                * Set back old 'errno' so we don't change the errno visible
+                * to the outside if we did not fail.
+                */
+               seterrno(oerrno);
+       }
+       return (ret);
+}
diff --git a/librols/stdio/niwrite.c b/librols/stdio/niwrite.c
new file mode 100644 (file)
index 0000000..a5ebd85
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)niwrite.c       1.5 04/08/08 Copyright 1986, 2001-2003 J. Schilling */
+/*
+ *     Non interruptable write
+ *
+ *     Copyright (c) 1986, 2001-2003 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "schilyio.h"
+#include <errno.h>
+
+EXPORT int
+_niwrite(f, buf, count)
+       int     f;
+       void    *buf;
+       int     count;
+{
+       int     ret;
+       int     oerrno = geterrno();
+
+       while ((ret = write(f, buf, count)) < 0 && geterrno() == EINTR) {
+               /*
+                * Set back old 'errno' so we don't change the errno visible
+                * to the outside if we did not fail.
+                */
+               seterrno(oerrno);
+       }
+       return (ret);
+}
diff --git a/librols/stdio/nixread.c b/librols/stdio/nixread.c
new file mode 100644 (file)
index 0000000..2d83987
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)nixread.c       1.12 04/08/08 Copyright 1986, 1996-2003 J. Schilling */
+/*
+ *     Non interruptable extended read
+ *
+ *     Copyright (c) 1986, 1996-2003 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "schilyio.h"
+#include <errno.h>
+
+EXPORT int
+_nixread(f, buf, count)
+       int     f;
+       void    *buf;
+       int     count;
+{
+       register char *p = (char *)buf;
+       register int ret;
+       register int total = 0;
+               int     oerrno = geterrno();
+
+       while (count > 0) {
+               while ((ret = read(f, p, count)) < 0) {
+                       if (geterrno() == EINTR) {
+                               /*
+                                * Set back old 'errno' so we don't change the
+                                * errno visible to the outside if we did
+                                * not fail.
+                                */
+                               seterrno(oerrno);
+                               continue;
+                       }
+                       return (ret);   /* Any other error */
+               }
+               if (ret == 0)           /* Something went wrong */
+                       break;
+
+               total += ret;
+               count -= ret;
+               p += ret;
+       }
+       return (total);
+}
diff --git a/librols/stdio/nixwrite.c b/librols/stdio/nixwrite.c
new file mode 100644 (file)
index 0000000..b9fa4df
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)nixwrite.c      1.5 04/08/08 Copyright 1986, 2001-2003 J. Schilling */
+/*
+ *     Non interruptable extended write
+ *
+ *     Copyright (c) 1986, 2001-2003 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "schilyio.h"
+#include <errno.h>
+
+EXPORT int
+_nixwrite(f, buf, count)
+       int     f;
+       void    *buf;
+       int     count;
+{
+       register char *p = (char *)buf;
+       register int ret;
+       register int total = 0;
+               int     oerrno = geterrno();
+
+       while (count > 0) {
+               while ((ret = write(f, p, count)) < 0) {
+                       if (geterrno() == EINTR) {
+                               /*
+                                * Set back old 'errno' so we don't change the
+                                * errno visible to the outside if we did
+                                * not fail.
+                                */
+                               seterrno(oerrno);
+                               continue;
+                       }
+                       return (ret);   /* Any other error */
+               }
+               if (ret == 0)           /* EOF */
+                       break;
+
+               total += ret;
+               count -= ret;
+               p += ret;
+       }
+       return (total);
+}
diff --git a/librols/stdio/openfd.c b/librols/stdio/openfd.c
new file mode 100644 (file)
index 0000000..d0e110c
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)openfd.c        1.9 04/08/08 Copyright 1986, 1995 J. Schilling */
+/*
+ *     Copyright (c) 1986, 1995 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "schilyio.h"
+
+#if    defined(_openfd) && !defined(USE_LARGEFILES)
+#      undef   _openfd
+#endif
+
+EXPORT int
+_openfd(name, omode)
+       const char      *name;
+       int             omode;
+{
+       return (open(name, omode, 0666));
+}
diff --git a/librols/stdio/peekc.c b/librols/stdio/peekc.c
new file mode 100644 (file)
index 0000000..ce98557
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)peekc.c 1.7 04/08/08 Copyright 1986, 1996-2003 J. Schilling */
+/*
+ *     Copyright (c) 1986, 1996-2003 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "schilyio.h"
+
+EXPORT int
+peekc(f)
+       FILE *f;
+{
+       int     c;
+
+       down2(f, _IOREAD, _IORW);
+
+       if (ferror(f))
+               return (EOF);
+       if ((c = getc(f)) != EOF)
+               ungetc(c, f);
+       return (c);
+}
diff --git a/librols/stdio/schilyio.h b/librols/stdio/schilyio.h
new file mode 100644 (file)
index 0000000..c97f845
--- /dev/null
@@ -0,0 +1,248 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)schilyio.h      2.22 04/09/04 Copyright 1986, 1995-2003 J. Schilling */
+/*
+ *     Copyright (c) 1986, 1995-2003 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef        _STDIO_SCHILYIO_H
+#define        _STDIO_SCHILYIO_H
+
+#include <mconfig.h>
+#include <stdio.h>
+#include <standard.h>
+#include <unixstd.h>
+#include <fctldefs.h>
+#include <schily.h>
+
+#ifdef NO_USG_STDIO
+#      ifdef   HAVE_USG_STDIO
+#              undef   HAVE_USG_STDIO
+#      endif
+#endif
+
+/*#if  _LFS_LARGEFILE*/
+#ifdef HAVE_LARGEFILES
+/*
+ * XXX We may need to put this code to a more global place to allow all
+ * XXX users of fseek()/ftell() to automaticaly use fseeko()/ftello()
+ * XXX if the latter are available.
+ *
+ * If HAVE_LARGEFILES is defined, it is guaranteed that fseeko()/ftello()
+ * both are available.
+ */
+#      define  fseek   fseeko
+#      define  ftell   ftello
+
+#else  /* !HAVE_LARGEFILES */
+/*
+ * If HAVE_LARGEFILES is not defined, we depend on specific tests for
+ * fseeko()/ftello() which must have been done before the tests for
+ * Large File support have been done.
+ * Note that this only works if the tests used below are really done before
+ * the Large File autoconf test is run. This is because autoconf does no
+ * clean testing but instead cumulatively modifes the envivonment used for
+ * testing.
+ */
+#ifdef HAVE_FSEEKO
+#      define  fseek   fseeko
+#endif
+#ifdef HAVE_FTELLO
+#      define  ftell   ftello
+#endif
+
+#endif
+
+/*
+ * speed things up...
+ */
+#ifndef        _OPENFD_SRC
+#ifdef _openfd
+#undef _openfd
+#endif
+#define        _openfd(name, omode)    (open(name, omode, 0666))
+#endif
+
+#define        DO_MYFLAG               /* use local flags */
+
+/*
+ * Flags used during fileopen(), ... by _fcons()/ _cvmod()
+ */
+#define        FI_NONE         0x0000  /* no flags defined */
+
+#define        FI_READ         0x0001  /* open for reading */
+#define        FI_WRITE        0x0002  /* open for writing */
+#define        FI_BINARY       0x0004  /* open in binary mode */
+#define        FI_APPEND       0x0008  /* append on each write */
+
+#define        FI_CREATE       0x0010  /* create if nessecary */
+#define        FI_TRUNC        0x0020  /* truncate file on open */
+#define        FI_UNBUF        0x0080  /* dont't buffer io */
+#define        FI_CLOSE        0x1000  /* close file on error */
+
+/*
+ * local flags
+ */
+#define        _IONORAISE      01      /* do no raisecond() on errors */
+#define        _IOUNBUF        02      /* do unbuffered i/o */
+
+#ifdef DO_MYFLAG
+
+struct _io_flags {
+       FILE    *fl_io;         /* file pointer */
+       struct _io_flags        /* pointer to next struct */
+               *fl_next;       /* if more file pointer to same fd */
+       int     fl_flags;       /* my flags */
+};
+
+typedef        struct _io_flags _io_fl;
+
+extern int     _io_glflag;     /* global default flag */
+extern _io_fl  *_io_myfl;      /* array of structs to hold my flags */
+extern int     _fl_max;        /* max fd currently in _io_myfl */
+
+/*
+ *     if fileno > max
+ *             expand
+ *     else if map[fileno].pointer == 0
+ *             return 0
+ *     else if map[fileno].pointer == p
+ *             return map[fileno].flags
+ *     else
+ *             search list
+ */
+#define        flp(p)          (&_io_myfl[fileno(p)])
+
+#ifdef MY_FLAG_IS_MACRO
+#define        my_flag(p)      ((int)fileno(p) >= _fl_max ?                    \
+                               _io_get_my_flag(p) :                    \
+                       ((flp(p)->fl_io == 0 || flp(p)->fl_io == p) ?   \
+                               flp(p)->fl_flags :                      \
+                               _io_get_my_flag(p)))
+#else
+#define        my_flag(p)      _io_get_my_flag(p)
+#endif
+
+#define        set_my_flag(p, v) _io_set_my_flag(p, v)
+#define        add_my_flag(p, v) _io_add_my_flag(p, v)
+
+extern int     _io_get_my_flag __PR((FILE *));
+extern void    _io_set_my_flag __PR((FILE *, int));
+extern void    _io_add_my_flag __PR((FILE *, int));
+
+#else  /* DO_MYFLAG */
+
+#define        my_flag(p)              _IONORAISE      /* Always noraise */
+#define        set_my_flag(p, v)                       /* Ignore */
+#define        add_my_flag(p, v)                       /* Ignore */
+
+#endif /* DO_MYFLAG */
+
+#ifdef HAVE_USG_STDIO
+
+/*
+ * Use the right filbuf()/flsbuf() function.
+ */
+#ifdef HAVE___FILBUF
+#      define  usg_filbuf(fp)          __filbuf(fp)
+#      define  usg_flsbuf(c, fp)       __flsbuf(c, fp)
+/*
+ * Define prototypes to verify if our interface is right
+ */
+extern int     __filbuf                __PR((FILE *));
+/*extern       int     __flsbuf                __PR(());*/
+#else
+#      ifdef   HAVE__FILBUF
+#      define  usg_filbuf(fp)          _filbuf(fp)
+#      define  usg_flsbuf(c, fp)       _flsbuf(c, fp)
+/*
+ * Define prototypes to verify if our interface is right
+ */
+extern int     _filbuf                 __PR((FILE *));
+/*extern       int     _flsbuf                 __PR(());*/
+#      else
+/*
+ * no filbuf() but this will not happen on USG_STDIO systems.
+ */
+#      endif
+#endif
+/*
+ * Do not check this because flsbuf()'s 1st parameter may be
+ * int                 SunOS
+ * unsigned int                Apollo
+ * unsigned char       HP-UX-11
+ *
+ * Note that the interface is now checked by autoconf.
+ */
+/*extern       int     _flsbuf __PR((int, FILE *));*/
+#else
+/*
+ * If we are on a non USG system we cannot down file pointers
+ */
+#undef DO_DOWN
+#endif
+
+#ifndef        DO_DOWN
+/*
+ *     No stream checking
+ */
+#define        down(f)
+#define        down1(f, fl1)
+#define        down2(f, fl1, fl2)
+#else
+/*
+ *     Do stream checking (works only on USG stdio)
+ *
+ *     New version of USG stdio.
+ *     _iob[] holds only a small amount of pointers.
+ *     Aditional space is allocated.
+ *     We may check only if the file pointer is != NULL
+ *     and if iop->_flag refers to a stream with appropriate modes.
+ *     If _iob[] gets expanded by malloc() we cannot check upper bound.
+ */
+#define        down(f)         ((f) == 0 || (f)->_flag == 0 ? \
+                               (raisecond(_badfile, 0L), (FILE *)0) : (f))
+
+#define        down1(f, fl1)   ((f) == 0 || (f)->_flag == 0 ? \
+                                       (raisecond(_badfile, 0L), (FILE *)0) : \
+                               (((f)->_flag & fl1) != fl1 ? \
+                                       (raisecond(_badop, 0L), (FILE *)0) : \
+                                       (f)))
+
+#define        down2(f, fl1, fl2)      ((f) == 0 || (f)->_flag == 0 ? \
+                               (raisecond(_badfile, 0L), (FILE *)0) : \
+                                   (((f)->_flag & fl1) != fl1 && \
+                                   ((f)->_flag & fl2)  != fl2 ? \
+                               (raisecond(_badop, 0L), (FILE *)0) : \
+                               (f)))
+#endif /* DO_DOWN */
+
+extern char    _badfile[];
+extern char    _badmode[];
+extern char    _badop[];
+
+#endif /* _STDIO_SCHILYIO_H */
diff --git a/librols/strcatl.c b/librols/strcatl.c
new file mode 100644 (file)
index 0000000..ef393f1
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)strcatl.c       1.12 03/10/29 Copyright 1985, 1989, 1995-2003 J. Schilling */
+/*
+ *     list version of strcat()
+ *
+ *     concatenates all past first parameter until a NULL pointer is reached
+ *
+ *     WARNING: a NULL constant is not a NULL pointer, so a caller must
+ *             cast a NULL constant to a pointer: (char *)NULL
+ *
+ *     returns pointer past last character (to '\0' byte)
+ *
+ *     Copyright (c) 1985, 1989, 1995-2003 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <mconfig.h>
+#include <vadefs.h>
+#include <standard.h>
+#include <schily.h>
+
+/* VARARGS3 */
+#ifdef PROTOTYPES
+EXPORT char *
+strcatl(char *to, ...)
+#else
+EXPORT char *
+strcatl(to, va_alist)
+       char *to;
+       va_dcl
+#endif
+{
+               va_list args;
+       register char   *p;
+       register char   *tor = to;
+
+#ifdef PROTOTYPES
+       va_start(args, to);
+#else
+       va_start(args);
+#endif
+       while ((p = va_arg(args, char *)) != NULL) {
+               while ((*tor = *p++) != '\0') {
+                       tor++;
+               }
+       }
+       *tor = '\0';
+       va_end(args);
+       return (tor);
+}
diff --git a/librols/strdup.c b/librols/strdup.c
new file mode 100644 (file)
index 0000000..1bc5968
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)strdup.c        1.1 03/02/27 Copyright 2003 J. Schilling */
+/*
+ *     strdup() to be used if missing on libc
+ *
+ *     Copyright (c) 2003 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <mconfig.h>
+#include <standard.h>
+#include <stdxlib.h>
+#include <strdefs.h>
+#include <schily.h>
+#include <libport.h>
+
+#ifndef        HAVE_STRDUP
+
+EXPORT char *
+strdup(s)
+       const char      *s;
+{
+       unsigned i      = strlen(s) + 1;
+       char     *res   = malloc(i);
+
+       if (res == NULL)
+               return (NULL);
+       if (i > 16) {
+               movebytes(s, res, (int) i);
+       } else {
+               char    *s2 = res;
+
+               while ((*s2++ = *s++) != '\0')
+                       ;
+       }
+       return (res);
+}
+#endif /* HAVE_STRDUP */
diff --git a/librols/streql.c b/librols/streql.c
new file mode 100644 (file)
index 0000000..4b9a117
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)streql.c        1.7 03/06/15 Copyright 1985, 1995-2003 J. Schilling */
+/*
+ *     Check if two strings are equal
+ *
+ *     Copyright (c) 1985, 1995-2003 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <standard.h>
+#include <schily.h>
+
+EXPORT int
+streql(a, b)
+       const char      *a;
+       const char      *b;
+{
+       register const char     *s1 = a;
+       register const char     *s2 = b;
+
+       if (s1 == NULL || s2 ==  NULL)
+               return (FALSE);
+
+       while (*s1 == *s2++)
+               if (*s1++ == '\0')
+                       return (TRUE);
+
+       return (FALSE);
+}
diff --git a/librols/swabbytes.c b/librols/swabbytes.c
new file mode 100644 (file)
index 0000000..f2c9a57
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)swabbytes.c     1.6 03/06/15 Copyright 1988, 1995-2003 J. Schilling */
+/*
+ *     swab bytes in memory
+ *
+ *     Copyright (c) 1988, 1995-2003 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <standard.h>
+#include <schily.h>
+
+#define        DO8(a)  a; a; a; a; a; a; a; a;
+
+EXPORT void
+swabbytes(vp, cnt)
+               void    *vp;
+       register int    cnt;
+{
+       register char   *bp = (char *)vp;
+       register char   c;
+
+       cnt /= 2;       /* even count only */
+       while ((cnt -= 8) >= 0) {
+               DO8(c = *bp++; bp[-1] = *bp; *bp++ = c;);
+       }
+       cnt += 8;
+       while (--cnt >= 0) {
+               c = *bp++; bp[-1] = *bp; *bp++ = c;
+       }
+}
diff --git a/librols/usleep.c b/librols/usleep.c
new file mode 100644 (file)
index 0000000..780f7e3
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)usleep.c        1.17 03/06/15 Copyright 1995-2003 J. Schilling */
+/*
+ *     Copyright (c) 1995-2003 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <mconfig.h>
+#define        usleep  __nothing_    /* prototype in unistd.h may be different */
+#include <standard.h>
+#include <stdxlib.h>
+#include <timedefs.h>
+#ifdef HAVE_POLL_H
+#      include <poll.h>
+#else
+#      ifdef   HAVE_SYS_POLL_H
+#      include <sys/poll.h>
+#      endif
+#endif
+#ifdef HAVE_SYS_SYSTEMINFO_H
+#include <sys/systeminfo.h>
+#endif
+#include <libport.h>
+#undef usleep
+
+#ifndef        HAVE_USLEEP
+EXPORT int     usleep          __PR((int usec));
+#endif
+
+#ifdef OPENSERVER
+/*
+ * Don't use the usleep() from libc on SCO's OPENSERVER.
+ * It will kill our processes with SIGALRM.
+ * SCO has a usleep() prototype in unistd.h, for this reason we
+ * #define usleep to __nothing__ before including unistd.h
+ */
+#undef HAVE_USLEEP
+#endif
+
+#ifdef apollo
+/*
+ * Apollo sys5.3 usleep is broken.  Define a version based on time_$wait.
+ */
+#include <apollo/base.h>
+#include <apollo/time.h>
+#undef HAVE_USLEEP
+#endif
+
+#if    !defined(HAVE_USLEEP)
+
+EXPORT int
+usleep(usec)
+       int     usec;
+{
+#if defined(apollo)
+       /*
+        * Need to check apollo before HAVE_SELECT, because Apollo has select,
+        * but it's time wait feature is also broken :-(
+        */
+#define        HAVE_USLEEP
+       /*
+        * XXX Do these vars need to be static on Domain/OS ???
+        */
+       static time_$clock_t    DomainDelay;
+       static status_$t        DomainStatus;
+
+       /*
+        * DomainDelay is a 48 bit value that defines how many 4uS periods to
+        * delay.  Since the input value range is 32 bits, the upper 16 bits of
+        * DomainDelay must be zero.  So we just divide the input value by 4 to
+        * determine how many "ticks" to wait
+        */
+       DomainDelay.c2.high16 = 0;
+       DomainDelay.c2.low32 = usec / 4;
+       time_$wait(time_$relative, DomainDelay, &DomainStatus);
+#endif /* Apollo */
+
+#if    defined(HAVE_SELECT) && !defined(HAVE_USLEEP)
+#define        HAVE_USLEEP
+
+       struct timeval tv;
+       tv.tv_sec = usec / 1000000;
+       tv.tv_usec = usec % 1000000;
+       select(0, 0, 0, 0, &tv);
+#endif
+
+#if    defined(HAVE_POLL) && !defined(HAVE_USLEEP)
+#define        HAVE_USLEEP
+
+       if (poll(0, 0, usec/1000) < 0)
+               comerr("poll delay failed.\n");
+
+#endif
+
+#if    defined(HAVE_NANOSLEEP) && !defined(HAVE_USLEEP)
+#define        HAVE_USLEEP
+
+       struct timespec ts;
+
+       ts.tv_sec = usec / 1000000;
+       ts.tv_nsec = (usec % 1000000) * 1000;
+
+       nanosleep(&ts, 0);
+#endif
+
+
+#if    !defined(HAVE_USLEEP)
+#define        HAVE_USLEEP
+
+       sleep((usec+500000)/1000000);
+#endif
+
+       return (0);
+}
+#endif
diff --git a/libunls/CMakeLists.txt b/libunls/CMakeLists.txt
new file mode 100644 (file)
index 0000000..29cb311
--- /dev/null
@@ -0,0 +1,12 @@
+PROJECT (LIBunls C)
+INCLUDE_DIRECTORIES(../include ../libhfs_iso ../wodim ${CMAKE_BINARY_DIR} ${CMAKE_BINARY_DIR}/include)
+ADD_DEFINITIONS(-DHAVE_CONFIG_H)
+
+    IF(HAVE_ICONV_H)
+ADD_DEFINITIONS(-DUSE_ICONV)
+    ENDIF(HAVE_ICONV_H)
+
+
+SET(LIBunls_SRCS nls_base.c nls_config.c nls_cp10000.c nls_cp10006.c nls_cp10007.c nls_cp10029.c nls_cp10079.c nls_cp10081.c nls_cp1250.c nls_cp1251.c nls_cp437.c nls_cp737.c nls_cp775.c nls_cp850.c nls_cp852.c nls_cp855.c nls_cp857.c nls_cp860.c nls_cp861.c nls_cp862.c nls_cp863.c nls_cp864.c nls_cp865.c nls_cp866.c nls_cp869.c nls_cp874.c nls_file.c nls_iso8859-1.c nls_iso8859-14.c nls_iso8859-15.c nls_iso8859-2.c nls_iso8859-3.c nls_iso8859-4.c nls_iso8859-5.c nls_iso8859-6.c nls_iso8859-7.c nls_iso8859-8.c nls_iso8859-9.c nls_koi8-r.c nls_koi8-u.c nls_iconv.c) 
+#SET_SOURCE_FILES_PROPERTIES(${LIBunls_SRCS} PROPERTIES )
+ADD_LIBRARY (unls STATIC ${LIBunls_SRCS})
diff --git a/libunls/nls.h b/libunls/nls.h
new file mode 100644 (file)
index 0000000..1165036
--- /dev/null
@@ -0,0 +1,130 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)nls.h   1.7 05/05/01 2000 J. Schilling */
+/*
+ *     Modifications to make the code portable Copyright (c) 2000 J. Schilling
+ *     Thanks to Georgy Salnikov <sge@nmr.nioch.nsc.ru>
+ *
+ *     Code taken from the Linux kernel.
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef        _NLS_H
+#define        _NLS_H
+
+#include <unls.h>
+
+#ifndef        NULL
+#define        NULL ((void *)0)
+#endif
+
+#define        MOD_INC_USE_COUNT
+#define        MOD_DEC_USE_COUNT
+
+#define        CONFIG_NLS_CODEPAGE_437
+#define        CONFIG_NLS_CODEPAGE_737
+#define        CONFIG_NLS_CODEPAGE_775
+#define        CONFIG_NLS_CODEPAGE_850
+#define        CONFIG_NLS_CODEPAGE_852
+#define        CONFIG_NLS_CODEPAGE_855
+#define        CONFIG_NLS_CODEPAGE_857
+#define        CONFIG_NLS_CODEPAGE_860
+#define        CONFIG_NLS_CODEPAGE_861
+#define        CONFIG_NLS_CODEPAGE_862
+#define        CONFIG_NLS_CODEPAGE_863
+#define        CONFIG_NLS_CODEPAGE_864
+#define        CONFIG_NLS_CODEPAGE_865
+#define        CONFIG_NLS_CODEPAGE_866
+#define        CONFIG_NLS_CODEPAGE_869
+#define        CONFIG_NLS_CODEPAGE_874
+#define        CONFIG_NLS_CODEPAGE_1250
+#define        CONFIG_NLS_CODEPAGE_1251
+#define        CONFIG_NLS_ISO8859_1
+#define        CONFIG_NLS_ISO8859_2
+#define        CONFIG_NLS_ISO8859_3
+#define        CONFIG_NLS_ISO8859_4
+#define        CONFIG_NLS_ISO8859_5
+#define        CONFIG_NLS_ISO8859_6
+#define        CONFIG_NLS_ISO8859_7
+#define        CONFIG_NLS_ISO8859_8
+#define        CONFIG_NLS_ISO8859_9
+#define        CONFIG_NLS_ISO8859_14
+#define        CONFIG_NLS_ISO8859_15
+#define        CONFIG_NLS_KOI8_R
+#define        CONFIG_NLS_KOI8_U
+
+#define        CONFIG_NLS_CODEPAGE_10000
+#define        CONFIG_NLS_CODEPAGE_10006
+#define        CONFIG_NLS_CODEPAGE_10007
+#define        CONFIG_NLS_CODEPAGE_10029
+#define        CONFIG_NLS_CODEPAGE_10079
+#define        CONFIG_NLS_CODEPAGE_10081
+
+extern int init_unls_iso8859_1(void);
+extern int init_unls_iso8859_2(void);
+extern int init_unls_iso8859_3(void);
+extern int init_unls_iso8859_4(void);
+extern int init_unls_iso8859_5(void);
+extern int init_unls_iso8859_6(void);
+extern int init_unls_iso8859_7(void);
+extern int init_unls_iso8859_8(void);
+extern int init_unls_iso8859_9(void);
+extern int init_unls_iso8859_14(void);
+extern int init_unls_iso8859_15(void);
+extern int init_unls_cp437(void);
+extern int init_unls_cp737(void);
+extern int init_unls_cp775(void);
+extern int init_unls_cp850(void);
+extern int init_unls_cp852(void);
+extern int init_unls_cp855(void);
+extern int init_unls_cp857(void);
+extern int init_unls_cp860(void);
+extern int init_unls_cp861(void);
+extern int init_unls_cp862(void);
+extern int init_unls_cp863(void);
+extern int init_unls_cp864(void);
+extern int init_unls_cp865(void);
+extern int init_unls_cp866(void);
+extern int init_unls_cp869(void);
+extern int init_unls_cp874(void);
+extern int init_unls_cp1250(void);
+extern int init_unls_cp1251(void);
+extern int init_unls_koi8_r(void);
+extern int init_unls_koi8_u(void);
+
+extern int init_unls_cp10000(void);
+extern int init_unls_cp10006(void);
+extern int init_unls_cp10007(void);
+extern int init_unls_cp10029(void);
+extern int init_unls_cp10079(void);
+extern int init_unls_cp10081(void);
+extern int init_unls_file(char *name);
+
+#ifdef USE_ICONV
+extern int init_nls_iconv(char *name);
+#endif
+
+#endif /* _NLS_H */
diff --git a/libunls/nls_base.c b/libunls/nls_base.c
new file mode 100644 (file)
index 0000000..e89aa44
--- /dev/null
@@ -0,0 +1,263 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)nls_base.c      1.5 05/05/01 2000 J. Schilling */
+/*
+ *     Modifications to make the code portable Copyright (c) 2000 J. Schilling
+ *     Thanks to Georgy Salnikov <sge@nmr.nioch.nsc.ru>
+ *
+ *     Code taken from the Linux kernel.
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/*
+ * linux/fs/nls.c
+ *
+ * Native language support--charsets and unicode translations.
+ * By Gordon Chaffee 1996, 1997
+ *
+ */
+
+#include <mconfig.h>
+#include <stdio.h>
+#include <strdefs.h>
+#include <errno.h>
+#include "nls.h"
+
+static struct unls_table *tables = (struct unls_table *) NULL;
+
+int
+register_unls(struct unls_table *unls)
+{
+       struct unls_table ** tmp = &tables;
+
+       if (!unls)
+               return (-EINVAL);
+       if (unls->unls_next)
+               return (-EBUSY);
+       while (*tmp) {
+               if (unls == *tmp) {
+                       return (-EBUSY);
+               }
+               tmp = &(*tmp)->unls_next;
+       }
+       unls->unls_next = tables;
+       tables = unls;
+       return (0);
+}
+
+int
+unregister_unls(struct unls_table *unls)
+{
+       struct unls_table ** tmp = &tables;
+
+       while (*tmp) {
+               if (unls == *tmp) {
+                       *tmp = unls->unls_next;
+                       return (0);
+               }
+               tmp = &(*tmp)->unls_next;
+       }
+       return (-EINVAL);
+}
+
+struct unls_table *
+find_unls(char *charset)
+{
+       struct unls_table *unls = tables;
+       while (unls) {
+               if (strcmp(unls->unls_name, charset) == 0)
+                       return (unls);
+               unls = unls->unls_next;
+       }
+       return (NULL);
+}
+
+void
+list_unls()
+{
+       struct unls_table *unls = tables;
+       while (unls) {
+               fprintf(stderr, "%s\n", unls->unls_name);
+               unls = unls->unls_next;
+       }
+}
+
+struct unls_table *
+load_unls(char *charset)
+{
+       struct unls_table *unls;
+
+       unls = find_unls(charset);
+       if (unls) {
+               return (unls);
+       }
+
+       return (NULL);
+}
+
+void
+unload_unls(struct unls_table *nls)
+{
+}
+
+static struct unls_unicode charset2uni[256] = {
+       /* 0x00*/
+       {0x00, 0x00}, {0x01, 0x00}, {0x02, 0x00}, {0x03, 0x00},
+       {0x04, 0x00}, {0x05, 0x00}, {0x06, 0x00}, {0x07, 0x00},
+       {0x08, 0x00}, {0x09, 0x00}, {0x0a, 0x00}, {0x0b, 0x00},
+       {0x0c, 0x00}, {0x0d, 0x00}, {0x0e, 0x00}, {0x0f, 0x00},
+       /* 0x10*/
+       {0x10, 0x00}, {0x11, 0x00}, {0x12, 0x00}, {0x13, 0x00},
+       {0x14, 0x00}, {0x15, 0x00}, {0x16, 0x00}, {0x17, 0x00},
+       {0x18, 0x00}, {0x19, 0x00}, {0x1a, 0x00}, {0x1b, 0x00},
+       {0x1c, 0x00}, {0x1d, 0x00}, {0x1e, 0x00}, {0x1f, 0x00},
+       /* 0x20*/
+       {0x20, 0x00}, {0x21, 0x00}, {0x22, 0x00}, {0x23, 0x00},
+       {0x24, 0x00}, {0x25, 0x00}, {0x26, 0x00}, {0x27, 0x00},
+       {0x28, 0x00}, {0x29, 0x00}, {0x2a, 0x00}, {0x2b, 0x00},
+       {0x2c, 0x00}, {0x2d, 0x00}, {0x2e, 0x00}, {0x2f, 0x00},
+       /* 0x30*/
+       {0x30, 0x00}, {0x31, 0x00}, {0x32, 0x00}, {0x33, 0x00},
+       {0x34, 0x00}, {0x35, 0x00}, {0x36, 0x00}, {0x37, 0x00},
+       {0x38, 0x00}, {0x39, 0x00}, {0x3a, 0x00}, {0x3b, 0x00},
+       {0x3c, 0x00}, {0x3d, 0x00}, {0x3e, 0x00}, {0x3f, 0x00},
+       /* 0x40*/
+       {0x40, 0x00}, {0x41, 0x00}, {0x42, 0x00}, {0x43, 0x00},
+       {0x44, 0x00}, {0x45, 0x00}, {0x46, 0x00}, {0x47, 0x00},
+       {0x48, 0x00}, {0x49, 0x00}, {0x4a, 0x00}, {0x4b, 0x00},
+       {0x4c, 0x00}, {0x4d, 0x00}, {0x4e, 0x00}, {0x4f, 0x00},
+       /* 0x50*/
+       {0x50, 0x00}, {0x51, 0x00}, {0x52, 0x00}, {0x53, 0x00},
+       {0x54, 0x00}, {0x55, 0x00}, {0x56, 0x00}, {0x57, 0x00},
+       {0x58, 0x00}, {0x59, 0x00}, {0x5a, 0x00}, {0x5b, 0x00},
+       {0x5c, 0x00}, {0x5d, 0x00}, {0x5e, 0x00}, {0x5f, 0x00},
+       /* 0x60*/
+       {0x60, 0x00}, {0x61, 0x00}, {0x62, 0x00}, {0x63, 0x00},
+       {0x64, 0x00}, {0x65, 0x00}, {0x66, 0x00}, {0x67, 0x00},
+       {0x68, 0x00}, {0x69, 0x00}, {0x6a, 0x00}, {0x6b, 0x00},
+       {0x6c, 0x00}, {0x6d, 0x00}, {0x6e, 0x00}, {0x6f, 0x00},
+       /* 0x70*/
+       {0x70, 0x00}, {0x71, 0x00}, {0x72, 0x00}, {0x73, 0x00},
+       {0x74, 0x00}, {0x75, 0x00}, {0x76, 0x00}, {0x77, 0x00},
+       {0x78, 0x00}, {0x79, 0x00}, {0x7a, 0x00}, {0x7b, 0x00},
+       {0x7c, 0x00}, {0x7d, 0x00}, {0x7e, 0x00}, {0x7f, 0x00},
+       /* 0x80*/
+       {0x80, 0x00}, {0x81, 0x00}, {0x82, 0x00}, {0x83, 0x00},
+       {0x84, 0x00}, {0x85, 0x00}, {0x86, 0x00}, {0x87, 0x00},
+       {0x88, 0x00}, {0x89, 0x00}, {0x8a, 0x00}, {0x8b, 0x00},
+       {0x8c, 0x00}, {0x8d, 0x00}, {0x8e, 0x00}, {0x8f, 0x00},
+       /* 0x90*/
+       {0x90, 0x00}, {0x91, 0x00}, {0x92, 0x00}, {0x93, 0x00},
+       {0x94, 0x00}, {0x95, 0x00}, {0x96, 0x00}, {0x97, 0x00},
+       {0x98, 0x00}, {0x99, 0x00}, {0x9a, 0x00}, {0x9b, 0x00},
+       {0x9c, 0x00}, {0x9d, 0x00}, {0x9e, 0x00}, {0x9f, 0x00},
+       /* 0xa0*/
+       {0xa0, 0x00}, {0xa1, 0x00}, {0xa2, 0x00}, {0xa3, 0x00},
+       {0xa4, 0x00}, {0xa5, 0x00}, {0xa6, 0x00}, {0xa7, 0x00},
+       {0xa8, 0x00}, {0xa9, 0x00}, {0xaa, 0x00}, {0xab, 0x00},
+       {0xac, 0x00}, {0xad, 0x00}, {0xae, 0x00}, {0xaf, 0x00},
+       /* 0xb0*/
+       {0xb0, 0x00}, {0xb1, 0x00}, {0xb2, 0x00}, {0xb3, 0x00},
+       {0xb4, 0x00}, {0xb5, 0x00}, {0xb6, 0x00}, {0xb7, 0x00},
+       {0xb8, 0x00}, {0xb9, 0x00}, {0xba, 0x00}, {0xbb, 0x00},
+       {0xbc, 0x00}, {0xbd, 0x00}, {0xbe, 0x00}, {0xbf, 0x00},
+       /* 0xc0*/
+       {0xc0, 0x00}, {0xc1, 0x00}, {0xc2, 0x00}, {0xc3, 0x00},
+       {0xc4, 0x00}, {0xc5, 0x00}, {0xc6, 0x00}, {0xc7, 0x00},
+       {0xc8, 0x00}, {0xc9, 0x00}, {0xca, 0x00}, {0xcb, 0x00},
+       {0xcc, 0x00}, {0xcd, 0x00}, {0xce, 0x00}, {0xcf, 0x00},
+       /* 0xd0*/
+       {0xd0, 0x00}, {0xd1, 0x00}, {0xd2, 0x00}, {0xd3, 0x00},
+       {0xd4, 0x00}, {0xd5, 0x00}, {0xd6, 0x00}, {0xd7, 0x00},
+       {0xd8, 0x00}, {0xd9, 0x00}, {0xda, 0x00}, {0xdb, 0x00},
+       {0xdc, 0x00}, {0xdd, 0x00}, {0xde, 0x00}, {0xdf, 0x00},
+       /* 0xe0*/
+       {0xe0, 0x00}, {0xe1, 0x00}, {0xe2, 0x00}, {0xe3, 0x00},
+       {0xe4, 0x00}, {0xe5, 0x00}, {0xe6, 0x00}, {0xe7, 0x00},
+       {0xe8, 0x00}, {0xe9, 0x00}, {0xea, 0x00}, {0xeb, 0x00},
+       {0xec, 0x00}, {0xed, 0x00}, {0xee, 0x00}, {0xef, 0x00},
+       /* 0xf0*/
+       {0xf0, 0x00}, {0xf1, 0x00}, {0xf2, 0x00}, {0xf3, 0x00},
+       {0xf4, 0x00}, {0xf5, 0x00}, {0xf6, 0x00}, {0xf7, 0x00},
+       {0xf8, 0x00}, {0xf9, 0x00}, {0xfa, 0x00}, {0xfb, 0x00},
+       {0xfc, 0x00}, {0xfd, 0x00}, {0xfe, 0x00}, {0xff, 0x00},
+};
+
+static unsigned char page00[256] = {
+       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+       0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
+       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
+       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
+       0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+       0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */
+       0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */
+       0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */
+       0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+       0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 0x80-0x87 */
+       0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, /* 0x88-0x8f */
+       0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, /* 0x90-0x97 */
+       0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, /* 0x98-0x9f */
+       0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, /* 0xa0-0xa7 */
+       0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
+       0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
+       0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* 0xb8-0xbf */
+       0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xc0-0xc7 */
+       0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
+       0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
+       0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, /* 0xd8-0xdf */
+       0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0xe0-0xe7 */
+       0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xe8-0xef */
+       0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
+       0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
+};
+
+static unsigned char *page_uni2charset[256] = {
+       page00
+};
+
+
+static struct unls_table default_table = {
+       "default",
+       page_uni2charset,
+       charset2uni,
+       NULL
+};
+
+
+
+/* Returns a simple default translation table */
+struct unls_table *
+load_unls_default()
+{
+       return (&default_table);
+}
diff --git a/libunls/nls_config.c b/libunls/nls_config.c
new file mode 100644 (file)
index 0000000..ec2b9f6
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)nls_config.c    1.5 05/05/01 2000,2001 J. Schilling */
+/*
+ *     Modifications to make the code portable Copyright (c) 2000 J. Schilling
+ *     This file contains code taken from nls_base.c to avoid loops
+ *     in dependency reported by tsort.
+ *
+ *     Thanks to Georgy Salnikov <sge@nmr.nioch.nsc.ru>
+ *
+ *     Code taken from the Linux kernel.
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <mconfig.h>
+#include "nls.h"
+
+int
+init_unls()
+{
+#ifdef CONFIG_NLS_ISO8859_1
+       init_unls_iso8859_1();
+#endif
+#ifdef CONFIG_NLS_ISO8859_2
+       init_unls_iso8859_2();
+#endif
+#ifdef CONFIG_NLS_ISO8859_3
+       init_unls_iso8859_3();
+#endif
+#ifdef CONFIG_NLS_ISO8859_4
+       init_unls_iso8859_4();
+#endif
+#ifdef CONFIG_NLS_ISO8859_5
+       init_unls_iso8859_5();
+#endif
+#ifdef CONFIG_NLS_ISO8859_6
+       init_unls_iso8859_6();
+#endif
+#ifdef CONFIG_NLS_ISO8859_7
+       init_unls_iso8859_7();
+#endif
+#ifdef CONFIG_NLS_ISO8859_8
+       init_unls_iso8859_8();
+#endif
+#ifdef CONFIG_NLS_ISO8859_9
+       init_unls_iso8859_9();
+#endif
+#ifdef CONFIG_NLS_ISO8859_14
+       init_unls_iso8859_14();
+#endif
+#ifdef CONFIG_NLS_ISO8859_15
+       init_unls_iso8859_15();
+#endif
+#ifdef CONFIG_NLS_CODEPAGE_437
+       init_unls_cp437();
+#endif
+#ifdef CONFIG_NLS_CODEPAGE_737
+       init_unls_cp737();
+#endif
+#ifdef CONFIG_NLS_CODEPAGE_775
+       init_unls_cp775();
+#endif
+#ifdef CONFIG_NLS_CODEPAGE_850
+       init_unls_cp850();
+#endif
+#ifdef CONFIG_NLS_CODEPAGE_852
+       init_unls_cp852();
+#endif
+#ifdef CONFIG_NLS_CODEPAGE_855
+       init_unls_cp855();
+#endif
+#ifdef CONFIG_NLS_CODEPAGE_857
+       init_unls_cp857();
+#endif
+#ifdef CONFIG_NLS_CODEPAGE_860
+       init_unls_cp860();
+#endif
+#ifdef CONFIG_NLS_CODEPAGE_861
+       init_unls_cp861();
+#endif
+#ifdef CONFIG_NLS_CODEPAGE_862
+       init_unls_cp862();
+#endif
+#ifdef CONFIG_NLS_CODEPAGE_863
+       init_unls_cp863();
+#endif
+#ifdef CONFIG_NLS_CODEPAGE_864
+       init_unls_cp864();
+#endif
+#ifdef CONFIG_NLS_CODEPAGE_865
+       init_unls_cp865();
+#endif
+#ifdef CONFIG_NLS_CODEPAGE_866
+       init_unls_cp866();
+#endif
+#ifdef CONFIG_NLS_CODEPAGE_869
+       init_unls_cp869();
+#endif
+#ifdef CONFIG_NLS_CODEPAGE_874
+       init_unls_cp874();
+#endif
+#ifdef CONFIG_NLS_CODEPAGE_1250
+       init_unls_cp1250();
+#endif
+#ifdef CONFIG_NLS_CODEPAGE_1251
+       init_unls_cp1251();
+#endif
+#ifdef CONFIG_NLS_KOI8_R
+       init_unls_koi8_r();
+#endif
+#ifdef CONFIG_NLS_KOI8_U
+       init_unls_koi8_u();
+#endif
+#ifdef CONFIG_NLS_CODEPAGE_10000
+       init_unls_cp10000();
+#endif
+#ifdef CONFIG_NLS_CODEPAGE_10006
+       init_unls_cp10006();
+#endif
+#ifdef CONFIG_NLS_CODEPAGE_10007
+       init_unls_cp10007();
+#endif
+#ifdef CONFIG_NLS_CODEPAGE_10029
+       init_unls_cp10029();
+#endif
+#ifdef CONFIG_NLS_CODEPAGE_10079
+       init_unls_cp10079();
+#endif
+#ifdef CONFIG_NLS_CODEPAGE_10081
+       init_unls_cp10081();
+#endif
+       return (0);
+}
diff --git a/libunls/nls_cp10000.c b/libunls/nls_cp10000.c
new file mode 100644 (file)
index 0000000..cc4a5b5
--- /dev/null
@@ -0,0 +1,607 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)nls_cp10000.c   1.3 05/05/01 2000 J. Schilling */
+/*
+ *      Modifications to make the code portable Copyright (c) 2000 J. Schilling
+ *
+ *     Code generated by James Pearson j.pearson@ge.ucl.ac.uk 26/4/2000
+ *     based on a script by Gordon Chaffee <chaffee@bmrc.berkeley.edu>
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/*
+ * linux/fs/nls_cp10000.c
+ *
+ * Charset cp10000 translation tables.
+ * Generated automatically from the Unicode and charset
+ * tables from the Unicode Organization (www.unicode.org).
+ * The Unicode to charset table has only exact mappings.
+ */
+
+#include <mconfig.h>
+#include "nls.h"
+
+static struct unls_unicode charset2uni[256] = {
+       /* 0x00*/
+       {0x00, 0x00}, {0x01, 0x00}, {0x02, 0x00}, {0x03, 0x00},
+       {0x04, 0x00}, {0x05, 0x00}, {0x06, 0x00}, {0x07, 0x00},
+       {0x08, 0x00}, {0x09, 0x00}, {0x0a, 0x00}, {0x0b, 0x00},
+       {0x0c, 0x00}, {0x0d, 0x00}, {0x0e, 0x00}, {0x0f, 0x00},
+       /* 0x10*/
+       {0x10, 0x00}, {0x11, 0x00}, {0x12, 0x00}, {0x13, 0x00},
+       {0x14, 0x00}, {0x15, 0x00}, {0x16, 0x00}, {0x17, 0x00},
+       {0x18, 0x00}, {0x19, 0x00}, {0x1a, 0x00}, {0x1b, 0x00},
+       {0x1c, 0x00}, {0x1d, 0x00}, {0x1e, 0x00}, {0x1f, 0x00},
+       /* 0x20*/
+       {0x20, 0x00}, {0x21, 0x00}, {0x22, 0x00}, {0x23, 0x00},
+       {0x24, 0x00}, {0x25, 0x00}, {0x26, 0x00}, {0x27, 0x00},
+       {0x28, 0x00}, {0x29, 0x00}, {0x2a, 0x00}, {0x2b, 0x00},
+       {0x2c, 0x00}, {0x2d, 0x00}, {0x2e, 0x00}, {0x2f, 0x00},
+       /* 0x30*/
+       {0x30, 0x00}, {0x31, 0x00}, {0x32, 0x00}, {0x33, 0x00},
+       {0x34, 0x00}, {0x35, 0x00}, {0x36, 0x00}, {0x37, 0x00},
+       {0x38, 0x00}, {0x39, 0x00}, {0x3a, 0x00}, {0x3b, 0x00},
+       {0x3c, 0x00}, {0x3d, 0x00}, {0x3e, 0x00}, {0x3f, 0x00},
+       /* 0x40*/
+       {0x40, 0x00}, {0x41, 0x00}, {0x42, 0x00}, {0x43, 0x00},
+       {0x44, 0x00}, {0x45, 0x00}, {0x46, 0x00}, {0x47, 0x00},
+       {0x48, 0x00}, {0x49, 0x00}, {0x4a, 0x00}, {0x4b, 0x00},
+       {0x4c, 0x00}, {0x4d, 0x00}, {0x4e, 0x00}, {0x4f, 0x00},
+       /* 0x50*/
+       {0x50, 0x00}, {0x51, 0x00}, {0x52, 0x00}, {0x53, 0x00},
+       {0x54, 0x00}, {0x55, 0x00}, {0x56, 0x00}, {0x57, 0x00},
+       {0x58, 0x00}, {0x59, 0x00}, {0x5a, 0x00}, {0x5b, 0x00},
+       {0x5c, 0x00}, {0x5d, 0x00}, {0x5e, 0x00}, {0x5f, 0x00},
+       /* 0x60*/
+       {0x60, 0x00}, {0x61, 0x00}, {0x62, 0x00}, {0x63, 0x00},
+       {0x64, 0x00}, {0x65, 0x00}, {0x66, 0x00}, {0x67, 0x00},
+       {0x68, 0x00}, {0x69, 0x00}, {0x6a, 0x00}, {0x6b, 0x00},
+       {0x6c, 0x00}, {0x6d, 0x00}, {0x6e, 0x00}, {0x6f, 0x00},
+       /* 0x70*/
+       {0x70, 0x00}, {0x71, 0x00}, {0x72, 0x00}, {0x73, 0x00},
+       {0x74, 0x00}, {0x75, 0x00}, {0x76, 0x00}, {0x77, 0x00},
+       {0x78, 0x00}, {0x79, 0x00}, {0x7a, 0x00}, {0x7b, 0x00},
+       {0x7c, 0x00}, {0x7d, 0x00}, {0x7e, 0x00}, {0x7f, 0x00},
+       /* 0x80*/
+       {0xc4, 0x00}, {0xc5, 0x00}, {0xc7, 0x00}, {0xc9, 0x00},
+       {0xd1, 0x00}, {0xd6, 0x00}, {0xdc, 0x00}, {0xe1, 0x00},
+       {0xe0, 0x00}, {0xe2, 0x00}, {0xe4, 0x00}, {0xe3, 0x00},
+       {0xe5, 0x00}, {0xe7, 0x00}, {0xe9, 0x00}, {0xe8, 0x00},
+       /* 0x90*/
+       {0xea, 0x00}, {0xeb, 0x00}, {0xed, 0x00}, {0xec, 0x00},
+       {0xee, 0x00}, {0xef, 0x00}, {0xf1, 0x00}, {0xf3, 0x00},
+       {0xf2, 0x00}, {0xf4, 0x00}, {0xf6, 0x00}, {0xf5, 0x00},
+       {0xfa, 0x00}, {0xf9, 0x00}, {0xfb, 0x00}, {0xfc, 0x00},
+       /* 0xa0*/
+       {0x20, 0x20}, {0xb0, 0x00}, {0xa2, 0x00}, {0xa3, 0x00},
+       {0xa7, 0x00}, {0x22, 0x20}, {0xb6, 0x00}, {0xdf, 0x00},
+       {0xae, 0x00}, {0xa9, 0x00}, {0x22, 0x21}, {0xb4, 0x00},
+       {0xa8, 0x00}, {0x60, 0x22}, {0xc6, 0x00}, {0xd8, 0x00},
+       /* 0xb0*/
+       {0x1e, 0x22}, {0xb1, 0x00}, {0x64, 0x22}, {0x65, 0x22},
+       {0xa5, 0x00}, {0xb5, 0x00}, {0x02, 0x22}, {0x11, 0x22},
+       {0x0f, 0x22}, {0xc0, 0x03}, {0x2b, 0x22}, {0xaa, 0x00},
+       {0xba, 0x00}, {0xa9, 0x03}, {0xe6, 0x00}, {0xf8, 0x00},
+       /* 0xc0*/
+       {0xbf, 0x00}, {0xa1, 0x00}, {0xac, 0x00}, {0x1a, 0x22},
+       {0x92, 0x01}, {0x48, 0x22}, {0x06, 0x22}, {0xab, 0x00},
+       {0xbb, 0x00}, {0x26, 0x20}, {0xa0, 0x00}, {0xc0, 0x00},
+       {0xc3, 0x00}, {0xd5, 0x00}, {0x52, 0x01}, {0x53, 0x01},
+       /* 0xd0*/
+       {0x13, 0x20}, {0x14, 0x20}, {0x1c, 0x20}, {0x1d, 0x20},
+       {0x18, 0x20}, {0x19, 0x20}, {0xf7, 0x00}, {0xca, 0x25},
+       {0xff, 0x00}, {0x78, 0x01}, {0x44, 0x20}, {0xac, 0x20},
+       {0x39, 0x20}, {0x3a, 0x20}, {0x01, 0xfb}, {0x02, 0xfb},
+       /* 0xe0*/
+       {0x21, 0x20}, {0xb7, 0x00}, {0x1a, 0x20}, {0x1e, 0x20},
+       {0x30, 0x20}, {0xc2, 0x00}, {0xca, 0x00}, {0xc1, 0x00},
+       {0xcb, 0x00}, {0xc8, 0x00}, {0xcd, 0x00}, {0xce, 0x00},
+       {0xcf, 0x00}, {0xcc, 0x00}, {0xd3, 0x00}, {0xd4, 0x00},
+       /* 0xf0*/
+       {0xff, 0xf8}, {0xd2, 0x00}, {0xda, 0x00}, {0xdb, 0x00},
+       {0xd9, 0x00}, {0x31, 0x01}, {0xc6, 0x02}, {0xdc, 0x02},
+       {0xaf, 0x00}, {0xd8, 0x02}, {0xd9, 0x02}, {0xda, 0x02},
+       {0xb8, 0x00}, {0xdd, 0x02}, {0xdb, 0x02}, {0xc7, 0x02},
+};
+
+static unsigned char page00[256] = {
+       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+       0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
+       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
+       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
+       0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+       0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */
+       0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */
+       0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */
+       0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0xca, 0xc1, 0xa2, 0xa3, 0x00, 0xb4, 0x00, 0xa4, /* 0xa0-0xa7 */
+       0xac, 0xa9, 0xbb, 0xc7, 0xc2, 0x00, 0xa8, 0xf8, /* 0xa8-0xaf */
+       0xa1, 0xb1, 0x00, 0x00, 0xab, 0xb5, 0xa6, 0xe1, /* 0xb0-0xb7 */
+       0xfc, 0x00, 0xbc, 0xc8, 0x00, 0x00, 0x00, 0xc0, /* 0xb8-0xbf */
+       0xcb, 0xe7, 0xe5, 0xcc, 0x80, 0x81, 0xae, 0x82, /* 0xc0-0xc7 */
+       0xe9, 0x83, 0xe6, 0xe8, 0xed, 0xea, 0xeb, 0xec, /* 0xc8-0xcf */
+       0x00, 0x84, 0xf1, 0xee, 0xef, 0xcd, 0x85, 0x00, /* 0xd0-0xd7 */
+       0xaf, 0xf4, 0xf2, 0xf3, 0x86, 0x00, 0x00, 0xa7, /* 0xd8-0xdf */
+       0x88, 0x87, 0x89, 0x8b, 0x8a, 0x8c, 0xbe, 0x8d, /* 0xe0-0xe7 */
+       0x8f, 0x8e, 0x90, 0x91, 0x93, 0x92, 0x94, 0x95, /* 0xe8-0xef */
+       0x00, 0x96, 0x98, 0x97, 0x99, 0x9b, 0x9a, 0xd6, /* 0xf0-0xf7 */
+       0xbf, 0x9d, 0x9c, 0x9e, 0x9f, 0x00, 0x00, 0xd8, /* 0xf8-0xff */
+};
+
+static unsigned char page01[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0xf5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0xce, 0xcf, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0xd9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0xc4, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page02[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, 0xff, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0xf9, 0xfa, 0xfb, 0xfe, 0xf7, 0xfd, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page03[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0xb9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page20[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0xd0, 0xd1, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0xd4, 0xd5, 0xe2, 0x00, 0xd2, 0xd3, 0xe3, 0x00, /* 0x18-0x1f */
+       0xa0, 0xe0, 0xa5, 0x00, 0x00, 0x00, 0xc9, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0xe4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0xdc, 0xdd, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0xda, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0xdb, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page21[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page22[256] = {
+       0x00, 0x00, 0xb6, 0x00, 0x00, 0x00, 0xc6, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, /* 0x08-0x0f */
+       0x00, 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0xc3, 0x00, 0x00, 0x00, 0xb0, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0xba, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0xc5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0xad, 0x00, 0x00, 0x00, 0xb2, 0xb3, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page25[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0xd7, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char pagef8[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, /* 0xf8-0xff */
+};
+
+static unsigned char pagefb[256] = {
+       0x00, 0xde, 0xdf, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char *page_uni2charset[256] = {
+       page00, page01, page02, page03, NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       page20, page21, page22, NULL,   NULL,   page25, NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       pagef8, NULL,   NULL,   pagefb, NULL,   NULL,   NULL,   NULL,
+};
+
+#if 0
+static unsigned char charset2upper[256] = {
+       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+       0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
+       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
+       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
+       0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+       0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x60-0x67 */
+       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x68-0x6f */
+       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x70-0x77 */
+       0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+       0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0xe7, /* 0x80-0x87 */
+       0xcb, 0xe5, 0x80, 0xcc, 0x81, 0x82, 0x83, 0xe9, /* 0x88-0x8f */
+       0xe6, 0xe8, 0xea, 0xed, 0xeb, 0xec, 0x84, 0xee, /* 0x90-0x97 */
+       0xf1, 0xef, 0x85, 0xcd, 0xf2, 0xf4, 0xf3, 0x86, /* 0x98-0x9f */
+       0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0x53, /* 0xa0-0xa7 */
+       0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
+       0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
+       0xb8, 0x50, 0xba, 0xbb, 0xbc, 0xbd, 0xae, 0xaf, /* 0xb8-0xbf */
+       0xc0, 0xc1, 0xc2, 0xc3, 0x46, 0xc5, 0xc6, 0xc7, /* 0xc0-0xc7 */
+       0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
+       0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
+       0xd9, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, /* 0xd8-0xdf */
+       0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0xe0-0xe7 */
+       0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xe8-0xef */
+       0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0x49, 0xf6, 0xf7, /* 0xf0-0xf7 */
+       0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
+};
+
+static unsigned char charset2lower[256] = {
+       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+       0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x40-0x47 */
+       0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x48-0x4f */
+       0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x50-0x57 */
+       0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+       0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */
+       0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */
+       0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */
+       0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+       0x8a, 0x8c, 0x8d, 0x8e, 0x96, 0x9a, 0x9f, 0x87, /* 0x80-0x87 */
+       0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, /* 0x88-0x8f */
+       0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, /* 0x90-0x97 */
+       0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, /* 0x98-0x9f */
+       0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, /* 0xa0-0xa7 */
+       0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xbe, 0xbf, /* 0xa8-0xaf */
+       0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
+       0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0x00, 0xbe, 0xbf, /* 0xb8-0xbf */
+       0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xc0-0xc7 */
+       0xc8, 0xc9, 0xca, 0x88, 0x8b, 0x9b, 0xce, 0xcf, /* 0xc8-0xcf */
+       0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
+       0xd8, 0xd8, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, /* 0xd8-0xdf */
+       0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0x89, 0x90, 0x87, /* 0xe0-0xe7 */
+       0x91, 0x8f, 0x92, 0x94, 0x95, 0x93, 0x97, 0x99, /* 0xe8-0xef */
+       0xf0, 0x98, 0x9c, 0x9e, 0x9d, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
+       0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
+};
+#endif
+
+static struct unls_table table = {
+       "cp10000",
+       page_uni2charset,
+       charset2uni,
+       NULL
+};
+
+int
+init_unls_cp10000()
+{
+       return (register_unls(&table));
+}
diff --git a/libunls/nls_cp10006.c b/libunls/nls_cp10006.c
new file mode 100644 (file)
index 0000000..8405fbe
--- /dev/null
@@ -0,0 +1,499 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)nls_cp10006.c   1.3 05/05/01 2000 J. Schilling */
+/*
+ *     Modifications to make the code portable Copyright (c) 2000 J. Schilling
+ *
+ *      Code generated by James Pearson j.pearson@ge.ucl.ac.uk 17/8/2000
+ *      based on a script by Gordon Chaffee <chaffee@bmrc.berkeley.edu>
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/*
+ * linux/fs/nls_cp10006.c
+ *
+ * Charset cp10006 translation tables.
+ * Generated automatically from the Unicode and charset
+ * tables from the Unicode Organization (www.unicode.org).
+ * The Unicode to charset table has only exact mappings.
+ */
+
+#include <mconfig.h>
+#include "nls.h"
+
+static struct unls_unicode charset2uni[256] = {
+       /* 0x00*/
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       /* 0x10*/
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       /* 0x20*/
+       {0x20, 0x00}, {0x21, 0x00}, {0x22, 0x00}, {0x23, 0x00},
+       {0x24, 0x00}, {0x25, 0x00}, {0x26, 0x00}, {0x27, 0x00},
+       {0x28, 0x00}, {0x29, 0x00}, {0x2a, 0x00}, {0x2b, 0x00},
+       {0x2c, 0x00}, {0x2d, 0x00}, {0x2e, 0x00}, {0x2f, 0x00},
+       /* 0x30*/
+       {0x30, 0x00}, {0x31, 0x00}, {0x32, 0x00}, {0x33, 0x00},
+       {0x34, 0x00}, {0x35, 0x00}, {0x36, 0x00}, {0x37, 0x00},
+       {0x38, 0x00}, {0x39, 0x00}, {0x3a, 0x00}, {0x3b, 0x00},
+       {0x3c, 0x00}, {0x3d, 0x00}, {0x3e, 0x00}, {0x3f, 0x00},
+       /* 0x40*/
+       {0x40, 0x00}, {0x41, 0x00}, {0x42, 0x00}, {0x43, 0x00},
+       {0x44, 0x00}, {0x45, 0x00}, {0x46, 0x00}, {0x47, 0x00},
+       {0x48, 0x00}, {0x49, 0x00}, {0x4a, 0x00}, {0x4b, 0x00},
+       {0x4c, 0x00}, {0x4d, 0x00}, {0x4e, 0x00}, {0x4f, 0x00},
+       /* 0x50*/
+       {0x50, 0x00}, {0x51, 0x00}, {0x52, 0x00}, {0x53, 0x00},
+       {0x54, 0x00}, {0x55, 0x00}, {0x56, 0x00}, {0x57, 0x00},
+       {0x58, 0x00}, {0x59, 0x00}, {0x5a, 0x00}, {0x5b, 0x00},
+       {0x5c, 0x00}, {0x5d, 0x00}, {0x5e, 0x00}, {0x5f, 0x00},
+       /* 0x60*/
+       {0x60, 0x00}, {0x61, 0x00}, {0x62, 0x00}, {0x63, 0x00},
+       {0x64, 0x00}, {0x65, 0x00}, {0x66, 0x00}, {0x67, 0x00},
+       {0x68, 0x00}, {0x69, 0x00}, {0x6a, 0x00}, {0x6b, 0x00},
+       {0x6c, 0x00}, {0x6d, 0x00}, {0x6e, 0x00}, {0x6f, 0x00},
+       /* 0x70*/
+       {0x70, 0x00}, {0x71, 0x00}, {0x72, 0x00}, {0x73, 0x00},
+       {0x74, 0x00}, {0x75, 0x00}, {0x76, 0x00}, {0x77, 0x00},
+       {0x78, 0x00}, {0x79, 0x00}, {0x7a, 0x00}, {0x7b, 0x00},
+       {0x7c, 0x00}, {0x7d, 0x00}, {0x7e, 0x00}, {0x00, 0x00},
+       /* 0x80*/
+       {0xc4, 0x00}, {0xb9, 0x00}, {0xb2, 0x00}, {0xc9, 0x00},
+       {0xb3, 0x00}, {0xd6, 0x00}, {0xdc, 0x00}, {0x85, 0x03},
+       {0xe0, 0x00}, {0xe2, 0x00}, {0xe4, 0x00}, {0x84, 0x03},
+       {0xa8, 0x00}, {0xe7, 0x00}, {0xe9, 0x00}, {0xe8, 0x00},
+       /* 0x90*/
+       {0xea, 0x00}, {0xeb, 0x00}, {0xa3, 0x00}, {0x22, 0x21},
+       {0xee, 0x00}, {0xef, 0x00}, {0x22, 0x20}, {0xbd, 0x00},
+       {0x30, 0x20}, {0xf4, 0x00}, {0xf6, 0x00}, {0xa6, 0x00},
+       {0xad, 0x00}, {0xf9, 0x00}, {0xfb, 0x00}, {0xfc, 0x00},
+       /* 0xa0*/
+       {0x20, 0x20}, {0x93, 0x03}, {0x94, 0x03}, {0x98, 0x03},
+       {0x9b, 0x03}, {0x9e, 0x03}, {0xa0, 0x03}, {0xdf, 0x00},
+       {0xae, 0x00}, {0xa9, 0x00}, {0xa3, 0x03}, {0xaa, 0x03},
+       {0xa7, 0x00}, {0x60, 0x22}, {0xb0, 0x00}, {0xb7, 0x00},
+       /* 0xb0*/
+       {0x91, 0x03}, {0xb1, 0x00}, {0x64, 0x22}, {0x65, 0x22},
+       {0xa5, 0x00}, {0x92, 0x03}, {0x95, 0x03}, {0x96, 0x03},
+       {0x97, 0x03}, {0x99, 0x03}, {0x9a, 0x03}, {0x9c, 0x03},
+       {0xa6, 0x03}, {0xab, 0x03}, {0xa8, 0x03}, {0xa9, 0x03},
+       /* 0xc0*/
+       {0xac, 0x03}, {0x9d, 0x03}, {0xac, 0x00}, {0x9f, 0x03},
+       {0xa1, 0x03}, {0x48, 0x22}, {0xa4, 0x03}, {0xab, 0x00},
+       {0xbb, 0x00}, {0x26, 0x20}, {0xa0, 0x00}, {0xa5, 0x03},
+       {0xa7, 0x03}, {0x86, 0x03}, {0x88, 0x03}, {0x53, 0x01},
+       /* 0xd0*/
+       {0x13, 0x20}, {0x15, 0x20}, {0x1c, 0x20}, {0x1d, 0x20},
+       {0x18, 0x20}, {0x19, 0x20}, {0xf7, 0x00}, {0x89, 0x03},
+       {0x8a, 0x03}, {0x8c, 0x03}, {0x8e, 0x03}, {0xad, 0x03},
+       {0xae, 0x03}, {0xaf, 0x03}, {0xcc, 0x03}, {0x8f, 0x03},
+       /* 0xe0*/
+       {0xcd, 0x03}, {0xb1, 0x03}, {0xb2, 0x03}, {0xc8, 0x03},
+       {0xb4, 0x03}, {0xb5, 0x03}, {0xc6, 0x03}, {0xb3, 0x03},
+       {0xb7, 0x03}, {0xb9, 0x03}, {0xbe, 0x03}, {0xba, 0x03},
+       {0xbb, 0x03}, {0xbc, 0x03}, {0xbd, 0x03}, {0xbf, 0x03},
+       /* 0xf0*/
+       {0xc0, 0x03}, {0xce, 0x03}, {0xc1, 0x03}, {0xc3, 0x03},
+       {0xc4, 0x03}, {0xb8, 0x03}, {0xc9, 0x03}, {0xc2, 0x03},
+       {0xc7, 0x03}, {0xc5, 0x03}, {0xb6, 0x03}, {0xca, 0x03},
+       {0xcb, 0x03}, {0x90, 0x03}, {0xb0, 0x03}, {0xa0, 0xf8},
+};
+
+static unsigned char page00[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+       0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
+       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
+       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
+       0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+       0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */
+       0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */
+       0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */
+       0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0xca, 0x00, 0x00, 0x92, 0x00, 0xb4, 0x9b, 0xac, /* 0xa0-0xa7 */
+       0x8c, 0xa9, 0x00, 0xc7, 0xc2, 0x9c, 0xa8, 0x00, /* 0xa8-0xaf */
+       0xae, 0xb1, 0x82, 0x84, 0x00, 0x00, 0x00, 0xaf, /* 0xb0-0xb7 */
+       0x00, 0x81, 0x00, 0xc8, 0x00, 0x97, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x83, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x85, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x86, 0x00, 0x00, 0xa7, /* 0xd8-0xdf */
+       0x88, 0x00, 0x89, 0x00, 0x8a, 0x00, 0x00, 0x8d, /* 0xe0-0xe7 */
+       0x8f, 0x8e, 0x90, 0x91, 0x00, 0x00, 0x94, 0x95, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x99, 0x00, 0x9a, 0xd6, /* 0xf0-0xf7 */
+       0x00, 0x9d, 0x00, 0x9e, 0x9f, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page01[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0xcf, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page03[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x8b, 0x87, 0xcd, 0x00, /* 0x80-0x87 */
+       0xce, 0xd7, 0xd8, 0x00, 0xd9, 0x00, 0xda, 0xdf, /* 0x88-0x8f */
+       0xfd, 0xb0, 0xb5, 0xa1, 0xa2, 0xb6, 0xb7, 0xb8, /* 0x90-0x97 */
+       0xa3, 0xb9, 0xba, 0xa4, 0xbb, 0xc1, 0xa5, 0xc3, /* 0x98-0x9f */
+       0xa6, 0xc4, 0x00, 0xaa, 0xc6, 0xcb, 0xbc, 0xcc, /* 0xa0-0xa7 */
+       0xbe, 0xbf, 0xab, 0xbd, 0xc0, 0xdb, 0xdc, 0xdd, /* 0xa8-0xaf */
+       0xfe, 0xe1, 0xe2, 0xe7, 0xe4, 0xe5, 0xfa, 0xe8, /* 0xb0-0xb7 */
+       0xf5, 0xe9, 0xeb, 0xec, 0xed, 0xee, 0xea, 0xef, /* 0xb8-0xbf */
+       0xf0, 0xf2, 0xf7, 0xf3, 0xf4, 0xf9, 0xe6, 0xf8, /* 0xc0-0xc7 */
+       0xe3, 0xf6, 0xfb, 0xfc, 0xde, 0xe0, 0xf1, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page20[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0xd0, 0x00, 0xd1, 0x00, 0x00, /* 0x10-0x17 */
+       0xd4, 0xd5, 0x00, 0x00, 0xd2, 0xd3, 0x00, 0x00, /* 0x18-0x1f */
+       0xa0, 0x00, 0x96, 0x00, 0x00, 0x00, 0xc9, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page21[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x93, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page22[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0xc5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0xad, 0x00, 0x00, 0x00, 0xb2, 0xb3, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char pagef8[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char *page_uni2charset[256] = {
+       page00, page01, NULL,   page03, NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       page20, page21, page22, NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       pagef8, NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+};
+
+#if 0
+static unsigned char charset2upper[256] = {
+       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+       0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
+       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
+       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
+       0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+       0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x60-0x67 */
+       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x68-0x6f */
+       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x70-0x77 */
+       0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+       0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 0x80-0x87 */
+       0x41, 0x41, 0x80, 0x8b, 0x8c, 0x43, 0x83, 0x45, /* 0x88-0x8f */
+       0x45, 0x45, 0x92, 0x93, 0x49, 0x49, 0x96, 0x97, /* 0x90-0x97 */
+       0x98, 0x4f, 0x85, 0x9b, 0x9c, 0x55, 0x55, 0x86, /* 0x98-0x9f */
+       0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0x53, /* 0xa0-0xa7 */
+       0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
+       0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
+       0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* 0xb8-0xbf */
+       0xcd, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xc0-0xc7 */
+       0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
+       0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
+       0xd8, 0xd9, 0xda, 0xce, 0xd7, 0xd8, 0xd9, 0xdf, /* 0xd8-0xdf */
+       0xda, 0xb0, 0xb5, 0xbe, 0xa2, 0xb6, 0xbc, 0xa1, /* 0xe0-0xe7 */
+       0xb8, 0xb9, 0xa5, 0xba, 0xa4, 0xbb, 0xc1, 0xc3, /* 0xe8-0xef */
+       0xa6, 0xdf, 0xc4, 0xaa, 0xc6, 0xa3, 0xbf, 0xaa, /* 0xf0-0xf7 */
+       0xcc, 0xcb, 0xb7, 0xab, 0xbd, 0xb9, 0xcb, 0xff, /* 0xf8-0xff */
+};
+
+static unsigned char charset2lower[256] = {
+       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+       0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x40-0x47 */
+       0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x48-0x4f */
+       0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x50-0x57 */
+       0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+       0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */
+       0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */
+       0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */
+       0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+       0x8a, 0x81, 0x82, 0x8e, 0x84, 0x9a, 0x9f, 0x87, /* 0x80-0x87 */
+       0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, /* 0x88-0x8f */
+       0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, /* 0x90-0x97 */
+       0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, /* 0x98-0x9f */
+       0xa0, 0xe7, 0xe4, 0xf5, 0xec, 0xea, 0xf0, 0xa7, /* 0xa0-0xa7 */
+       0xa8, 0xa9, 0xf3, 0xfb, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
+       0xe1, 0xb1, 0xb2, 0xb3, 0xb4, 0xe2, 0xe5, 0xfa, /* 0xb0-0xb7 */
+       0xe8, 0xe9, 0xeb, 0xed, 0xe6, 0xfc, 0xe3, 0xf6, /* 0xb8-0xbf */
+       0xc0, 0xee, 0xc2, 0xef, 0xf2, 0xc5, 0xf4, 0xc7, /* 0xc0-0xc7 */
+       0xc8, 0xc9, 0xca, 0xf9, 0xf8, 0xc0, 0xdb, 0xcf, /* 0xc8-0xcf */
+       0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xdc, /* 0xd0-0xd7 */
+       0xdd, 0xde, 0xe0, 0xdb, 0xdc, 0xdd, 0xde, 0xf1, /* 0xd8-0xdf */
+       0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0xe0-0xe7 */
+       0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xe8-0xef */
+       0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
+       0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
+};
+#endif
+
+static struct unls_table table = {
+       "cp10006",
+       page_uni2charset,
+       charset2uni,
+       NULL
+};
+
+int
+init_unls_cp10006()
+{
+       return (register_unls(&table));
+}
diff --git a/libunls/nls_cp10007.c b/libunls/nls_cp10007.c
new file mode 100644 (file)
index 0000000..e743aad
--- /dev/null
@@ -0,0 +1,436 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)nls_cp10007.c   1.3 05/05/01 2000 J. Schilling */
+/*
+ *     Modifications to make the code portable Copyright (c) 2000 J. Schilling
+ *
+ *      Code generated by James Pearson j.pearson@ge.ucl.ac.uk 17/8/2000
+ *      based on a script by Gordon Chaffee <chaffee@bmrc.berkeley.edu>
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/*
+ * linux/fs/nls_cp10007.c
+ *
+ * Charset cp10007 translation tables.
+ * Generated automatically from the Unicode and charset
+ * tables from the Unicode Organization (www.unicode.org).
+ * The Unicode to charset table has only exact mappings.
+ */
+
+#include <mconfig.h>
+#include "nls.h"
+
+static struct unls_unicode charset2uni[256] = {
+       /* 0x00*/
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       /* 0x10*/
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       /* 0x20*/
+       {0x20, 0x00}, {0x21, 0x00}, {0x22, 0x00}, {0x23, 0x00},
+       {0x24, 0x00}, {0x25, 0x00}, {0x26, 0x00}, {0x27, 0x00},
+       {0x28, 0x00}, {0x29, 0x00}, {0x2a, 0x00}, {0x2b, 0x00},
+       {0x2c, 0x00}, {0x2d, 0x00}, {0x2e, 0x00}, {0x2f, 0x00},
+       /* 0x30*/
+       {0x30, 0x00}, {0x31, 0x00}, {0x32, 0x00}, {0x33, 0x00},
+       {0x34, 0x00}, {0x35, 0x00}, {0x36, 0x00}, {0x37, 0x00},
+       {0x38, 0x00}, {0x39, 0x00}, {0x3a, 0x00}, {0x3b, 0x00},
+       {0x3c, 0x00}, {0x3d, 0x00}, {0x3e, 0x00}, {0x3f, 0x00},
+       /* 0x40*/
+       {0x40, 0x00}, {0x41, 0x00}, {0x42, 0x00}, {0x43, 0x00},
+       {0x44, 0x00}, {0x45, 0x00}, {0x46, 0x00}, {0x47, 0x00},
+       {0x48, 0x00}, {0x49, 0x00}, {0x4a, 0x00}, {0x4b, 0x00},
+       {0x4c, 0x00}, {0x4d, 0x00}, {0x4e, 0x00}, {0x4f, 0x00},
+       /* 0x50*/
+       {0x50, 0x00}, {0x51, 0x00}, {0x52, 0x00}, {0x53, 0x00},
+       {0x54, 0x00}, {0x55, 0x00}, {0x56, 0x00}, {0x57, 0x00},
+       {0x58, 0x00}, {0x59, 0x00}, {0x5a, 0x00}, {0x5b, 0x00},
+       {0x5c, 0x00}, {0x5d, 0x00}, {0x5e, 0x00}, {0x5f, 0x00},
+       /* 0x60*/
+       {0x60, 0x00}, {0x61, 0x00}, {0x62, 0x00}, {0x63, 0x00},
+       {0x64, 0x00}, {0x65, 0x00}, {0x66, 0x00}, {0x67, 0x00},
+       {0x68, 0x00}, {0x69, 0x00}, {0x6a, 0x00}, {0x6b, 0x00},
+       {0x6c, 0x00}, {0x6d, 0x00}, {0x6e, 0x00}, {0x6f, 0x00},
+       /* 0x70*/
+       {0x70, 0x00}, {0x71, 0x00}, {0x72, 0x00}, {0x73, 0x00},
+       {0x74, 0x00}, {0x75, 0x00}, {0x76, 0x00}, {0x77, 0x00},
+       {0x78, 0x00}, {0x79, 0x00}, {0x7a, 0x00}, {0x7b, 0x00},
+       {0x7c, 0x00}, {0x7d, 0x00}, {0x7e, 0x00}, {0x00, 0x00},
+       /* 0x80*/
+       {0x10, 0x04}, {0x11, 0x04}, {0x12, 0x04}, {0x13, 0x04},
+       {0x14, 0x04}, {0x15, 0x04}, {0x16, 0x04}, {0x17, 0x04},
+       {0x18, 0x04}, {0x19, 0x04}, {0x1a, 0x04}, {0x1b, 0x04},
+       {0x1c, 0x04}, {0x1d, 0x04}, {0x1e, 0x04}, {0x1f, 0x04},
+       /* 0x90*/
+       {0x20, 0x04}, {0x21, 0x04}, {0x22, 0x04}, {0x23, 0x04},
+       {0x24, 0x04}, {0x25, 0x04}, {0x26, 0x04}, {0x27, 0x04},
+       {0x28, 0x04}, {0x29, 0x04}, {0x2a, 0x04}, {0x2b, 0x04},
+       {0x2c, 0x04}, {0x2d, 0x04}, {0x2e, 0x04}, {0x2f, 0x04},
+       /* 0xa0*/
+       {0x20, 0x20}, {0xb0, 0x00}, {0x90, 0x04}, {0xa3, 0x00},
+       {0xa7, 0x00}, {0x22, 0x20}, {0xb6, 0x00}, {0x06, 0x04},
+       {0xae, 0x00}, {0xa9, 0x00}, {0x22, 0x21}, {0x02, 0x04},
+       {0x52, 0x04}, {0x60, 0x22}, {0x03, 0x04}, {0x53, 0x04},
+       /* 0xb0*/
+       {0x1e, 0x22}, {0xb1, 0x00}, {0x64, 0x22}, {0x65, 0x22},
+       {0x56, 0x04}, {0xb5, 0x00}, {0x91, 0x04}, {0x08, 0x04},
+       {0x04, 0x04}, {0x54, 0x04}, {0x07, 0x04}, {0x57, 0x04},
+       {0x09, 0x04}, {0x59, 0x04}, {0x0a, 0x04}, {0x5a, 0x04},
+       /* 0xc0*/
+       {0x58, 0x04}, {0x05, 0x04}, {0xac, 0x00}, {0x1a, 0x22},
+       {0x92, 0x01}, {0x48, 0x22}, {0x06, 0x22}, {0xab, 0x00},
+       {0xbb, 0x00}, {0x26, 0x20}, {0xa0, 0x00}, {0x0b, 0x04},
+       {0x5b, 0x04}, {0x0c, 0x04}, {0x5c, 0x04}, {0x55, 0x04},
+       /* 0xd0*/
+       {0x13, 0x20}, {0x14, 0x20}, {0x1c, 0x20}, {0x1d, 0x20},
+       {0x18, 0x20}, {0x19, 0x20}, {0xf7, 0x00}, {0x1e, 0x20},
+       {0x0e, 0x04}, {0x5e, 0x04}, {0x0f, 0x04}, {0x5f, 0x04},
+       {0x16, 0x21}, {0x01, 0x04}, {0x51, 0x04}, {0x4f, 0x04},
+       /* 0xe0*/
+       {0x30, 0x04}, {0x31, 0x04}, {0x32, 0x04}, {0x33, 0x04},
+       {0x34, 0x04}, {0x35, 0x04}, {0x36, 0x04}, {0x37, 0x04},
+       {0x38, 0x04}, {0x39, 0x04}, {0x3a, 0x04}, {0x3b, 0x04},
+       {0x3c, 0x04}, {0x3d, 0x04}, {0x3e, 0x04}, {0x3f, 0x04},
+       /* 0xf0*/
+       {0x40, 0x04}, {0x41, 0x04}, {0x42, 0x04}, {0x43, 0x04},
+       {0x44, 0x04}, {0x45, 0x04}, {0x46, 0x04}, {0x47, 0x04},
+       {0x48, 0x04}, {0x49, 0x04}, {0x4a, 0x04}, {0x4b, 0x04},
+       {0x4c, 0x04}, {0x4d, 0x04}, {0x4e, 0x04}, {0xac, 0x20},
+};
+
+static unsigned char page00[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+       0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
+       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
+       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
+       0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+       0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */
+       0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */
+       0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */
+       0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0xca, 0x00, 0x00, 0xa3, 0x00, 0x00, 0x00, 0xa4, /* 0xa0-0xa7 */
+       0x00, 0xa9, 0x00, 0xc7, 0xc2, 0x00, 0xa8, 0x00, /* 0xa8-0xaf */
+       0xa1, 0xb1, 0x00, 0x00, 0x00, 0xb5, 0xa6, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0xc8, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd6, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page01[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0xc4, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page04[256] = {
+       0x00, 0xdd, 0xab, 0xae, 0xb8, 0xc1, 0xa7, 0xba, /* 0x00-0x07 */
+       0xb7, 0xbc, 0xbe, 0xcb, 0xcd, 0x00, 0xd8, 0xda, /* 0x08-0x0f */
+       0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 0x10-0x17 */
+       0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, /* 0x18-0x1f */
+       0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, /* 0x20-0x27 */
+       0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, /* 0x28-0x2f */
+       0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0x30-0x37 */
+       0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0x38-0x3f */
+       0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0x40-0x47 */
+       0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xdf, /* 0x48-0x4f */
+       0x00, 0xde, 0xac, 0xaf, 0xb9, 0xcf, 0xb4, 0xbb, /* 0x50-0x57 */
+       0xc0, 0xbd, 0xbf, 0xcc, 0xce, 0x00, 0xd9, 0xdb, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0xa2, 0xb6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page20[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0xd0, 0xd1, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0xd4, 0xd5, 0x00, 0x00, 0xd2, 0xd3, 0xd7, 0x00, /* 0x18-0x1f */
+       0xa0, 0x00, 0xa5, 0x00, 0x00, 0x00, 0xc9, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page21[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page22[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0xc3, 0x00, 0x00, 0x00, 0xb0, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0xc5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0xad, 0x00, 0x00, 0x00, 0xb2, 0xb3, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char *page_uni2charset[256] = {
+       page00, page01, NULL,   NULL,   page04, NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       page20, page21, page22, NULL,   NULL,   NULL,   NULL,   NULL,
+};
+
+#if 0
+static unsigned char charset2upper[256] = {
+       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+       0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
+       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
+       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
+       0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+       0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x60-0x67 */
+       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x68-0x6f */
+       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x70-0x77 */
+       0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+       0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 0x80-0x87 */
+       0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, /* 0x88-0x8f */
+       0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, /* 0x90-0x97 */
+       0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, /* 0x98-0x9f */
+       0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, /* 0xa0-0xa7 */
+       0xa8, 0xa9, 0xaa, 0xab, 0xab, 0xad, 0xae, 0xae, /* 0xa8-0xaf */
+       0xb0, 0xb1, 0xb2, 0xb3, 0xa7, 0xb5, 0xa2, 0xb7, /* 0xb0-0xb7 */
+       0xb8, 0xb8, 0xba, 0xba, 0xbc, 0xbc, 0xbe, 0xbe, /* 0xb8-0xbf */
+       0xb7, 0xc1, 0xc2, 0xc3, 0x46, 0xc5, 0xc6, 0xc7, /* 0xc0-0xc7 */
+       0xc8, 0xc9, 0xca, 0xcb, 0xcb, 0xcd, 0xcd, 0xc1, /* 0xc8-0xcf */
+       0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
+       0xd8, 0xd8, 0xda, 0xda, 0xdc, 0xdd, 0xdd, 0x9f, /* 0xd8-0xdf */
+       0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 0xe0-0xe7 */
+       0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, /* 0xe8-0xef */
+       0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, /* 0xf0-0xf7 */
+       0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0xff, /* 0xf8-0xff */
+};
+
+static unsigned char charset2lower[256] = {
+       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+       0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x40-0x47 */
+       0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x48-0x4f */
+       0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x50-0x57 */
+       0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+       0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */
+       0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */
+       0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */
+       0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+       0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0x80-0x87 */
+       0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0x88-0x8f */
+       0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0x90-0x97 */
+       0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xdf, /* 0x98-0x9f */
+       0xa0, 0xa1, 0xb6, 0xa3, 0xa4, 0xa5, 0xa6, 0xb4, /* 0xa0-0xa7 */
+       0xa8, 0xa9, 0xaa, 0xac, 0xac, 0xad, 0xaf, 0xaf, /* 0xa8-0xaf */
+       0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xc0, /* 0xb0-0xb7 */
+       0xb9, 0xb9, 0xbb, 0xbb, 0xbd, 0xbd, 0xbf, 0xbf, /* 0xb8-0xbf */
+       0xc0, 0xcf, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xc0-0xc7 */
+       0xc8, 0xc9, 0xca, 0xcc, 0xcc, 0xce, 0xce, 0xcf, /* 0xc8-0xcf */
+       0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
+       0xd9, 0xd9, 0xdb, 0xdb, 0xdc, 0xde, 0xde, 0xdf, /* 0xd8-0xdf */
+       0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0xe0-0xe7 */
+       0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xe8-0xef */
+       0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
+       0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
+};
+#endif
+
+static struct unls_table table = {
+       "cp10007",
+       page_uni2charset,
+       charset2uni,
+       NULL
+};
+
+int
+init_unls_cp10007()
+{
+       return (register_unls(&table));
+}
diff --git a/libunls/nls_cp10029.c b/libunls/nls_cp10029.c
new file mode 100644 (file)
index 0000000..afdbac0
--- /dev/null
@@ -0,0 +1,472 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)nls_cp10029.c   1.3 05/05/01 2000 J. Schilling */
+/*
+ *     Modifications to make the code portable Copyright (c) 2000 J. Schilling
+ *
+ *      Code generated by James Pearson j.pearson@ge.ucl.ac.uk 17/8/2000
+ *      based on a script by Gordon Chaffee <chaffee@bmrc.berkeley.edu>
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/*
+ * linux/fs/nls_cp10029.c
+ *
+ * Charset cp10029 translation tables.
+ * Generated automatically from the Unicode and charset
+ * tables from the Unicode Organization (www.unicode.org).
+ * The Unicode to charset table has only exact mappings.
+ */
+
+#include <mconfig.h>
+#include "nls.h"
+
+static struct unls_unicode charset2uni[256] = {
+       /* 0x00*/
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       /* 0x10*/
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       /* 0x20*/
+       {0x20, 0x00}, {0x21, 0x00}, {0x22, 0x00}, {0x23, 0x00},
+       {0x24, 0x00}, {0x25, 0x00}, {0x26, 0x00}, {0x27, 0x00},
+       {0x28, 0x00}, {0x29, 0x00}, {0x2a, 0x00}, {0x2b, 0x00},
+       {0x2c, 0x00}, {0x2d, 0x00}, {0x2e, 0x00}, {0x2f, 0x00},
+       /* 0x30*/
+       {0x30, 0x00}, {0x31, 0x00}, {0x32, 0x00}, {0x33, 0x00},
+       {0x34, 0x00}, {0x35, 0x00}, {0x36, 0x00}, {0x37, 0x00},
+       {0x38, 0x00}, {0x39, 0x00}, {0x3a, 0x00}, {0x3b, 0x00},
+       {0x3c, 0x00}, {0x3d, 0x00}, {0x3e, 0x00}, {0x3f, 0x00},
+       /* 0x40*/
+       {0x40, 0x00}, {0x41, 0x00}, {0x42, 0x00}, {0x43, 0x00},
+       {0x44, 0x00}, {0x45, 0x00}, {0x46, 0x00}, {0x47, 0x00},
+       {0x48, 0x00}, {0x49, 0x00}, {0x4a, 0x00}, {0x4b, 0x00},
+       {0x4c, 0x00}, {0x4d, 0x00}, {0x4e, 0x00}, {0x4f, 0x00},
+       /* 0x50*/
+       {0x50, 0x00}, {0x51, 0x00}, {0x52, 0x00}, {0x53, 0x00},
+       {0x54, 0x00}, {0x55, 0x00}, {0x56, 0x00}, {0x57, 0x00},
+       {0x58, 0x00}, {0x59, 0x00}, {0x5a, 0x00}, {0x5b, 0x00},
+       {0x5c, 0x00}, {0x5d, 0x00}, {0x5e, 0x00}, {0x5f, 0x00},
+       /* 0x60*/
+       {0x60, 0x00}, {0x61, 0x00}, {0x62, 0x00}, {0x63, 0x00},
+       {0x64, 0x00}, {0x65, 0x00}, {0x66, 0x00}, {0x67, 0x00},
+       {0x68, 0x00}, {0x69, 0x00}, {0x6a, 0x00}, {0x6b, 0x00},
+       {0x6c, 0x00}, {0x6d, 0x00}, {0x6e, 0x00}, {0x6f, 0x00},
+       /* 0x70*/
+       {0x70, 0x00}, {0x71, 0x00}, {0x72, 0x00}, {0x73, 0x00},
+       {0x74, 0x00}, {0x75, 0x00}, {0x76, 0x00}, {0x77, 0x00},
+       {0x78, 0x00}, {0x79, 0x00}, {0x7a, 0x00}, {0x7b, 0x00},
+       {0x7c, 0x00}, {0x7d, 0x00}, {0x7e, 0x00}, {0x00, 0x00},
+       /* 0x80*/
+       {0xc4, 0x00}, {0x00, 0x01}, {0x01, 0x01}, {0xc9, 0x00},
+       {0x04, 0x01}, {0xd6, 0x00}, {0xdc, 0x00}, {0xe1, 0x00},
+       {0x05, 0x01}, {0x0c, 0x01}, {0xe4, 0x00}, {0x0d, 0x01},
+       {0x06, 0x01}, {0x07, 0x01}, {0xe9, 0x00}, {0x79, 0x01},
+       /* 0x90*/
+       {0x7a, 0x01}, {0x0e, 0x01}, {0xed, 0x00}, {0x0f, 0x01},
+       {0x12, 0x01}, {0x13, 0x01}, {0x16, 0x01}, {0xf3, 0x00},
+       {0x17, 0x01}, {0xf4, 0x00}, {0xf6, 0x00}, {0xf5, 0x00},
+       {0xfa, 0x00}, {0x1a, 0x01}, {0x1b, 0x01}, {0xfc, 0x00},
+       /* 0xa0*/
+       {0x20, 0x20}, {0xb0, 0x00}, {0x18, 0x01}, {0xa3, 0x00},
+       {0xa7, 0x00}, {0x22, 0x20}, {0xb6, 0x00}, {0xdf, 0x00},
+       {0xae, 0x00}, {0xa9, 0x00}, {0x22, 0x21}, {0x19, 0x01},
+       {0xa8, 0x00}, {0x60, 0x22}, {0x23, 0x01}, {0x2e, 0x01},
+       /* 0xb0*/
+       {0x2f, 0x01}, {0x2a, 0x01}, {0x64, 0x22}, {0x65, 0x22},
+       {0x2b, 0x01}, {0x36, 0x01}, {0x02, 0x22}, {0x11, 0x22},
+       {0x42, 0x01}, {0x3b, 0x01}, {0x3c, 0x01}, {0x3d, 0x01},
+       {0x3e, 0x01}, {0x39, 0x01}, {0x3a, 0x01}, {0x45, 0x01},
+       /* 0xc0*/
+       {0x46, 0x01}, {0x43, 0x01}, {0xac, 0x00}, {0x1a, 0x22},
+       {0x44, 0x01}, {0x47, 0x01}, {0x06, 0x22}, {0xab, 0x00},
+       {0xbb, 0x00}, {0x26, 0x20}, {0xa0, 0x00}, {0x48, 0x01},
+       {0x50, 0x01}, {0xd5, 0x00}, {0x51, 0x01}, {0x4c, 0x01},
+       /* 0xd0*/
+       {0x13, 0x20}, {0x14, 0x20}, {0x1c, 0x20}, {0x1d, 0x20},
+       {0x18, 0x20}, {0x19, 0x20}, {0xf7, 0x00}, {0xca, 0x25},
+       {0x4d, 0x01}, {0x54, 0x01}, {0x55, 0x01}, {0x58, 0x01},
+       {0x39, 0x20}, {0x3a, 0x20}, {0x59, 0x01}, {0x56, 0x01},
+       /* 0xe0*/
+       {0x57, 0x01}, {0x60, 0x01}, {0x1a, 0x20}, {0x1e, 0x20},
+       {0x61, 0x01}, {0x5a, 0x01}, {0x5b, 0x01}, {0xc1, 0x00},
+       {0x64, 0x01}, {0x65, 0x01}, {0xcd, 0x00}, {0x7d, 0x01},
+       {0x7e, 0x01}, {0x6a, 0x01}, {0xd3, 0x00}, {0xd4, 0x00},
+       /* 0xf0*/
+       {0x6b, 0x01}, {0x6e, 0x01}, {0xda, 0x00}, {0x6f, 0x01},
+       {0x70, 0x01}, {0x71, 0x01}, {0x72, 0x01}, {0x73, 0x01},
+       {0xdd, 0x00}, {0xfd, 0x00}, {0x37, 0x01}, {0x7b, 0x01},
+       {0x41, 0x01}, {0x7c, 0x01}, {0x22, 0x01}, {0xc7, 0x02},
+};
+
+static unsigned char page00[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+       0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
+       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
+       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
+       0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+       0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */
+       0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */
+       0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */
+       0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0xca, 0x00, 0x00, 0xa3, 0x00, 0x00, 0x00, 0xa4, /* 0xa0-0xa7 */
+       0xac, 0xa9, 0x00, 0xc7, 0xc2, 0x00, 0xa8, 0x00, /* 0xa8-0xaf */
+       0xa1, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa6, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0xc8, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0xe7, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x83, 0x00, 0x00, 0x00, 0xea, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0xee, 0xef, 0xcd, 0x85, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0xf2, 0x00, 0x86, 0xf8, 0x00, 0xa7, /* 0xd8-0xdf */
+       0x00, 0x87, 0x00, 0x00, 0x8a, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x8e, 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x97, 0x99, 0x9b, 0x9a, 0xd6, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x9c, 0x00, 0x9f, 0xf9, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page01[256] = {
+       0x81, 0x82, 0x00, 0x00, 0x84, 0x88, 0x8c, 0x8d, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x89, 0x8b, 0x91, 0x93, /* 0x08-0x0f */
+       0x00, 0x00, 0x94, 0x95, 0x00, 0x00, 0x96, 0x98, /* 0x10-0x17 */
+       0xa2, 0xab, 0x9d, 0x9e, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0xfe, 0xae, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0xb1, 0xb4, 0x00, 0x00, 0xaf, 0xb0, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb5, 0xfa, /* 0x30-0x37 */
+       0x00, 0xbd, 0xbe, 0xb9, 0xba, 0xbb, 0xbc, 0x00, /* 0x38-0x3f */
+       0x00, 0xfc, 0xb8, 0xc1, 0xc4, 0xbf, 0xc0, 0xc5, /* 0x40-0x47 */
+       0xcb, 0x00, 0x00, 0x00, 0xcf, 0xd8, 0x00, 0x00, /* 0x48-0x4f */
+       0xcc, 0xce, 0x00, 0x00, 0xd9, 0xda, 0xdf, 0xe0, /* 0x50-0x57 */
+       0xdb, 0xde, 0xe5, 0xe6, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0xe1, 0xe4, 0x00, 0x00, 0xe8, 0xe9, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0xed, 0xf0, 0x00, 0x00, 0xf1, 0xf3, /* 0x68-0x6f */
+       0xf4, 0xf5, 0xf6, 0xf7, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x8f, 0x90, 0xfb, 0xfd, 0xeb, 0xec, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page02[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page20[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0xd0, 0xd1, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0xd4, 0xd5, 0xe2, 0x00, 0xd2, 0xd3, 0xe3, 0x00, /* 0x18-0x1f */
+       0xa0, 0x00, 0xa5, 0x00, 0x00, 0x00, 0xc9, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0xdc, 0xdd, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page21[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page22[256] = {
+       0x00, 0x00, 0xb6, 0x00, 0x00, 0x00, 0xc6, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0xad, 0x00, 0x00, 0x00, 0xb2, 0xb3, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page25[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0xd7, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char *page_uni2charset[256] = {
+       page00, page01, page02, NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       page20, page21, page22, NULL,   NULL,   page25, NULL,   NULL,
+};
+
+#if 0
+static unsigned char charset2upper[256] = {
+       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+       0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
+       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
+       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
+       0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+       0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x60-0x67 */
+       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x68-0x6f */
+       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x70-0x77 */
+       0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+       0x80, 0x81, 0x81, 0x83, 0x84, 0x85, 0x86, 0xe7, /* 0x80-0x87 */
+       0x84, 0x89, 0x80, 0x89, 0x8c, 0x8c, 0x83, 0x8f, /* 0x88-0x8f */
+       0x8f, 0x91, 0xea, 0x91, 0x94, 0x94, 0x96, 0xee, /* 0x90-0x97 */
+       0x96, 0xef, 0x85, 0xcd, 0xf2, 0x9d, 0x9d, 0x86, /* 0x98-0x9f */
+       0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0x53, /* 0xa0-0xa7 */
+       0xa8, 0xa9, 0xaa, 0xa2, 0xac, 0xad, 0xfe, 0xaf, /* 0xa8-0xaf */
+       0xaf, 0xb1, 0xb2, 0xb3, 0xb1, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
+       0xfc, 0xb9, 0xb9, 0xbb, 0xbb, 0xbd, 0xbd, 0xbf, /* 0xb8-0xbf */
+       0xbf, 0xc1, 0xc2, 0xc3, 0xc1, 0xc5, 0xc6, 0xc7, /* 0xc0-0xc7 */
+       0xc8, 0xc9, 0xca, 0xc5, 0xcc, 0xcd, 0xcc, 0xcf, /* 0xc8-0xcf */
+       0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
+       0xcf, 0xd9, 0xd9, 0xdb, 0xdc, 0xdd, 0xdb, 0xdf, /* 0xd8-0xdf */
+       0xdf, 0xe1, 0xe2, 0xe3, 0xe1, 0xe5, 0xe5, 0xe7, /* 0xe0-0xe7 */
+       0xe8, 0xe8, 0xea, 0xeb, 0xeb, 0xed, 0xee, 0xef, /* 0xe8-0xef */
+       0xed, 0xf1, 0xf2, 0xf1, 0xf4, 0xf4, 0xf6, 0xf6, /* 0xf0-0xf7 */
+       0xf8, 0xf8, 0xb5, 0xfb, 0xfc, 0xfb, 0xfe, 0xff, /* 0xf8-0xff */
+};
+
+static unsigned char charset2lower[256] = {
+       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+       0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x40-0x47 */
+       0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x48-0x4f */
+       0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x50-0x57 */
+       0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+       0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */
+       0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */
+       0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */
+       0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+       0x8a, 0x82, 0x82, 0x8e, 0x88, 0x9a, 0x9f, 0x87, /* 0x80-0x87 */
+       0x88, 0x8b, 0x8a, 0x8b, 0x8d, 0x8d, 0x8e, 0x90, /* 0x88-0x8f */
+       0x90, 0x93, 0x92, 0x93, 0x95, 0x95, 0x98, 0x97, /* 0x90-0x97 */
+       0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9e, 0x9e, 0x9f, /* 0x98-0x9f */
+       0xa0, 0xa1, 0xab, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, /* 0xa0-0xa7 */
+       0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xb0, /* 0xa8-0xaf */
+       0xb0, 0xb4, 0xb2, 0xb3, 0xb4, 0xfa, 0xb6, 0xb7, /* 0xb0-0xb7 */
+       0xb8, 0xba, 0xba, 0xbc, 0xbc, 0xbe, 0xbe, 0xc0, /* 0xb8-0xbf */
+       0xc0, 0xc4, 0xc2, 0xc3, 0xc4, 0xcb, 0xc6, 0xc7, /* 0xc0-0xc7 */
+       0xc8, 0xc9, 0xca, 0xcb, 0xce, 0x9b, 0xce, 0xd8, /* 0xc8-0xcf */
+       0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
+       0xd8, 0xda, 0xda, 0xde, 0xdc, 0xdd, 0xde, 0xe0, /* 0xd8-0xdf */
+       0xe0, 0xe4, 0xe2, 0xe3, 0xe4, 0xe6, 0xe6, 0x87, /* 0xe0-0xe7 */
+       0xe9, 0xe9, 0x92, 0xec, 0xec, 0xf0, 0x97, 0x99, /* 0xe8-0xef */
+       0xf0, 0xf3, 0x9c, 0xf3, 0xf5, 0xf5, 0xf7, 0xf7, /* 0xf0-0xf7 */
+       0xf9, 0xf9, 0xfa, 0xfd, 0xb8, 0xfd, 0xae, 0xff, /* 0xf8-0xff */
+};
+#endif
+
+static struct unls_table table = {
+       "cp10029",
+       page_uni2charset,
+       charset2uni,
+       NULL
+};
+
+int
+init_unls_cp10029()
+{
+       return (register_unls(&table));
+}
diff --git a/libunls/nls_cp10079.c b/libunls/nls_cp10079.c
new file mode 100644 (file)
index 0000000..7b4a1ee
--- /dev/null
@@ -0,0 +1,571 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)nls_cp10079.c   1.3 05/05/01 2000 J. Schilling */
+/*
+ *     Modifications to make the code portable Copyright (c) 2000 J. Schilling
+ *
+ *      Code generated by James Pearson j.pearson@ge.ucl.ac.uk 17/8/2000
+ *      based on a script by Gordon Chaffee <chaffee@bmrc.berkeley.edu>
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/*
+ * linux/fs/nls_cp10079.c
+ *
+ * Charset cp10079 translation tables.
+ * Generated automatically from the Unicode and charset
+ * tables from the Unicode Organization (www.unicode.org).
+ * The Unicode to charset table has only exact mappings.
+ */
+
+#include <mconfig.h>
+#include "nls.h"
+
+static struct unls_unicode charset2uni[256] = {
+       /* 0x00*/
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       /* 0x10*/
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       /* 0x20*/
+       {0x20, 0x00}, {0x21, 0x00}, {0x22, 0x00}, {0x23, 0x00},
+       {0x24, 0x00}, {0x25, 0x00}, {0x26, 0x00}, {0x27, 0x00},
+       {0x28, 0x00}, {0x29, 0x00}, {0x2a, 0x00}, {0x2b, 0x00},
+       {0x2c, 0x00}, {0x2d, 0x00}, {0x2e, 0x00}, {0x2f, 0x00},
+       /* 0x30*/
+       {0x30, 0x00}, {0x31, 0x00}, {0x32, 0x00}, {0x33, 0x00},
+       {0x34, 0x00}, {0x35, 0x00}, {0x36, 0x00}, {0x37, 0x00},
+       {0x38, 0x00}, {0x39, 0x00}, {0x3a, 0x00}, {0x3b, 0x00},
+       {0x3c, 0x00}, {0x3d, 0x00}, {0x3e, 0x00}, {0x3f, 0x00},
+       /* 0x40*/
+       {0x40, 0x00}, {0x41, 0x00}, {0x42, 0x00}, {0x43, 0x00},
+       {0x44, 0x00}, {0x45, 0x00}, {0x46, 0x00}, {0x47, 0x00},
+       {0x48, 0x00}, {0x49, 0x00}, {0x4a, 0x00}, {0x4b, 0x00},
+       {0x4c, 0x00}, {0x4d, 0x00}, {0x4e, 0x00}, {0x4f, 0x00},
+       /* 0x50*/
+       {0x50, 0x00}, {0x51, 0x00}, {0x52, 0x00}, {0x53, 0x00},
+       {0x54, 0x00}, {0x55, 0x00}, {0x56, 0x00}, {0x57, 0x00},
+       {0x58, 0x00}, {0x59, 0x00}, {0x5a, 0x00}, {0x5b, 0x00},
+       {0x5c, 0x00}, {0x5d, 0x00}, {0x5e, 0x00}, {0x5f, 0x00},
+       /* 0x60*/
+       {0x60, 0x00}, {0x61, 0x00}, {0x62, 0x00}, {0x63, 0x00},
+       {0x64, 0x00}, {0x65, 0x00}, {0x66, 0x00}, {0x67, 0x00},
+       {0x68, 0x00}, {0x69, 0x00}, {0x6a, 0x00}, {0x6b, 0x00},
+       {0x6c, 0x00}, {0x6d, 0x00}, {0x6e, 0x00}, {0x6f, 0x00},
+       /* 0x70*/
+       {0x70, 0x00}, {0x71, 0x00}, {0x72, 0x00}, {0x73, 0x00},
+       {0x74, 0x00}, {0x75, 0x00}, {0x76, 0x00}, {0x77, 0x00},
+       {0x78, 0x00}, {0x79, 0x00}, {0x7a, 0x00}, {0x7b, 0x00},
+       {0x7c, 0x00}, {0x7d, 0x00}, {0x7e, 0x00}, {0x00, 0x00},
+       /* 0x80*/
+       {0xc4, 0x00}, {0xc5, 0x00}, {0xc7, 0x00}, {0xc9, 0x00},
+       {0xd1, 0x00}, {0xd6, 0x00}, {0xdc, 0x00}, {0xe1, 0x00},
+       {0xe0, 0x00}, {0xe2, 0x00}, {0xe4, 0x00}, {0xe3, 0x00},
+       {0xe5, 0x00}, {0xe7, 0x00}, {0xe9, 0x00}, {0xe8, 0x00},
+       /* 0x90*/
+       {0xea, 0x00}, {0xeb, 0x00}, {0xed, 0x00}, {0xec, 0x00},
+       {0xee, 0x00}, {0xef, 0x00}, {0xf1, 0x00}, {0xf3, 0x00},
+       {0xf2, 0x00}, {0xf4, 0x00}, {0xf6, 0x00}, {0xf5, 0x00},
+       {0xfa, 0x00}, {0xf9, 0x00}, {0xfb, 0x00}, {0xfc, 0x00},
+       /* 0xa0*/
+       {0xdd, 0x00}, {0xb0, 0x00}, {0xa2, 0x00}, {0xa3, 0x00},
+       {0xa7, 0x00}, {0x22, 0x20}, {0xb6, 0x00}, {0xdf, 0x00},
+       {0xae, 0x00}, {0xa9, 0x00}, {0x22, 0x21}, {0xb4, 0x00},
+       {0xa8, 0x00}, {0x60, 0x22}, {0xc6, 0x00}, {0xd8, 0x00},
+       /* 0xb0*/
+       {0x1e, 0x22}, {0xb1, 0x00}, {0x64, 0x22}, {0x65, 0x22},
+       {0xa5, 0x00}, {0xb5, 0x00}, {0x02, 0x22}, {0x11, 0x22},
+       {0x0f, 0x22}, {0xc0, 0x03}, {0x2b, 0x22}, {0xaa, 0x00},
+       {0xba, 0x00}, {0xa9, 0x03}, {0xe6, 0x00}, {0xf8, 0x00},
+       /* 0xc0*/
+       {0xbf, 0x00}, {0xa1, 0x00}, {0xac, 0x00}, {0x1a, 0x22},
+       {0x92, 0x01}, {0x48, 0x22}, {0x06, 0x22}, {0xab, 0x00},
+       {0xbb, 0x00}, {0x26, 0x20}, {0xa0, 0x00}, {0xc0, 0x00},
+       {0xc3, 0x00}, {0xd5, 0x00}, {0x52, 0x01}, {0x53, 0x01},
+       /* 0xd0*/
+       {0x13, 0x20}, {0x14, 0x20}, {0x1c, 0x20}, {0x1d, 0x20},
+       {0x18, 0x20}, {0x19, 0x20}, {0xf7, 0x00}, {0xca, 0x25},
+       {0xff, 0x00}, {0x78, 0x01}, {0x44, 0x20}, {0xac, 0x20},
+       {0xd0, 0x00}, {0xf0, 0x00}, {0xde, 0x00}, {0xfe, 0x00},
+       /* 0xe0*/
+       {0xfd, 0x00}, {0xb7, 0x00}, {0x1a, 0x20}, {0x1e, 0x20},
+       {0x30, 0x20}, {0xc2, 0x00}, {0xca, 0x00}, {0xc1, 0x00},
+       {0xcb, 0x00}, {0xc8, 0x00}, {0xcd, 0x00}, {0xce, 0x00},
+       {0xcf, 0x00}, {0xcc, 0x00}, {0xd3, 0x00}, {0xd4, 0x00},
+       /* 0xf0*/
+       {0xff, 0xf8}, {0xd2, 0x00}, {0xda, 0x00}, {0xdb, 0x00},
+       {0xd9, 0x00}, {0x31, 0x01}, {0xc6, 0x02}, {0xdc, 0x02},
+       {0xaf, 0x00}, {0xd8, 0x02}, {0xd9, 0x02}, {0xda, 0x02},
+       {0xb8, 0x00}, {0xdd, 0x02}, {0xdb, 0x02}, {0xc7, 0x02},
+};
+
+static unsigned char page00[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+       0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
+       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
+       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
+       0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+       0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */
+       0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */
+       0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */
+       0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0xca, 0xc1, 0xa2, 0xa3, 0x00, 0xb4, 0x00, 0xa4, /* 0xa0-0xa7 */
+       0xac, 0xa9, 0xbb, 0xc7, 0xc2, 0x00, 0xa8, 0xf8, /* 0xa8-0xaf */
+       0xa1, 0xb1, 0x00, 0x00, 0xab, 0xb5, 0xa6, 0xe1, /* 0xb0-0xb7 */
+       0xfc, 0x00, 0xbc, 0xc8, 0x00, 0x00, 0x00, 0xc0, /* 0xb8-0xbf */
+       0xcb, 0xe7, 0xe5, 0xcc, 0x80, 0x81, 0xae, 0x82, /* 0xc0-0xc7 */
+       0xe9, 0x83, 0xe6, 0xe8, 0xed, 0xea, 0xeb, 0xec, /* 0xc8-0xcf */
+       0xdc, 0x84, 0xf1, 0xee, 0xef, 0xcd, 0x85, 0x00, /* 0xd0-0xd7 */
+       0xaf, 0xf4, 0xf2, 0xf3, 0x86, 0xa0, 0xde, 0xa7, /* 0xd8-0xdf */
+       0x88, 0x87, 0x89, 0x8b, 0x8a, 0x8c, 0xbe, 0x8d, /* 0xe0-0xe7 */
+       0x8f, 0x8e, 0x90, 0x91, 0x93, 0x92, 0x94, 0x95, /* 0xe8-0xef */
+       0xdd, 0x96, 0x98, 0x97, 0x99, 0x9b, 0x9a, 0xd6, /* 0xf0-0xf7 */
+       0xbf, 0x9d, 0x9c, 0x9e, 0x9f, 0xe0, 0xdf, 0xd8, /* 0xf8-0xff */
+};
+
+static unsigned char page01[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0xf5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0xce, 0xcf, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0xd9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0xc4, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page02[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, 0xff, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0xf9, 0xfa, 0xfb, 0xfe, 0xf7, 0xfd, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page03[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0xb9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page20[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0xd0, 0xd1, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0xd4, 0xd5, 0xe2, 0x00, 0xd2, 0xd3, 0xe3, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0xa5, 0x00, 0x00, 0x00, 0xc9, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0xe4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0xda, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0xdb, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page21[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page22[256] = {
+       0x00, 0x00, 0xb6, 0x00, 0x00, 0x00, 0xc6, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, /* 0x08-0x0f */
+       0x00, 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0xc3, 0x00, 0x00, 0x00, 0xb0, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0xba, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0xc5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0xad, 0x00, 0x00, 0x00, 0xb2, 0xb3, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page25[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0xd7, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char pagef8[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, /* 0xf8-0xff */
+};
+
+static unsigned char *page_uni2charset[256] = {
+       page00, page01, page02, page03, NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       page20, page21, page22, NULL,   NULL,   page25, NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       pagef8, NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+};
+
+#if 0
+static unsigned char charset2upper[256] = {
+       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+       0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
+       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
+       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
+       0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+       0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x60-0x67 */
+       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x68-0x6f */
+       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x70-0x77 */
+       0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+       0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0xe7, /* 0x80-0x87 */
+       0xcb, 0xe5, 0x80, 0xcc, 0x81, 0x82, 0x83, 0xe9, /* 0x88-0x8f */
+       0xe6, 0xe8, 0xea, 0xed, 0xeb, 0xec, 0x84, 0xee, /* 0x90-0x97 */
+       0xf1, 0xef, 0x85, 0xcd, 0xf2, 0xf4, 0xf3, 0x86, /* 0x98-0x9f */
+       0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0x53, /* 0xa0-0xa7 */
+       0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
+       0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
+       0xb8, 0x50, 0xba, 0xbb, 0xbc, 0xbd, 0xae, 0xaf, /* 0xb8-0xbf */
+       0xc0, 0xc1, 0xc2, 0xc3, 0x46, 0xc5, 0xc6, 0xc7, /* 0xc0-0xc7 */
+       0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
+       0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
+       0xd9, 0xd9, 0xda, 0xdb, 0xdc, 0xdc, 0xde, 0xde, /* 0xd8-0xdf */
+       0xa0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0xe0-0xe7 */
+       0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xe8-0xef */
+       0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0x49, 0xf6, 0xf7, /* 0xf0-0xf7 */
+       0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
+};
+
+static unsigned char charset2lower[256] = {
+       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+       0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x40-0x47 */
+       0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x48-0x4f */
+       0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x50-0x57 */
+       0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+       0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */
+       0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */
+       0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */
+       0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+       0x8a, 0x8c, 0x8d, 0x8e, 0x96, 0x9a, 0x9f, 0x87, /* 0x80-0x87 */
+       0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, /* 0x88-0x8f */
+       0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, /* 0x90-0x97 */
+       0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, /* 0x98-0x9f */
+       0xe0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, /* 0xa0-0xa7 */
+       0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xbe, 0xbf, /* 0xa8-0xaf */
+       0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
+       0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0x00, 0xbe, 0xbf, /* 0xb8-0xbf */
+       0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xc0-0xc7 */
+       0xc8, 0xc9, 0xca, 0x88, 0x8b, 0x9b, 0xce, 0xcf, /* 0xc8-0xcf */
+       0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
+       0xd8, 0xd8, 0xda, 0xdb, 0xdd, 0xdd, 0xdf, 0xdf, /* 0xd8-0xdf */
+       0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0x89, 0x90, 0x87, /* 0xe0-0xe7 */
+       0x91, 0x8f, 0x92, 0x94, 0x95, 0x93, 0x97, 0x99, /* 0xe8-0xef */
+       0xf0, 0x98, 0x9c, 0x9e, 0x9d, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
+       0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
+};
+#endif
+
+static struct unls_table table = {
+       "cp10079",
+       page_uni2charset,
+       charset2uni,
+       NULL
+};
+
+int
+init_unls_cp10079()
+{
+       return (register_unls(&table));
+}
diff --git a/libunls/nls_cp10081.c b/libunls/nls_cp10081.c
new file mode 100644 (file)
index 0000000..a4be758
--- /dev/null
@@ -0,0 +1,571 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)nls_cp10081.c   1.3 05/05/01 2000 J. Schilling */
+/*
+ *     Modifications to make the code portable Copyright (c) 2000 J. Schilling
+ *
+ *      Code generated by James Pearson j.pearson@ge.ucl.ac.uk 17/8/2000
+ *      based on a script by Gordon Chaffee <chaffee@bmrc.berkeley.edu>
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/*
+ * linux/fs/nls_cp10081.c
+ *
+ * Charset cp10081 translation tables.
+ * Generated automatically from the Unicode and charset
+ * tables from the Unicode Organization (www.unicode.org).
+ * The Unicode to charset table has only exact mappings.
+ */
+
+#include <mconfig.h>
+#include "nls.h"
+
+static struct unls_unicode charset2uni[256] = {
+       /* 0x00*/
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       /* 0x10*/
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       /* 0x20*/
+       {0x20, 0x00}, {0x21, 0x00}, {0x22, 0x00}, {0x23, 0x00},
+       {0x24, 0x00}, {0x25, 0x00}, {0x26, 0x00}, {0x27, 0x00},
+       {0x28, 0x00}, {0x29, 0x00}, {0x2a, 0x00}, {0x2b, 0x00},
+       {0x2c, 0x00}, {0x2d, 0x00}, {0x2e, 0x00}, {0x2f, 0x00},
+       /* 0x30*/
+       {0x30, 0x00}, {0x31, 0x00}, {0x32, 0x00}, {0x33, 0x00},
+       {0x34, 0x00}, {0x35, 0x00}, {0x36, 0x00}, {0x37, 0x00},
+       {0x38, 0x00}, {0x39, 0x00}, {0x3a, 0x00}, {0x3b, 0x00},
+       {0x3c, 0x00}, {0x3d, 0x00}, {0x3e, 0x00}, {0x3f, 0x00},
+       /* 0x40*/
+       {0x40, 0x00}, {0x41, 0x00}, {0x42, 0x00}, {0x43, 0x00},
+       {0x44, 0x00}, {0x45, 0x00}, {0x46, 0x00}, {0x47, 0x00},
+       {0x48, 0x00}, {0x49, 0x00}, {0x4a, 0x00}, {0x4b, 0x00},
+       {0x4c, 0x00}, {0x4d, 0x00}, {0x4e, 0x00}, {0x4f, 0x00},
+       /* 0x50*/
+       {0x50, 0x00}, {0x51, 0x00}, {0x52, 0x00}, {0x53, 0x00},
+       {0x54, 0x00}, {0x55, 0x00}, {0x56, 0x00}, {0x57, 0x00},
+       {0x58, 0x00}, {0x59, 0x00}, {0x5a, 0x00}, {0x5b, 0x00},
+       {0x5c, 0x00}, {0x5d, 0x00}, {0x5e, 0x00}, {0x5f, 0x00},
+       /* 0x60*/
+       {0x60, 0x00}, {0x61, 0x00}, {0x62, 0x00}, {0x63, 0x00},
+       {0x64, 0x00}, {0x65, 0x00}, {0x66, 0x00}, {0x67, 0x00},
+       {0x68, 0x00}, {0x69, 0x00}, {0x6a, 0x00}, {0x6b, 0x00},
+       {0x6c, 0x00}, {0x6d, 0x00}, {0x6e, 0x00}, {0x6f, 0x00},
+       /* 0x70*/
+       {0x70, 0x00}, {0x71, 0x00}, {0x72, 0x00}, {0x73, 0x00},
+       {0x74, 0x00}, {0x75, 0x00}, {0x76, 0x00}, {0x77, 0x00},
+       {0x78, 0x00}, {0x79, 0x00}, {0x7a, 0x00}, {0x7b, 0x00},
+       {0x7c, 0x00}, {0x7d, 0x00}, {0x7e, 0x00}, {0x00, 0x00},
+       /* 0x80*/
+       {0xc4, 0x00}, {0xc5, 0x00}, {0xc7, 0x00}, {0xc9, 0x00},
+       {0xd1, 0x00}, {0xd6, 0x00}, {0xdc, 0x00}, {0xe1, 0x00},
+       {0xe0, 0x00}, {0xe2, 0x00}, {0xe4, 0x00}, {0xe3, 0x00},
+       {0xe5, 0x00}, {0xe7, 0x00}, {0xe9, 0x00}, {0xe8, 0x00},
+       /* 0x90*/
+       {0xea, 0x00}, {0xeb, 0x00}, {0xed, 0x00}, {0xec, 0x00},
+       {0xee, 0x00}, {0xef, 0x00}, {0xf1, 0x00}, {0xf3, 0x00},
+       {0xf2, 0x00}, {0xf4, 0x00}, {0xf6, 0x00}, {0xf5, 0x00},
+       {0xfa, 0x00}, {0xf9, 0x00}, {0xfb, 0x00}, {0xfc, 0x00},
+       /* 0xa0*/
+       {0x20, 0x20}, {0xb0, 0x00}, {0xa2, 0x00}, {0xa3, 0x00},
+       {0xa7, 0x00}, {0x22, 0x20}, {0xb6, 0x00}, {0xdf, 0x00},
+       {0xae, 0x00}, {0xa9, 0x00}, {0x22, 0x21}, {0xb4, 0x00},
+       {0xa8, 0x00}, {0x60, 0x22}, {0xc6, 0x00}, {0xd8, 0x00},
+       /* 0xb0*/
+       {0x1e, 0x22}, {0xb1, 0x00}, {0x64, 0x22}, {0x65, 0x22},
+       {0xa5, 0x00}, {0xb5, 0x00}, {0x02, 0x22}, {0x11, 0x22},
+       {0x0f, 0x22}, {0xc0, 0x03}, {0x2b, 0x22}, {0xaa, 0x00},
+       {0xba, 0x00}, {0xa9, 0x03}, {0xe6, 0x00}, {0xf8, 0x00},
+       /* 0xc0*/
+       {0xbf, 0x00}, {0xa1, 0x00}, {0xac, 0x00}, {0x1a, 0x22},
+       {0x92, 0x01}, {0x48, 0x22}, {0x06, 0x22}, {0xab, 0x00},
+       {0xbb, 0x00}, {0x26, 0x20}, {0xa0, 0x00}, {0xc0, 0x00},
+       {0xc3, 0x00}, {0xd5, 0x00}, {0x52, 0x01}, {0x53, 0x01},
+       /* 0xd0*/
+       {0x13, 0x20}, {0x14, 0x20}, {0x1c, 0x20}, {0x1d, 0x20},
+       {0x18, 0x20}, {0x19, 0x20}, {0xf7, 0x00}, {0xca, 0x25},
+       {0xff, 0x00}, {0x78, 0x01}, {0x1e, 0x01}, {0x1f, 0x01},
+       {0x30, 0x01}, {0x31, 0x01}, {0x5e, 0x01}, {0x5f, 0x01},
+       /* 0xe0*/
+       {0x21, 0x20}, {0xb7, 0x00}, {0x1a, 0x20}, {0x1e, 0x20},
+       {0x30, 0x20}, {0xc2, 0x00}, {0xca, 0x00}, {0xc1, 0x00},
+       {0xcb, 0x00}, {0xc8, 0x00}, {0xcd, 0x00}, {0xce, 0x00},
+       {0xcf, 0x00}, {0xcc, 0x00}, {0xd3, 0x00}, {0xd4, 0x00},
+       /* 0xf0*/
+       {0xff, 0xf8}, {0xd2, 0x00}, {0xda, 0x00}, {0xdb, 0x00},
+       {0xd9, 0x00}, {0xa0, 0xf8}, {0xc6, 0x02}, {0xdc, 0x02},
+       {0xaf, 0x00}, {0xd8, 0x02}, {0xd9, 0x02}, {0xda, 0x02},
+       {0xb8, 0x00}, {0xdd, 0x02}, {0xdb, 0x02}, {0xc7, 0x02},
+};
+
+static unsigned char page00[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+       0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
+       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
+       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
+       0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+       0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */
+       0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */
+       0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */
+       0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0xca, 0xc1, 0xa2, 0xa3, 0x00, 0xb4, 0x00, 0xa4, /* 0xa0-0xa7 */
+       0xac, 0xa9, 0xbb, 0xc7, 0xc2, 0x00, 0xa8, 0xf8, /* 0xa8-0xaf */
+       0xa1, 0xb1, 0x00, 0x00, 0xab, 0xb5, 0xa6, 0xe1, /* 0xb0-0xb7 */
+       0xfc, 0x00, 0xbc, 0xc8, 0x00, 0x00, 0x00, 0xc0, /* 0xb8-0xbf */
+       0xcb, 0xe7, 0xe5, 0xcc, 0x80, 0x81, 0xae, 0x82, /* 0xc0-0xc7 */
+       0xe9, 0x83, 0xe6, 0xe8, 0xed, 0xea, 0xeb, 0xec, /* 0xc8-0xcf */
+       0x00, 0x84, 0xf1, 0xee, 0xef, 0xcd, 0x85, 0x00, /* 0xd0-0xd7 */
+       0xaf, 0xf4, 0xf2, 0xf3, 0x86, 0x00, 0x00, 0xa7, /* 0xd8-0xdf */
+       0x88, 0x87, 0x89, 0x8b, 0x8a, 0x8c, 0xbe, 0x8d, /* 0xe0-0xe7 */
+       0x8f, 0x8e, 0x90, 0x91, 0x93, 0x92, 0x94, 0x95, /* 0xe8-0xef */
+       0x00, 0x96, 0x98, 0x97, 0x99, 0x9b, 0x9a, 0xd6, /* 0xf0-0xf7 */
+       0xbf, 0x9d, 0x9c, 0x9e, 0x9f, 0x00, 0x00, 0xd8, /* 0xf8-0xff */
+};
+
+static unsigned char page01[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xda, 0xdb, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0xdc, 0xdd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0xce, 0xcf, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xde, 0xdf, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0xd9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0xc4, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page02[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, 0xff, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0xf9, 0xfa, 0xfb, 0xfe, 0xf7, 0xfd, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page03[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0xb9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page20[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0xd0, 0xd1, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0xd4, 0xd5, 0xe2, 0x00, 0xd2, 0xd3, 0xe3, 0x00, /* 0x18-0x1f */
+       0xa0, 0xe0, 0xa5, 0x00, 0x00, 0x00, 0xc9, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0xe4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page21[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page22[256] = {
+       0x00, 0x00, 0xb6, 0x00, 0x00, 0x00, 0xc6, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, /* 0x08-0x0f */
+       0x00, 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0xc3, 0x00, 0x00, 0x00, 0xb0, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0xba, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0xc5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0xad, 0x00, 0x00, 0x00, 0xb2, 0xb3, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page25[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0xd7, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char pagef8[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0xf5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, /* 0xf8-0xff */
+};
+
+static unsigned char *page_uni2charset[256] = {
+       page00, page01, page02, page03, NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       page20, page21, page22, NULL,   NULL,   page25, NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       pagef8, NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+};
+
+#if 0
+static unsigned char charset2upper[256] = {
+       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+       0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
+       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
+       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
+       0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+       0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x60-0x67 */
+       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x68-0x6f */
+       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x70-0x77 */
+       0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+       0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0xe7, /* 0x80-0x87 */
+       0xcb, 0xe5, 0x80, 0xcc, 0x81, 0x82, 0x83, 0xe9, /* 0x88-0x8f */
+       0xe6, 0xe8, 0xea, 0xed, 0xeb, 0xec, 0x84, 0xee, /* 0x90-0x97 */
+       0xf1, 0xef, 0x85, 0xcd, 0xf2, 0xf4, 0xf3, 0x86, /* 0x98-0x9f */
+       0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0x53, /* 0xa0-0xa7 */
+       0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
+       0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
+       0xb8, 0x50, 0xba, 0xbb, 0xbc, 0xbd, 0xae, 0xaf, /* 0xb8-0xbf */
+       0xc0, 0xc1, 0xc2, 0xc3, 0x46, 0xc5, 0xc6, 0xc7, /* 0xc0-0xc7 */
+       0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
+       0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
+       0xd9, 0xd9, 0xda, 0xda, 0xdc, 0x49, 0xde, 0xde, /* 0xd8-0xdf */
+       0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0xe0-0xe7 */
+       0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xe8-0xef */
+       0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
+       0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
+};
+
+static unsigned char charset2lower[256] = {
+       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+       0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x40-0x47 */
+       0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x48-0x4f */
+       0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x50-0x57 */
+       0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+       0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */
+       0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */
+       0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */
+       0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+       0x8a, 0x8c, 0x8d, 0x8e, 0x96, 0x9a, 0x9f, 0x87, /* 0x80-0x87 */
+       0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, /* 0x88-0x8f */
+       0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, /* 0x90-0x97 */
+       0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, /* 0x98-0x9f */
+       0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, /* 0xa0-0xa7 */
+       0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xbe, 0xbf, /* 0xa8-0xaf */
+       0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
+       0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0x00, 0xbe, 0xbf, /* 0xb8-0xbf */
+       0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xc0-0xc7 */
+       0xc8, 0xc9, 0xca, 0x88, 0x8b, 0x9b, 0xce, 0xcf, /* 0xc8-0xcf */
+       0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
+       0xd8, 0xd8, 0xdb, 0xdb, 0x69, 0xdd, 0xdf, 0xdf, /* 0xd8-0xdf */
+       0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0x89, 0x90, 0x87, /* 0xe0-0xe7 */
+       0x91, 0x8f, 0x92, 0x94, 0x95, 0x93, 0x97, 0x99, /* 0xe8-0xef */
+       0xf0, 0x98, 0x9c, 0x9e, 0x9d, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
+       0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
+};
+#endif
+
+static struct unls_table table = {
+       "cp10081",
+       page_uni2charset,
+       charset2uni,
+       NULL
+};
+
+int
+init_unls_cp10081()
+{
+       return (register_unls(&table));
+}
diff --git a/libunls/nls_cp1250.c b/libunls/nls_cp1250.c
new file mode 100644 (file)
index 0000000..7dfc390
--- /dev/null
@@ -0,0 +1,343 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)nls_cp1250.c    1.2 05/05/01 2002 Petr Balas */
+/*
+ *     Modifications to make the code portable Copyright (c) 2000 J. Schilling
+ *
+ *     Code taken from the Linux kernel.
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/*
+ * linux/fs/nls_cp1250.c
+ *
+ * Charset cp1250 translation tables.
+ * Generated automatically from the Unicode and charset
+ * tables from the Unicode Organization (www.unicode.org).
+ * The Unicode to charset table has only exact mappings.
+ */
+
+#include <mconfig.h>
+#include "nls.h"
+
+static struct unls_unicode charset2uni[256] = {
+       /* 0x00*/
+       {0x00, 0x00}, {0x01, 0x00}, {0x02, 0x00}, {0x03, 0x00},
+       {0x04, 0x00}, {0x05, 0x00}, {0x06, 0x00}, {0x07, 0x00},
+       {0x08, 0x00}, {0x09, 0x00}, {0x0a, 0x00}, {0x0b, 0x00},
+       {0x0c, 0x00}, {0x0d, 0x00}, {0x0e, 0x00}, {0x0f, 0x00},
+       /* 0x10*/
+       {0x10, 0x00}, {0x11, 0x00}, {0x12, 0x00}, {0x13, 0x00},
+       {0x14, 0x00}, {0x15, 0x00}, {0x16, 0x00}, {0x17, 0x00},
+       {0x18, 0x00}, {0x19, 0x00}, {0x1a, 0x00}, {0x1b, 0x00},
+       {0x1c, 0x00}, {0x1d, 0x00}, {0x1e, 0x00}, {0x1f, 0x00},
+       /* 0x20*/
+       {0x20, 0x00}, {0x21, 0x00}, {0x22, 0x00}, {0x23, 0x00},
+       {0x24, 0x00}, {0x25, 0x00}, {0x26, 0x00}, {0x27, 0x00},
+       {0x28, 0x00}, {0x29, 0x00}, {0x2a, 0x00}, {0x2b, 0x00},
+       {0x2c, 0x00}, {0x2d, 0x00}, {0x2e, 0x00}, {0x2f, 0x00},
+       /* 0x30*/
+       {0x30, 0x00}, {0x31, 0x00}, {0x32, 0x00}, {0x33, 0x00},
+       {0x34, 0x00}, {0x35, 0x00}, {0x36, 0x00}, {0x37, 0x00},
+       {0x38, 0x00}, {0x39, 0x00}, {0x3a, 0x00}, {0x3b, 0x00},
+       {0x3c, 0x00}, {0x3d, 0x00}, {0x3e, 0x00}, {0x3f, 0x00},
+       /* 0x40*/
+       {0x40, 0x00}, {0x41, 0x00}, {0x42, 0x00}, {0x43, 0x00},
+       {0x44, 0x00}, {0x45, 0x00}, {0x46, 0x00}, {0x47, 0x00},
+       {0x48, 0x00}, {0x49, 0x00}, {0x4a, 0x00}, {0x4b, 0x00},
+       {0x4c, 0x00}, {0x4d, 0x00}, {0x4e, 0x00}, {0x4f, 0x00},
+       /* 0x50*/
+       {0x50, 0x00}, {0x51, 0x00}, {0x52, 0x00}, {0x53, 0x00},
+       {0x54, 0x00}, {0x55, 0x00}, {0x56, 0x00}, {0x57, 0x00},
+       {0x58, 0x00}, {0x59, 0x00}, {0x5a, 0x00}, {0x5b, 0x00},
+       {0x5c, 0x00}, {0x5d, 0x00}, {0x5e, 0x00}, {0x5f, 0x00},
+       /* 0x60*/
+       {0x60, 0x00}, {0x61, 0x00}, {0x62, 0x00}, {0x63, 0x00},
+       {0x64, 0x00}, {0x65, 0x00}, {0x66, 0x00}, {0x67, 0x00},
+       {0x68, 0x00}, {0x69, 0x00}, {0x6a, 0x00}, {0x6b, 0x00},
+       {0x6c, 0x00}, {0x6d, 0x00}, {0x6e, 0x00}, {0x6f, 0x00},
+       /* 0x70*/
+       {0x70, 0x00}, {0x71, 0x00}, {0x72, 0x00}, {0x73, 0x00},
+       {0x74, 0x00}, {0x75, 0x00}, {0x76, 0x00}, {0x77, 0x00},
+       {0x78, 0x00}, {0x79, 0x00}, {0x7a, 0x00}, {0x7b, 0x00},
+       {0x7c, 0x00}, {0x7d, 0x00}, {0x7e, 0x00}, {0x7f, 0x00},
+       /* 0x80*/
+       {0xac, 0x20}, {0x00, 0x00}, {0x1a, 0x20}, {0x00, 0x00},
+       {0x1e, 0x20}, {0x26, 0x20}, {0x20, 0x20}, {0x21, 0x20},
+       {0x00, 0x00}, {0x30, 0x20}, {0x60, 0x01}, {0x39, 0x20},
+       {0x5a, 0x01}, {0x64, 0x01}, {0x7d, 0x01}, {0x79, 0x01},
+       /* 0x90*/
+       {0x00, 0x00}, {0x18, 0x20}, {0x19, 0x20}, {0x1c, 0x20},
+       {0x1d, 0x20}, {0x22, 0x20}, {0x13, 0x20}, {0x14, 0x20},
+       {0x00, 0x00}, {0x22, 0x21}, {0x61, 0x01}, {0x3a, 0x20},
+       {0x5b, 0x01}, {0x65, 0x01}, {0x7e, 0x01}, {0x7a, 0x01},
+       /* 0xa0*/
+       {0xa0, 0x00}, {0xc7, 0x02}, {0xd8, 0x02}, {0x41, 0x01},
+       {0xa4, 0x00}, {0x04, 0x01}, {0xa6, 0x00}, {0xa7, 0x00},
+       {0xa8, 0x00}, {0xa9, 0x00}, {0x5e, 0x01}, {0xab, 0x00},
+       {0xac, 0x00}, {0xad, 0x00}, {0xae, 0x00}, {0x7b, 0x01},
+       /* 0xb0*/
+       {0xb0, 0x00}, {0xb1, 0x00}, {0xdb, 0x02}, {0x42, 0x01},
+       {0xb4, 0x00}, {0xb5, 0x00}, {0xb6, 0x00}, {0xb7, 0x00},
+       {0xb8, 0x00}, {0x05, 0x01}, {0x5f, 0x01}, {0xbb, 0x00},
+       {0x3d, 0x01}, {0xdd, 0x02}, {0x3e, 0x01}, {0x7c, 0x01},
+       /* 0xc0*/
+       {0x54, 0x01}, {0xc1, 0x00}, {0xc2, 0x00}, {0x02, 0x01},
+       {0xc4, 0x00}, {0x39, 0x01}, {0x06, 0x01}, {0xc7, 0x00},
+       {0x0c, 0x01}, {0xc9, 0x00}, {0x18, 0x01}, {0xcb, 0x00},
+       {0x1a, 0x01}, {0xcd, 0x00}, {0xce, 0x00}, {0x0e, 0x01},
+       /* 0xd0*/
+       {0x10, 0x01}, {0x43, 0x01}, {0x47, 0x01}, {0xd3, 0x00},
+       {0xd4, 0x00}, {0x50, 0x01}, {0xd6, 0x00}, {0xd7, 0x00},
+       {0x58, 0x01}, {0x6e, 0x01}, {0xda, 0x00}, {0x70, 0x01},
+       {0xdc, 0x00}, {0xdd, 0x00}, {0x62, 0x01}, {0xdf, 0x00},
+       /* 0xe0*/
+       {0x55, 0x01}, {0xe1, 0x00}, {0xe2, 0x00}, {0x03, 0x01},
+       {0xe4, 0x00}, {0x3a, 0x01}, {0x07, 0x01}, {0xe7, 0x00},
+       {0x0d, 0x01}, {0xe9, 0x00}, {0x19, 0x01}, {0xeb, 0x00},
+       {0x1b, 0x01}, {0xed, 0x00}, {0xee, 0x00}, {0x0f, 0x01},
+       /* 0xf0*/
+       {0x11, 0x01}, {0x44, 0x01}, {0x48, 0x01}, {0xf3, 0x00},
+       {0xf4, 0x00}, {0x51, 0x01}, {0xf6, 0x00}, {0xf7, 0x00},
+       {0x59, 0x01}, {0x6f, 0x01}, {0xfa, 0x00}, {0x71, 0x01},
+       {0xfc, 0x00}, {0xfd, 0x00}, {0x63, 0x01}, {0xd9, 0x02},
+       };
+
+static unsigned char page00[256] = {
+       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+       0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
+       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
+       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
+       0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+       0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */
+       0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */
+       0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */
+       0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0xa0, 0x00, 0x00, 0x00, 0xa4, 0x00, 0xa6, 0xa7, /* 0xa0-0xa7 */
+       0xa8, 0xa9, 0x00, 0xab, 0xac, 0xad, 0xae, 0x00, /* 0xa8-0xaf */
+       0xb0, 0xb1, 0x00, 0x00, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
+       0xb8, 0x00, 0x00, 0xbb, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0xc1, 0xc2, 0x00, 0xc4, 0x00, 0x00, 0xc7, /* 0xc0-0xc7 */
+       0x00, 0xc9, 0x00, 0xcb, 0x00, 0xcd, 0xce, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0xd3, 0xd4, 0x00, 0xd6, 0xd7, /* 0xd0-0xd7 */
+       0x00, 0x00, 0xda, 0x00, 0xdc, 0xdd, 0x00, 0xdf, /* 0xd8-0xdf */
+       0x00, 0xe1, 0xe2, 0x00, 0xe4, 0x00, 0x00, 0xe7, /* 0xe0-0xe7 */
+       0x00, 0xe9, 0x00, 0xeb, 0x00, 0xed, 0xee, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0xf3, 0xf4, 0x00, 0xf6, 0xf7, /* 0xf0-0xf7 */
+       0x00, 0x00, 0xfa, 0x00, 0xfc, 0xfd, 0x00, 0x00, /* 0xf8-0xff */
+       };
+
+static unsigned char page01[256] = {
+       0x00, 0x00, 0xc3, 0xe3, 0xa5, 0xb9, 0xc6, 0xe6, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0xc8, 0xe8, 0xcf, 0xef, /* 0x08-0x0f */
+       0xd0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0xca, 0xea, 0xcc, 0xec, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0xc5, 0xe5, 0x00, 0x00, 0xbc, 0xbe, 0x00, /* 0x38-0x3f */
+       0x00, 0xa3, 0xb3, 0xd1, 0xf1, 0x00, 0x00, 0xd2, /* 0x40-0x47 */
+       0xf2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0xd5, 0xf5, 0x00, 0x00, 0xc0, 0xe0, 0x00, 0x00, /* 0x50-0x57 */
+       0xd8, 0xf8, 0x8c, 0x9c, 0x00, 0x00, 0xaa, 0xba, /* 0x58-0x5f */
+       0x8a, 0x9a, 0xde, 0xfe, 0x8d, 0x9d, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd9, 0xf9, /* 0x68-0x6f */
+       0xdb, 0xfb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x8f, 0x9f, 0xaf, 0xbf, 0x8e, 0x9e, 0x00, /* 0x78-0x7f */
+
+       };
+
+static unsigned char page02[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa1, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0xa2, 0xff, 0x00, 0xb2, 0x00, 0xbd, 0x00, 0x00, /* 0xd8-0xdf */
+       };
+
+static unsigned char page20[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x96, 0x97, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x91, 0x92, 0x82, 0x00, 0x93, 0x94, 0x84, 0x00, /* 0x18-0x1f */
+       0x86, 0x87, 0x95, 0x00, 0x00, 0x00, 0x85, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x8b, 0x9b, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       };
+
+static unsigned char page21[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x99, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       };
+
+static unsigned char *page_uni2charset[256] = {
+       page00, page01, page02, NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       page20, page21, NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       };
+
+#if 0
+static unsigned char charset2lower[256] = {
+       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+       0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x40-0x47 */
+       0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x48-0x4f */
+       0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x50-0x57 */
+       0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+       0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */
+       0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */
+       0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */
+       0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+       0x80, 0x00, 0x82, 0x00, 0x84, 0x85, 0x86, 0x87, /* 0x80-0x87 */
+       0x00, 0x89, 0x9a, 0x8b, 0x9c, 0x9d, 0x9e, 0x9f, /* 0x88-0x8f */
+       0x00, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, /* 0x90-0x97 */
+       0x00, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, /* 0x98-0x9f */
+       0xa0, 0xa1, 0xa2, 0xb3, 0xa4, 0xb9, 0xa6, 0xa7, /* 0xa0-0xa7 */
+       0xa8, 0xa9, 0xba, 0xab, 0xac, 0xad, 0xae, 0xbf, /* 0xa8-0xaf */
+       0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
+       0xb8, 0xb9, 0xba, 0xbb, 0xbe, 0xbd, 0xbe, 0xbf, /* 0xb8-0xbf */
+       0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0xc0-0xc7 */
+       0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xc8-0xcf */
+       0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xd7, /* 0xd0-0xd7 */
+       0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xdf, /* 0xd8-0xdf */
+       0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0xe0-0xe7 */
+       0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xe8-0xef */
+       0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
+       0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
+       };
+
+static unsigned char charset2upper[256] = {
+       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+       0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
+       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
+       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
+       0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+       0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x60-0x67 */
+       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x68-0x6f */
+       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x70-0x77 */
+       0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+       0x80, 0x00, 0x82, 0x00, 0x84, 0x85, 0x86, 0x87, /* 0x80-0x87 */
+       0x00, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, /* 0x88-0x8f */
+       0x00, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, /* 0x90-0x97 */
+       0x00, 0x99, 0x8a, 0x9b, 0x8c, 0x8d, 0x8e, 0x8f, /* 0x98-0x9f */
+       0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, /* 0xa0-0xa7 */
+       0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
+       0xb0, 0xb1, 0xb2, 0xa3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
+       0xb8, 0xa5, 0xaa, 0xbb, 0xbc, 0xbd, 0xbc, 0xaf, /* 0xb8-0xbf */
+       0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xc0-0xc7 */
+       0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
+       0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
+       0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0x00, /* 0xd8-0xdf */
+       0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xe0-0xe7 */
+       0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xe8-0xef */
+       0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xf7, /* 0xf0-0xf7 */
+       0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xff, /* 0xf8-0xff */
+       };
+#endif
+
+static struct unls_table table = {
+       "cp1250",
+       page_uni2charset,
+       charset2uni,
+       NULL
+};
+
+int
+init_unls_cp1250()
+{
+       return (register_unls(&table));
+}
diff --git a/libunls/nls_cp1251.c b/libunls/nls_cp1251.c
new file mode 100644 (file)
index 0000000..89c9156
--- /dev/null
@@ -0,0 +1,298 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)nls_cp1251.c    1.2 05/05/01 2002 */
+/*
+ *     Modifications to make the code portable Copyright (c) 2000 J. Schilling
+ *
+ *     Code taken from the Linux kernel.
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/*
+ * linux/fs/nls_cp1251.c
+ *
+ * Charset cp1251 translation tables.
+ * Generated automatically from the Unicode and charset
+ * tables from the Unicode Organization (www.unicode.org).
+ * The Unicode to charset table has only exact mappings.
+ */
+
+#include <mconfig.h>
+#include "nls.h"
+
+static struct unls_unicode charset2uni[256] = {
+       /* 0x00*/
+       {0x00, 0x00}, {0x01, 0x00}, {0x02, 0x00}, {0x03, 0x00},
+       {0x04, 0x00}, {0x05, 0x00}, {0x06, 0x00}, {0x07, 0x00},
+       {0x08, 0x00}, {0x09, 0x00}, {0x0A, 0x00}, {0x0B, 0x00},
+       {0x0C, 0x00}, {0x0D, 0x00}, {0x0E, 0x00}, {0x0F, 0x00},
+       /* 0x10*/
+       {0x10, 0x00}, {0x11, 0x00}, {0x12, 0x00}, {0x13, 0x00},
+       {0x14, 0x00}, {0x15, 0x00}, {0x16, 0x00}, {0x17, 0x00},
+       {0x18, 0x00}, {0x19, 0x00}, {0x1A, 0x00}, {0x1B, 0x00},
+       {0x1C, 0x00}, {0x1D, 0x00}, {0x1E, 0x00}, {0x1F, 0x00},
+       /* 0x20*/
+       {0x20, 0x00}, {0x21, 0x00}, {0x22, 0x00}, {0x23, 0x00},
+       {0x24, 0x00}, {0x25, 0x00}, {0x26, 0x00}, {0x27, 0x00},
+       {0x28, 0x00}, {0x29, 0x00}, {0x2A, 0x00}, {0x2B, 0x00},
+       {0x2C, 0x00}, {0x2D, 0x00}, {0x2E, 0x00}, {0x2F, 0x00},
+       /* 0x30*/
+       {0x30, 0x00}, {0x31, 0x00}, {0x32, 0x00}, {0x33, 0x00},
+       {0x34, 0x00}, {0x35, 0x00}, {0x36, 0x00}, {0x37, 0x00},
+       {0x38, 0x00}, {0x39, 0x00}, {0x3A, 0x00}, {0x3B, 0x00},
+       {0x3C, 0x00}, {0x3D, 0x00}, {0x3E, 0x00}, {0x3F, 0x00},
+       /* 0x40*/
+       {0x40, 0x00}, {0x41, 0x00}, {0x42, 0x00}, {0x43, 0x00},
+       {0x44, 0x00}, {0x45, 0x00}, {0x46, 0x00}, {0x47, 0x00},
+       {0x48, 0x00}, {0x49, 0x00}, {0x4A, 0x00}, {0x4B, 0x00},
+       {0x4C, 0x00}, {0x4D, 0x00}, {0x4E, 0x00}, {0x4F, 0x00},
+       /* 0x50*/
+       {0x50, 0x00}, {0x51, 0x00}, {0x52, 0x00}, {0x53, 0x00},
+       {0x54, 0x00}, {0x55, 0x00}, {0x56, 0x00}, {0x57, 0x00},
+       {0x58, 0x00}, {0x59, 0x00}, {0x5A, 0x00}, {0x5B, 0x00},
+       {0x5C, 0x00}, {0x5D, 0x00}, {0x5E, 0x00}, {0x5F, 0x00},
+       /* 0x60*/
+       {0x60, 0x00}, {0x61, 0x00}, {0x62, 0x00}, {0x63, 0x00},
+       {0x64, 0x00}, {0x65, 0x00}, {0x66, 0x00}, {0x67, 0x00},
+       {0x68, 0x00}, {0x69, 0x00}, {0x6A, 0x00}, {0x6B, 0x00},
+       {0x6C, 0x00}, {0x6D, 0x00}, {0x6E, 0x00}, {0x6F, 0x00},
+       /* 0x70*/
+       {0x70, 0x00}, {0x71, 0x00}, {0x72, 0x00}, {0x73, 0x00},
+       {0x74, 0x00}, {0x75, 0x00}, {0x76, 0x00}, {0x77, 0x00},
+       {0x78, 0x00}, {0x79, 0x00}, {0x7A, 0x00}, {0x7B, 0x00},
+       {0x7C, 0x00}, {0x7D, 0x00}, {0x7E, 0x00}, {0x7F, 0x00},
+       /* 0x80*/
+       {0x02, 0x04}, {0x03, 0x04}, {0x1A, 0x20}, {0x53, 0x04},
+       {0x1E, 0x20}, {0x26, 0x20}, {0x20, 0x20}, {0x21, 0x20},
+       {0xAC, 0x20}, {0x30, 0x20}, {0x09, 0x04}, {0x39, 0x20},
+       {0x0A, 0x04}, {0x0C, 0x04}, {0x0B, 0x04}, {0x0F, 0x04},
+       /* 0x90*/
+       {0x52, 0x04}, {0x18, 0x20}, {0x19, 0x20}, {0x1C, 0x20},
+       {0x1D, 0x20}, {0x22, 0x20}, {0x13, 0x20}, {0x14, 0x20},
+       {0x00, 0x00}, {0x22, 0x21}, {0x59, 0x04}, {0x3A, 0x20},
+       {0x5A, 0x04}, {0x5C, 0x04}, {0x5B, 0x04}, {0x5F, 0x04},
+       /* 0xA0*/
+       {0xA0, 0x00}, {0x0E, 0x04}, {0x5E, 0x04}, {0x08, 0x04},
+       {0xA4, 0x00}, {0x90, 0x04}, {0xA6, 0x00}, {0xA7, 0x00},
+       {0x01, 0x04}, {0xA9, 0x00}, {0x04, 0x04}, {0xAB, 0x00},
+       {0xAC, 0x00}, {0xAD, 0x00}, {0xAE, 0x00}, {0x07, 0x04},
+       /* 0xB0*/
+       {0xB0, 0x00}, {0xB1, 0x00}, {0x06, 0x04}, {0x56, 0x04},
+       {0x91, 0x04}, {0xB5, 0x00}, {0xB6, 0x00}, {0xB7, 0x00},
+       {0x51, 0x04}, {0x16, 0x21}, {0x54, 0x04}, {0xBB, 0x00},
+       {0x58, 0x04}, {0x05, 0x04}, {0x55, 0x04}, {0x57, 0x04},
+       /* 0xC0*/
+       {0x10, 0x04}, {0x11, 0x04}, {0x12, 0x04}, {0x13, 0x04},
+       {0x14, 0x04}, {0x15, 0x04}, {0x16, 0x04}, {0x17, 0x04},
+       {0x18, 0x04}, {0x19, 0x04}, {0x1A, 0x04}, {0x1B, 0x04},
+       {0x1C, 0x04}, {0x1D, 0x04}, {0x1E, 0x04}, {0x1F, 0x04},
+       /* 0xD0*/
+       {0x20, 0x04}, {0x21, 0x04}, {0x22, 0x04}, {0x23, 0x04},
+       {0x24, 0x04}, {0x25, 0x04}, {0x26, 0x04}, {0x27, 0x04},
+       {0x28, 0x04}, {0x29, 0x04}, {0x2A, 0x04}, {0x2B, 0x04},
+       {0x2C, 0x04}, {0x2D, 0x04}, {0x2E, 0x04}, {0x2F, 0x04},
+       /* 0xE0*/
+       {0x30, 0x04}, {0x31, 0x04}, {0x32, 0x04}, {0x33, 0x04},
+       {0x34, 0x04}, {0x35, 0x04}, {0x36, 0x04}, {0x37, 0x04},
+       {0x38, 0x04}, {0x39, 0x04}, {0x3A, 0x04}, {0x3B, 0x04},
+       {0x3C, 0x04}, {0x3D, 0x04}, {0x3E, 0x04}, {0x3F, 0x04},
+       /* 0xF0*/
+       {0x40, 0x04}, {0x41, 0x04}, {0x42, 0x04}, {0x43, 0x04},
+       {0x44, 0x04}, {0x45, 0x04}, {0x46, 0x04}, {0x47, 0x04},
+       {0x48, 0x04}, {0x49, 0x04}, {0x4A, 0x04}, {0x4B, 0x04},
+       {0x4C, 0x04}, {0x4D, 0x04}, {0x4E, 0x04}, {0x4F, 0x04}
+};
+
+
+static unsigned char page00[256] = {
+       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+       0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
+       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
+       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
+       0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+       0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */
+       0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */
+       0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */
+       0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0xa0, 0x00, 0x00, 0x00, 0xa4, 0x00, 0xa6, 0xa7, /* 0xa0-0xa7 */
+       0x00, 0xa9, 0x00, 0xab, 0xac, 0xad, 0xae, 0x00, /* 0xa8-0xaf */
+       0xb0, 0xb1, 0x00, 0x00, 0x00, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0xbb, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0xbb, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0xbb, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0xbb, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0xbb, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0xbb, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0xbb, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0xbb, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0xbb, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page04[256] = {
+       0x00, 0xa8, 0x80, 0x81, 0xaa, 0xbd, 0xb2, 0xaf, /* 0x00-0x07 */
+       0xa3, 0x8a, 0x8c, 0x8e, 0x8d, 0x00, 0xa1, 0x8f, /* 0x08-0x0f */
+       0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0x10-0x17 */
+       0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0x18-0x1f */
+       0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0x20-0x27 */
+       0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, /* 0x28-0x2f */
+       0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0x30-0x37 */
+       0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0x38-0x3f */
+       0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0x40-0x47 */
+       0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0x48-0x4f */
+       0x00, 0xb8, 0x90, 0x83, 0xba, 0xbe, 0xb3, 0xbf, /* 0x50-0x57 */
+       0xbc, 0x9a, 0x9c, 0x9e, 0x9d, 0x00, 0xa2, 0x9f, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0xa5, 0xb4, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+};
+
+static unsigned char page20[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x96, 0x97, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x91, 0x92, 0x82, 0x00, 0x93, 0x94, 0x84, 0x00, /* 0x18-0x1f */
+       0x86, 0x87, 0x95, 0x00, 0x00, 0x00, 0x85, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x8b, 0x9b, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+};
+
+static unsigned char page21[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb9, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x99, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+};
+
+static unsigned char *page_uni2charset[256] = {
+       page00, NULL,   NULL,   NULL,   page04, NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       page20, page21, NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+};
+
+#if 0
+static unsigned char charset2lower[256] = {
+       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+       0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
+       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
+       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
+       0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+       0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x60-0x67 */
+       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x68-0x6f */
+       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x70-0x77 */
+       0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+       0x90, 0x83, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 0x80-0x87 */
+       0x88, 0x89, 0x9a, 0x8b, 0x9c, 0x9d, 0x9e, 0x9f, /* 0x88-0x8f */
+       0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, /* 0x90-0x97 */
+       0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, /* 0x98-0x9f */
+       0xa0, 0xa2, 0xa2, 0xbc, 0xa4, 0xb4, 0xa6, 0xa7, /* 0xa0-0xa7 */
+       0xb8, 0xa9, 0xba, 0xab, 0xac, 0xad, 0xae, 0xbf, /* 0xa8-0xaf */
+       0xb0, 0xb1, 0xb3, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
+       0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbe, 0xbe, 0xbf, /* 0xb8-0xbf */
+       0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0xc0-0xc7 */
+       0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xc8-0xcf */
+       0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xd0-0xd7 */
+       0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xd8-0xdf */
+       0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0xe0-0xe7 */
+       0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xe8-0xef */
+       0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
+       0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
+};
+
+static unsigned char charset2upper[256] = {
+       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+       0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
+       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
+       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
+       0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+       0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x60-0x67 */
+       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x68-0x6f */
+       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x70-0x77 */
+       0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+       0x80, 0x81, 0x82, 0x81, 0x84, 0x85, 0x86, 0x87, /* 0x80-0x87 */
+       0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, /* 0x88-0x8f */
+       0x80, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, /* 0x90-0x97 */
+       0x98, 0x99, 0x8a, 0x9b, 0x8c, 0x8d, 0x8e, 0x8f, /* 0x98-0x9f */
+       0xa0, 0xa1, 0xa1, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, /* 0xa0-0xa7 */
+       0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
+       0xb0, 0xb1, 0xb2, 0xb2, 0xa5, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
+       0xa8, 0xb9, 0xaa, 0xbb, 0xa3, 0xbd, 0xbd, 0xaf, /* 0xb8-0xbf */
+       0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xc0-0xc7 */
+       0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
+       0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
+       0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, /* 0xd8-0xdf */
+       0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xe0-0xe7 */
+       0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xe8-0xef */
+       0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xf0-0xf7 */
+       0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, /* 0xf8-0xff */
+};
+#endif
+
+static struct unls_table table = {
+       "cp1251",
+       page_uni2charset,
+       charset2uni,
+       NULL
+};
+
+int
+init_unls_cp1251()
+{
+       return (register_unls(&table));
+}
diff --git a/libunls/nls_cp437.c b/libunls/nls_cp437.c
new file mode 100644 (file)
index 0000000..1dcd2ee
--- /dev/null
@@ -0,0 +1,436 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)nls_cp437.c     1.2 05/05/01 2000 J. Schilling */
+/*
+ *     Modifications to make the code portable Copyright (c) 2000 J. Schilling
+ *
+ *     Code taken from the Linux kernel.
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/*
+ * linux/fs/nls_cp437.c
+ *
+ * Charset cp437 translation tables.
+ * Generated automatically from the Unicode and charset
+ * tables from the Unicode Organization (www.unicode.org).
+ * The Unicode to charset table has only exact mappings.
+ */
+
+#include <mconfig.h>
+#include "nls.h"
+
+static struct unls_unicode charset2uni[256] = {
+       /* 0x00*/
+       {0x00, 0x00}, {0x01, 0x00}, {0x02, 0x00}, {0x03, 0x00},
+       {0x04, 0x00}, {0x05, 0x00}, {0x06, 0x00}, {0x07, 0x00},
+       {0x08, 0x00}, {0x09, 0x00}, {0x0a, 0x00}, {0x0b, 0x00},
+       {0x0c, 0x00}, {0x0d, 0x00}, {0x0e, 0x00}, {0x0f, 0x00},
+       /* 0x10*/
+       {0x10, 0x00}, {0x11, 0x00}, {0x12, 0x00}, {0x13, 0x00},
+       {0x14, 0x00}, {0x15, 0x00}, {0x16, 0x00}, {0x17, 0x00},
+       {0x18, 0x00}, {0x19, 0x00}, {0x1a, 0x00}, {0x1b, 0x00},
+       {0x1c, 0x00}, {0x1d, 0x00}, {0x1e, 0x00}, {0x1f, 0x00},
+       /* 0x20*/
+       {0x20, 0x00}, {0x21, 0x00}, {0x22, 0x00}, {0x23, 0x00},
+       {0x24, 0x00}, {0x25, 0x00}, {0x26, 0x00}, {0x27, 0x00},
+       {0x28, 0x00}, {0x29, 0x00}, {0x2a, 0x00}, {0x2b, 0x00},
+       {0x2c, 0x00}, {0x2d, 0x00}, {0x2e, 0x00}, {0x2f, 0x00},
+       /* 0x30*/
+       {0x30, 0x00}, {0x31, 0x00}, {0x32, 0x00}, {0x33, 0x00},
+       {0x34, 0x00}, {0x35, 0x00}, {0x36, 0x00}, {0x37, 0x00},
+       {0x38, 0x00}, {0x39, 0x00}, {0x3a, 0x00}, {0x3b, 0x00},
+       {0x3c, 0x00}, {0x3d, 0x00}, {0x3e, 0x00}, {0x3f, 0x00},
+       /* 0x40*/
+       {0x40, 0x00}, {0x41, 0x00}, {0x42, 0x00}, {0x43, 0x00},
+       {0x44, 0x00}, {0x45, 0x00}, {0x46, 0x00}, {0x47, 0x00},
+       {0x48, 0x00}, {0x49, 0x00}, {0x4a, 0x00}, {0x4b, 0x00},
+       {0x4c, 0x00}, {0x4d, 0x00}, {0x4e, 0x00}, {0x4f, 0x00},
+       /* 0x50*/
+       {0x50, 0x00}, {0x51, 0x00}, {0x52, 0x00}, {0x53, 0x00},
+       {0x54, 0x00}, {0x55, 0x00}, {0x56, 0x00}, {0x57, 0x00},
+       {0x58, 0x00}, {0x59, 0x00}, {0x5a, 0x00}, {0x5b, 0x00},
+       {0x5c, 0x00}, {0x5d, 0x00}, {0x5e, 0x00}, {0x5f, 0x00},
+       /* 0x60*/
+       {0x60, 0x00}, {0x61, 0x00}, {0x62, 0x00}, {0x63, 0x00},
+       {0x64, 0x00}, {0x65, 0x00}, {0x66, 0x00}, {0x67, 0x00},
+       {0x68, 0x00}, {0x69, 0x00}, {0x6a, 0x00}, {0x6b, 0x00},
+       {0x6c, 0x00}, {0x6d, 0x00}, {0x6e, 0x00}, {0x6f, 0x00},
+       /* 0x70*/
+       {0x70, 0x00}, {0x71, 0x00}, {0x72, 0x00}, {0x73, 0x00},
+       {0x74, 0x00}, {0x75, 0x00}, {0x76, 0x00}, {0x77, 0x00},
+       {0x78, 0x00}, {0x79, 0x00}, {0x7a, 0x00}, {0x7b, 0x00},
+       {0x7c, 0x00}, {0x7d, 0x00}, {0x7e, 0x00}, {0x7f, 0x00},
+       /* 0x80*/
+       {0xc7, 0x00}, {0xfc, 0x00}, {0xe9, 0x00}, {0xe2, 0x00},
+       {0xe4, 0x00}, {0xe0, 0x00}, {0xe5, 0x00}, {0xe7, 0x00},
+       {0xea, 0x00}, {0xeb, 0x00}, {0xe8, 0x00}, {0xef, 0x00},
+       {0xee, 0x00}, {0xec, 0x00}, {0xc4, 0x00}, {0xc5, 0x00},
+       /* 0x90*/
+       {0xc9, 0x00}, {0xe6, 0x00}, {0xc6, 0x00}, {0xf4, 0x00},
+       {0xf6, 0x00}, {0xf2, 0x00}, {0xfb, 0x00}, {0xf9, 0x00},
+       {0xff, 0x00}, {0xd6, 0x00}, {0xdc, 0x00}, {0xa2, 0x00},
+       {0xa3, 0x00}, {0xa5, 0x00}, {0xa7, 0x20}, {0x92, 0x01},
+       /* 0xa0*/
+       {0xe1, 0x00}, {0xed, 0x00}, {0xf3, 0x00}, {0xfa, 0x00},
+       {0xf1, 0x00}, {0xd1, 0x00}, {0xaa, 0x00}, {0xba, 0x00},
+       {0xbf, 0x00}, {0x10, 0x23}, {0xac, 0x00}, {0xbd, 0x00},
+       {0xbc, 0x00}, {0xa1, 0x00}, {0xab, 0x00}, {0xbb, 0x00},
+       /* 0xb0*/
+       {0x91, 0x25}, {0x92, 0x25}, {0x93, 0x25}, {0x02, 0x25},
+       {0x24, 0x25}, {0x61, 0x25}, {0x62, 0x25}, {0x56, 0x25},
+       {0x55, 0x25}, {0x63, 0x25}, {0x51, 0x25}, {0x57, 0x25},
+       {0x5d, 0x25}, {0x5c, 0x25}, {0x5b, 0x25}, {0x10, 0x25},
+       /* 0xc0*/
+       {0x14, 0x25}, {0x34, 0x25}, {0x2c, 0x25}, {0x1c, 0x25},
+       {0x00, 0x25}, {0x3c, 0x25}, {0x5e, 0x25}, {0x5f, 0x25},
+       {0x5a, 0x25}, {0x54, 0x25}, {0x69, 0x25}, {0x66, 0x25},
+       {0x60, 0x25}, {0x50, 0x25}, {0x6c, 0x25}, {0x67, 0x25},
+       /* 0xd0*/
+       {0x68, 0x25}, {0x64, 0x25}, {0x65, 0x25}, {0x59, 0x25},
+       {0x58, 0x25}, {0x52, 0x25}, {0x53, 0x25}, {0x6b, 0x25},
+       {0x6a, 0x25}, {0x18, 0x25}, {0x0c, 0x25}, {0x88, 0x25},
+       {0x84, 0x25}, {0x8c, 0x25}, {0x90, 0x25}, {0x80, 0x25},
+       /* 0xe0*/
+       {0xb1, 0x03}, {0xdf, 0x00}, {0x93, 0x03}, {0xc0, 0x03},
+       {0xa3, 0x03}, {0xc3, 0x03}, {0xb5, 0x00}, {0xc4, 0x03},
+       {0xa6, 0x03}, {0x98, 0x03}, {0xa9, 0x03}, {0xb4, 0x03},
+       {0x1e, 0x22}, {0xc6, 0x03}, {0xb5, 0x03}, {0x29, 0x22},
+       /* 0xf0*/
+       {0x61, 0x22}, {0xb1, 0x00}, {0x65, 0x22}, {0x64, 0x22},
+       {0x20, 0x23}, {0x21, 0x23}, {0xf7, 0x00}, {0x48, 0x22},
+       {0xb0, 0x00}, {0x19, 0x22}, {0xb7, 0x00}, {0x1a, 0x22},
+       {0x7f, 0x20}, {0xb2, 0x00}, {0xa0, 0x25}, {0xa0, 0x00},
+};
+
+static unsigned char page00[256] = {
+       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+       0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
+       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
+       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
+       0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+       0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */
+       0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */
+       0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */
+       0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0xff, 0xad, 0x9b, 0x9c, 0x00, 0x9d, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0xa6, 0xae, 0xaa, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0xf8, 0xf1, 0xfd, 0x00, 0x00, 0xe6, 0x00, 0xfa, /* 0xb0-0xb7 */
+       0x00, 0x00, 0xa7, 0xaf, 0xac, 0xab, 0x00, 0xa8, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x8e, 0x8f, 0x92, 0x80, /* 0xc0-0xc7 */
+       0x00, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0xa5, 0x00, 0x00, 0x00, 0x00, 0x99, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x9a, 0x00, 0x00, 0xe1, /* 0xd8-0xdf */
+       0x85, 0xa0, 0x83, 0x00, 0x84, 0x86, 0x91, 0x87, /* 0xe0-0xe7 */
+       0x8a, 0x82, 0x88, 0x89, 0x8d, 0xa1, 0x8c, 0x8b, /* 0xe8-0xef */
+       0x00, 0xa4, 0x95, 0xa2, 0x93, 0x00, 0x94, 0xf6, /* 0xf0-0xf7 */
+       0x00, 0x97, 0xa3, 0x96, 0x81, 0x00, 0x00, 0x98, /* 0xf8-0xff */
+};
+
+static unsigned char page01[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x9f, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page03[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0xe9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0xe4, 0x00, 0x00, 0xe8, 0x00, /* 0xa0-0xa7 */
+       0x00, 0xea, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0xe0, 0x00, 0x00, 0xeb, 0xee, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0xe3, 0x00, 0x00, 0xe5, 0xe7, 0x00, 0xed, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page20[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9e, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page22[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0xf9, 0xfb, 0x00, 0x00, 0x00, 0xec, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0xf0, 0x00, 0x00, 0xf3, 0xf2, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page23[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0xa9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0xf4, 0xf5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page25[256] = {
+       0xc4, 0x00, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0xda, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0xbf, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0xd9, 0x00, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0xc2, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0xc1, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0xc5, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0xcd, 0xba, 0xd5, 0xd6, 0xc9, 0xb8, 0xb7, 0xbb, /* 0x50-0x57 */
+       0xd4, 0xd3, 0xc8, 0xbe, 0xbd, 0xbc, 0xc6, 0xc7, /* 0x58-0x5f */
+       0xcc, 0xb5, 0xb6, 0xb9, 0xd1, 0xd2, 0xcb, 0xcf, /* 0x60-0x67 */
+       0xd0, 0xca, 0xd8, 0xd7, 0xce, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0xdf, 0x00, 0x00, 0x00, 0xdc, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0xdb, 0x00, 0x00, 0x00, 0xdd, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0xde, 0xb0, 0xb1, 0xb2, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char *page_uni2charset[256] = {
+       page00, page01, NULL,   page03, NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       page20, NULL,   page22, page23, NULL,   page25, NULL,   NULL,
+};
+
+#if 0
+static unsigned char charset2upper[256] = {
+       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+       0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
+       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
+       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
+       0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+       0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+       0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8e, 0x8f, /* 0x88-0x8f */
+       0x90, 0x91, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0xa5, 0xa6, 0xa7, /* 0xa0-0xa7 */
+       0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
+       0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
+       0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* 0xb8-0xbf */
+       0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xc0-0xc7 */
+       0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
+       0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
+       0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, /* 0xd8-0xdf */
+       0x00, 0x00, 0xe2, 0x00, 0xe4, 0x00, 0xe6, 0x00, /* 0xe0-0xe7 */
+       0xe8, 0xe9, 0xea, 0x00, 0xec, 0x00, 0x00, 0xef, /* 0xe8-0xef */
+       0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
+       0xf8, 0xf9, 0xfa, 0xfb, 0x00, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
+};
+#endif
+
+static struct unls_table table = {
+       "cp437",
+       page_uni2charset,
+       charset2uni,
+       NULL
+};
+
+int
+init_unls_cp437()
+{
+       return (register_unls(&table));
+}
diff --git a/libunls/nls_cp737.c b/libunls/nls_cp737.c
new file mode 100644 (file)
index 0000000..1cb4b44
--- /dev/null
@@ -0,0 +1,364 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)nls_cp737.c     1.2 05/05/01 2000 J. Schilling */
+/*
+ *     Modifications to make the code portable Copyright (c) 2000 J. Schilling
+ *
+ *     Code taken from the Linux kernel.
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/*
+ * linux/fs/nls_cp737.c
+ *
+ * Charset cp737 translation tables.
+ * Generated automatically from the Unicode and charset
+ * tables from the Unicode Organization (www.unicode.org).
+ * The Unicode to charset table has only exact mappings.
+ */
+
+#include <mconfig.h>
+#include "nls.h"
+
+static struct unls_unicode charset2uni[256] = {
+       /* 0x00*/
+       {0x00, 0x00}, {0x01, 0x00}, {0x02, 0x00}, {0x03, 0x00},
+       {0x04, 0x00}, {0x05, 0x00}, {0x06, 0x00}, {0x07, 0x00},
+       {0x08, 0x00}, {0x09, 0x00}, {0x0a, 0x00}, {0x0b, 0x00},
+       {0x0c, 0x00}, {0x0d, 0x00}, {0x0e, 0x00}, {0x0f, 0x00},
+       /* 0x10*/
+       {0x10, 0x00}, {0x11, 0x00}, {0x12, 0x00}, {0x13, 0x00},
+       {0x14, 0x00}, {0x15, 0x00}, {0x16, 0x00}, {0x17, 0x00},
+       {0x18, 0x00}, {0x19, 0x00}, {0x1a, 0x00}, {0x1b, 0x00},
+       {0x1c, 0x00}, {0x1d, 0x00}, {0x1e, 0x00}, {0x1f, 0x00},
+       /* 0x20*/
+       {0x20, 0x00}, {0x21, 0x00}, {0x22, 0x00}, {0x23, 0x00},
+       {0x24, 0x00}, {0x25, 0x00}, {0x26, 0x00}, {0x27, 0x00},
+       {0x28, 0x00}, {0x29, 0x00}, {0x2a, 0x00}, {0x2b, 0x00},
+       {0x2c, 0x00}, {0x2d, 0x00}, {0x2e, 0x00}, {0x2f, 0x00},
+       /* 0x30*/
+       {0x30, 0x00}, {0x31, 0x00}, {0x32, 0x00}, {0x33, 0x00},
+       {0x34, 0x00}, {0x35, 0x00}, {0x36, 0x00}, {0x37, 0x00},
+       {0x38, 0x00}, {0x39, 0x00}, {0x3a, 0x00}, {0x3b, 0x00},
+       {0x3c, 0x00}, {0x3d, 0x00}, {0x3e, 0x00}, {0x3f, 0x00},
+       /* 0x40*/
+       {0x40, 0x00}, {0x41, 0x00}, {0x42, 0x00}, {0x43, 0x00},
+       {0x44, 0x00}, {0x45, 0x00}, {0x46, 0x00}, {0x47, 0x00},
+       {0x48, 0x00}, {0x49, 0x00}, {0x4a, 0x00}, {0x4b, 0x00},
+       {0x4c, 0x00}, {0x4d, 0x00}, {0x4e, 0x00}, {0x4f, 0x00},
+       /* 0x50*/
+       {0x50, 0x00}, {0x51, 0x00}, {0x52, 0x00}, {0x53, 0x00},
+       {0x54, 0x00}, {0x55, 0x00}, {0x56, 0x00}, {0x57, 0x00},
+       {0x58, 0x00}, {0x59, 0x00}, {0x5a, 0x00}, {0x5b, 0x00},
+       {0x5c, 0x00}, {0x5d, 0x00}, {0x5e, 0x00}, {0x5f, 0x00},
+       /* 0x60*/
+       {0x60, 0x00}, {0x61, 0x00}, {0x62, 0x00}, {0x63, 0x00},
+       {0x64, 0x00}, {0x65, 0x00}, {0x66, 0x00}, {0x67, 0x00},
+       {0x68, 0x00}, {0x69, 0x00}, {0x6a, 0x00}, {0x6b, 0x00},
+       {0x6c, 0x00}, {0x6d, 0x00}, {0x6e, 0x00}, {0x6f, 0x00},
+       /* 0x70*/
+       {0x70, 0x00}, {0x71, 0x00}, {0x72, 0x00}, {0x73, 0x00},
+       {0x74, 0x00}, {0x75, 0x00}, {0x76, 0x00}, {0x77, 0x00},
+       {0x78, 0x00}, {0x79, 0x00}, {0x7a, 0x00}, {0x7b, 0x00},
+       {0x7c, 0x00}, {0x7d, 0x00}, {0x7e, 0x00}, {0x7f, 0x00},
+       /* 0x80*/
+       {0x91, 0x03}, {0x92, 0x03}, {0x93, 0x03}, {0x94, 0x03},
+       {0x95, 0x03}, {0x96, 0x03}, {0x97, 0x03}, {0x98, 0x03},
+       {0x99, 0x03}, {0x9a, 0x03}, {0x9b, 0x03}, {0x9c, 0x03},
+       {0x9d, 0x03}, {0x9e, 0x03}, {0x9f, 0x03}, {0xa0, 0x03},
+       /* 0x90*/
+       {0xa1, 0x03}, {0xa3, 0x03}, {0xa4, 0x03}, {0xa5, 0x03},
+       {0xa6, 0x03}, {0xa7, 0x03}, {0xa8, 0x03}, {0xa9, 0x03},
+       {0xb1, 0x03}, {0xb2, 0x03}, {0xb3, 0x03}, {0xb4, 0x03},
+       {0xb5, 0x03}, {0xb6, 0x03}, {0xb7, 0x03}, {0xb8, 0x03},
+       /* 0xa0*/
+       {0xb9, 0x03}, {0xba, 0x03}, {0xbb, 0x03}, {0xbc, 0x03},
+       {0xbd, 0x03}, {0xbe, 0x03}, {0xbf, 0x03}, {0xc0, 0x03},
+       {0xc1, 0x03}, {0xc3, 0x03}, {0xc2, 0x03}, {0xc4, 0x03},
+       {0xc5, 0x03}, {0xc6, 0x03}, {0xc7, 0x03}, {0xc8, 0x03},
+       /* 0xb0*/
+       {0x91, 0x25}, {0x92, 0x25}, {0x93, 0x25}, {0x02, 0x25},
+       {0x24, 0x25}, {0x61, 0x25}, {0x62, 0x25}, {0x56, 0x25},
+       {0x55, 0x25}, {0x63, 0x25}, {0x51, 0x25}, {0x57, 0x25},
+       {0x5d, 0x25}, {0x5c, 0x25}, {0x5b, 0x25}, {0x10, 0x25},
+       /* 0xc0*/
+       {0x14, 0x25}, {0x34, 0x25}, {0x2c, 0x25}, {0x1c, 0x25},
+       {0x00, 0x25}, {0x3c, 0x25}, {0x5e, 0x25}, {0x5f, 0x25},
+       {0x5a, 0x25}, {0x54, 0x25}, {0x69, 0x25}, {0x66, 0x25},
+       {0x60, 0x25}, {0x50, 0x25}, {0x6c, 0x25}, {0x67, 0x25},
+       /* 0xd0*/
+       {0x68, 0x25}, {0x64, 0x25}, {0x65, 0x25}, {0x59, 0x25},
+       {0x58, 0x25}, {0x52, 0x25}, {0x53, 0x25}, {0x6b, 0x25},
+       {0x6a, 0x25}, {0x18, 0x25}, {0x0c, 0x25}, {0x88, 0x25},
+       {0x84, 0x25}, {0x8c, 0x25}, {0x90, 0x25}, {0x80, 0x25},
+       /* 0xe0*/
+       {0xc9, 0x03}, {0xac, 0x03}, {0xad, 0x03}, {0xae, 0x03},
+       {0xca, 0x03}, {0xaf, 0x03}, {0xcc, 0x03}, {0xcd, 0x03},
+       {0xcb, 0x03}, {0xce, 0x03}, {0x86, 0x03}, {0x88, 0x03},
+       {0x89, 0x03}, {0x8a, 0x03}, {0x8c, 0x03}, {0x8e, 0x03},
+       /* 0xf0*/
+       {0x8f, 0x03}, {0xb1, 0x00}, {0x65, 0x22}, {0x64, 0x22},
+       {0xaa, 0x03}, {0xab, 0x03}, {0xf7, 0x00}, {0x48, 0x22},
+       {0xb0, 0x00}, {0x19, 0x22}, {0xb7, 0x00}, {0x1a, 0x22},
+       {0x7f, 0x20}, {0xb2, 0x00}, {0xa0, 0x25}, {0xa0, 0x00},
+};
+
+static unsigned char page00[256] = {
+       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+       0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
+       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
+       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
+       0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+       0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */
+       0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */
+       0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */
+       0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0xf8, 0xf1, 0xfd, 0x00, 0x00, 0x00, 0x00, 0xfa, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page03[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xea, 0x00, /* 0x80-0x87 */
+       0xeb, 0xec, 0xed, 0x00, 0xee, 0x00, 0xef, 0xf0, /* 0x88-0x8f */
+       0x00, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, /* 0x90-0x97 */
+       0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, /* 0x98-0x9f */
+       0x8f, 0x90, 0x00, 0x91, 0x92, 0x93, 0x94, 0x95, /* 0xa0-0xa7 */
+       0x96, 0x97, 0xf4, 0xf5, 0xe1, 0xe2, 0xe3, 0xe5, /* 0xa8-0xaf */
+       0x00, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, /* 0xb0-0xb7 */
+       0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, /* 0xb8-0xbf */
+       0xa7, 0xa8, 0xaa, 0xa9, 0xab, 0xac, 0xad, 0xae, /* 0xc0-0xc7 */
+       0xaf, 0xe0, 0xe4, 0xe8, 0xe6, 0xe7, 0xe9, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page20[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page22[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0xf9, 0xfb, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0xf3, 0xf2, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page25[256] = {
+       0xc4, 0x00, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0xda, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0xbf, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0xd9, 0x00, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0xc2, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0xc1, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0xc5, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0xcd, 0xba, 0xd5, 0xd6, 0xc9, 0xb8, 0xb7, 0xbb, /* 0x50-0x57 */
+       0xd4, 0xd3, 0xc8, 0xbe, 0xbd, 0xbc, 0xc6, 0xc7, /* 0x58-0x5f */
+       0xcc, 0xb5, 0xb6, 0xb9, 0xd1, 0xd2, 0xcb, 0xcf, /* 0x60-0x67 */
+       0xd0, 0xca, 0xd8, 0xd7, 0xce, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0xdf, 0x00, 0x00, 0x00, 0xdc, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0xdb, 0x00, 0x00, 0x00, 0xdd, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0xde, 0xb0, 0xb1, 0xb2, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char *page_uni2charset[256] = {
+       page00, NULL,   NULL,   page03, NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       page20, NULL,   page22, NULL,   NULL,   page25, NULL,   NULL,
+};
+
+#if 0
+static unsigned char charset2upper[256] = {
+       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+       0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
+       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
+       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
+       0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+       0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+       0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 0x80-0x87 */
+       0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, /* 0x88-0x8f */
+       0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
+       0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* 0xb8-0xbf */
+       0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xc0-0xc7 */
+       0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
+       0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
+       0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xe8-0xef */
+       0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
+       0xf8, 0xf9, 0xfa, 0xfb, 0x00, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
+};
+#endif
+
+static struct unls_table table = {
+       "cp737",
+       page_uni2charset,
+       charset2uni,
+       NULL
+};
+
+int
+init_unls_cp737()
+{
+       return (register_unls(&table));
+}
diff --git a/libunls/nls_cp775.c b/libunls/nls_cp775.c
new file mode 100644 (file)
index 0000000..d34580d
--- /dev/null
@@ -0,0 +1,364 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)nls_cp775.c     1.2 05/05/01 2000 J. Schilling */
+/*
+ *     Modifications to make the code portable Copyright (c) 2000 J. Schilling
+ *
+ *     Code taken from the Linux kernel.
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/*
+ * linux/fs/nls_cp775.c
+ *
+ * Charset cp775 translation tables.
+ * Generated automatically from the Unicode and charset
+ * tables from the Unicode Organization (www.unicode.org).
+ * The Unicode to charset table has only exact mappings.
+ */
+
+#include <mconfig.h>
+#include "nls.h"
+
+static struct unls_unicode charset2uni[256] = {
+       /* 0x00*/
+       {0x00, 0x00}, {0x01, 0x00}, {0x02, 0x00}, {0x03, 0x00},
+       {0x04, 0x00}, {0x05, 0x00}, {0x06, 0x00}, {0x07, 0x00},
+       {0x08, 0x00}, {0x09, 0x00}, {0x0a, 0x00}, {0x0b, 0x00},
+       {0x0c, 0x00}, {0x0d, 0x00}, {0x0e, 0x00}, {0x0f, 0x00},
+       /* 0x10*/
+       {0x10, 0x00}, {0x11, 0x00}, {0x12, 0x00}, {0x13, 0x00},
+       {0x14, 0x00}, {0x15, 0x00}, {0x16, 0x00}, {0x17, 0x00},
+       {0x18, 0x00}, {0x19, 0x00}, {0x1a, 0x00}, {0x1b, 0x00},
+       {0x1c, 0x00}, {0x1d, 0x00}, {0x1e, 0x00}, {0x1f, 0x00},
+       /* 0x20*/
+       {0x20, 0x00}, {0x21, 0x00}, {0x22, 0x00}, {0x23, 0x00},
+       {0x24, 0x00}, {0x25, 0x00}, {0x26, 0x00}, {0x27, 0x00},
+       {0x28, 0x00}, {0x29, 0x00}, {0x2a, 0x00}, {0x2b, 0x00},
+       {0x2c, 0x00}, {0x2d, 0x00}, {0x2e, 0x00}, {0x2f, 0x00},
+       /* 0x30*/
+       {0x30, 0x00}, {0x31, 0x00}, {0x32, 0x00}, {0x33, 0x00},
+       {0x34, 0x00}, {0x35, 0x00}, {0x36, 0x00}, {0x37, 0x00},
+       {0x38, 0x00}, {0x39, 0x00}, {0x3a, 0x00}, {0x3b, 0x00},
+       {0x3c, 0x00}, {0x3d, 0x00}, {0x3e, 0x00}, {0x3f, 0x00},
+       /* 0x40*/
+       {0x40, 0x00}, {0x41, 0x00}, {0x42, 0x00}, {0x43, 0x00},
+       {0x44, 0x00}, {0x45, 0x00}, {0x46, 0x00}, {0x47, 0x00},
+       {0x48, 0x00}, {0x49, 0x00}, {0x4a, 0x00}, {0x4b, 0x00},
+       {0x4c, 0x00}, {0x4d, 0x00}, {0x4e, 0x00}, {0x4f, 0x00},
+       /* 0x50*/
+       {0x50, 0x00}, {0x51, 0x00}, {0x52, 0x00}, {0x53, 0x00},
+       {0x54, 0x00}, {0x55, 0x00}, {0x56, 0x00}, {0x57, 0x00},
+       {0x58, 0x00}, {0x59, 0x00}, {0x5a, 0x00}, {0x5b, 0x00},
+       {0x5c, 0x00}, {0x5d, 0x00}, {0x5e, 0x00}, {0x5f, 0x00},
+       /* 0x60*/
+       {0x60, 0x00}, {0x61, 0x00}, {0x62, 0x00}, {0x63, 0x00},
+       {0x64, 0x00}, {0x65, 0x00}, {0x66, 0x00}, {0x67, 0x00},
+       {0x68, 0x00}, {0x69, 0x00}, {0x6a, 0x00}, {0x6b, 0x00},
+       {0x6c, 0x00}, {0x6d, 0x00}, {0x6e, 0x00}, {0x6f, 0x00},
+       /* 0x70*/
+       {0x70, 0x00}, {0x71, 0x00}, {0x72, 0x00}, {0x73, 0x00},
+       {0x74, 0x00}, {0x75, 0x00}, {0x76, 0x00}, {0x77, 0x00},
+       {0x78, 0x00}, {0x79, 0x00}, {0x7a, 0x00}, {0x7b, 0x00},
+       {0x7c, 0x00}, {0x7d, 0x00}, {0x7e, 0x00}, {0x7f, 0x00},
+       /* 0x80*/
+       {0x06, 0x01}, {0xfc, 0x00}, {0xe9, 0x00}, {0x01, 0x01},
+       {0xe4, 0x00}, {0x23, 0x01}, {0xe5, 0x00}, {0x07, 0x01},
+       {0x42, 0x01}, {0x13, 0x01}, {0x56, 0x01}, {0x57, 0x01},
+       {0x2b, 0x01}, {0x79, 0x01}, {0xc4, 0x00}, {0xc5, 0x00},
+       /* 0x90*/
+       {0xc9, 0x00}, {0xe6, 0x00}, {0xc6, 0x00}, {0x4d, 0x01},
+       {0xf6, 0x00}, {0x22, 0x01}, {0xa2, 0x00}, {0x5a, 0x01},
+       {0x5b, 0x01}, {0xd6, 0x00}, {0xdc, 0x00}, {0xf8, 0x00},
+       {0xa3, 0x00}, {0xd8, 0x00}, {0xd7, 0x00}, {0xa4, 0x00},
+       /* 0xa0*/
+       {0x00, 0x01}, {0x2a, 0x01}, {0xf3, 0x00}, {0x7b, 0x01},
+       {0x7c, 0x01}, {0x7a, 0x01}, {0x1d, 0x20}, {0xa6, 0x00},
+       {0xa9, 0x00}, {0xae, 0x00}, {0xac, 0x00}, {0xbd, 0x00},
+       {0xbc, 0x00}, {0x41, 0x01}, {0xab, 0x00}, {0xbb, 0x00},
+       /* 0xb0*/
+       {0x91, 0x25}, {0x92, 0x25}, {0x93, 0x25}, {0x02, 0x25},
+       {0x24, 0x25}, {0x04, 0x01}, {0x0c, 0x01}, {0x18, 0x01},
+       {0x16, 0x01}, {0x63, 0x25}, {0x51, 0x25}, {0x57, 0x25},
+       {0x5d, 0x25}, {0x2e, 0x01}, {0x60, 0x01}, {0x10, 0x25},
+       /* 0xc0*/
+       {0x14, 0x25}, {0x34, 0x25}, {0x2c, 0x25}, {0x1c, 0x25},
+       {0x00, 0x25}, {0x3c, 0x25}, {0x72, 0x01}, {0x6a, 0x01},
+       {0x5a, 0x25}, {0x54, 0x25}, {0x69, 0x25}, {0x66, 0x25},
+       {0x60, 0x25}, {0x50, 0x25}, {0x6c, 0x25}, {0x7d, 0x01},
+       /* 0xd0*/
+       {0x05, 0x01}, {0x0d, 0x01}, {0x19, 0x01}, {0x17, 0x01},
+       {0x2f, 0x01}, {0x61, 0x01}, {0x73, 0x01}, {0x6b, 0x01},
+       {0x7e, 0x01}, {0x18, 0x25}, {0x0c, 0x25}, {0x88, 0x25},
+       {0x84, 0x25}, {0x8c, 0x25}, {0x90, 0x25}, {0x80, 0x25},
+       /* 0xe0*/
+       {0xd3, 0x00}, {0xdf, 0x00}, {0x4c, 0x01}, {0x43, 0x01},
+       {0xf5, 0x00}, {0xd5, 0x00}, {0xb5, 0x00}, {0x44, 0x01},
+       {0x36, 0x01}, {0x37, 0x01}, {0x3b, 0x01}, {0x3c, 0x01},
+       {0x46, 0x01}, {0x12, 0x01}, {0x45, 0x01}, {0x19, 0x20},
+       /* 0xf0*/
+       {0xad, 0x00}, {0xb1, 0x00}, {0x1c, 0x20}, {0xbe, 0x00},
+       {0xb6, 0x00}, {0xa7, 0x00}, {0xf7, 0x00}, {0x1e, 0x20},
+       {0xb0, 0x00}, {0x19, 0x22}, {0xb7, 0x00}, {0xb9, 0x00},
+       {0xb3, 0x00}, {0xb2, 0x00}, {0xa0, 0x25}, {0xa0, 0x00},
+};
+
+static unsigned char page00[256] = {
+       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+       0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
+       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
+       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
+       0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+       0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */
+       0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */
+       0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */
+       0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0xff, 0x00, 0x96, 0x9c, 0x9f, 0x00, 0xa7, 0xf5, /* 0xa0-0xa7 */
+       0x00, 0xa8, 0x00, 0xae, 0xaa, 0xf0, 0xa9, 0x00, /* 0xa8-0xaf */
+       0xf8, 0xf1, 0xfd, 0xfc, 0x00, 0xe6, 0xf4, 0xfa, /* 0xb0-0xb7 */
+       0x00, 0xfb, 0x00, 0xaf, 0xac, 0xab, 0xf3, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x8e, 0x8f, 0x92, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0xe0, 0x00, 0xe5, 0x99, 0x9e, /* 0xd0-0xd7 */
+       0x9d, 0x00, 0x00, 0x00, 0x9a, 0x00, 0x00, 0xe1, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x84, 0x86, 0x91, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0xa2, 0x00, 0xe4, 0x94, 0xf6, /* 0xf0-0xf7 */
+       0x9b, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page01[256] = {
+       0xa0, 0x83, 0x00, 0x00, 0xb5, 0xd0, 0x80, 0x87, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0xb6, 0xd1, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0xed, 0x89, 0x00, 0x00, 0xb8, 0xd3, /* 0x10-0x17 */
+       0xb7, 0xd2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x95, 0x85, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0xa1, 0x8c, 0x00, 0x00, 0xbd, 0xd4, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, 0xe9, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0xea, 0xeb, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0xad, 0x88, 0xe3, 0xe7, 0xee, 0xec, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0xe2, 0x93, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8a, 0x8b, /* 0x50-0x57 */
+       0x00, 0x00, 0x97, 0x98, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0xbe, 0xd5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0xc7, 0xd7, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0xc6, 0xd6, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x8d, 0xa5, 0xa3, 0xa4, 0xcf, 0xd8, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page20[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0xef, 0x00, 0x00, 0xf2, 0xa6, 0xf7, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page22[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page25[256] = {
+       0xc4, 0x00, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0xda, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0xbf, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0xd9, 0x00, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0xc2, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0xc1, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0xc5, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0xcd, 0xba, 0x00, 0x00, 0xc9, 0x00, 0x00, 0xbb, /* 0x50-0x57 */
+       0x00, 0x00, 0xc8, 0x00, 0x00, 0xbc, 0x00, 0x00, /* 0x58-0x5f */
+       0xcc, 0x00, 0x00, 0xb9, 0x00, 0x00, 0xcb, 0x00, /* 0x60-0x67 */
+       0x00, 0xca, 0x00, 0x00, 0xce, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0xdf, 0x00, 0x00, 0x00, 0xdc, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0xdb, 0x00, 0x00, 0x00, 0xdd, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0xde, 0xb0, 0xb1, 0xb2, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char *page_uni2charset[256] = {
+       page00, page01, NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       page20, NULL,   page22, NULL,   NULL,   page25, NULL,   NULL,
+};
+
+#if 0
+static unsigned char charset2upper[256] = {
+       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+       0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
+       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
+       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
+       0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+       0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+       0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x8a, 0x00, 0x00, 0x8d, 0x8e, 0x8f, /* 0x88-0x8f */
+       0x90, 0x91, 0x92, 0x00, 0x00, 0x95, 0x96, 0x97, /* 0x90-0x97 */
+       0x00, 0x99, 0x9a, 0x00, 0x9c, 0x9d, 0x9e, 0x9f, /* 0x98-0x9f */
+       0xa0, 0xa1, 0x00, 0xa3, 0x00, 0x00, 0xa6, 0xa7, /* 0xa0-0xa7 */
+       0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
+       0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
+       0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* 0xb8-0xbf */
+       0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xc0-0xc7 */
+       0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, /* 0xd8-0xdf */
+       0xe0, 0x00, 0xe2, 0xe3, 0x00, 0xe5, 0xe6, 0x00, /* 0xe0-0xe7 */
+       0xe8, 0x00, 0xea, 0x00, 0x00, 0xed, 0xee, 0xef, /* 0xe8-0xef */
+       0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
+       0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
+};
+#endif
+
+static struct unls_table table = {
+       "cp775",
+       page_uni2charset,
+       charset2uni,
+       NULL
+};
+
+int
+init_unls_cp775()
+{
+       return (register_unls(&table));
+}
diff --git a/libunls/nls_cp850.c b/libunls/nls_cp850.c
new file mode 100644 (file)
index 0000000..6f82ed0
--- /dev/null
@@ -0,0 +1,328 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)nls_cp850.c     1.2 05/05/01 2000 J. Schilling */
+/*
+ *     Modifications to make the code portable Copyright (c) 2000 J. Schilling
+ *
+ *     Code taken from the Linux kernel.
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/*
+ * linux/fs/nls_cp850.c
+ *
+ * Charset cp850 translation tables.
+ * Generated automatically from the Unicode and charset
+ * tables from the Unicode Organization (www.unicode.org).
+ * The Unicode to charset table has only exact mappings.
+ */
+
+#include <mconfig.h>
+#include "nls.h"
+
+static struct unls_unicode charset2uni[256] = {
+       /* 0x00*/
+       {0x00, 0x00}, {0x01, 0x00}, {0x02, 0x00}, {0x03, 0x00},
+       {0x04, 0x00}, {0x05, 0x00}, {0x06, 0x00}, {0x07, 0x00},
+       {0x08, 0x00}, {0x09, 0x00}, {0x0a, 0x00}, {0x0b, 0x00},
+       {0x0c, 0x00}, {0x0d, 0x00}, {0x0e, 0x00}, {0x0f, 0x00},
+       /* 0x10*/
+       {0x10, 0x00}, {0x11, 0x00}, {0x12, 0x00}, {0x13, 0x00},
+       {0x14, 0x00}, {0x15, 0x00}, {0x16, 0x00}, {0x17, 0x00},
+       {0x18, 0x00}, {0x19, 0x00}, {0x1a, 0x00}, {0x1b, 0x00},
+       {0x1c, 0x00}, {0x1d, 0x00}, {0x1e, 0x00}, {0x1f, 0x00},
+       /* 0x20*/
+       {0x20, 0x00}, {0x21, 0x00}, {0x22, 0x00}, {0x23, 0x00},
+       {0x24, 0x00}, {0x25, 0x00}, {0x26, 0x00}, {0x27, 0x00},
+       {0x28, 0x00}, {0x29, 0x00}, {0x2a, 0x00}, {0x2b, 0x00},
+       {0x2c, 0x00}, {0x2d, 0x00}, {0x2e, 0x00}, {0x2f, 0x00},
+       /* 0x30*/
+       {0x30, 0x00}, {0x31, 0x00}, {0x32, 0x00}, {0x33, 0x00},
+       {0x34, 0x00}, {0x35, 0x00}, {0x36, 0x00}, {0x37, 0x00},
+       {0x38, 0x00}, {0x39, 0x00}, {0x3a, 0x00}, {0x3b, 0x00},
+       {0x3c, 0x00}, {0x3d, 0x00}, {0x3e, 0x00}, {0x3f, 0x00},
+       /* 0x40*/
+       {0x40, 0x00}, {0x41, 0x00}, {0x42, 0x00}, {0x43, 0x00},
+       {0x44, 0x00}, {0x45, 0x00}, {0x46, 0x00}, {0x47, 0x00},
+       {0x48, 0x00}, {0x49, 0x00}, {0x4a, 0x00}, {0x4b, 0x00},
+       {0x4c, 0x00}, {0x4d, 0x00}, {0x4e, 0x00}, {0x4f, 0x00},
+       /* 0x50*/
+       {0x50, 0x00}, {0x51, 0x00}, {0x52, 0x00}, {0x53, 0x00},
+       {0x54, 0x00}, {0x55, 0x00}, {0x56, 0x00}, {0x57, 0x00},
+       {0x58, 0x00}, {0x59, 0x00}, {0x5a, 0x00}, {0x5b, 0x00},
+       {0x5c, 0x00}, {0x5d, 0x00}, {0x5e, 0x00}, {0x5f, 0x00},
+       /* 0x60*/
+       {0x60, 0x00}, {0x61, 0x00}, {0x62, 0x00}, {0x63, 0x00},
+       {0x64, 0x00}, {0x65, 0x00}, {0x66, 0x00}, {0x67, 0x00},
+       {0x68, 0x00}, {0x69, 0x00}, {0x6a, 0x00}, {0x6b, 0x00},
+       {0x6c, 0x00}, {0x6d, 0x00}, {0x6e, 0x00}, {0x6f, 0x00},
+       /* 0x70*/
+       {0x70, 0x00}, {0x71, 0x00}, {0x72, 0x00}, {0x73, 0x00},
+       {0x74, 0x00}, {0x75, 0x00}, {0x76, 0x00}, {0x77, 0x00},
+       {0x78, 0x00}, {0x79, 0x00}, {0x7a, 0x00}, {0x7b, 0x00},
+       {0x7c, 0x00}, {0x7d, 0x00}, {0x7e, 0x00}, {0x7f, 0x00},
+       /* 0x80*/
+       {0xc7, 0x00}, {0xfc, 0x00}, {0xe9, 0x00}, {0xe2, 0x00},
+       {0xe4, 0x00}, {0xe0, 0x00}, {0xe5, 0x00}, {0xe7, 0x00},
+       {0xea, 0x00}, {0xeb, 0x00}, {0xe8, 0x00}, {0xef, 0x00},
+       {0xee, 0x00}, {0xec, 0x00}, {0xc4, 0x00}, {0xc5, 0x00},
+       /* 0x90*/
+       {0xc9, 0x00}, {0xe6, 0x00}, {0xc6, 0x00}, {0xf4, 0x00},
+       {0xf6, 0x00}, {0xf2, 0x00}, {0xfb, 0x00}, {0xf9, 0x00},
+       {0xff, 0x00}, {0xd6, 0x00}, {0xdc, 0x00}, {0xf8, 0x00},
+       {0xa3, 0x00}, {0xd8, 0x00}, {0xd7, 0x00}, {0x92, 0x01},
+       /* 0xa0*/
+       {0xe1, 0x00}, {0xed, 0x00}, {0xf3, 0x00}, {0xfa, 0x00},
+       {0xf1, 0x00}, {0xd1, 0x00}, {0xaa, 0x00}, {0xba, 0x00},
+       {0xbf, 0x00}, {0xae, 0x00}, {0xac, 0x00}, {0xbd, 0x00},
+       {0xbc, 0x00}, {0xa1, 0x00}, {0xab, 0x00}, {0xbb, 0x00},
+       /* 0xb0*/
+       {0x91, 0x25}, {0x92, 0x25}, {0x93, 0x25}, {0x02, 0x25},
+       {0x24, 0x25}, {0xc1, 0x00}, {0xc2, 0x00}, {0xc0, 0x00},
+       {0xa9, 0x00}, {0x63, 0x25}, {0x51, 0x25}, {0x57, 0x25},
+       {0x5d, 0x25}, {0xa2, 0x00}, {0xa5, 0x00}, {0x10, 0x25},
+       /* 0xc0*/
+       {0x14, 0x25}, {0x34, 0x25}, {0x2c, 0x25}, {0x1c, 0x25},
+       {0x00, 0x25}, {0x3c, 0x25}, {0xe3, 0x00}, {0xc3, 0x00},
+       {0x5a, 0x25}, {0x54, 0x25}, {0x69, 0x25}, {0x66, 0x25},
+       {0x60, 0x25}, {0x50, 0x25}, {0x6c, 0x25}, {0xa4, 0x00},
+       /* 0xd0*/
+       {0xf0, 0x00}, {0xd0, 0x00}, {0xca, 0x00}, {0xcb, 0x00},
+       {0xc8, 0x00}, {0x31, 0x01}, {0xcd, 0x00}, {0xce, 0x00},
+       {0xcf, 0x00}, {0x18, 0x25}, {0x0c, 0x25}, {0x88, 0x25},
+       {0x84, 0x25}, {0xa6, 0x00}, {0xcc, 0x00}, {0x80, 0x25},
+       /* 0xe0*/
+       {0xd3, 0x00}, {0xdf, 0x00}, {0xd4, 0x00}, {0xd2, 0x00},
+       {0xf5, 0x00}, {0xd5, 0x00}, {0xb5, 0x00}, {0xfe, 0x00},
+       {0xde, 0x00}, {0xda, 0x00}, {0xdb, 0x00}, {0xd9, 0x00},
+       {0xfd, 0x00}, {0xdd, 0x00}, {0xaf, 0x00}, {0xb4, 0x00},
+       /* 0xf0*/
+       {0xad, 0x00}, {0xb1, 0x00}, {0x17, 0x20}, {0xbe, 0x00},
+       {0xb6, 0x00}, {0xa7, 0x00}, {0xf7, 0x00}, {0xb8, 0x00},
+       {0xb0, 0x00}, {0xa8, 0x00}, {0xb7, 0x00}, {0xb9, 0x00},
+       {0xb3, 0x00}, {0xb2, 0x00}, {0xa0, 0x25}, {0xa0, 0x00},
+};
+
+static unsigned char page00[256] = {
+       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+       0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
+       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
+       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
+       0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+       0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */
+       0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */
+       0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */
+       0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0xff, 0xad, 0xbd, 0x9c, 0xcf, 0xbe, 0xdd, 0xf5, /* 0xa0-0xa7 */
+       0xf9, 0xb8, 0xa6, 0xae, 0xaa, 0xf0, 0xa9, 0xee, /* 0xa8-0xaf */
+       0xf8, 0xf1, 0xfd, 0xfc, 0xef, 0xe6, 0xf4, 0xfa, /* 0xb0-0xb7 */
+       0xf7, 0xfb, 0xa7, 0xaf, 0xac, 0xab, 0xf3, 0xa8, /* 0xb8-0xbf */
+       0xb7, 0xb5, 0xb6, 0xc7, 0x8e, 0x8f, 0x92, 0x80, /* 0xc0-0xc7 */
+       0xd4, 0x90, 0xd2, 0xd3, 0xde, 0xd6, 0xd7, 0xd8, /* 0xc8-0xcf */
+       0xd1, 0xa5, 0xe3, 0xe0, 0xe2, 0xe5, 0x99, 0x9e, /* 0xd0-0xd7 */
+       0x9d, 0xeb, 0xe9, 0xea, 0x9a, 0xed, 0xe8, 0xe1, /* 0xd8-0xdf */
+       0x85, 0xa0, 0x83, 0xc6, 0x84, 0x86, 0x91, 0x87, /* 0xe0-0xe7 */
+       0x8a, 0x82, 0x88, 0x89, 0x8d, 0xa1, 0x8c, 0x8b, /* 0xe8-0xef */
+       0xd0, 0xa4, 0x95, 0xa2, 0x93, 0xe4, 0x94, 0xf6, /* 0xf0-0xf7 */
+       0x9b, 0x97, 0xa3, 0x96, 0x81, 0xec, 0xe7, 0x98, /* 0xf8-0xff */
+};
+
+static unsigned char page01[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0xd5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x9f, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page20[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf2, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page25[256] = {
+       0xc4, 0x00, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0xda, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0xbf, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0xd9, 0x00, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0xc2, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0xc1, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0xc5, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0xcd, 0xba, 0x00, 0x00, 0xc9, 0x00, 0x00, 0xbb, /* 0x50-0x57 */
+       0x00, 0x00, 0xc8, 0x00, 0x00, 0xbc, 0x00, 0x00, /* 0x58-0x5f */
+       0xcc, 0x00, 0x00, 0xb9, 0x00, 0x00, 0xcb, 0x00, /* 0x60-0x67 */
+       0x00, 0xca, 0x00, 0x00, 0xce, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0xdf, 0x00, 0x00, 0x00, 0xdc, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0xdb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0xb0, 0xb1, 0xb2, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char *page_uni2charset[256] = {
+       page00, page01, NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       page20, NULL,   NULL,   NULL,   NULL,   page25, NULL,   NULL,
+};
+
+#if 0
+static unsigned char charset2upper[256] = {
+       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+       0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
+       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
+       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
+       0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+       0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+       0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8e, 0x8f, /* 0x88-0x8f */
+       0x90, 0x91, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x99, 0x9a, 0x00, 0x9c, 0x9d, 0x9e, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0xa5, 0xa6, 0xa7, /* 0xa0-0xa7 */
+       0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
+       0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
+       0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* 0xb8-0xbf */
+       0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0x00, 0xc7, /* 0xc0-0xc7 */
+       0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
+       0x00, 0xd1, 0xd2, 0xd3, 0xd4, 0x00, 0xd6, 0xd7, /* 0xd0-0xd7 */
+       0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, /* 0xd8-0xdf */
+       0xe0, 0x00, 0xe2, 0xe3, 0x00, 0xe5, 0xe6, 0x00, /* 0xe0-0xe7 */
+       0xe8, 0xe9, 0xea, 0xeb, 0x00, 0xed, 0xee, 0xef, /* 0xe8-0xef */
+       0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
+       0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
+};
+#endif
+
+static struct unls_table table = {
+       "cp850",
+       page_uni2charset,
+       charset2uni,
+       NULL
+};
+
+int
+init_unls_cp850()
+{
+       return (register_unls(&table));
+}
diff --git a/libunls/nls_cp852.c b/libunls/nls_cp852.c
new file mode 100644 (file)
index 0000000..040d5be
--- /dev/null
@@ -0,0 +1,328 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)nls_cp852.c     1.2 05/05/01 2000 J. Schilling */
+/*
+ *     Modifications to make the code portable Copyright (c) 2000 J. Schilling
+ *
+ *     Code taken from the Linux kernel.
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/*
+ * linux/fs/nls_cp852.c
+ *
+ * Charset cp852 translation tables.
+ * Generated automatically from the Unicode and charset
+ * tables from the Unicode Organization (www.unicode.org).
+ * The Unicode to charset table has only exact mappings.
+ */
+
+#include <mconfig.h>
+#include "nls.h"
+
+static struct unls_unicode charset2uni[256] = {
+       /* 0x00*/
+       {0x00, 0x00}, {0x01, 0x00}, {0x02, 0x00}, {0x03, 0x00},
+       {0x04, 0x00}, {0x05, 0x00}, {0x06, 0x00}, {0x07, 0x00},
+       {0x08, 0x00}, {0x09, 0x00}, {0x0a, 0x00}, {0x0b, 0x00},
+       {0x0c, 0x00}, {0x0d, 0x00}, {0x0e, 0x00}, {0x0f, 0x00},
+       /* 0x10*/
+       {0x10, 0x00}, {0x11, 0x00}, {0x12, 0x00}, {0x13, 0x00},
+       {0x14, 0x00}, {0x15, 0x00}, {0x16, 0x00}, {0x17, 0x00},
+       {0x18, 0x00}, {0x19, 0x00}, {0x1a, 0x00}, {0x1b, 0x00},
+       {0x1c, 0x00}, {0x1d, 0x00}, {0x1e, 0x00}, {0x1f, 0x00},
+       /* 0x20*/
+       {0x20, 0x00}, {0x21, 0x00}, {0x22, 0x00}, {0x23, 0x00},
+       {0x24, 0x00}, {0x25, 0x00}, {0x26, 0x00}, {0x27, 0x00},
+       {0x28, 0x00}, {0x29, 0x00}, {0x2a, 0x00}, {0x2b, 0x00},
+       {0x2c, 0x00}, {0x2d, 0x00}, {0x2e, 0x00}, {0x2f, 0x00},
+       /* 0x30*/
+       {0x30, 0x00}, {0x31, 0x00}, {0x32, 0x00}, {0x33, 0x00},
+       {0x34, 0x00}, {0x35, 0x00}, {0x36, 0x00}, {0x37, 0x00},
+       {0x38, 0x00}, {0x39, 0x00}, {0x3a, 0x00}, {0x3b, 0x00},
+       {0x3c, 0x00}, {0x3d, 0x00}, {0x3e, 0x00}, {0x3f, 0x00},
+       /* 0x40*/
+       {0x40, 0x00}, {0x41, 0x00}, {0x42, 0x00}, {0x43, 0x00},
+       {0x44, 0x00}, {0x45, 0x00}, {0x46, 0x00}, {0x47, 0x00},
+       {0x48, 0x00}, {0x49, 0x00}, {0x4a, 0x00}, {0x4b, 0x00},
+       {0x4c, 0x00}, {0x4d, 0x00}, {0x4e, 0x00}, {0x4f, 0x00},
+       /* 0x50*/
+       {0x50, 0x00}, {0x51, 0x00}, {0x52, 0x00}, {0x53, 0x00},
+       {0x54, 0x00}, {0x55, 0x00}, {0x56, 0x00}, {0x57, 0x00},
+       {0x58, 0x00}, {0x59, 0x00}, {0x5a, 0x00}, {0x5b, 0x00},
+       {0x5c, 0x00}, {0x5d, 0x00}, {0x5e, 0x00}, {0x5f, 0x00},
+       /* 0x60*/
+       {0x60, 0x00}, {0x61, 0x00}, {0x62, 0x00}, {0x63, 0x00},
+       {0x64, 0x00}, {0x65, 0x00}, {0x66, 0x00}, {0x67, 0x00},
+       {0x68, 0x00}, {0x69, 0x00}, {0x6a, 0x00}, {0x6b, 0x00},
+       {0x6c, 0x00}, {0x6d, 0x00}, {0x6e, 0x00}, {0x6f, 0x00},
+       /* 0x70*/
+       {0x70, 0x00}, {0x71, 0x00}, {0x72, 0x00}, {0x73, 0x00},
+       {0x74, 0x00}, {0x75, 0x00}, {0x76, 0x00}, {0x77, 0x00},
+       {0x78, 0x00}, {0x79, 0x00}, {0x7a, 0x00}, {0x7b, 0x00},
+       {0x7c, 0x00}, {0x7d, 0x00}, {0x7e, 0x00}, {0x7f, 0x00},
+       /* 0x80*/
+       {0xc7, 0x00}, {0xfc, 0x00}, {0xe9, 0x00}, {0xe2, 0x00},
+       {0xe4, 0x00}, {0x6f, 0x01}, {0x07, 0x01}, {0xe7, 0x00},
+       {0x42, 0x01}, {0xeb, 0x00}, {0x50, 0x01}, {0x51, 0x01},
+       {0xee, 0x00}, {0x79, 0x01}, {0xc4, 0x00}, {0x06, 0x01},
+       /* 0x90*/
+       {0xc9, 0x00}, {0x39, 0x01}, {0x3a, 0x01}, {0xf4, 0x00},
+       {0xf6, 0x00}, {0x3d, 0x01}, {0x3e, 0x01}, {0x5a, 0x01},
+       {0x5b, 0x01}, {0xd6, 0x00}, {0xdc, 0x00}, {0x64, 0x01},
+       {0x65, 0x01}, {0x41, 0x01}, {0xd7, 0x00}, {0x0d, 0x01},
+       /* 0xa0*/
+       {0xe1, 0x00}, {0xed, 0x00}, {0xf3, 0x00}, {0xfa, 0x00},
+       {0x04, 0x01}, {0x05, 0x01}, {0x7d, 0x01}, {0x7e, 0x01},
+       {0x18, 0x01}, {0x19, 0x01}, {0xac, 0x00}, {0x7a, 0x01},
+       {0x0c, 0x01}, {0x5f, 0x01}, {0xab, 0x00}, {0xbb, 0x00},
+       /* 0xb0*/
+       {0x91, 0x25}, {0x92, 0x25}, {0x93, 0x25}, {0x02, 0x25},
+       {0x24, 0x25}, {0xc1, 0x00}, {0xc2, 0x00}, {0x1a, 0x01},
+       {0x5e, 0x01}, {0x63, 0x25}, {0x51, 0x25}, {0x57, 0x25},
+       {0x5d, 0x25}, {0x7b, 0x01}, {0x7c, 0x01}, {0x10, 0x25},
+       /* 0xc0*/
+       {0x14, 0x25}, {0x34, 0x25}, {0x2c, 0x25}, {0x1c, 0x25},
+       {0x00, 0x25}, {0x3c, 0x25}, {0x02, 0x01}, {0x03, 0x01},
+       {0x5a, 0x25}, {0x54, 0x25}, {0x69, 0x25}, {0x66, 0x25},
+       {0x60, 0x25}, {0x50, 0x25}, {0x6c, 0x25}, {0xa4, 0x00},
+       /* 0xd0*/
+       {0x11, 0x01}, {0x10, 0x01}, {0x0e, 0x01}, {0xcb, 0x00},
+       {0x0f, 0x01}, {0x47, 0x01}, {0xcd, 0x00}, {0xce, 0x00},
+       {0x1b, 0x01}, {0x18, 0x25}, {0x0c, 0x25}, {0x88, 0x25},
+       {0x84, 0x25}, {0x62, 0x01}, {0x6e, 0x01}, {0x80, 0x25},
+       /* 0xe0*/
+       {0xd3, 0x00}, {0xdf, 0x00}, {0xd4, 0x00}, {0x43, 0x01},
+       {0x44, 0x01}, {0x48, 0x01}, {0x60, 0x01}, {0x61, 0x01},
+       {0x54, 0x01}, {0xda, 0x00}, {0x55, 0x01}, {0x70, 0x01},
+       {0xfd, 0x00}, {0xdd, 0x00}, {0x63, 0x01}, {0xb4, 0x00},
+       /* 0xf0*/
+       {0xad, 0x00}, {0xdd, 0x02}, {0xdb, 0x02}, {0xc7, 0x02},
+       {0xd8, 0x02}, {0xa7, 0x00}, {0xf7, 0x00}, {0xb8, 0x00},
+       {0xb0, 0x00}, {0xa8, 0x00}, {0xd9, 0x02}, {0x71, 0x01},
+       {0x58, 0x01}, {0x59, 0x01}, {0xa0, 0x25}, {0xa0, 0x00},
+};
+
+static unsigned char page00[256] = {
+       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+       0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
+       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
+       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
+       0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+       0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */
+       0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */
+       0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */
+       0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0xff, 0x00, 0x00, 0x00, 0xcf, 0x00, 0x00, 0xf5, /* 0xa0-0xa7 */
+       0xf9, 0x00, 0x00, 0xae, 0xaa, 0xf0, 0x00, 0x00, /* 0xa8-0xaf */
+       0xf8, 0x00, 0x00, 0x00, 0xef, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0xf7, 0x00, 0x00, 0xaf, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0xb5, 0xb6, 0x00, 0x8e, 0x00, 0x00, 0x80, /* 0xc0-0xc7 */
+       0x00, 0x90, 0x00, 0xd3, 0x00, 0xd6, 0xd7, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0xe0, 0xe2, 0x00, 0x99, 0x9e, /* 0xd0-0xd7 */
+       0x00, 0x00, 0xe9, 0x00, 0x9a, 0xed, 0x00, 0xe1, /* 0xd8-0xdf */
+       0x00, 0xa0, 0x83, 0x00, 0x84, 0x00, 0x00, 0x87, /* 0xe0-0xe7 */
+       0x00, 0x82, 0x00, 0x89, 0x00, 0xa1, 0x8c, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0xa2, 0x93, 0x00, 0x94, 0xf6, /* 0xf0-0xf7 */
+       0x00, 0x00, 0xa3, 0x00, 0x81, 0xec, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page01[256] = {
+       0x00, 0x00, 0xc6, 0xc7, 0xa4, 0xa5, 0x8f, 0x86, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0xac, 0x9f, 0xd2, 0xd4, /* 0x08-0x0f */
+       0xd1, 0xd0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0xa8, 0xa9, 0xb7, 0xd8, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x91, 0x92, 0x00, 0x00, 0x95, 0x96, 0x00, /* 0x38-0x3f */
+       0x00, 0x9d, 0x88, 0xe3, 0xe4, 0x00, 0x00, 0xd5, /* 0x40-0x47 */
+       0xe5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x8a, 0x8b, 0x00, 0x00, 0xe8, 0xea, 0x00, 0x00, /* 0x50-0x57 */
+       0xfc, 0xfd, 0x97, 0x98, 0x00, 0x00, 0xb8, 0xad, /* 0x58-0x5f */
+       0xe6, 0xe7, 0xdd, 0xee, 0x9b, 0x9c, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xde, 0x85, /* 0x68-0x6f */
+       0xeb, 0xfb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x8d, 0xab, 0xbd, 0xbe, 0xa6, 0xa7, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page02[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf3, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0xf4, 0xfa, 0x00, 0xf2, 0x00, 0xf1, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page25[256] = {
+       0xc4, 0x00, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0xda, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0xbf, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0xd9, 0x00, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0xc2, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0xc1, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0xc5, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0xcd, 0xba, 0x00, 0x00, 0xc9, 0x00, 0x00, 0xbb, /* 0x50-0x57 */
+       0x00, 0x00, 0xc8, 0x00, 0x00, 0xbc, 0x00, 0x00, /* 0x58-0x5f */
+       0xcc, 0x00, 0x00, 0xb9, 0x00, 0x00, 0xcb, 0x00, /* 0x60-0x67 */
+       0x00, 0xca, 0x00, 0x00, 0xce, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0xdf, 0x00, 0x00, 0x00, 0xdc, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0xdb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0xb0, 0xb1, 0xb2, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char *page_uni2charset[256] = {
+       page00, page01, page02, NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   page25, NULL,   NULL,
+};
+
+#if 0
+static unsigned char charset2upper[256] = {
+       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+       0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
+       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
+       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
+       0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+       0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+       0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x8a, 0x00, 0x00, 0x8d, 0x8e, 0x8f, /* 0x88-0x8f */
+       0x90, 0x91, 0x00, 0x00, 0x00, 0x95, 0x00, 0x97, /* 0x90-0x97 */
+       0x00, 0x99, 0x9a, 0x9b, 0x00, 0x9d, 0x9e, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0xa4, 0x00, 0xa6, 0x00, /* 0xa0-0xa7 */
+       0xa8, 0x00, 0xaa, 0x00, 0xac, 0x00, 0xae, 0xaf, /* 0xa8-0xaf */
+       0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
+       0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0x00, 0xbf, /* 0xb8-0xbf */
+       0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0x00, /* 0xc0-0xc7 */
+       0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
+       0x00, 0xd1, 0xd2, 0xd3, 0x00, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
+       0x00, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, /* 0xd8-0xdf */
+       0xe0, 0x00, 0xe2, 0xe3, 0x00, 0x00, 0xe6, 0x00, /* 0xe0-0xe7 */
+       0xe8, 0xe9, 0x00, 0xeb, 0x00, 0xed, 0x00, 0xef, /* 0xe8-0xef */
+       0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
+       0xf8, 0xf9, 0xfa, 0x00, 0xfc, 0x00, 0xfe, 0xff, /* 0xf8-0xff */
+};
+#endif
+
+static struct unls_table table = {
+       "cp852",
+       page_uni2charset,
+       charset2uni,
+       NULL
+};
+
+int
+init_unls_cp852()
+{
+       return (register_unls(&table));
+}
diff --git a/libunls/nls_cp855.c b/libunls/nls_cp855.c
new file mode 100644 (file)
index 0000000..56642df
--- /dev/null
@@ -0,0 +1,328 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)nls_cp855.c     1.2 05/05/01 2000 J. Schilling */
+/*
+ *     Modifications to make the code portable Copyright (c) 2000 J. Schilling
+ *
+ *     Code taken from the Linux kernel.
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/*
+ * linux/fs/nls_cp855.c
+ *
+ * Charset cp855 translation tables.
+ * Generated automatically from the Unicode and charset
+ * tables from the Unicode Organization (www.unicode.org).
+ * The Unicode to charset table has only exact mappings.
+ */
+
+#include <mconfig.h>
+#include "nls.h"
+
+static struct unls_unicode charset2uni[256] = {
+       /* 0x00*/
+       {0x00, 0x00}, {0x01, 0x00}, {0x02, 0x00}, {0x03, 0x00},
+       {0x04, 0x00}, {0x05, 0x00}, {0x06, 0x00}, {0x07, 0x00},
+       {0x08, 0x00}, {0x09, 0x00}, {0x0a, 0x00}, {0x0b, 0x00},
+       {0x0c, 0x00}, {0x0d, 0x00}, {0x0e, 0x00}, {0x0f, 0x00},
+       /* 0x10*/
+       {0x10, 0x00}, {0x11, 0x00}, {0x12, 0x00}, {0x13, 0x00},
+       {0x14, 0x00}, {0x15, 0x00}, {0x16, 0x00}, {0x17, 0x00},
+       {0x18, 0x00}, {0x19, 0x00}, {0x1a, 0x00}, {0x1b, 0x00},
+       {0x1c, 0x00}, {0x1d, 0x00}, {0x1e, 0x00}, {0x1f, 0x00},
+       /* 0x20*/
+       {0x20, 0x00}, {0x21, 0x00}, {0x22, 0x00}, {0x23, 0x00},
+       {0x24, 0x00}, {0x25, 0x00}, {0x26, 0x00}, {0x27, 0x00},
+       {0x28, 0x00}, {0x29, 0x00}, {0x2a, 0x00}, {0x2b, 0x00},
+       {0x2c, 0x00}, {0x2d, 0x00}, {0x2e, 0x00}, {0x2f, 0x00},
+       /* 0x30*/
+       {0x30, 0x00}, {0x31, 0x00}, {0x32, 0x00}, {0x33, 0x00},
+       {0x34, 0x00}, {0x35, 0x00}, {0x36, 0x00}, {0x37, 0x00},
+       {0x38, 0x00}, {0x39, 0x00}, {0x3a, 0x00}, {0x3b, 0x00},
+       {0x3c, 0x00}, {0x3d, 0x00}, {0x3e, 0x00}, {0x3f, 0x00},
+       /* 0x40*/
+       {0x40, 0x00}, {0x41, 0x00}, {0x42, 0x00}, {0x43, 0x00},
+       {0x44, 0x00}, {0x45, 0x00}, {0x46, 0x00}, {0x47, 0x00},
+       {0x48, 0x00}, {0x49, 0x00}, {0x4a, 0x00}, {0x4b, 0x00},
+       {0x4c, 0x00}, {0x4d, 0x00}, {0x4e, 0x00}, {0x4f, 0x00},
+       /* 0x50*/
+       {0x50, 0x00}, {0x51, 0x00}, {0x52, 0x00}, {0x53, 0x00},
+       {0x54, 0x00}, {0x55, 0x00}, {0x56, 0x00}, {0x57, 0x00},
+       {0x58, 0x00}, {0x59, 0x00}, {0x5a, 0x00}, {0x5b, 0x00},
+       {0x5c, 0x00}, {0x5d, 0x00}, {0x5e, 0x00}, {0x5f, 0x00},
+       /* 0x60*/
+       {0x60, 0x00}, {0x61, 0x00}, {0x62, 0x00}, {0x63, 0x00},
+       {0x64, 0x00}, {0x65, 0x00}, {0x66, 0x00}, {0x67, 0x00},
+       {0x68, 0x00}, {0x69, 0x00}, {0x6a, 0x00}, {0x6b, 0x00},
+       {0x6c, 0x00}, {0x6d, 0x00}, {0x6e, 0x00}, {0x6f, 0x00},
+       /* 0x70*/
+       {0x70, 0x00}, {0x71, 0x00}, {0x72, 0x00}, {0x73, 0x00},
+       {0x74, 0x00}, {0x75, 0x00}, {0x76, 0x00}, {0x77, 0x00},
+       {0x78, 0x00}, {0x79, 0x00}, {0x7a, 0x00}, {0x7b, 0x00},
+       {0x7c, 0x00}, {0x7d, 0x00}, {0x7e, 0x00}, {0x7f, 0x00},
+       /* 0x80*/
+       {0x52, 0x04}, {0x02, 0x04}, {0x53, 0x04}, {0x03, 0x04},
+       {0x51, 0x04}, {0x01, 0x04}, {0x54, 0x04}, {0x04, 0x04},
+       {0x55, 0x04}, {0x05, 0x04}, {0x56, 0x04}, {0x06, 0x04},
+       {0x57, 0x04}, {0x07, 0x04}, {0x58, 0x04}, {0x08, 0x04},
+       /* 0x90*/
+       {0x59, 0x04}, {0x09, 0x04}, {0x5a, 0x04}, {0x0a, 0x04},
+       {0x5b, 0x04}, {0x0b, 0x04}, {0x5c, 0x04}, {0x0c, 0x04},
+       {0x5e, 0x04}, {0x0e, 0x04}, {0x5f, 0x04}, {0x0f, 0x04},
+       {0x4e, 0x04}, {0x2e, 0x04}, {0x4a, 0x04}, {0x2a, 0x04},
+       /* 0xa0*/
+       {0x30, 0x04}, {0x10, 0x04}, {0x31, 0x04}, {0x11, 0x04},
+       {0x46, 0x04}, {0x26, 0x04}, {0x34, 0x04}, {0x14, 0x04},
+       {0x35, 0x04}, {0x15, 0x04}, {0x44, 0x04}, {0x24, 0x04},
+       {0x33, 0x04}, {0x13, 0x04}, {0xab, 0x00}, {0xbb, 0x00},
+       /* 0xb0*/
+       {0x91, 0x25}, {0x92, 0x25}, {0x93, 0x25}, {0x02, 0x25},
+       {0x24, 0x25}, {0x45, 0x04}, {0x25, 0x04}, {0x38, 0x04},
+       {0x18, 0x04}, {0x63, 0x25}, {0x51, 0x25}, {0x57, 0x25},
+       {0x5d, 0x25}, {0x39, 0x04}, {0x19, 0x04}, {0x10, 0x25},
+       /* 0xc0*/
+       {0x14, 0x25}, {0x34, 0x25}, {0x2c, 0x25}, {0x1c, 0x25},
+       {0x00, 0x25}, {0x3c, 0x25}, {0x3a, 0x04}, {0x1a, 0x04},
+       {0x5a, 0x25}, {0x54, 0x25}, {0x69, 0x25}, {0x66, 0x25},
+       {0x60, 0x25}, {0x50, 0x25}, {0x6c, 0x25}, {0xa4, 0x00},
+       /* 0xd0*/
+       {0x3b, 0x04}, {0x1b, 0x04}, {0x3c, 0x04}, {0x1c, 0x04},
+       {0x3d, 0x04}, {0x1d, 0x04}, {0x3e, 0x04}, {0x1e, 0x04},
+       {0x3f, 0x04}, {0x18, 0x25}, {0x0c, 0x25}, {0x88, 0x25},
+       {0x84, 0x25}, {0x1f, 0x04}, {0x4f, 0x04}, {0x80, 0x25},
+       /* 0xe0*/
+       {0x2f, 0x04}, {0x40, 0x04}, {0x20, 0x04}, {0x41, 0x04},
+       {0x21, 0x04}, {0x42, 0x04}, {0x22, 0x04}, {0x43, 0x04},
+       {0x23, 0x04}, {0x36, 0x04}, {0x16, 0x04}, {0x32, 0x04},
+       {0x12, 0x04}, {0x4c, 0x04}, {0x2c, 0x04}, {0x16, 0x21},
+       /* 0xf0*/
+       {0xad, 0x00}, {0x4b, 0x04}, {0x2b, 0x04}, {0x37, 0x04},
+       {0x17, 0x04}, {0x48, 0x04}, {0x28, 0x04}, {0x4d, 0x04},
+       {0x2d, 0x04}, {0x49, 0x04}, {0x29, 0x04}, {0x47, 0x04},
+       {0x27, 0x04}, {0xa7, 0x00}, {0xa0, 0x25}, {0xa0, 0x00},
+};
+
+static unsigned char page00[256] = {
+       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+       0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
+       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
+       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
+       0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+       0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */
+       0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */
+       0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */
+       0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0xff, 0x00, 0x00, 0x00, 0xcf, 0x00, 0x00, 0xfd, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0xae, 0x00, 0xf0, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0xaf, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page04[256] = {
+       0x00, 0x85, 0x81, 0x83, 0x87, 0x89, 0x8b, 0x8d, /* 0x00-0x07 */
+       0x8f, 0x91, 0x93, 0x95, 0x97, 0x00, 0x99, 0x9b, /* 0x08-0x0f */
+       0xa1, 0xa3, 0xec, 0xad, 0xa7, 0xa9, 0xea, 0xf4, /* 0x10-0x17 */
+       0xb8, 0xbe, 0xc7, 0xd1, 0xd3, 0xd5, 0xd7, 0xdd, /* 0x18-0x1f */
+       0xe2, 0xe4, 0xe6, 0xe8, 0xab, 0xb6, 0xa5, 0xfc, /* 0x20-0x27 */
+       0xf6, 0xfa, 0x9f, 0xf2, 0xee, 0xf8, 0x9d, 0xe0, /* 0x28-0x2f */
+       0xa0, 0xa2, 0xeb, 0xac, 0xa6, 0xa8, 0xe9, 0xf3, /* 0x30-0x37 */
+       0xb7, 0xbd, 0xc6, 0xd0, 0xd2, 0xd4, 0xd6, 0xd8, /* 0x38-0x3f */
+       0xe1, 0xe3, 0xe5, 0xe7, 0xaa, 0xb5, 0xa4, 0xfb, /* 0x40-0x47 */
+       0xf5, 0xf9, 0x9e, 0xf1, 0xed, 0xf7, 0x9c, 0xde, /* 0x48-0x4f */
+       0x00, 0x84, 0x80, 0x82, 0x86, 0x88, 0x8a, 0x8c, /* 0x50-0x57 */
+       0x8e, 0x90, 0x92, 0x94, 0x96, 0x00, 0x98, 0x9a, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page21[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xef, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page25[256] = {
+       0xc4, 0x00, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0xda, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0xbf, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0xd9, 0x00, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0xc2, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0xc1, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0xc5, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0xcd, 0xba, 0x00, 0x00, 0xc9, 0x00, 0x00, 0xbb, /* 0x50-0x57 */
+       0x00, 0x00, 0xc8, 0x00, 0x00, 0xbc, 0x00, 0x00, /* 0x58-0x5f */
+       0xcc, 0x00, 0x00, 0xb9, 0x00, 0x00, 0xcb, 0x00, /* 0x60-0x67 */
+       0x00, 0xca, 0x00, 0x00, 0xce, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0xdf, 0x00, 0x00, 0x00, 0xdc, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0xdb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0xb0, 0xb1, 0xb2, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char *page_uni2charset[256] = {
+       page00, NULL,   NULL,   NULL,   page04, NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   page21, NULL,   NULL,   NULL,   page25, NULL,   NULL,
+};
+
+#if 0
+static unsigned char charset2upper[256] = {
+       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+       0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
+       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
+       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
+       0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+       0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+       0x00, 0x81, 0x00, 0x83, 0x00, 0x85, 0x00, 0x87, /* 0x80-0x87 */
+       0x00, 0x89, 0x00, 0x8b, 0x00, 0x8d, 0x00, 0x8f, /* 0x88-0x8f */
+       0x00, 0x91, 0x00, 0x93, 0x00, 0x95, 0x00, 0x97, /* 0x90-0x97 */
+       0x00, 0x99, 0x00, 0x9b, 0x00, 0x9d, 0x00, 0x9f, /* 0x98-0x9f */
+       0x00, 0xa1, 0x00, 0xa3, 0x00, 0xa5, 0x00, 0xa7, /* 0xa0-0xa7 */
+       0x00, 0xa9, 0x00, 0xab, 0x00, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
+       0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0x00, 0xb6, 0x00, /* 0xb0-0xb7 */
+       0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0x00, 0xbe, 0xbf, /* 0xb8-0xbf */
+       0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0x00, 0xc7, /* 0xc0-0xc7 */
+       0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
+       0x00, 0xd1, 0x00, 0xd3, 0x00, 0xd5, 0x00, 0xd7, /* 0xd0-0xd7 */
+       0x00, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0x00, 0xdf, /* 0xd8-0xdf */
+       0xe0, 0x00, 0xe2, 0x00, 0xe4, 0x00, 0xe6, 0x00, /* 0xe0-0xe7 */
+       0xe8, 0x00, 0xea, 0x00, 0xec, 0x00, 0xee, 0xef, /* 0xe8-0xef */
+       0xf0, 0x00, 0xf2, 0x00, 0xf4, 0x00, 0xf6, 0x00, /* 0xf0-0xf7 */
+       0xf8, 0x00, 0xfa, 0x00, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
+};
+#endif
+
+static struct unls_table table = {
+       "cp855",
+       page_uni2charset,
+       charset2uni,
+       NULL
+};
+
+int
+init_unls_cp855()
+{
+       return (register_unls(&table));
+}
diff --git a/libunls/nls_cp857.c b/libunls/nls_cp857.c
new file mode 100644 (file)
index 0000000..22f6af0
--- /dev/null
@@ -0,0 +1,292 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)nls_cp857.c     1.2 05/05/01 2000 J. Schilling */
+/*
+ *     Modifications to make the code portable Copyright (c) 2000 J. Schilling
+ *
+ *     Code taken from the Linux kernel.
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/*
+ * linux/fs/nls_cp857.c
+ *
+ * Charset cp857 translation tables.
+ * Generated automatically from the Unicode and charset
+ * tables from the Unicode Organization (www.unicode.org).
+ * The Unicode to charset table has only exact mappings.
+ */
+
+#include <mconfig.h>
+#include "nls.h"
+
+static struct unls_unicode charset2uni[256] = {
+       /* 0x00*/
+       {0x00, 0x00}, {0x01, 0x00}, {0x02, 0x00}, {0x03, 0x00},
+       {0x04, 0x00}, {0x05, 0x00}, {0x06, 0x00}, {0x07, 0x00},
+       {0x08, 0x00}, {0x09, 0x00}, {0x0a, 0x00}, {0x0b, 0x00},
+       {0x0c, 0x00}, {0x0d, 0x00}, {0x0e, 0x00}, {0x0f, 0x00},
+       /* 0x10*/
+       {0x10, 0x00}, {0x11, 0x00}, {0x12, 0x00}, {0x13, 0x00},
+       {0x14, 0x00}, {0x15, 0x00}, {0x16, 0x00}, {0x17, 0x00},
+       {0x18, 0x00}, {0x19, 0x00}, {0x1a, 0x00}, {0x1b, 0x00},
+       {0x1c, 0x00}, {0x1d, 0x00}, {0x1e, 0x00}, {0x1f, 0x00},
+       /* 0x20*/
+       {0x20, 0x00}, {0x21, 0x00}, {0x22, 0x00}, {0x23, 0x00},
+       {0x24, 0x00}, {0x25, 0x00}, {0x26, 0x00}, {0x27, 0x00},
+       {0x28, 0x00}, {0x29, 0x00}, {0x2a, 0x00}, {0x2b, 0x00},
+       {0x2c, 0x00}, {0x2d, 0x00}, {0x2e, 0x00}, {0x2f, 0x00},
+       /* 0x30*/
+       {0x30, 0x00}, {0x31, 0x00}, {0x32, 0x00}, {0x33, 0x00},
+       {0x34, 0x00}, {0x35, 0x00}, {0x36, 0x00}, {0x37, 0x00},
+       {0x38, 0x00}, {0x39, 0x00}, {0x3a, 0x00}, {0x3b, 0x00},
+       {0x3c, 0x00}, {0x3d, 0x00}, {0x3e, 0x00}, {0x3f, 0x00},
+       /* 0x40*/
+       {0x40, 0x00}, {0x41, 0x00}, {0x42, 0x00}, {0x43, 0x00},
+       {0x44, 0x00}, {0x45, 0x00}, {0x46, 0x00}, {0x47, 0x00},
+       {0x48, 0x00}, {0x49, 0x00}, {0x4a, 0x00}, {0x4b, 0x00},
+       {0x4c, 0x00}, {0x4d, 0x00}, {0x4e, 0x00}, {0x4f, 0x00},
+       /* 0x50*/
+       {0x50, 0x00}, {0x51, 0x00}, {0x52, 0x00}, {0x53, 0x00},
+       {0x54, 0x00}, {0x55, 0x00}, {0x56, 0x00}, {0x57, 0x00},
+       {0x58, 0x00}, {0x59, 0x00}, {0x5a, 0x00}, {0x5b, 0x00},
+       {0x5c, 0x00}, {0x5d, 0x00}, {0x5e, 0x00}, {0x5f, 0x00},
+       /* 0x60*/
+       {0x60, 0x00}, {0x61, 0x00}, {0x62, 0x00}, {0x63, 0x00},
+       {0x64, 0x00}, {0x65, 0x00}, {0x66, 0x00}, {0x67, 0x00},
+       {0x68, 0x00}, {0x69, 0x00}, {0x6a, 0x00}, {0x6b, 0x00},
+       {0x6c, 0x00}, {0x6d, 0x00}, {0x6e, 0x00}, {0x6f, 0x00},
+       /* 0x70*/
+       {0x70, 0x00}, {0x71, 0x00}, {0x72, 0x00}, {0x73, 0x00},
+       {0x74, 0x00}, {0x75, 0x00}, {0x76, 0x00}, {0x77, 0x00},
+       {0x78, 0x00}, {0x79, 0x00}, {0x7a, 0x00}, {0x7b, 0x00},
+       {0x7c, 0x00}, {0x7d, 0x00}, {0x7e, 0x00}, {0x7f, 0x00},
+       /* 0x80*/
+       {0xc7, 0x00}, {0xfc, 0x00}, {0xe9, 0x00}, {0xe2, 0x00},
+       {0xe4, 0x00}, {0xe0, 0x00}, {0xe5, 0x00}, {0xe7, 0x00},
+       {0xea, 0x00}, {0xeb, 0x00}, {0xe8, 0x00}, {0xef, 0x00},
+       {0xee, 0x00}, {0x31, 0x01}, {0xc4, 0x00}, {0xc5, 0x00},
+       /* 0x90*/
+       {0xc9, 0x00}, {0xe6, 0x00}, {0xc6, 0x00}, {0xf4, 0x00},
+       {0xf6, 0x00}, {0xf2, 0x00}, {0xfb, 0x00}, {0xf9, 0x00},
+       {0x30, 0x01}, {0xd6, 0x00}, {0xdc, 0x00}, {0xf8, 0x00},
+       {0xa3, 0x00}, {0xd8, 0x00}, {0x5e, 0x01}, {0x5f, 0x01},
+       /* 0xa0*/
+       {0xe1, 0x00}, {0xed, 0x00}, {0xf3, 0x00}, {0xfa, 0x00},
+       {0xf1, 0x00}, {0xd1, 0x00}, {0x1e, 0x01}, {0x1f, 0x01},
+       {0xbf, 0x00}, {0xae, 0x00}, {0xac, 0x00}, {0xbd, 0x00},
+       {0xbc, 0x00}, {0xa1, 0x00}, {0xab, 0x00}, {0xbb, 0x00},
+       /* 0xb0*/
+       {0x91, 0x25}, {0x92, 0x25}, {0x93, 0x25}, {0x02, 0x25},
+       {0x24, 0x25}, {0xc1, 0x00}, {0xc2, 0x00}, {0xc0, 0x00},
+       {0xa9, 0x00}, {0x63, 0x25}, {0x51, 0x25}, {0x57, 0x25},
+       {0x5d, 0x25}, {0xa2, 0x00}, {0xa5, 0x00}, {0x10, 0x25},
+       /* 0xc0*/
+       {0x14, 0x25}, {0x34, 0x25}, {0x2c, 0x25}, {0x1c, 0x25},
+       {0x00, 0x25}, {0x3c, 0x25}, {0xe3, 0x00}, {0xc3, 0x00},
+       {0x5a, 0x25}, {0x54, 0x25}, {0x69, 0x25}, {0x66, 0x25},
+       {0x60, 0x25}, {0x50, 0x25}, {0x6c, 0x25}, {0xa4, 0x00},
+       /* 0xd0*/
+       {0xba, 0x00}, {0xaa, 0x00}, {0xca, 0x00}, {0xcb, 0x00},
+       {0xc8, 0x00}, {0x00, 0x00}, {0xcd, 0x00}, {0xce, 0x00},
+       {0xcf, 0x00}, {0x18, 0x25}, {0x0c, 0x25}, {0x88, 0x25},
+       {0x84, 0x25}, {0xa6, 0x00}, {0xcc, 0x00}, {0x80, 0x25},
+       /* 0xe0*/
+       {0xd3, 0x00}, {0xdf, 0x00}, {0xd4, 0x00}, {0xd2, 0x00},
+       {0xf5, 0x00}, {0xd5, 0x00}, {0xb5, 0x00}, {0x00, 0x00},
+       {0xd7, 0x00}, {0xda, 0x00}, {0xdb, 0x00}, {0xd9, 0x00},
+       {0xec, 0x00}, {0xff, 0x00}, {0xaf, 0x00}, {0xb4, 0x00},
+       /* 0xf0*/
+       {0xad, 0x00}, {0xb1, 0x00}, {0x00, 0x00}, {0xbe, 0x00},
+       {0xb6, 0x00}, {0xa7, 0x00}, {0xf7, 0x00}, {0xb8, 0x00},
+       {0xb0, 0x00}, {0xa8, 0x00}, {0xb7, 0x00}, {0xb9, 0x00},
+       {0xb3, 0x00}, {0xb2, 0x00}, {0xa0, 0x25}, {0xa0, 0x00},
+};
+
+static unsigned char page00[256] = {
+       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+       0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
+       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
+       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
+       0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+       0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */
+       0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */
+       0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */
+       0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0xff, 0xad, 0xbd, 0x9c, 0xcf, 0xbe, 0xdd, 0xf5, /* 0xa0-0xa7 */
+       0xf9, 0xb8, 0xd1, 0xae, 0xaa, 0xf0, 0xa9, 0xee, /* 0xa8-0xaf */
+       0xf8, 0xf1, 0xfd, 0xfc, 0xef, 0xe6, 0xf4, 0xfa, /* 0xb0-0xb7 */
+       0xf7, 0xfb, 0xd0, 0xaf, 0xac, 0xab, 0xf3, 0xa8, /* 0xb8-0xbf */
+       0xb7, 0xb5, 0xb6, 0xc7, 0x8e, 0x8f, 0x92, 0x80, /* 0xc0-0xc7 */
+       0xd4, 0x90, 0xd2, 0xd3, 0xde, 0xd6, 0xd7, 0xd8, /* 0xc8-0xcf */
+       0x00, 0xa5, 0xe3, 0xe0, 0xe2, 0xe5, 0x99, 0xe8, /* 0xd0-0xd7 */
+       0x9d, 0xeb, 0xe9, 0xea, 0x9a, 0x00, 0x00, 0xe1, /* 0xd8-0xdf */
+       0x85, 0xa0, 0x83, 0xc6, 0x84, 0x86, 0x91, 0x87, /* 0xe0-0xe7 */
+       0x8a, 0x82, 0x88, 0x89, 0xec, 0xa1, 0x8c, 0x8b, /* 0xe8-0xef */
+       0x00, 0xa4, 0x95, 0xa2, 0x93, 0xe4, 0x94, 0xf6, /* 0xf0-0xf7 */
+       0x9b, 0x97, 0xa3, 0x96, 0x81, 0x00, 0x00, 0xed, /* 0xf8-0xff */
+};
+
+static unsigned char page01[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa6, 0xa7, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x98, 0x8d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9e, 0x9f, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page25[256] = {
+       0xc4, 0x00, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0xda, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0xbf, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0xd9, 0x00, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0xc2, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0xc1, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0xc5, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0xcd, 0xba, 0x00, 0x00, 0xc9, 0x00, 0x00, 0xbb, /* 0x50-0x57 */
+       0x00, 0x00, 0xc8, 0x00, 0x00, 0xbc, 0x00, 0x00, /* 0x58-0x5f */
+       0xcc, 0x00, 0x00, 0xb9, 0x00, 0x00, 0xcb, 0x00, /* 0x60-0x67 */
+       0x00, 0xca, 0x00, 0x00, 0xce, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0xdf, 0x00, 0x00, 0x00, 0xdc, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0xdb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0xb0, 0xb1, 0xb2, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char *page_uni2charset[256] = {
+       page00, page01, NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   page25, NULL,   NULL,
+};
+
+#if 0
+static unsigned char charset2upper[256] = {
+       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+       0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
+       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
+       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
+       0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+       0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+       0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8e, 0x8f, /* 0x88-0x8f */
+       0x90, 0x91, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x98, 0x99, 0x9a, 0x00, 0x9c, 0x9d, 0x9e, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0xa5, 0xa6, 0x00, /* 0xa0-0xa7 */
+       0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
+       0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
+       0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* 0xb8-0xbf */
+       0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0x00, 0xc7, /* 0xc0-0xc7 */
+       0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
+       0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
+       0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, /* 0xd8-0xdf */
+       0xe0, 0x00, 0xe2, 0xe3, 0x00, 0xe5, 0xe6, 0xe7, /* 0xe0-0xe7 */
+       0xe8, 0xe9, 0xea, 0xeb, 0x00, 0x00, 0xee, 0xef, /* 0xe8-0xef */
+       0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
+       0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
+};
+#endif
+
+static struct unls_table table = {
+       "cp857",
+       page_uni2charset,
+       charset2uni,
+       NULL
+};
+
+int
+init_unls_cp857()
+{
+       return (register_unls(&table));
+}
diff --git a/libunls/nls_cp860.c b/libunls/nls_cp860.c
new file mode 100644 (file)
index 0000000..467ec00
--- /dev/null
@@ -0,0 +1,400 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)nls_cp860.c     1.2 05/05/01 2000 J. Schilling */
+/*
+ *     Modifications to make the code portable Copyright (c) 2000 J. Schilling
+ *
+ *     Code taken from the Linux kernel.
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/*
+ * linux/fs/nls_cp860.c
+ *
+ * Charset cp860 translation tables.
+ * Generated automatically from the Unicode and charset
+ * tables from the Unicode Organization (www.unicode.org).
+ * The Unicode to charset table has only exact mappings.
+ */
+
+#include <mconfig.h>
+#include "nls.h"
+
+static struct unls_unicode charset2uni[256] = {
+       /* 0x00*/
+       {0x00, 0x00}, {0x01, 0x00}, {0x02, 0x00}, {0x03, 0x00},
+       {0x04, 0x00}, {0x05, 0x00}, {0x06, 0x00}, {0x07, 0x00},
+       {0x08, 0x00}, {0x09, 0x00}, {0x0a, 0x00}, {0x0b, 0x00},
+       {0x0c, 0x00}, {0x0d, 0x00}, {0x0e, 0x00}, {0x0f, 0x00},
+       /* 0x10*/
+       {0x10, 0x00}, {0x11, 0x00}, {0x12, 0x00}, {0x13, 0x00},
+       {0x14, 0x00}, {0x15, 0x00}, {0x16, 0x00}, {0x17, 0x00},
+       {0x18, 0x00}, {0x19, 0x00}, {0x1a, 0x00}, {0x1b, 0x00},
+       {0x1c, 0x00}, {0x1d, 0x00}, {0x1e, 0x00}, {0x1f, 0x00},
+       /* 0x20*/
+       {0x20, 0x00}, {0x21, 0x00}, {0x22, 0x00}, {0x23, 0x00},
+       {0x24, 0x00}, {0x25, 0x00}, {0x26, 0x00}, {0x27, 0x00},
+       {0x28, 0x00}, {0x29, 0x00}, {0x2a, 0x00}, {0x2b, 0x00},
+       {0x2c, 0x00}, {0x2d, 0x00}, {0x2e, 0x00}, {0x2f, 0x00},
+       /* 0x30*/
+       {0x30, 0x00}, {0x31, 0x00}, {0x32, 0x00}, {0x33, 0x00},
+       {0x34, 0x00}, {0x35, 0x00}, {0x36, 0x00}, {0x37, 0x00},
+       {0x38, 0x00}, {0x39, 0x00}, {0x3a, 0x00}, {0x3b, 0x00},
+       {0x3c, 0x00}, {0x3d, 0x00}, {0x3e, 0x00}, {0x3f, 0x00},
+       /* 0x40*/
+       {0x40, 0x00}, {0x41, 0x00}, {0x42, 0x00}, {0x43, 0x00},
+       {0x44, 0x00}, {0x45, 0x00}, {0x46, 0x00}, {0x47, 0x00},
+       {0x48, 0x00}, {0x49, 0x00}, {0x4a, 0x00}, {0x4b, 0x00},
+       {0x4c, 0x00}, {0x4d, 0x00}, {0x4e, 0x00}, {0x4f, 0x00},
+       /* 0x50*/
+       {0x50, 0x00}, {0x51, 0x00}, {0x52, 0x00}, {0x53, 0x00},
+       {0x54, 0x00}, {0x55, 0x00}, {0x56, 0x00}, {0x57, 0x00},
+       {0x58, 0x00}, {0x59, 0x00}, {0x5a, 0x00}, {0x5b, 0x00},
+       {0x5c, 0x00}, {0x5d, 0x00}, {0x5e, 0x00}, {0x5f, 0x00},
+       /* 0x60*/
+       {0x60, 0x00}, {0x61, 0x00}, {0x62, 0x00}, {0x63, 0x00},
+       {0x64, 0x00}, {0x65, 0x00}, {0x66, 0x00}, {0x67, 0x00},
+       {0x68, 0x00}, {0x69, 0x00}, {0x6a, 0x00}, {0x6b, 0x00},
+       {0x6c, 0x00}, {0x6d, 0x00}, {0x6e, 0x00}, {0x6f, 0x00},
+       /* 0x70*/
+       {0x70, 0x00}, {0x71, 0x00}, {0x72, 0x00}, {0x73, 0x00},
+       {0x74, 0x00}, {0x75, 0x00}, {0x76, 0x00}, {0x77, 0x00},
+       {0x78, 0x00}, {0x79, 0x00}, {0x7a, 0x00}, {0x7b, 0x00},
+       {0x7c, 0x00}, {0x7d, 0x00}, {0x7e, 0x00}, {0x7f, 0x00},
+       /* 0x80*/
+       {0xc7, 0x00}, {0xfc, 0x00}, {0xe9, 0x00}, {0xe2, 0x00},
+       {0xe3, 0x00}, {0xe0, 0x00}, {0xc1, 0x00}, {0xe7, 0x00},
+       {0xea, 0x00}, {0xca, 0x00}, {0xe8, 0x00}, {0xcd, 0x00},
+       {0xd4, 0x00}, {0xec, 0x00}, {0xc3, 0x00}, {0xc2, 0x00},
+       /* 0x90*/
+       {0xc9, 0x00}, {0xc0, 0x00}, {0xc8, 0x00}, {0xf4, 0x00},
+       {0xf5, 0x00}, {0xf2, 0x00}, {0xda, 0x00}, {0xf9, 0x00},
+       {0xcc, 0x00}, {0xd5, 0x00}, {0xdc, 0x00}, {0xa2, 0x00},
+       {0xa3, 0x00}, {0xd9, 0x00}, {0xa7, 0x20}, {0xd3, 0x00},
+       /* 0xa0*/
+       {0xe1, 0x00}, {0xed, 0x00}, {0xf3, 0x00}, {0xfa, 0x00},
+       {0xf1, 0x00}, {0xd1, 0x00}, {0xaa, 0x00}, {0xba, 0x00},
+       {0xbf, 0x00}, {0xd2, 0x00}, {0xac, 0x00}, {0xbd, 0x00},
+       {0xbc, 0x00}, {0xa1, 0x00}, {0xab, 0x00}, {0xbb, 0x00},
+       /* 0xb0*/
+       {0x91, 0x25}, {0x92, 0x25}, {0x93, 0x25}, {0x02, 0x25},
+       {0x24, 0x25}, {0x61, 0x25}, {0x62, 0x25}, {0x56, 0x25},
+       {0x55, 0x25}, {0x63, 0x25}, {0x51, 0x25}, {0x57, 0x25},
+       {0x5d, 0x25}, {0x5c, 0x25}, {0x5b, 0x25}, {0x10, 0x25},
+       /* 0xc0*/
+       {0x14, 0x25}, {0x34, 0x25}, {0x2c, 0x25}, {0x1c, 0x25},
+       {0x00, 0x25}, {0x3c, 0x25}, {0x5e, 0x25}, {0x5f, 0x25},
+       {0x5a, 0x25}, {0x54, 0x25}, {0x69, 0x25}, {0x66, 0x25},
+       {0x60, 0x25}, {0x50, 0x25}, {0x6c, 0x25}, {0x67, 0x25},
+       /* 0xd0*/
+       {0x68, 0x25}, {0x64, 0x25}, {0x65, 0x25}, {0x59, 0x25},
+       {0x58, 0x25}, {0x52, 0x25}, {0x53, 0x25}, {0x6b, 0x25},
+       {0x6a, 0x25}, {0x18, 0x25}, {0x0c, 0x25}, {0x88, 0x25},
+       {0x84, 0x25}, {0x8c, 0x25}, {0x90, 0x25}, {0x80, 0x25},
+       /* 0xe0*/
+       {0xb1, 0x03}, {0xdf, 0x00}, {0x93, 0x03}, {0xc0, 0x03},
+       {0xa3, 0x03}, {0xc3, 0x03}, {0xb5, 0x00}, {0xc4, 0x03},
+       {0xa6, 0x03}, {0x98, 0x03}, {0xa9, 0x03}, {0xb4, 0x03},
+       {0x1e, 0x22}, {0xc6, 0x03}, {0xb5, 0x03}, {0x29, 0x22},
+       /* 0xf0*/
+       {0x61, 0x22}, {0xb1, 0x00}, {0x65, 0x22}, {0x64, 0x22},
+       {0x20, 0x23}, {0x21, 0x23}, {0xf7, 0x00}, {0x48, 0x22},
+       {0xb0, 0x00}, {0x19, 0x22}, {0xb7, 0x00}, {0x1a, 0x22},
+       {0x7f, 0x20}, {0xb2, 0x00}, {0xa0, 0x25}, {0xa0, 0x00},
+};
+
+static unsigned char page00[256] = {
+       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+       0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
+       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
+       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
+       0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+       0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */
+       0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */
+       0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */
+       0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0xff, 0xad, 0x9b, 0x9c, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0xa6, 0xae, 0xaa, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0xf8, 0xf1, 0xfd, 0x00, 0x00, 0xe6, 0x00, 0xfa, /* 0xb0-0xb7 */
+       0x00, 0x00, 0xa7, 0xaf, 0xac, 0xab, 0x00, 0xa8, /* 0xb8-0xbf */
+       0x91, 0x86, 0x8f, 0x8e, 0x00, 0x00, 0x00, 0x80, /* 0xc0-0xc7 */
+       0x92, 0x90, 0x89, 0x00, 0x98, 0x8b, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0xa5, 0xa9, 0x9f, 0x8c, 0x99, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x9d, 0x96, 0x00, 0x9a, 0x00, 0x00, 0xe1, /* 0xd8-0xdf */
+       0x85, 0xa0, 0x83, 0x84, 0x00, 0x00, 0x00, 0x87, /* 0xe0-0xe7 */
+       0x8a, 0x82, 0x88, 0x00, 0x8d, 0xa1, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0xa4, 0x95, 0xa2, 0x93, 0x94, 0x00, 0xf6, /* 0xf0-0xf7 */
+       0x00, 0x97, 0xa3, 0x00, 0x81, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page03[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0xe9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0xe4, 0x00, 0x00, 0xe8, 0x00, /* 0xa0-0xa7 */
+       0x00, 0xea, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0xe0, 0x00, 0x00, 0xeb, 0xee, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0xe3, 0x00, 0x00, 0xe5, 0xe7, 0x00, 0xed, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page20[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9e, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page22[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0xf9, 0xfb, 0x00, 0x00, 0x00, 0xec, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0xf0, 0x00, 0x00, 0xf3, 0xf2, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page23[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0xf4, 0xf5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page25[256] = {
+       0xc4, 0x00, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0xda, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0xbf, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0xd9, 0x00, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0xc2, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0xc1, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0xc5, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0xcd, 0xba, 0xd5, 0xd6, 0xc9, 0xb8, 0xb7, 0xbb, /* 0x50-0x57 */
+       0xd4, 0xd3, 0xc8, 0xbe, 0xbd, 0xbc, 0xc6, 0xc7, /* 0x58-0x5f */
+       0xcc, 0xb5, 0xb6, 0xb9, 0xd1, 0xd2, 0xcb, 0xcf, /* 0x60-0x67 */
+       0xd0, 0xca, 0xd8, 0xd7, 0xce, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0xdf, 0x00, 0x00, 0x00, 0xdc, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0xdb, 0x00, 0x00, 0x00, 0xdd, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0xde, 0xb0, 0xb1, 0xb2, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char *page_uni2charset[256] = {
+       page00, NULL,   NULL,   page03, NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       page20, NULL,   page22, page23, NULL,   page25, NULL,   NULL,
+};
+
+#if 0
+static unsigned char charset2upper[256] = {
+       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+       0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
+       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
+       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
+       0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+       0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+       0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0x00, /* 0x80-0x87 */
+       0x00, 0x89, 0x00, 0x8b, 0x8c, 0x00, 0x8e, 0x8f, /* 0x88-0x8f */
+       0x90, 0x91, 0x92, 0x00, 0x00, 0x00, 0x96, 0x00, /* 0x90-0x97 */
+       0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0xa5, 0xa6, 0xa7, /* 0xa0-0xa7 */
+       0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
+       0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
+       0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* 0xb8-0xbf */
+       0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xc0-0xc7 */
+       0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
+       0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
+       0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, /* 0xd8-0xdf */
+       0x00, 0x00, 0xe2, 0x00, 0xe4, 0x00, 0xe6, 0x00, /* 0xe0-0xe7 */
+       0xe8, 0xe9, 0xea, 0x00, 0xec, 0x00, 0x00, 0xef, /* 0xe8-0xef */
+       0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
+       0xf8, 0xf9, 0xfa, 0xfb, 0x00, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
+};
+#endif
+
+static struct unls_table table = {
+       "cp860",
+       page_uni2charset,
+       charset2uni,
+       NULL
+};
+
+int
+init_unls_cp860()
+{
+       return (register_unls(&table));
+}
diff --git a/libunls/nls_cp861.c b/libunls/nls_cp861.c
new file mode 100644 (file)
index 0000000..74bc73c
--- /dev/null
@@ -0,0 +1,436 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)nls_cp861.c     1.2 05/05/01 2000 J. Schilling */
+/*
+ *     Modifications to make the code portable Copyright (c) 2000 J. Schilling
+ *
+ *     Code taken from the Linux kernel.
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/*
+ * linux/fs/nls_cp861.c
+ *
+ * Charset cp861 translation tables.
+ * Generated automatically from the Unicode and charset
+ * tables from the Unicode Organization (www.unicode.org).
+ * The Unicode to charset table has only exact mappings.
+ */
+
+#include <mconfig.h>
+#include "nls.h"
+
+static struct unls_unicode charset2uni[256] = {
+       /* 0x00*/
+       {0x00, 0x00}, {0x01, 0x00}, {0x02, 0x00}, {0x03, 0x00},
+       {0x04, 0x00}, {0x05, 0x00}, {0x06, 0x00}, {0x07, 0x00},
+       {0x08, 0x00}, {0x09, 0x00}, {0x0a, 0x00}, {0x0b, 0x00},
+       {0x0c, 0x00}, {0x0d, 0x00}, {0x0e, 0x00}, {0x0f, 0x00},
+       /* 0x10*/
+       {0x10, 0x00}, {0x11, 0x00}, {0x12, 0x00}, {0x13, 0x00},
+       {0x14, 0x00}, {0x15, 0x00}, {0x16, 0x00}, {0x17, 0x00},
+       {0x18, 0x00}, {0x19, 0x00}, {0x1a, 0x00}, {0x1b, 0x00},
+       {0x1c, 0x00}, {0x1d, 0x00}, {0x1e, 0x00}, {0x1f, 0x00},
+       /* 0x20*/
+       {0x20, 0x00}, {0x21, 0x00}, {0x22, 0x00}, {0x23, 0x00},
+       {0x24, 0x00}, {0x25, 0x00}, {0x26, 0x00}, {0x27, 0x00},
+       {0x28, 0x00}, {0x29, 0x00}, {0x2a, 0x00}, {0x2b, 0x00},
+       {0x2c, 0x00}, {0x2d, 0x00}, {0x2e, 0x00}, {0x2f, 0x00},
+       /* 0x30*/
+       {0x30, 0x00}, {0x31, 0x00}, {0x32, 0x00}, {0x33, 0x00},
+       {0x34, 0x00}, {0x35, 0x00}, {0x36, 0x00}, {0x37, 0x00},
+       {0x38, 0x00}, {0x39, 0x00}, {0x3a, 0x00}, {0x3b, 0x00},
+       {0x3c, 0x00}, {0x3d, 0x00}, {0x3e, 0x00}, {0x3f, 0x00},
+       /* 0x40*/
+       {0x40, 0x00}, {0x41, 0x00}, {0x42, 0x00}, {0x43, 0x00},
+       {0x44, 0x00}, {0x45, 0x00}, {0x46, 0x00}, {0x47, 0x00},
+       {0x48, 0x00}, {0x49, 0x00}, {0x4a, 0x00}, {0x4b, 0x00},
+       {0x4c, 0x00}, {0x4d, 0x00}, {0x4e, 0x00}, {0x4f, 0x00},
+       /* 0x50*/
+       {0x50, 0x00}, {0x51, 0x00}, {0x52, 0x00}, {0x53, 0x00},
+       {0x54, 0x00}, {0x55, 0x00}, {0x56, 0x00}, {0x57, 0x00},
+       {0x58, 0x00}, {0x59, 0x00}, {0x5a, 0x00}, {0x5b, 0x00},
+       {0x5c, 0x00}, {0x5d, 0x00}, {0x5e, 0x00}, {0x5f, 0x00},
+       /* 0x60*/
+       {0x60, 0x00}, {0x61, 0x00}, {0x62, 0x00}, {0x63, 0x00},
+       {0x64, 0x00}, {0x65, 0x00}, {0x66, 0x00}, {0x67, 0x00},
+       {0x68, 0x00}, {0x69, 0x00}, {0x6a, 0x00}, {0x6b, 0x00},
+       {0x6c, 0x00}, {0x6d, 0x00}, {0x6e, 0x00}, {0x6f, 0x00},
+       /* 0x70*/
+       {0x70, 0x00}, {0x71, 0x00}, {0x72, 0x00}, {0x73, 0x00},
+       {0x74, 0x00}, {0x75, 0x00}, {0x76, 0x00}, {0x77, 0x00},
+       {0x78, 0x00}, {0x79, 0x00}, {0x7a, 0x00}, {0x7b, 0x00},
+       {0x7c, 0x00}, {0x7d, 0x00}, {0x7e, 0x00}, {0x7f, 0x00},
+       /* 0x80*/
+       {0xc7, 0x00}, {0xfc, 0x00}, {0xe9, 0x00}, {0xe2, 0x00},
+       {0xe4, 0x00}, {0xe0, 0x00}, {0xe5, 0x00}, {0xe7, 0x00},
+       {0xea, 0x00}, {0xeb, 0x00}, {0xe8, 0x00}, {0xd0, 0x00},
+       {0xf0, 0x00}, {0xde, 0x00}, {0xc4, 0x00}, {0xc5, 0x00},
+       /* 0x90*/
+       {0xc9, 0x00}, {0xe6, 0x00}, {0xc6, 0x00}, {0xf4, 0x00},
+       {0xf6, 0x00}, {0xfe, 0x00}, {0xfb, 0x00}, {0xdd, 0x00},
+       {0xfd, 0x00}, {0xd6, 0x00}, {0xdc, 0x00}, {0xf8, 0x00},
+       {0xa3, 0x00}, {0xd8, 0x00}, {0xa7, 0x20}, {0x92, 0x01},
+       /* 0xa0*/
+       {0xe1, 0x00}, {0xed, 0x00}, {0xf3, 0x00}, {0xfa, 0x00},
+       {0xc1, 0x00}, {0xcd, 0x00}, {0xd3, 0x00}, {0xda, 0x00},
+       {0xbf, 0x00}, {0x10, 0x23}, {0xac, 0x00}, {0xbd, 0x00},
+       {0xbc, 0x00}, {0xa1, 0x00}, {0xab, 0x00}, {0xbb, 0x00},
+       /* 0xb0*/
+       {0x91, 0x25}, {0x92, 0x25}, {0x93, 0x25}, {0x02, 0x25},
+       {0x24, 0x25}, {0x61, 0x25}, {0x62, 0x25}, {0x56, 0x25},
+       {0x55, 0x25}, {0x63, 0x25}, {0x51, 0x25}, {0x57, 0x25},
+       {0x5d, 0x25}, {0x5c, 0x25}, {0x5b, 0x25}, {0x10, 0x25},
+       /* 0xc0*/
+       {0x14, 0x25}, {0x34, 0x25}, {0x2c, 0x25}, {0x1c, 0x25},
+       {0x00, 0x25}, {0x3c, 0x25}, {0x5e, 0x25}, {0x5f, 0x25},
+       {0x5a, 0x25}, {0x54, 0x25}, {0x69, 0x25}, {0x66, 0x25},
+       {0x60, 0x25}, {0x50, 0x25}, {0x6c, 0x25}, {0x67, 0x25},
+       /* 0xd0*/
+       {0x68, 0x25}, {0x64, 0x25}, {0x65, 0x25}, {0x59, 0x25},
+       {0x58, 0x25}, {0x52, 0x25}, {0x53, 0x25}, {0x6b, 0x25},
+       {0x6a, 0x25}, {0x18, 0x25}, {0x0c, 0x25}, {0x88, 0x25},
+       {0x84, 0x25}, {0x8c, 0x25}, {0x90, 0x25}, {0x80, 0x25},
+       /* 0xe0*/
+       {0xb1, 0x03}, {0xdf, 0x00}, {0x93, 0x03}, {0xc0, 0x03},
+       {0xa3, 0x03}, {0xc3, 0x03}, {0xb5, 0x00}, {0xc4, 0x03},
+       {0xa6, 0x03}, {0x98, 0x03}, {0xa9, 0x03}, {0xb4, 0x03},
+       {0x1e, 0x22}, {0xc6, 0x03}, {0xb5, 0x03}, {0x29, 0x22},
+       /* 0xf0*/
+       {0x61, 0x22}, {0xb1, 0x00}, {0x65, 0x22}, {0x64, 0x22},
+       {0x20, 0x23}, {0x21, 0x23}, {0xf7, 0x00}, {0x48, 0x22},
+       {0xb0, 0x00}, {0x19, 0x22}, {0xb7, 0x00}, {0x1a, 0x22},
+       {0x7f, 0x20}, {0xb2, 0x00}, {0xa0, 0x25}, {0xa0, 0x00},
+};
+
+static unsigned char page00[256] = {
+       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+       0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
+       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
+       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
+       0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+       0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */
+       0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */
+       0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */
+       0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0xff, 0xad, 0x00, 0x9c, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0xae, 0xaa, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0xf8, 0xf1, 0xfd, 0x00, 0x00, 0xe6, 0x00, 0xfa, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0xaf, 0xac, 0xab, 0x00, 0xa8, /* 0xb8-0xbf */
+       0x00, 0xa4, 0x00, 0x00, 0x8e, 0x8f, 0x92, 0x80, /* 0xc0-0xc7 */
+       0x00, 0x90, 0x00, 0x00, 0x00, 0xa5, 0x00, 0x00, /* 0xc8-0xcf */
+       0x8b, 0x00, 0x00, 0xa6, 0x00, 0x00, 0x99, 0x00, /* 0xd0-0xd7 */
+       0x9d, 0x00, 0xa7, 0x00, 0x9a, 0x97, 0x8d, 0xe1, /* 0xd8-0xdf */
+       0x85, 0xa0, 0x83, 0x00, 0x84, 0x86, 0x91, 0x87, /* 0xe0-0xe7 */
+       0x8a, 0x82, 0x88, 0x89, 0x00, 0xa1, 0x00, 0x00, /* 0xe8-0xef */
+       0x8c, 0x00, 0x00, 0xa2, 0x93, 0x00, 0x94, 0xf6, /* 0xf0-0xf7 */
+       0x9b, 0x00, 0xa3, 0x96, 0x81, 0x98, 0x95, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page01[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x9f, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page03[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0xe9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0xe4, 0x00, 0x00, 0xe8, 0x00, /* 0xa0-0xa7 */
+       0x00, 0xea, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0xe0, 0x00, 0x00, 0xeb, 0xee, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0xe3, 0x00, 0x00, 0xe5, 0xe7, 0x00, 0xed, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page20[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9e, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page22[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0xf9, 0xfb, 0x00, 0x00, 0x00, 0xec, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0xf0, 0x00, 0x00, 0xf3, 0xf2, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page23[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0xa9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0xf4, 0xf5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page25[256] = {
+       0xc4, 0x00, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0xda, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0xbf, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0xd9, 0x00, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0xc2, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0xc1, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0xc5, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0xcd, 0xba, 0xd5, 0xd6, 0xc9, 0xb8, 0xb7, 0xbb, /* 0x50-0x57 */
+       0xd4, 0xd3, 0xc8, 0xbe, 0xbd, 0xbc, 0xc6, 0xc7, /* 0x58-0x5f */
+       0xcc, 0xb5, 0xb6, 0xb9, 0xd1, 0xd2, 0xcb, 0xcf, /* 0x60-0x67 */
+       0xd0, 0xca, 0xd8, 0xd7, 0xce, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0xdf, 0x00, 0x00, 0x00, 0xdc, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0xdb, 0x00, 0x00, 0x00, 0xdd, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0xde, 0xb0, 0xb1, 0xb2, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char *page_uni2charset[256] = {
+       page00, page01, NULL,   page03, NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       page20, NULL,   page22, page23, NULL,   page25, NULL,   NULL,
+};
+
+#if 0
+static unsigned char charset2upper[256] = {
+       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+       0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
+       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
+       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
+       0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+       0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+       0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x8b, 0x00, 0x8d, 0x8e, 0x8f, /* 0x88-0x8f */
+       0x90, 0x91, 0x92, 0x00, 0x00, 0x00, 0x00, 0x97, /* 0x90-0x97 */
+       0x00, 0x99, 0x9a, 0x00, 0x9c, 0x9d, 0x9e, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0xa4, 0xa5, 0xa6, 0xa7, /* 0xa0-0xa7 */
+       0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
+       0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
+       0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* 0xb8-0xbf */
+       0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xc0-0xc7 */
+       0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
+       0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
+       0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, /* 0xd8-0xdf */
+       0x00, 0x00, 0xe2, 0x00, 0xe4, 0x00, 0xe6, 0x00, /* 0xe0-0xe7 */
+       0xe8, 0xe9, 0xea, 0x00, 0xec, 0x00, 0x00, 0xef, /* 0xe8-0xef */
+       0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
+       0xf8, 0xf9, 0xfa, 0xfb, 0x00, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
+};
+#endif
+
+static struct unls_table table = {
+       "cp861",
+       page_uni2charset,
+       charset2uni,
+       NULL
+};
+
+int
+init_unls_cp861()
+{
+       return (register_unls(&table));
+}
diff --git a/libunls/nls_cp862.c b/libunls/nls_cp862.c
new file mode 100644 (file)
index 0000000..b174b5b
--- /dev/null
@@ -0,0 +1,472 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)nls_cp862.c     1.2 05/05/01 2000 J. Schilling */
+/*
+ *     Modifications to make the code portable Copyright (c) 2000 J. Schilling
+ *
+ *     Code taken from the Linux kernel.
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/*
+ * linux/fs/nls_cp862.c
+ *
+ * Charset cp862 translation tables.
+ * Generated automatically from the Unicode and charset
+ * tables from the Unicode Organization (www.unicode.org).
+ * The Unicode to charset table has only exact mappings.
+ */
+
+#include <mconfig.h>
+#include "nls.h"
+
+static struct unls_unicode charset2uni[256] = {
+       /* 0x00*/
+       {0x00, 0x00}, {0x01, 0x00}, {0x02, 0x00}, {0x03, 0x00},
+       {0x04, 0x00}, {0x05, 0x00}, {0x06, 0x00}, {0x07, 0x00},
+       {0x08, 0x00}, {0x09, 0x00}, {0x0a, 0x00}, {0x0b, 0x00},
+       {0x0c, 0x00}, {0x0d, 0x00}, {0x0e, 0x00}, {0x0f, 0x00},
+       /* 0x10*/
+       {0x10, 0x00}, {0x11, 0x00}, {0x12, 0x00}, {0x13, 0x00},
+       {0x14, 0x00}, {0x15, 0x00}, {0x16, 0x00}, {0x17, 0x00},
+       {0x18, 0x00}, {0x19, 0x00}, {0x1a, 0x00}, {0x1b, 0x00},
+       {0x1c, 0x00}, {0x1d, 0x00}, {0x1e, 0x00}, {0x1f, 0x00},
+       /* 0x20*/
+       {0x20, 0x00}, {0x21, 0x00}, {0x22, 0x00}, {0x23, 0x00},
+       {0x24, 0x00}, {0x25, 0x00}, {0x26, 0x00}, {0x27, 0x00},
+       {0x28, 0x00}, {0x29, 0x00}, {0x2a, 0x00}, {0x2b, 0x00},
+       {0x2c, 0x00}, {0x2d, 0x00}, {0x2e, 0x00}, {0x2f, 0x00},
+       /* 0x30*/
+       {0x30, 0x00}, {0x31, 0x00}, {0x32, 0x00}, {0x33, 0x00},
+       {0x34, 0x00}, {0x35, 0x00}, {0x36, 0x00}, {0x37, 0x00},
+       {0x38, 0x00}, {0x39, 0x00}, {0x3a, 0x00}, {0x3b, 0x00},
+       {0x3c, 0x00}, {0x3d, 0x00}, {0x3e, 0x00}, {0x3f, 0x00},
+       /* 0x40*/
+       {0x40, 0x00}, {0x41, 0x00}, {0x42, 0x00}, {0x43, 0x00},
+       {0x44, 0x00}, {0x45, 0x00}, {0x46, 0x00}, {0x47, 0x00},
+       {0x48, 0x00}, {0x49, 0x00}, {0x4a, 0x00}, {0x4b, 0x00},
+       {0x4c, 0x00}, {0x4d, 0x00}, {0x4e, 0x00}, {0x4f, 0x00},
+       /* 0x50*/
+       {0x50, 0x00}, {0x51, 0x00}, {0x52, 0x00}, {0x53, 0x00},
+       {0x54, 0x00}, {0x55, 0x00}, {0x56, 0x00}, {0x57, 0x00},
+       {0x58, 0x00}, {0x59, 0x00}, {0x5a, 0x00}, {0x5b, 0x00},
+       {0x5c, 0x00}, {0x5d, 0x00}, {0x5e, 0x00}, {0x5f, 0x00},
+       /* 0x60*/
+       {0x60, 0x00}, {0x61, 0x00}, {0x62, 0x00}, {0x63, 0x00},
+       {0x64, 0x00}, {0x65, 0x00}, {0x66, 0x00}, {0x67, 0x00},
+       {0x68, 0x00}, {0x69, 0x00}, {0x6a, 0x00}, {0x6b, 0x00},
+       {0x6c, 0x00}, {0x6d, 0x00}, {0x6e, 0x00}, {0x6f, 0x00},
+       /* 0x70*/
+       {0x70, 0x00}, {0x71, 0x00}, {0x72, 0x00}, {0x73, 0x00},
+       {0x74, 0x00}, {0x75, 0x00}, {0x76, 0x00}, {0x77, 0x00},
+       {0x78, 0x00}, {0x79, 0x00}, {0x7a, 0x00}, {0x7b, 0x00},
+       {0x7c, 0x00}, {0x7d, 0x00}, {0x7e, 0x00}, {0x7f, 0x00},
+       /* 0x80*/
+       {0xd0, 0x05}, {0xd1, 0x05}, {0xd2, 0x05}, {0xd3, 0x05},
+       {0xd4, 0x05}, {0xd5, 0x05}, {0xd6, 0x05}, {0xd7, 0x05},
+       {0xd8, 0x05}, {0xd9, 0x05}, {0xda, 0x05}, {0xdb, 0x05},
+       {0xdc, 0x05}, {0xdd, 0x05}, {0xde, 0x05}, {0xdf, 0x05},
+       /* 0x90*/
+       {0xe0, 0x05}, {0xe1, 0x05}, {0xe2, 0x05}, {0xe3, 0x05},
+       {0xe4, 0x05}, {0xe5, 0x05}, {0xe6, 0x05}, {0xe7, 0x05},
+       {0xe8, 0x05}, {0xe9, 0x05}, {0xea, 0x05}, {0xa2, 0x00},
+       {0xa3, 0x00}, {0xa5, 0x00}, {0xa7, 0x20}, {0x92, 0x01},
+       /* 0xa0*/
+       {0xe1, 0x00}, {0xed, 0x00}, {0xf3, 0x00}, {0xfa, 0x00},
+       {0xf1, 0x00}, {0xd1, 0x00}, {0xaa, 0x00}, {0xba, 0x00},
+       {0xbf, 0x00}, {0x10, 0x23}, {0xac, 0x00}, {0xbd, 0x00},
+       {0xbc, 0x00}, {0xa1, 0x00}, {0xab, 0x00}, {0xbb, 0x00},
+       /* 0xb0*/
+       {0x91, 0x25}, {0x92, 0x25}, {0x93, 0x25}, {0x02, 0x25},
+       {0x24, 0x25}, {0x61, 0x25}, {0x62, 0x25}, {0x56, 0x25},
+       {0x55, 0x25}, {0x63, 0x25}, {0x51, 0x25}, {0x57, 0x25},
+       {0x5d, 0x25}, {0x5c, 0x25}, {0x5b, 0x25}, {0x10, 0x25},
+       /* 0xc0*/
+       {0x14, 0x25}, {0x34, 0x25}, {0x2c, 0x25}, {0x1c, 0x25},
+       {0x00, 0x25}, {0x3c, 0x25}, {0x5e, 0x25}, {0x5f, 0x25},
+       {0x5a, 0x25}, {0x54, 0x25}, {0x69, 0x25}, {0x66, 0x25},
+       {0x60, 0x25}, {0x50, 0x25}, {0x6c, 0x25}, {0x67, 0x25},
+       /* 0xd0*/
+       {0x68, 0x25}, {0x64, 0x25}, {0x65, 0x25}, {0x59, 0x25},
+       {0x58, 0x25}, {0x52, 0x25}, {0x53, 0x25}, {0x6b, 0x25},
+       {0x6a, 0x25}, {0x18, 0x25}, {0x0c, 0x25}, {0x88, 0x25},
+       {0x84, 0x25}, {0x8c, 0x25}, {0x90, 0x25}, {0x80, 0x25},
+       /* 0xe0*/
+       {0xb1, 0x03}, {0xdf, 0x00}, {0x93, 0x03}, {0xc0, 0x03},
+       {0xa3, 0x03}, {0xc3, 0x03}, {0xb5, 0x00}, {0xc4, 0x03},
+       {0xa6, 0x03}, {0x98, 0x03}, {0xa9, 0x03}, {0xb4, 0x03},
+       {0x1e, 0x22}, {0xc6, 0x03}, {0xb5, 0x03}, {0x29, 0x22},
+       /* 0xf0*/
+       {0x61, 0x22}, {0xb1, 0x00}, {0x65, 0x22}, {0x64, 0x22},
+       {0x20, 0x23}, {0x21, 0x23}, {0xf7, 0x00}, {0x48, 0x22},
+       {0xb0, 0x00}, {0x19, 0x22}, {0xb7, 0x00}, {0x1a, 0x22},
+       {0x7f, 0x20}, {0xb2, 0x00}, {0xa0, 0x25}, {0xa0, 0x00},
+};
+
+static unsigned char page00[256] = {
+       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+       0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
+       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
+       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
+       0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+       0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */
+       0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */
+       0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */
+       0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0xff, 0xad, 0x9b, 0x9c, 0x00, 0x9d, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0xa6, 0xae, 0xaa, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0xf8, 0xf1, 0xfd, 0x00, 0x00, 0xe6, 0x00, 0xfa, /* 0xb0-0xb7 */
+       0x00, 0x00, 0xa7, 0xaf, 0xac, 0xab, 0x00, 0xa8, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0xa5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe1, /* 0xd8-0xdf */
+       0x00, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0xa1, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0xa4, 0x00, 0xa2, 0x00, 0x00, 0x00, 0xf6, /* 0xf0-0xf7 */
+       0x00, 0x00, 0xa3, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page01[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x9f, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page03[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0xe9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0xe4, 0x00, 0x00, 0xe8, 0x00, /* 0xa0-0xa7 */
+       0x00, 0xea, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0xe0, 0x00, 0x00, 0xeb, 0xee, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0xe3, 0x00, 0x00, 0xe5, 0xe7, 0x00, 0xed, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page05[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 0xd0-0xd7 */
+       0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, /* 0xd8-0xdf */
+       0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, /* 0xe0-0xe7 */
+       0x98, 0x99, 0x9a, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page20[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9e, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page22[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0xf9, 0xfb, 0x00, 0x00, 0x00, 0xec, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0xf0, 0x00, 0x00, 0xf3, 0xf2, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page23[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0xa9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0xf4, 0xf5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page25[256] = {
+       0xc4, 0x00, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0xda, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0xbf, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0xd9, 0x00, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0xc2, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0xc1, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0xc5, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0xcd, 0xba, 0xd5, 0xd6, 0xc9, 0xb8, 0xb7, 0xbb, /* 0x50-0x57 */
+       0xd4, 0xd3, 0xc8, 0xbe, 0xbd, 0xbc, 0xc6, 0xc7, /* 0x58-0x5f */
+       0xcc, 0xb5, 0xb6, 0xb9, 0xd1, 0xd2, 0xcb, 0xcf, /* 0x60-0x67 */
+       0xd0, 0xca, 0xd8, 0xd7, 0xce, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0xdf, 0x00, 0x00, 0x00, 0xdc, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0xdb, 0x00, 0x00, 0x00, 0xdd, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0xde, 0xb0, 0xb1, 0xb2, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char *page_uni2charset[256] = {
+       page00, page01, NULL,   page03, NULL,   page05, NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       page20, NULL,   page22, page23, NULL,   page25, NULL,   NULL,
+};
+
+#if 0
+static unsigned char charset2upper[256] = {
+       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+       0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
+       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
+       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
+       0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+       0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+       0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 0x80-0x87 */
+       0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, /* 0x88-0x8f */
+       0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, /* 0x90-0x97 */
+       0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0xa5, 0xa6, 0xa7, /* 0xa0-0xa7 */
+       0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
+       0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
+       0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* 0xb8-0xbf */
+       0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xc0-0xc7 */
+       0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
+       0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
+       0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, /* 0xd8-0xdf */
+       0x00, 0x00, 0xe2, 0x00, 0xe4, 0x00, 0xe6, 0x00, /* 0xe0-0xe7 */
+       0xe8, 0xe9, 0xea, 0x00, 0xec, 0x00, 0x00, 0xef, /* 0xe8-0xef */
+       0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
+       0xf8, 0xf9, 0xfa, 0xfb, 0x00, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
+};
+#endif
+
+static struct unls_table table = {
+       "cp862",
+       page_uni2charset,
+       charset2uni,
+       NULL
+};
+
+int
+init_unls_cp862()
+{
+       return (register_unls(&table));
+}
diff --git a/libunls/nls_cp863.c b/libunls/nls_cp863.c
new file mode 100644 (file)
index 0000000..da88111
--- /dev/null
@@ -0,0 +1,436 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)nls_cp863.c     1.2 05/05/01 2000 J. Schilling */
+/*
+ *     Modifications to make the code portable Copyright (c) 2000 J. Schilling
+ *
+ *     Code taken from the Linux kernel.
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/*
+ * linux/fs/nls_cp863.c
+ *
+ * Charset cp863 translation tables.
+ * Generated automatically from the Unicode and charset
+ * tables from the Unicode Organization (www.unicode.org).
+ * The Unicode to charset table has only exact mappings.
+ */
+
+#include <mconfig.h>
+#include "nls.h"
+
+static struct unls_unicode charset2uni[256] = {
+       /* 0x00*/
+       {0x00, 0x00}, {0x01, 0x00}, {0x02, 0x00}, {0x03, 0x00},
+       {0x04, 0x00}, {0x05, 0x00}, {0x06, 0x00}, {0x07, 0x00},
+       {0x08, 0x00}, {0x09, 0x00}, {0x0a, 0x00}, {0x0b, 0x00},
+       {0x0c, 0x00}, {0x0d, 0x00}, {0x0e, 0x00}, {0x0f, 0x00},
+       /* 0x10*/
+       {0x10, 0x00}, {0x11, 0x00}, {0x12, 0x00}, {0x13, 0x00},
+       {0x14, 0x00}, {0x15, 0x00}, {0x16, 0x00}, {0x17, 0x00},
+       {0x18, 0x00}, {0x19, 0x00}, {0x1a, 0x00}, {0x1b, 0x00},
+       {0x1c, 0x00}, {0x1d, 0x00}, {0x1e, 0x00}, {0x1f, 0x00},
+       /* 0x20*/
+       {0x20, 0x00}, {0x21, 0x00}, {0x22, 0x00}, {0x23, 0x00},
+       {0x24, 0x00}, {0x25, 0x00}, {0x26, 0x00}, {0x27, 0x00},
+       {0x28, 0x00}, {0x29, 0x00}, {0x2a, 0x00}, {0x2b, 0x00},
+       {0x2c, 0x00}, {0x2d, 0x00}, {0x2e, 0x00}, {0x2f, 0x00},
+       /* 0x30*/
+       {0x30, 0x00}, {0x31, 0x00}, {0x32, 0x00}, {0x33, 0x00},
+       {0x34, 0x00}, {0x35, 0x00}, {0x36, 0x00}, {0x37, 0x00},
+       {0x38, 0x00}, {0x39, 0x00}, {0x3a, 0x00}, {0x3b, 0x00},
+       {0x3c, 0x00}, {0x3d, 0x00}, {0x3e, 0x00}, {0x3f, 0x00},
+       /* 0x40*/
+       {0x40, 0x00}, {0x41, 0x00}, {0x42, 0x00}, {0x43, 0x00},
+       {0x44, 0x00}, {0x45, 0x00}, {0x46, 0x00}, {0x47, 0x00},
+       {0x48, 0x00}, {0x49, 0x00}, {0x4a, 0x00}, {0x4b, 0x00},
+       {0x4c, 0x00}, {0x4d, 0x00}, {0x4e, 0x00}, {0x4f, 0x00},
+       /* 0x50*/
+       {0x50, 0x00}, {0x51, 0x00}, {0x52, 0x00}, {0x53, 0x00},
+       {0x54, 0x00}, {0x55, 0x00}, {0x56, 0x00}, {0x57, 0x00},
+       {0x58, 0x00}, {0x59, 0x00}, {0x5a, 0x00}, {0x5b, 0x00},
+       {0x5c, 0x00}, {0x5d, 0x00}, {0x5e, 0x00}, {0x5f, 0x00},
+       /* 0x60*/
+       {0x60, 0x00}, {0x61, 0x00}, {0x62, 0x00}, {0x63, 0x00},
+       {0x64, 0x00}, {0x65, 0x00}, {0x66, 0x00}, {0x67, 0x00},
+       {0x68, 0x00}, {0x69, 0x00}, {0x6a, 0x00}, {0x6b, 0x00},
+       {0x6c, 0x00}, {0x6d, 0x00}, {0x6e, 0x00}, {0x6f, 0x00},
+       /* 0x70*/
+       {0x70, 0x00}, {0x71, 0x00}, {0x72, 0x00}, {0x73, 0x00},
+       {0x74, 0x00}, {0x75, 0x00}, {0x76, 0x00}, {0x77, 0x00},
+       {0x78, 0x00}, {0x79, 0x00}, {0x7a, 0x00}, {0x7b, 0x00},
+       {0x7c, 0x00}, {0x7d, 0x00}, {0x7e, 0x00}, {0x7f, 0x00},
+       /* 0x80*/
+       {0xc7, 0x00}, {0xfc, 0x00}, {0xe9, 0x00}, {0xe2, 0x00},
+       {0xc2, 0x00}, {0xe0, 0x00}, {0xb6, 0x00}, {0xe7, 0x00},
+       {0xea, 0x00}, {0xeb, 0x00}, {0xe8, 0x00}, {0xef, 0x00},
+       {0xee, 0x00}, {0x17, 0x20}, {0xc0, 0x00}, {0xa7, 0x00},
+       /* 0x90*/
+       {0xc9, 0x00}, {0xc8, 0x00}, {0xca, 0x00}, {0xf4, 0x00},
+       {0xcb, 0x00}, {0xcf, 0x00}, {0xfb, 0x00}, {0xf9, 0x00},
+       {0xa4, 0x00}, {0xd4, 0x00}, {0xdc, 0x00}, {0xa2, 0x00},
+       {0xa3, 0x00}, {0xd9, 0x00}, {0xdb, 0x00}, {0x92, 0x01},
+       /* 0xa0*/
+       {0xa6, 0x00}, {0xb4, 0x00}, {0xf3, 0x00}, {0xfa, 0x00},
+       {0xa8, 0x00}, {0xb8, 0x00}, {0xb3, 0x00}, {0xaf, 0x00},
+       {0xce, 0x00}, {0x10, 0x23}, {0xac, 0x00}, {0xbd, 0x00},
+       {0xbc, 0x00}, {0xbe, 0x00}, {0xab, 0x00}, {0xbb, 0x00},
+       /* 0xb0*/
+       {0x91, 0x25}, {0x92, 0x25}, {0x93, 0x25}, {0x02, 0x25},
+       {0x24, 0x25}, {0x61, 0x25}, {0x62, 0x25}, {0x56, 0x25},
+       {0x55, 0x25}, {0x63, 0x25}, {0x51, 0x25}, {0x57, 0x25},
+       {0x5d, 0x25}, {0x5c, 0x25}, {0x5b, 0x25}, {0x10, 0x25},
+       /* 0xc0*/
+       {0x14, 0x25}, {0x34, 0x25}, {0x2c, 0x25}, {0x1c, 0x25},
+       {0x00, 0x25}, {0x3c, 0x25}, {0x5e, 0x25}, {0x5f, 0x25},
+       {0x5a, 0x25}, {0x54, 0x25}, {0x69, 0x25}, {0x66, 0x25},
+       {0x60, 0x25}, {0x50, 0x25}, {0x6c, 0x25}, {0x67, 0x25},
+       /* 0xd0*/
+       {0x68, 0x25}, {0x64, 0x25}, {0x65, 0x25}, {0x59, 0x25},
+       {0x58, 0x25}, {0x52, 0x25}, {0x53, 0x25}, {0x6b, 0x25},
+       {0x6a, 0x25}, {0x18, 0x25}, {0x0c, 0x25}, {0x88, 0x25},
+       {0x84, 0x25}, {0x8c, 0x25}, {0x90, 0x25}, {0x80, 0x25},
+       /* 0xe0*/
+       {0xb1, 0x03}, {0xdf, 0x00}, {0x93, 0x03}, {0xc0, 0x03},
+       {0xa3, 0x03}, {0xc3, 0x03}, {0xb5, 0x00}, {0xc4, 0x03},
+       {0xa6, 0x03}, {0x98, 0x03}, {0xa9, 0x03}, {0xb4, 0x03},
+       {0x1e, 0x22}, {0xc6, 0x03}, {0xb5, 0x03}, {0x29, 0x22},
+       /* 0xf0*/
+       {0x61, 0x22}, {0xb1, 0x00}, {0x65, 0x22}, {0x64, 0x22},
+       {0x20, 0x23}, {0x21, 0x23}, {0xf7, 0x00}, {0x48, 0x22},
+       {0xb0, 0x00}, {0x19, 0x22}, {0xb7, 0x00}, {0x1a, 0x22},
+       {0x7f, 0x20}, {0xb2, 0x00}, {0xa0, 0x25}, {0xa0, 0x00},
+};
+
+static unsigned char page00[256] = {
+       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+       0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
+       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
+       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
+       0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+       0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */
+       0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */
+       0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */
+       0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0xff, 0x00, 0x9b, 0x9c, 0x98, 0x00, 0xa0, 0x8f, /* 0xa0-0xa7 */
+       0xa4, 0x00, 0x00, 0xae, 0xaa, 0x00, 0x00, 0xa7, /* 0xa8-0xaf */
+       0xf8, 0xf1, 0xfd, 0xa6, 0xa1, 0xe6, 0x86, 0xfa, /* 0xb0-0xb7 */
+       0xa5, 0x00, 0x00, 0xaf, 0xac, 0xab, 0xad, 0x00, /* 0xb8-0xbf */
+       0x8e, 0x00, 0x84, 0x00, 0x00, 0x00, 0x00, 0x80, /* 0xc0-0xc7 */
+       0x91, 0x90, 0x92, 0x94, 0x00, 0x00, 0xa8, 0x95, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x99, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x9d, 0x00, 0x9e, 0x9a, 0x00, 0x00, 0xe1, /* 0xd8-0xdf */
+       0x85, 0x00, 0x83, 0x00, 0x00, 0x00, 0x00, 0x87, /* 0xe0-0xe7 */
+       0x8a, 0x82, 0x88, 0x89, 0x00, 0x00, 0x8c, 0x8b, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0xa2, 0x93, 0x00, 0x00, 0xf6, /* 0xf0-0xf7 */
+       0x00, 0x97, 0xa3, 0x96, 0x81, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page01[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x9f, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page03[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0xe9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0xe4, 0x00, 0x00, 0xe8, 0x00, /* 0xa0-0xa7 */
+       0x00, 0xea, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0xe0, 0x00, 0x00, 0xeb, 0xee, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0xe3, 0x00, 0x00, 0xe5, 0xe7, 0x00, 0xed, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page20[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8d, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page22[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0xf9, 0xfb, 0x00, 0x00, 0x00, 0xec, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0xf0, 0x00, 0x00, 0xf3, 0xf2, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page23[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0xa9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0xf4, 0xf5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page25[256] = {
+       0xc4, 0x00, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0xda, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0xbf, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0xd9, 0x00, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0xc2, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0xc1, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0xc5, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0xcd, 0xba, 0xd5, 0xd6, 0xc9, 0xb8, 0xb7, 0xbb, /* 0x50-0x57 */
+       0xd4, 0xd3, 0xc8, 0xbe, 0xbd, 0xbc, 0xc6, 0xc7, /* 0x58-0x5f */
+       0xcc, 0xb5, 0xb6, 0xb9, 0xd1, 0xd2, 0xcb, 0xcf, /* 0x60-0x67 */
+       0xd0, 0xca, 0xd8, 0xd7, 0xce, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0xdf, 0x00, 0x00, 0x00, 0xdc, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0xdb, 0x00, 0x00, 0x00, 0xdd, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0xde, 0xb0, 0xb1, 0xb2, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char *page_uni2charset[256] = {
+       page00, page01, NULL,   page03, NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       page20, NULL,   page22, page23, NULL,   page25, NULL,   NULL,
+};
+
+#if 0
+static unsigned char charset2upper[256] = {
+       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+       0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
+       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
+       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
+       0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+       0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+       0x80, 0x00, 0x00, 0x00, 0x84, 0x00, 0x86, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x8d, 0x8e, 0x8f, /* 0x88-0x8f */
+       0x90, 0x91, 0x92, 0x00, 0x94, 0x95, 0x00, 0x00, /* 0x90-0x97 */
+       0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x00, /* 0x98-0x9f */
+       0xa0, 0xa1, 0x00, 0x00, 0xa4, 0xa5, 0xa6, 0xa7, /* 0xa0-0xa7 */
+       0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
+       0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
+       0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* 0xb8-0xbf */
+       0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xc0-0xc7 */
+       0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
+       0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
+       0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, /* 0xd8-0xdf */
+       0x00, 0x00, 0xe2, 0x00, 0xe4, 0x00, 0xe6, 0x00, /* 0xe0-0xe7 */
+       0xe8, 0xe9, 0xea, 0x00, 0xec, 0x00, 0x00, 0xef, /* 0xe8-0xef */
+       0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
+       0xf8, 0xf9, 0xfa, 0xfb, 0x00, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
+};
+#endif
+
+static struct unls_table table = {
+       "cp863",
+       page_uni2charset,
+       charset2uni,
+       NULL
+};
+
+int
+init_unls_cp863()
+{
+       return (register_unls(&table));
+}
diff --git a/libunls/nls_cp864.c b/libunls/nls_cp864.c
new file mode 100644 (file)
index 0000000..cacd866
--- /dev/null
@@ -0,0 +1,427 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)nls_cp864.c     1.2 05/05/01 2000 J. Schilling */
+/*
+ *     Modifications to make the code portable Copyright (c) 2000 J. Schilling
+ *
+ *     Code taken from the Linux kernel.
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/*
+ * linux/fs/nls_cp864.c
+ *
+ * Charset cp864 translation tables.
+ * Generated automatically from the Unicode and charset
+ * tables from the Unicode Organization (www.unicode.org).
+ * The Unicode to charset table has only exact mappings.
+ */
+
+#include <mconfig.h>
+#include "nls.h"
+
+static struct unls_unicode charset2uni[256] = {
+       /* 0x00*/
+       {0x00, 0x00}, {0x01, 0x00}, {0x02, 0x00}, {0x03, 0x00},
+       {0x04, 0x00}, {0x05, 0x00}, {0x06, 0x00}, {0x07, 0x00},
+       {0x08, 0x00}, {0x09, 0x00}, {0x0a, 0x00}, {0x0b, 0x00},
+       {0x0c, 0x00}, {0x0d, 0x00}, {0x0e, 0x00}, {0x0f, 0x00},
+       /* 0x10*/
+       {0x10, 0x00}, {0x11, 0x00}, {0x12, 0x00}, {0x13, 0x00},
+       {0x14, 0x00}, {0x15, 0x00}, {0x16, 0x00}, {0x17, 0x00},
+       {0x18, 0x00}, {0x19, 0x00}, {0x1a, 0x00}, {0x1b, 0x00},
+       {0x1c, 0x00}, {0x1d, 0x00}, {0x1e, 0x00}, {0x1f, 0x00},
+       /* 0x20*/
+       {0x20, 0x00}, {0x21, 0x00}, {0x22, 0x00}, {0x23, 0x00},
+       {0x24, 0x00}, {0x6a, 0x06}, {0x26, 0x00}, {0x27, 0x00},
+       {0x28, 0x00}, {0x29, 0x00}, {0x2a, 0x00}, {0x2b, 0x00},
+       {0x2c, 0x00}, {0x2d, 0x00}, {0x2e, 0x00}, {0x2f, 0x00},
+       /* 0x30*/
+       {0x30, 0x00}, {0x31, 0x00}, {0x32, 0x00}, {0x33, 0x00},
+       {0x34, 0x00}, {0x35, 0x00}, {0x36, 0x00}, {0x37, 0x00},
+       {0x38, 0x00}, {0x39, 0x00}, {0x3a, 0x00}, {0x3b, 0x00},
+       {0x3c, 0x00}, {0x3d, 0x00}, {0x3e, 0x00}, {0x3f, 0x00},
+       /* 0x40*/
+       {0x40, 0x00}, {0x41, 0x00}, {0x42, 0x00}, {0x43, 0x00},
+       {0x44, 0x00}, {0x45, 0x00}, {0x46, 0x00}, {0x47, 0x00},
+       {0x48, 0x00}, {0x49, 0x00}, {0x4a, 0x00}, {0x4b, 0x00},
+       {0x4c, 0x00}, {0x4d, 0x00}, {0x4e, 0x00}, {0x4f, 0x00},
+       /* 0x50*/
+       {0x50, 0x00}, {0x51, 0x00}, {0x52, 0x00}, {0x53, 0x00},
+       {0x54, 0x00}, {0x55, 0x00}, {0x56, 0x00}, {0x57, 0x00},
+       {0x58, 0x00}, {0x59, 0x00}, {0x5a, 0x00}, {0x5b, 0x00},
+       {0x5c, 0x00}, {0x5d, 0x00}, {0x5e, 0x00}, {0x5f, 0x00},
+       /* 0x60*/
+       {0x60, 0x00}, {0x61, 0x00}, {0x62, 0x00}, {0x63, 0x00},
+       {0x64, 0x00}, {0x65, 0x00}, {0x66, 0x00}, {0x67, 0x00},
+       {0x68, 0x00}, {0x69, 0x00}, {0x6a, 0x00}, {0x6b, 0x00},
+       {0x6c, 0x00}, {0x6d, 0x00}, {0x6e, 0x00}, {0x6f, 0x00},
+       /* 0x70*/
+       {0x70, 0x00}, {0x71, 0x00}, {0x72, 0x00}, {0x73, 0x00},
+       {0x74, 0x00}, {0x75, 0x00}, {0x76, 0x00}, {0x77, 0x00},
+       {0x78, 0x00}, {0x79, 0x00}, {0x7a, 0x00}, {0x7b, 0x00},
+       {0x7c, 0x00}, {0x7d, 0x00}, {0x7e, 0x00}, {0x7f, 0x00},
+       /* 0x80*/
+       {0xb0, 0x00}, {0xb7, 0x00}, {0x19, 0x22}, {0x1a, 0x22},
+       {0x92, 0x25}, {0x00, 0x25}, {0x02, 0x25}, {0x3c, 0x25},
+       {0x24, 0x25}, {0x2c, 0x25}, {0x1c, 0x25}, {0x34, 0x25},
+       {0x10, 0x25}, {0x0c, 0x25}, {0x14, 0x25}, {0x18, 0x25},
+       /* 0x90*/
+       {0xb2, 0x03}, {0x1e, 0x22}, {0xc6, 0x03}, {0xb1, 0x00},
+       {0xbd, 0x00}, {0xbc, 0x00}, {0x48, 0x22}, {0xab, 0x00},
+       {0xbb, 0x00}, {0xf7, 0xfe}, {0xf8, 0xfe}, {0x00, 0x00},
+       {0x00, 0x00}, {0xfb, 0xfe}, {0xfc, 0xfe}, {0x00, 0x00},
+       /* 0xa0*/
+       {0xa0, 0x00}, {0xad, 0x00}, {0x82, 0xfe}, {0xa3, 0x00},
+       {0xa4, 0x00}, {0x84, 0xfe}, {0x00, 0x00}, {0x00, 0x00},
+       {0x8e, 0xfe}, {0x8f, 0xfe}, {0x95, 0xfe}, {0x99, 0xfe},
+       {0x0c, 0x06}, {0x9d, 0xfe}, {0xa1, 0xfe}, {0xa5, 0xfe},
+       /* 0xb0*/
+       {0x60, 0x06}, {0x61, 0x06}, {0x62, 0x06}, {0x63, 0x06},
+       {0x64, 0x06}, {0x65, 0x06}, {0x66, 0x06}, {0x67, 0x06},
+       {0x68, 0x06}, {0x69, 0x06}, {0xd1, 0xfe}, {0x1b, 0x06},
+       {0xb1, 0xfe}, {0xb5, 0xfe}, {0xb9, 0xfe}, {0x1f, 0x06},
+       /* 0xc0*/
+       {0xa2, 0x00}, {0x80, 0xfe}, {0x81, 0xfe}, {0x83, 0xfe},
+       {0x85, 0xfe}, {0xca, 0xfe}, {0x8b, 0xfe}, {0x8d, 0xfe},
+       {0x91, 0xfe}, {0x93, 0xfe}, {0x97, 0xfe}, {0x9b, 0xfe},
+       {0x9f, 0xfe}, {0xa3, 0xfe}, {0xa7, 0xfe}, {0xa9, 0xfe},
+       /* 0xd0*/
+       {0xab, 0xfe}, {0xad, 0xfe}, {0xaf, 0xfe}, {0xb3, 0xfe},
+       {0xb7, 0xfe}, {0xbb, 0xfe}, {0xbf, 0xfe}, {0xc1, 0xfe},
+       {0xc5, 0xfe}, {0xcb, 0xfe}, {0xcf, 0xfe}, {0xa6, 0x00},
+       {0xac, 0x00}, {0xf7, 0x00}, {0xd7, 0x00}, {0xc9, 0xfe},
+       /* 0xe0*/
+       {0x40, 0x06}, {0xd3, 0xfe}, {0xd7, 0xfe}, {0xdb, 0xfe},
+       {0xdf, 0xfe}, {0xe3, 0xfe}, {0xe7, 0xfe}, {0xeb, 0xfe},
+       {0xed, 0xfe}, {0xef, 0xfe}, {0xf3, 0xfe}, {0xbd, 0xfe},
+       {0xcc, 0xfe}, {0xce, 0xfe}, {0xcd, 0xfe}, {0xe1, 0xfe},
+       /* 0xf0*/
+       {0x7d, 0xfe}, {0x51, 0x06}, {0xe5, 0xfe}, {0xe9, 0xfe},
+       {0xec, 0xfe}, {0xf0, 0xfe}, {0xf2, 0xfe}, {0xd0, 0xfe},
+       {0xd5, 0xfe}, {0xf5, 0xfe}, {0xf6, 0xfe}, {0xdd, 0xfe},
+       {0xd9, 0xfe}, {0xf1, 0xfe}, {0xa0, 0x25}, {0x00, 0x00},
+};
+
+static unsigned char page00[256] = {
+       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+       0x20, 0x21, 0x22, 0x23, 0x24, 0x00, 0x26, 0x27, /* 0x20-0x27 */
+       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+       0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
+       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
+       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
+       0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+       0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */
+       0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */
+       0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */
+       0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0xa0, 0x00, 0xc0, 0xa3, 0xa4, 0x00, 0xdb, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x97, 0xdc, 0xa1, 0x00, 0x00, /* 0xa8-0xaf */
+       0x80, 0x93, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x98, 0x95, 0x94, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xde, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdd, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page03[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x92, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page06[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0xac, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0xbb, 0x00, 0x00, 0x00, 0xbf, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0xf1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0x60-0x67 */
+       0xb8, 0xb9, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page22[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x82, 0x83, 0x00, 0x00, 0x00, 0x91, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page25[256] = {
+       0x85, 0x00, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x8d, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x8c, 0x00, 0x00, 0x00, 0x8e, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x8f, 0x00, 0x00, 0x00, 0x8a, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x89, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x8b, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x87, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char pagefe[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, /* 0x78-0x7f */
+
+       0xc1, 0xc2, 0xa2, 0xc3, 0xa5, 0xc4, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0xc6, 0x00, 0xc7, 0xa8, 0xa9, /* 0x88-0x8f */
+       0x00, 0xc8, 0x00, 0xc9, 0x00, 0xaa, 0x00, 0xca, /* 0x90-0x97 */
+       0x00, 0xab, 0x00, 0xcb, 0x00, 0xad, 0x00, 0xcc, /* 0x98-0x9f */
+       0x00, 0xae, 0x00, 0xcd, 0x00, 0xaf, 0x00, 0xce, /* 0xa0-0xa7 */
+       0x00, 0xcf, 0x00, 0xd0, 0x00, 0xd1, 0x00, 0xd2, /* 0xa8-0xaf */
+       0x00, 0xbc, 0x00, 0xd3, 0x00, 0xbd, 0x00, 0xd4, /* 0xb0-0xb7 */
+       0x00, 0xbe, 0x00, 0xd5, 0x00, 0xeb, 0x00, 0xd6, /* 0xb8-0xbf */
+       0x00, 0xd7, 0x00, 0x00, 0x00, 0xd8, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0xdf, 0xc5, 0xd9, 0xec, 0xee, 0xed, 0xda, /* 0xc8-0xcf */
+       0xf7, 0xba, 0x00, 0xe1, 0x00, 0xf8, 0x00, 0xe2, /* 0xd0-0xd7 */
+       0x00, 0xfc, 0x00, 0xe3, 0x00, 0xfb, 0x00, 0xe4, /* 0xd8-0xdf */
+       0x00, 0xef, 0x00, 0xe5, 0x00, 0xf2, 0x00, 0xe6, /* 0xe0-0xe7 */
+       0x00, 0xf3, 0x00, 0xe7, 0xf4, 0xe8, 0x00, 0xe9, /* 0xe8-0xef */
+       0xf5, 0xfd, 0xf6, 0xea, 0x00, 0xf9, 0xfa, 0x99, /* 0xf0-0xf7 */
+       0x9a, 0x00, 0x00, 0x9d, 0x9e, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char *page_uni2charset[256] = {
+       page00, NULL,   NULL,   page03, NULL,   NULL,   page06, NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   page22, NULL,   NULL,   page25, NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   pagefe, NULL,
+};
+
+#if 0
+static unsigned char charset2upper[256] = {
+       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+       0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
+       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
+       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
+       0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+       0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+       0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 0x80-0x87 */
+       0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, /* 0x88-0x8f */
+       0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, /* 0x90-0x97 */
+       0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, /* 0x98-0x9f */
+       0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, /* 0xa0-0xa7 */
+       0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
+       0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
+       0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* 0xb8-0xbf */
+       0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xc0-0xc7 */
+       0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
+       0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
+       0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, /* 0xd8-0xdf */
+       0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0xe0-0xe7 */
+       0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xe8-0xef */
+       0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
+       0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
+};
+#endif
+
+static struct unls_table table = {
+       "cp864",
+       page_uni2charset,
+       charset2uni,
+       NULL
+};
+
+int
+init_unls_cp864()
+{
+       return (register_unls(&table));
+}
diff --git a/libunls/nls_cp865.c b/libunls/nls_cp865.c
new file mode 100644 (file)
index 0000000..dfe37fd
--- /dev/null
@@ -0,0 +1,436 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)nls_cp865.c     1.2 05/05/01 2000 J. Schilling */
+/*
+ *     Modifications to make the code portable Copyright (c) 2000 J. Schilling
+ *
+ *     Code taken from the Linux kernel.
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/*
+ * linux/fs/nls_cp865.c
+ *
+ * Charset cp865 translation tables.
+ * Generated automatically from the Unicode and charset
+ * tables from the Unicode Organization (www.unicode.org).
+ * The Unicode to charset table has only exact mappings.
+ */
+
+#include <mconfig.h>
+#include "nls.h"
+
+static struct unls_unicode charset2uni[256] = {
+       /* 0x00*/
+       {0x00, 0x00}, {0x01, 0x00}, {0x02, 0x00}, {0x03, 0x00},
+       {0x04, 0x00}, {0x05, 0x00}, {0x06, 0x00}, {0x07, 0x00},
+       {0x08, 0x00}, {0x09, 0x00}, {0x0a, 0x00}, {0x0b, 0x00},
+       {0x0c, 0x00}, {0x0d, 0x00}, {0x0e, 0x00}, {0x0f, 0x00},
+       /* 0x10*/
+       {0x10, 0x00}, {0x11, 0x00}, {0x12, 0x00}, {0x13, 0x00},
+       {0x14, 0x00}, {0x15, 0x00}, {0x16, 0x00}, {0x17, 0x00},
+       {0x18, 0x00}, {0x19, 0x00}, {0x1a, 0x00}, {0x1b, 0x00},
+       {0x1c, 0x00}, {0x1d, 0x00}, {0x1e, 0x00}, {0x1f, 0x00},
+       /* 0x20*/
+       {0x20, 0x00}, {0x21, 0x00}, {0x22, 0x00}, {0x23, 0x00},
+       {0x24, 0x00}, {0x25, 0x00}, {0x26, 0x00}, {0x27, 0x00},
+       {0x28, 0x00}, {0x29, 0x00}, {0x2a, 0x00}, {0x2b, 0x00},
+       {0x2c, 0x00}, {0x2d, 0x00}, {0x2e, 0x00}, {0x2f, 0x00},
+       /* 0x30*/
+       {0x30, 0x00}, {0x31, 0x00}, {0x32, 0x00}, {0x33, 0x00},
+       {0x34, 0x00}, {0x35, 0x00}, {0x36, 0x00}, {0x37, 0x00},
+       {0x38, 0x00}, {0x39, 0x00}, {0x3a, 0x00}, {0x3b, 0x00},
+       {0x3c, 0x00}, {0x3d, 0x00}, {0x3e, 0x00}, {0x3f, 0x00},
+       /* 0x40*/
+       {0x40, 0x00}, {0x41, 0x00}, {0x42, 0x00}, {0x43, 0x00},
+       {0x44, 0x00}, {0x45, 0x00}, {0x46, 0x00}, {0x47, 0x00},
+       {0x48, 0x00}, {0x49, 0x00}, {0x4a, 0x00}, {0x4b, 0x00},
+       {0x4c, 0x00}, {0x4d, 0x00}, {0x4e, 0x00}, {0x4f, 0x00},
+       /* 0x50*/
+       {0x50, 0x00}, {0x51, 0x00}, {0x52, 0x00}, {0x53, 0x00},
+       {0x54, 0x00}, {0x55, 0x00}, {0x56, 0x00}, {0x57, 0x00},
+       {0x58, 0x00}, {0x59, 0x00}, {0x5a, 0x00}, {0x5b, 0x00},
+       {0x5c, 0x00}, {0x5d, 0x00}, {0x5e, 0x00}, {0x5f, 0x00},
+       /* 0x60*/
+       {0x60, 0x00}, {0x61, 0x00}, {0x62, 0x00}, {0x63, 0x00},
+       {0x64, 0x00}, {0x65, 0x00}, {0x66, 0x00}, {0x67, 0x00},
+       {0x68, 0x00}, {0x69, 0x00}, {0x6a, 0x00}, {0x6b, 0x00},
+       {0x6c, 0x00}, {0x6d, 0x00}, {0x6e, 0x00}, {0x6f, 0x00},
+       /* 0x70*/
+       {0x70, 0x00}, {0x71, 0x00}, {0x72, 0x00}, {0x73, 0x00},
+       {0x74, 0x00}, {0x75, 0x00}, {0x76, 0x00}, {0x77, 0x00},
+       {0x78, 0x00}, {0x79, 0x00}, {0x7a, 0x00}, {0x7b, 0x00},
+       {0x7c, 0x00}, {0x7d, 0x00}, {0x7e, 0x00}, {0x7f, 0x00},
+       /* 0x80*/
+       {0xc7, 0x00}, {0xfc, 0x00}, {0xe9, 0x00}, {0xe2, 0x00},
+       {0xe4, 0x00}, {0xe0, 0x00}, {0xe5, 0x00}, {0xe7, 0x00},
+       {0xea, 0x00}, {0xeb, 0x00}, {0xe8, 0x00}, {0xef, 0x00},
+       {0xee, 0x00}, {0xec, 0x00}, {0xc4, 0x00}, {0xc5, 0x00},
+       /* 0x90*/
+       {0xc9, 0x00}, {0xe6, 0x00}, {0xc6, 0x00}, {0xf4, 0x00},
+       {0xf6, 0x00}, {0xf2, 0x00}, {0xfb, 0x00}, {0xf9, 0x00},
+       {0xff, 0x00}, {0xd6, 0x00}, {0xdc, 0x00}, {0xf8, 0x00},
+       {0xa3, 0x00}, {0xd8, 0x00}, {0xa7, 0x20}, {0x92, 0x01},
+       /* 0xa0*/
+       {0xe1, 0x00}, {0xed, 0x00}, {0xf3, 0x00}, {0xfa, 0x00},
+       {0xf1, 0x00}, {0xd1, 0x00}, {0xaa, 0x00}, {0xba, 0x00},
+       {0xbf, 0x00}, {0x10, 0x23}, {0xac, 0x00}, {0xbd, 0x00},
+       {0xbc, 0x00}, {0xa1, 0x00}, {0xab, 0x00}, {0xa4, 0x00},
+       /* 0xb0*/
+       {0x91, 0x25}, {0x92, 0x25}, {0x93, 0x25}, {0x02, 0x25},
+       {0x24, 0x25}, {0x61, 0x25}, {0x62, 0x25}, {0x56, 0x25},
+       {0x55, 0x25}, {0x63, 0x25}, {0x51, 0x25}, {0x57, 0x25},
+       {0x5d, 0x25}, {0x5c, 0x25}, {0x5b, 0x25}, {0x10, 0x25},
+       /* 0xc0*/
+       {0x14, 0x25}, {0x34, 0x25}, {0x2c, 0x25}, {0x1c, 0x25},
+       {0x00, 0x25}, {0x3c, 0x25}, {0x5e, 0x25}, {0x5f, 0x25},
+       {0x5a, 0x25}, {0x54, 0x25}, {0x69, 0x25}, {0x66, 0x25},
+       {0x60, 0x25}, {0x50, 0x25}, {0x6c, 0x25}, {0x67, 0x25},
+       /* 0xd0*/
+       {0x68, 0x25}, {0x64, 0x25}, {0x65, 0x25}, {0x59, 0x25},
+       {0x58, 0x25}, {0x52, 0x25}, {0x53, 0x25}, {0x6b, 0x25},
+       {0x6a, 0x25}, {0x18, 0x25}, {0x0c, 0x25}, {0x88, 0x25},
+       {0x84, 0x25}, {0x8c, 0x25}, {0x90, 0x25}, {0x80, 0x25},
+       /* 0xe0*/
+       {0xb1, 0x03}, {0xdf, 0x00}, {0x93, 0x03}, {0xc0, 0x03},
+       {0xa3, 0x03}, {0xc3, 0x03}, {0xb5, 0x00}, {0xc4, 0x03},
+       {0xa6, 0x03}, {0x98, 0x03}, {0xa9, 0x03}, {0xb4, 0x03},
+       {0x1e, 0x22}, {0xc6, 0x03}, {0xb5, 0x03}, {0x29, 0x22},
+       /* 0xf0*/
+       {0x61, 0x22}, {0xb1, 0x00}, {0x65, 0x22}, {0x64, 0x22},
+       {0x20, 0x23}, {0x21, 0x23}, {0xf7, 0x00}, {0x48, 0x22},
+       {0xb0, 0x00}, {0x19, 0x22}, {0xb7, 0x00}, {0x1a, 0x22},
+       {0x7f, 0x20}, {0xb2, 0x00}, {0xa0, 0x25}, {0xa0, 0x00},
+};
+
+static unsigned char page00[256] = {
+       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+       0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
+       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
+       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
+       0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+       0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */
+       0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */
+       0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */
+       0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0xff, 0xad, 0x00, 0x9c, 0xaf, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0xa6, 0xae, 0xaa, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0xf8, 0xf1, 0xfd, 0x00, 0x00, 0xe6, 0x00, 0xfa, /* 0xb0-0xb7 */
+       0x00, 0x00, 0xa7, 0x00, 0xac, 0xab, 0x00, 0xa8, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x8e, 0x8f, 0x92, 0x80, /* 0xc0-0xc7 */
+       0x00, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0xa5, 0x00, 0x00, 0x00, 0x00, 0x99, 0x00, /* 0xd0-0xd7 */
+       0x9d, 0x00, 0x00, 0x00, 0x9a, 0x00, 0x00, 0xe1, /* 0xd8-0xdf */
+       0x85, 0xa0, 0x83, 0x00, 0x84, 0x86, 0x91, 0x87, /* 0xe0-0xe7 */
+       0x8a, 0x82, 0x88, 0x89, 0x8d, 0xa1, 0x8c, 0x8b, /* 0xe8-0xef */
+       0x00, 0xa4, 0x95, 0xa2, 0x93, 0x00, 0x94, 0xf6, /* 0xf0-0xf7 */
+       0x9b, 0x97, 0xa3, 0x96, 0x81, 0x00, 0x00, 0x98, /* 0xf8-0xff */
+};
+
+static unsigned char page01[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x9f, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page03[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0xe9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0xe4, 0x00, 0x00, 0xe8, 0x00, /* 0xa0-0xa7 */
+       0x00, 0xea, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0xe0, 0x00, 0x00, 0xeb, 0xee, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0xe3, 0x00, 0x00, 0xe5, 0xe7, 0x00, 0xed, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page20[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9e, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page22[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0xf9, 0xfb, 0x00, 0x00, 0x00, 0xec, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0xf0, 0x00, 0x00, 0xf3, 0xf2, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page23[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0xa9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0xf4, 0xf5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page25[256] = {
+       0xc4, 0x00, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0xda, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0xbf, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0xd9, 0x00, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0xc2, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0xc1, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0xc5, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0xcd, 0xba, 0xd5, 0xd6, 0xc9, 0xb8, 0xb7, 0xbb, /* 0x50-0x57 */
+       0xd4, 0xd3, 0xc8, 0xbe, 0xbd, 0xbc, 0xc6, 0xc7, /* 0x58-0x5f */
+       0xcc, 0xb5, 0xb6, 0xb9, 0xd1, 0xd2, 0xcb, 0xcf, /* 0x60-0x67 */
+       0xd0, 0xca, 0xd8, 0xd7, 0xce, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0xdf, 0x00, 0x00, 0x00, 0xdc, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0xdb, 0x00, 0x00, 0x00, 0xdd, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0xde, 0xb0, 0xb1, 0xb2, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char *page_uni2charset[256] = {
+       page00, page01, NULL,   page03, NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       page20, NULL,   page22, page23, NULL,   page25, NULL,   NULL,
+};
+
+#if 0
+static unsigned char charset2upper[256] = {
+       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+       0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
+       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
+       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
+       0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+       0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+       0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8e, 0x8f, /* 0x88-0x8f */
+       0x90, 0x91, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x99, 0x9a, 0x00, 0x9c, 0x9d, 0x9e, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0xa5, 0xa6, 0xa7, /* 0xa0-0xa7 */
+       0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
+       0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
+       0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* 0xb8-0xbf */
+       0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xc0-0xc7 */
+       0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
+       0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
+       0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, /* 0xd8-0xdf */
+       0x00, 0x00, 0xe2, 0x00, 0xe4, 0x00, 0xe6, 0x00, /* 0xe0-0xe7 */
+       0xe8, 0xe9, 0xea, 0x00, 0xec, 0x00, 0x00, 0xef, /* 0xe8-0xef */
+       0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
+       0xf8, 0xf9, 0xfa, 0xfb, 0x00, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
+};
+#endif
+
+static struct unls_table table = {
+       "cp865",
+       page_uni2charset,
+       charset2uni,
+       NULL
+};
+
+int
+init_unls_cp865()
+{
+       return (register_unls(&table));
+}
diff --git a/libunls/nls_cp866.c b/libunls/nls_cp866.c
new file mode 100644 (file)
index 0000000..6c0be0d
--- /dev/null
@@ -0,0 +1,364 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)nls_cp866.c     1.2 05/05/01 2000 J. Schilling */
+/*
+ *     Modifications to make the code portable Copyright (c) 2000 J. Schilling
+ *
+ *     Code taken from the Linux kernel.
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/*
+ * linux/fs/nls_cp866.c
+ *
+ * Charset cp866 translation tables.
+ * Generated automatically from the Unicode and charset
+ * tables from the Unicode Organization (www.unicode.org).
+ * The Unicode to charset table has only exact mappings.
+ */
+
+#include <mconfig.h>
+#include "nls.h"
+
+static struct unls_unicode charset2uni[256] = {
+       /* 0x00*/
+       {0x00, 0x00}, {0x01, 0x00}, {0x02, 0x00}, {0x03, 0x00},
+       {0x04, 0x00}, {0x05, 0x00}, {0x06, 0x00}, {0x07, 0x00},
+       {0x08, 0x00}, {0x09, 0x00}, {0x0a, 0x00}, {0x0b, 0x00},
+       {0x0c, 0x00}, {0x0d, 0x00}, {0x0e, 0x00}, {0x0f, 0x00},
+       /* 0x10*/
+       {0x10, 0x00}, {0x11, 0x00}, {0x12, 0x00}, {0x13, 0x00},
+       {0x14, 0x00}, {0x15, 0x00}, {0x16, 0x00}, {0x17, 0x00},
+       {0x18, 0x00}, {0x19, 0x00}, {0x1a, 0x00}, {0x1b, 0x00},
+       {0x1c, 0x00}, {0x1d, 0x00}, {0x1e, 0x00}, {0x1f, 0x00},
+       /* 0x20*/
+       {0x20, 0x00}, {0x21, 0x00}, {0x22, 0x00}, {0x23, 0x00},
+       {0x24, 0x00}, {0x25, 0x00}, {0x26, 0x00}, {0x27, 0x00},
+       {0x28, 0x00}, {0x29, 0x00}, {0x2a, 0x00}, {0x2b, 0x00},
+       {0x2c, 0x00}, {0x2d, 0x00}, {0x2e, 0x00}, {0x2f, 0x00},
+       /* 0x30*/
+       {0x30, 0x00}, {0x31, 0x00}, {0x32, 0x00}, {0x33, 0x00},
+       {0x34, 0x00}, {0x35, 0x00}, {0x36, 0x00}, {0x37, 0x00},
+       {0x38, 0x00}, {0x39, 0x00}, {0x3a, 0x00}, {0x3b, 0x00},
+       {0x3c, 0x00}, {0x3d, 0x00}, {0x3e, 0x00}, {0x3f, 0x00},
+       /* 0x40*/
+       {0x40, 0x00}, {0x41, 0x00}, {0x42, 0x00}, {0x43, 0x00},
+       {0x44, 0x00}, {0x45, 0x00}, {0x46, 0x00}, {0x47, 0x00},
+       {0x48, 0x00}, {0x49, 0x00}, {0x4a, 0x00}, {0x4b, 0x00},
+       {0x4c, 0x00}, {0x4d, 0x00}, {0x4e, 0x00}, {0x4f, 0x00},
+       /* 0x50*/
+       {0x50, 0x00}, {0x51, 0x00}, {0x52, 0x00}, {0x53, 0x00},
+       {0x54, 0x00}, {0x55, 0x00}, {0x56, 0x00}, {0x57, 0x00},
+       {0x58, 0x00}, {0x59, 0x00}, {0x5a, 0x00}, {0x5b, 0x00},
+       {0x5c, 0x00}, {0x5d, 0x00}, {0x5e, 0x00}, {0x5f, 0x00},
+       /* 0x60*/
+       {0x60, 0x00}, {0x61, 0x00}, {0x62, 0x00}, {0x63, 0x00},
+       {0x64, 0x00}, {0x65, 0x00}, {0x66, 0x00}, {0x67, 0x00},
+       {0x68, 0x00}, {0x69, 0x00}, {0x6a, 0x00}, {0x6b, 0x00},
+       {0x6c, 0x00}, {0x6d, 0x00}, {0x6e, 0x00}, {0x6f, 0x00},
+       /* 0x70*/
+       {0x70, 0x00}, {0x71, 0x00}, {0x72, 0x00}, {0x73, 0x00},
+       {0x74, 0x00}, {0x75, 0x00}, {0x76, 0x00}, {0x77, 0x00},
+       {0x78, 0x00}, {0x79, 0x00}, {0x7a, 0x00}, {0x7b, 0x00},
+       {0x7c, 0x00}, {0x7d, 0x00}, {0x7e, 0x00}, {0x7f, 0x00},
+       /* 0x80*/
+       {0x10, 0x04}, {0x11, 0x04}, {0x12, 0x04}, {0x13, 0x04},
+       {0x14, 0x04}, {0x15, 0x04}, {0x16, 0x04}, {0x17, 0x04},
+       {0x18, 0x04}, {0x19, 0x04}, {0x1a, 0x04}, {0x1b, 0x04},
+       {0x1c, 0x04}, {0x1d, 0x04}, {0x1e, 0x04}, {0x1f, 0x04},
+       /* 0x90*/
+       {0x20, 0x04}, {0x21, 0x04}, {0x22, 0x04}, {0x23, 0x04},
+       {0x24, 0x04}, {0x25, 0x04}, {0x26, 0x04}, {0x27, 0x04},
+       {0x28, 0x04}, {0x29, 0x04}, {0x2a, 0x04}, {0x2b, 0x04},
+       {0x2c, 0x04}, {0x2d, 0x04}, {0x2e, 0x04}, {0x2f, 0x04},
+       /* 0xa0*/
+       {0x30, 0x04}, {0x31, 0x04}, {0x32, 0x04}, {0x33, 0x04},
+       {0x34, 0x04}, {0x35, 0x04}, {0x36, 0x04}, {0x37, 0x04},
+       {0x38, 0x04}, {0x39, 0x04}, {0x3a, 0x04}, {0x3b, 0x04},
+       {0x3c, 0x04}, {0x3d, 0x04}, {0x3e, 0x04}, {0x3f, 0x04},
+       /* 0xb0*/
+       {0x91, 0x25}, {0x92, 0x25}, {0x93, 0x25}, {0x02, 0x25},
+       {0x24, 0x25}, {0x61, 0x25}, {0x62, 0x25}, {0x56, 0x25},
+       {0x55, 0x25}, {0x63, 0x25}, {0x51, 0x25}, {0x57, 0x25},
+       {0x5d, 0x25}, {0x5c, 0x25}, {0x5b, 0x25}, {0x10, 0x25},
+       /* 0xc0*/
+       {0x14, 0x25}, {0x34, 0x25}, {0x2c, 0x25}, {0x1c, 0x25},
+       {0x00, 0x25}, {0x3c, 0x25}, {0x5e, 0x25}, {0x5f, 0x25},
+       {0x5a, 0x25}, {0x54, 0x25}, {0x69, 0x25}, {0x66, 0x25},
+       {0x60, 0x25}, {0x50, 0x25}, {0x6c, 0x25}, {0x67, 0x25},
+       /* 0xd0*/
+       {0x68, 0x25}, {0x64, 0x25}, {0x65, 0x25}, {0x59, 0x25},
+       {0x58, 0x25}, {0x52, 0x25}, {0x53, 0x25}, {0x6b, 0x25},
+       {0x6a, 0x25}, {0x18, 0x25}, {0x0c, 0x25}, {0x88, 0x25},
+       {0x84, 0x25}, {0x8c, 0x25}, {0x90, 0x25}, {0x80, 0x25},
+       /* 0xe0*/
+       {0x40, 0x04}, {0x41, 0x04}, {0x42, 0x04}, {0x43, 0x04},
+       {0x44, 0x04}, {0x45, 0x04}, {0x46, 0x04}, {0x47, 0x04},
+       {0x48, 0x04}, {0x49, 0x04}, {0x4a, 0x04}, {0x4b, 0x04},
+       {0x4c, 0x04}, {0x4d, 0x04}, {0x4e, 0x04}, {0x4f, 0x04},
+       /* 0xf0*/
+       {0x01, 0x04}, {0x51, 0x04}, {0x04, 0x04}, {0x54, 0x04},
+       {0x07, 0x04}, {0x57, 0x04}, {0x0e, 0x04}, {0x5e, 0x04},
+       {0xb0, 0x00}, {0x19, 0x22}, {0xb7, 0x00}, {0x1a, 0x22},
+       {0x16, 0x21}, {0xa4, 0x00}, {0xa0, 0x25}, {0xa0, 0x00},
+};
+
+static unsigned char page00[256] = {
+       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+       0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
+       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
+       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
+       0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+       0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */
+       0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */
+       0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */
+       0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0xff, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfa, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page04[256] = {
+       0x00, 0xf0, 0x00, 0x00, 0xf2, 0x00, 0x00, 0xf4, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, 0x00, /* 0x08-0x0f */
+       0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 0x10-0x17 */
+       0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, /* 0x18-0x1f */
+       0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, /* 0x20-0x27 */
+       0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, /* 0x28-0x2f */
+       0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, /* 0x30-0x37 */
+       0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0x38-0x3f */
+       0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0x40-0x47 */
+       0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0x48-0x4f */
+       0x00, 0xf1, 0x00, 0x00, 0xf3, 0x00, 0x00, 0xf5, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf7, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page21[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page22[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0xf9, 0xfb, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page25[256] = {
+       0xc4, 0x00, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0xda, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0xbf, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0xd9, 0x00, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0xc2, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0xc1, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0xc5, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0xcd, 0xba, 0xd5, 0xd6, 0xc9, 0xb8, 0xb7, 0xbb, /* 0x50-0x57 */
+       0xd4, 0xd3, 0xc8, 0xbe, 0xbd, 0xbc, 0xc6, 0xc7, /* 0x58-0x5f */
+       0xcc, 0xb5, 0xb6, 0xb9, 0xd1, 0xd2, 0xcb, 0xcf, /* 0x60-0x67 */
+       0xd0, 0xca, 0xd8, 0xd7, 0xce, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0xdf, 0x00, 0x00, 0x00, 0xdc, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0xdb, 0x00, 0x00, 0x00, 0xdd, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0xde, 0xb0, 0xb1, 0xb2, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char *page_uni2charset[256] = {
+       page00, NULL,   NULL,   NULL,   page04, NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   page21, page22, NULL,   NULL,   page25, NULL,   NULL,
+};
+
+#if 0
+static unsigned char charset2upper[256] = {
+       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+       0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
+       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
+       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
+       0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+       0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+       0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 0x80-0x87 */
+       0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, /* 0x88-0x8f */
+       0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, /* 0x90-0x97 */
+       0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
+       0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* 0xb8-0xbf */
+       0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xc0-0xc7 */
+       0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
+       0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
+       0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0xf0, 0x00, 0xf2, 0x00, 0xf4, 0x00, 0xf6, 0x00, /* 0xf0-0xf7 */
+       0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
+};
+#endif
+
+static struct unls_table table = {
+       "cp866",
+       page_uni2charset,
+       charset2uni,
+       NULL
+};
+
+int
+init_unls_cp866()
+{
+       return (register_unls(&table));
+}
diff --git a/libunls/nls_cp869.c b/libunls/nls_cp869.c
new file mode 100644 (file)
index 0000000..066f9e7
--- /dev/null
@@ -0,0 +1,328 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)nls_cp869.c     1.2 05/05/01 2000 J. Schilling */
+/*
+ *     Modifications to make the code portable Copyright (c) 2000 J. Schilling
+ *
+ *     Code taken from the Linux kernel.
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/*
+ * linux/fs/nls_cp869.c
+ *
+ * Charset cp869 translation tables.
+ * Generated automatically from the Unicode and charset
+ * tables from the Unicode Organization (www.unicode.org).
+ * The Unicode to charset table has only exact mappings.
+ */
+
+#include <mconfig.h>
+#include "nls.h"
+
+static struct unls_unicode charset2uni[256] = {
+       /* 0x00*/
+       {0x00, 0x00}, {0x01, 0x00}, {0x02, 0x00}, {0x03, 0x00},
+       {0x04, 0x00}, {0x05, 0x00}, {0x06, 0x00}, {0x07, 0x00},
+       {0x08, 0x00}, {0x09, 0x00}, {0x0a, 0x00}, {0x0b, 0x00},
+       {0x0c, 0x00}, {0x0d, 0x00}, {0x0e, 0x00}, {0x0f, 0x00},
+       /* 0x10*/
+       {0x10, 0x00}, {0x11, 0x00}, {0x12, 0x00}, {0x13, 0x00},
+       {0x14, 0x00}, {0x15, 0x00}, {0x16, 0x00}, {0x17, 0x00},
+       {0x18, 0x00}, {0x19, 0x00}, {0x1a, 0x00}, {0x1b, 0x00},
+       {0x1c, 0x00}, {0x1d, 0x00}, {0x1e, 0x00}, {0x1f, 0x00},
+       /* 0x20*/
+       {0x20, 0x00}, {0x21, 0x00}, {0x22, 0x00}, {0x23, 0x00},
+       {0x24, 0x00}, {0x25, 0x00}, {0x26, 0x00}, {0x27, 0x00},
+       {0x28, 0x00}, {0x29, 0x00}, {0x2a, 0x00}, {0x2b, 0x00},
+       {0x2c, 0x00}, {0x2d, 0x00}, {0x2e, 0x00}, {0x2f, 0x00},
+       /* 0x30*/
+       {0x30, 0x00}, {0x31, 0x00}, {0x32, 0x00}, {0x33, 0x00},
+       {0x34, 0x00}, {0x35, 0x00}, {0x36, 0x00}, {0x37, 0x00},
+       {0x38, 0x00}, {0x39, 0x00}, {0x3a, 0x00}, {0x3b, 0x00},
+       {0x3c, 0x00}, {0x3d, 0x00}, {0x3e, 0x00}, {0x3f, 0x00},
+       /* 0x40*/
+       {0x40, 0x00}, {0x41, 0x00}, {0x42, 0x00}, {0x43, 0x00},
+       {0x44, 0x00}, {0x45, 0x00}, {0x46, 0x00}, {0x47, 0x00},
+       {0x48, 0x00}, {0x49, 0x00}, {0x4a, 0x00}, {0x4b, 0x00},
+       {0x4c, 0x00}, {0x4d, 0x00}, {0x4e, 0x00}, {0x4f, 0x00},
+       /* 0x50*/
+       {0x50, 0x00}, {0x51, 0x00}, {0x52, 0x00}, {0x53, 0x00},
+       {0x54, 0x00}, {0x55, 0x00}, {0x56, 0x00}, {0x57, 0x00},
+       {0x58, 0x00}, {0x59, 0x00}, {0x5a, 0x00}, {0x5b, 0x00},
+       {0x5c, 0x00}, {0x5d, 0x00}, {0x5e, 0x00}, {0x5f, 0x00},
+       /* 0x60*/
+       {0x60, 0x00}, {0x61, 0x00}, {0x62, 0x00}, {0x63, 0x00},
+       {0x64, 0x00}, {0x65, 0x00}, {0x66, 0x00}, {0x67, 0x00},
+       {0x68, 0x00}, {0x69, 0x00}, {0x6a, 0x00}, {0x6b, 0x00},
+       {0x6c, 0x00}, {0x6d, 0x00}, {0x6e, 0x00}, {0x6f, 0x00},
+       /* 0x70*/
+       {0x70, 0x00}, {0x71, 0x00}, {0x72, 0x00}, {0x73, 0x00},
+       {0x74, 0x00}, {0x75, 0x00}, {0x76, 0x00}, {0x77, 0x00},
+       {0x78, 0x00}, {0x79, 0x00}, {0x7a, 0x00}, {0x7b, 0x00},
+       {0x7c, 0x00}, {0x7d, 0x00}, {0x7e, 0x00}, {0x7f, 0x00},
+       /* 0x80*/
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x86, 0x03}, {0x00, 0x00},
+       {0xb7, 0x00}, {0xac, 0x00}, {0xa6, 0x00}, {0x18, 0x20},
+       {0x19, 0x20}, {0x88, 0x03}, {0x15, 0x20}, {0x89, 0x03},
+       /* 0x90*/
+       {0x8a, 0x03}, {0xaa, 0x03}, {0x8c, 0x03}, {0x00, 0x00},
+       {0x00, 0x00}, {0x8e, 0x03}, {0xab, 0x03}, {0xa9, 0x00},
+       {0x8f, 0x03}, {0xb2, 0x00}, {0xb3, 0x00}, {0xac, 0x03},
+       {0xa3, 0x00}, {0xad, 0x03}, {0xae, 0x03}, {0xaf, 0x03},
+       /* 0xa0*/
+       {0xca, 0x03}, {0x90, 0x03}, {0xcc, 0x03}, {0xcd, 0x03},
+       {0x91, 0x03}, {0x92, 0x03}, {0x93, 0x03}, {0x94, 0x03},
+       {0x95, 0x03}, {0x96, 0x03}, {0x97, 0x03}, {0xbd, 0x00},
+       {0x98, 0x03}, {0x99, 0x03}, {0xab, 0x00}, {0xbb, 0x00},
+       /* 0xb0*/
+       {0x91, 0x25}, {0x92, 0x25}, {0x93, 0x25}, {0x02, 0x25},
+       {0x24, 0x25}, {0x9a, 0x03}, {0x9b, 0x03}, {0x9c, 0x03},
+       {0x9d, 0x03}, {0x63, 0x25}, {0x51, 0x25}, {0x57, 0x25},
+       {0x5d, 0x25}, {0x9e, 0x03}, {0x9f, 0x03}, {0x10, 0x25},
+       /* 0xc0*/
+       {0x14, 0x25}, {0x34, 0x25}, {0x2c, 0x25}, {0x1c, 0x25},
+       {0x00, 0x25}, {0x3c, 0x25}, {0xa0, 0x03}, {0xa1, 0x03},
+       {0x5a, 0x25}, {0x54, 0x25}, {0x69, 0x25}, {0x66, 0x25},
+       {0x60, 0x25}, {0x50, 0x25}, {0x6c, 0x25}, {0xa3, 0x03},
+       /* 0xd0*/
+       {0xa4, 0x03}, {0xa5, 0x03}, {0xa6, 0x03}, {0xa7, 0x03},
+       {0xa8, 0x03}, {0xa9, 0x03}, {0xb1, 0x03}, {0xb2, 0x03},
+       {0xb3, 0x03}, {0x18, 0x25}, {0x0c, 0x25}, {0x88, 0x25},
+       {0x84, 0x25}, {0xb4, 0x03}, {0xb5, 0x03}, {0x80, 0x25},
+       /* 0xe0*/
+       {0xb6, 0x03}, {0xb7, 0x03}, {0xb8, 0x03}, {0xb9, 0x03},
+       {0xba, 0x03}, {0xbb, 0x03}, {0xbc, 0x03}, {0xbd, 0x03},
+       {0xbe, 0x03}, {0xbf, 0x03}, {0xc0, 0x03}, {0xc1, 0x03},
+       {0xc3, 0x03}, {0xc2, 0x03}, {0xc4, 0x03}, {0x84, 0x03},
+       /* 0xf0*/
+       {0xad, 0x00}, {0xb1, 0x00}, {0xc5, 0x03}, {0xc6, 0x03},
+       {0xc7, 0x03}, {0xa7, 0x00}, {0xc8, 0x03}, {0x85, 0x03},
+       {0xb0, 0x00}, {0xa8, 0x00}, {0xc9, 0x03}, {0xcb, 0x03},
+       {0xb0, 0x03}, {0xce, 0x03}, {0xa0, 0x25}, {0xa0, 0x00},
+};
+
+static unsigned char page00[256] = {
+       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+       0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
+       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
+       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
+       0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+       0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */
+       0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */
+       0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */
+       0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0xff, 0x00, 0x00, 0x9c, 0x00, 0x00, 0x8a, 0xf5, /* 0xa0-0xa7 */
+       0xf9, 0x97, 0x00, 0xae, 0x89, 0xf0, 0x00, 0x00, /* 0xa8-0xaf */
+       0xf8, 0xf1, 0x99, 0x9a, 0x00, 0x00, 0x00, 0x88, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0xaf, 0x00, 0xab, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page03[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0xef, 0xf7, 0x86, 0x00, /* 0x80-0x87 */
+       0x8d, 0x8f, 0x90, 0x00, 0x92, 0x00, 0x95, 0x98, /* 0x88-0x8f */
+       0xa1, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, /* 0x90-0x97 */
+       0xac, 0xad, 0xb5, 0xb6, 0xb7, 0xb8, 0xbd, 0xbe, /* 0x98-0x9f */
+       0xc6, 0xc7, 0x00, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, /* 0xa0-0xa7 */
+       0xd4, 0xd5, 0x91, 0x96, 0x9b, 0x9d, 0x9e, 0x9f, /* 0xa8-0xaf */
+       0xfc, 0xd6, 0xd7, 0xd8, 0xdd, 0xde, 0xe0, 0xe1, /* 0xb0-0xb7 */
+       0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, /* 0xb8-0xbf */
+       0xea, 0xeb, 0xed, 0xec, 0xee, 0xf2, 0xf3, 0xf4, /* 0xc0-0xc7 */
+       0xf6, 0xfa, 0xa0, 0xfb, 0xa2, 0xa3, 0xfd, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page20[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x8e, 0x00, 0x00, /* 0x10-0x17 */
+       0x8b, 0x8c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page25[256] = {
+       0xc4, 0x00, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0xda, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0xbf, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0xd9, 0x00, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0xc2, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0xc1, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0xc5, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0xcd, 0xba, 0x00, 0x00, 0xc9, 0x00, 0x00, 0xbb, /* 0x50-0x57 */
+       0x00, 0x00, 0xc8, 0x00, 0x00, 0xbc, 0x00, 0x00, /* 0x58-0x5f */
+       0xcc, 0x00, 0x00, 0xb9, 0x00, 0x00, 0xcb, 0x00, /* 0x60-0x67 */
+       0x00, 0xca, 0x00, 0x00, 0xce, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0xdf, 0x00, 0x00, 0x00, 0xdc, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0xdb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0xb0, 0xb1, 0xb2, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char *page_uni2charset[256] = {
+       page00, NULL,   NULL,   page03, NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       page20, NULL,   NULL,   NULL,   NULL,   page25, NULL,   NULL,
+};
+
+#if 0
+static unsigned char charset2upper[256] = {
+       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+       0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
+       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
+       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
+       0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+       0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+       0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 0x80-0x87 */
+       0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, /* 0x88-0x8f */
+       0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, /* 0x90-0x97 */
+       0x98, 0x99, 0x9a, 0x00, 0x9c, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0xa4, 0xa5, 0xa6, 0xa7, /* 0xa0-0xa7 */
+       0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
+       0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
+       0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* 0xb8-0xbf */
+       0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xc0-0xc7 */
+       0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
+       0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0xd9, 0xda, 0xdb, 0xdc, 0x00, 0x00, 0xdf, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xef, /* 0xe8-0xef */
+       0xf0, 0xf1, 0x00, 0x00, 0x00, 0xf5, 0x00, 0xf7, /* 0xf0-0xf7 */
+       0xf8, 0xf9, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, /* 0xf8-0xff */
+};
+#endif
+
+static struct unls_table table = {
+       "cp869",
+       page_uni2charset,
+       charset2uni,
+       NULL
+};
+
+int
+init_unls_cp869()
+{
+       return (register_unls(&table));
+}
diff --git a/libunls/nls_cp874.c b/libunls/nls_cp874.c
new file mode 100644 (file)
index 0000000..4867c2c
--- /dev/null
@@ -0,0 +1,292 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)nls_cp874.c     1.2 05/05/01 2000 J. Schilling */
+/*
+ *     Modifications to make the code portable Copyright (c) 2000 J. Schilling
+ *
+ *     Code taken from the Linux kernel.
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/*
+ * linux/fs/nls_cp874.c
+ *
+ * Charset cp874 translation tables.
+ * Generated automatically from the Unicode and charset
+ * tables from the Unicode Organization (www.unicode.org).
+ * The Unicode to charset table has only exact mappings.
+ */
+
+#include <mconfig.h>
+#include "nls.h"
+
+static struct unls_unicode charset2uni[256] = {
+       /* 0x00*/
+       {0x00, 0x00}, {0x01, 0x00}, {0x02, 0x00}, {0x03, 0x00},
+       {0x04, 0x00}, {0x05, 0x00}, {0x06, 0x00}, {0x07, 0x00},
+       {0x08, 0x00}, {0x09, 0x00}, {0x0a, 0x00}, {0x0b, 0x00},
+       {0x0c, 0x00}, {0x0d, 0x00}, {0x0e, 0x00}, {0x0f, 0x00},
+       /* 0x10*/
+       {0x10, 0x00}, {0x11, 0x00}, {0x12, 0x00}, {0x13, 0x00},
+       {0x14, 0x00}, {0x15, 0x00}, {0x16, 0x00}, {0x17, 0x00},
+       {0x18, 0x00}, {0x19, 0x00}, {0x1a, 0x00}, {0x1b, 0x00},
+       {0x1c, 0x00}, {0x1d, 0x00}, {0x1e, 0x00}, {0x1f, 0x00},
+       /* 0x20*/
+       {0x20, 0x00}, {0x21, 0x00}, {0x22, 0x00}, {0x23, 0x00},
+       {0x24, 0x00}, {0x25, 0x00}, {0x26, 0x00}, {0x27, 0x00},
+       {0x28, 0x00}, {0x29, 0x00}, {0x2a, 0x00}, {0x2b, 0x00},
+       {0x2c, 0x00}, {0x2d, 0x00}, {0x2e, 0x00}, {0x2f, 0x00},
+       /* 0x30*/
+       {0x30, 0x00}, {0x31, 0x00}, {0x32, 0x00}, {0x33, 0x00},
+       {0x34, 0x00}, {0x35, 0x00}, {0x36, 0x00}, {0x37, 0x00},
+       {0x38, 0x00}, {0x39, 0x00}, {0x3a, 0x00}, {0x3b, 0x00},
+       {0x3c, 0x00}, {0x3d, 0x00}, {0x3e, 0x00}, {0x3f, 0x00},
+       /* 0x40*/
+       {0x40, 0x00}, {0x41, 0x00}, {0x42, 0x00}, {0x43, 0x00},
+       {0x44, 0x00}, {0x45, 0x00}, {0x46, 0x00}, {0x47, 0x00},
+       {0x48, 0x00}, {0x49, 0x00}, {0x4a, 0x00}, {0x4b, 0x00},
+       {0x4c, 0x00}, {0x4d, 0x00}, {0x4e, 0x00}, {0x4f, 0x00},
+       /* 0x50*/
+       {0x50, 0x00}, {0x51, 0x00}, {0x52, 0x00}, {0x53, 0x00},
+       {0x54, 0x00}, {0x55, 0x00}, {0x56, 0x00}, {0x57, 0x00},
+       {0x58, 0x00}, {0x59, 0x00}, {0x5a, 0x00}, {0x5b, 0x00},
+       {0x5c, 0x00}, {0x5d, 0x00}, {0x5e, 0x00}, {0x5f, 0x00},
+       /* 0x60*/
+       {0x60, 0x00}, {0x61, 0x00}, {0x62, 0x00}, {0x63, 0x00},
+       {0x64, 0x00}, {0x65, 0x00}, {0x66, 0x00}, {0x67, 0x00},
+       {0x68, 0x00}, {0x69, 0x00}, {0x6a, 0x00}, {0x6b, 0x00},
+       {0x6c, 0x00}, {0x6d, 0x00}, {0x6e, 0x00}, {0x6f, 0x00},
+       /* 0x70*/
+       {0x70, 0x00}, {0x71, 0x00}, {0x72, 0x00}, {0x73, 0x00},
+       {0x74, 0x00}, {0x75, 0x00}, {0x76, 0x00}, {0x77, 0x00},
+       {0x78, 0x00}, {0x79, 0x00}, {0x7a, 0x00}, {0x7b, 0x00},
+       {0x7c, 0x00}, {0x7d, 0x00}, {0x7e, 0x00}, {0x7f, 0x00},
+       /* 0x80*/
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x26, 0x20}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       /* 0x90*/
+       {0x00, 0x00}, {0x18, 0x20}, {0x19, 0x20}, {0x1c, 0x20},
+       {0x1d, 0x20}, {0x22, 0x20}, {0x13, 0x20}, {0x14, 0x20},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       /* 0xa0*/
+       {0xa0, 0x00}, {0x01, 0x0e}, {0x02, 0x0e}, {0x03, 0x0e},
+       {0x04, 0x0e}, {0x05, 0x0e}, {0x06, 0x0e}, {0x07, 0x0e},
+       {0x08, 0x0e}, {0x09, 0x0e}, {0x0a, 0x0e}, {0x0b, 0x0e},
+       {0x0c, 0x0e}, {0x0d, 0x0e}, {0x0e, 0x0e}, {0x0f, 0x0e},
+       /* 0xb0*/
+       {0x10, 0x0e}, {0x11, 0x0e}, {0x12, 0x0e}, {0x13, 0x0e},
+       {0x14, 0x0e}, {0x15, 0x0e}, {0x16, 0x0e}, {0x17, 0x0e},
+       {0x18, 0x0e}, {0x19, 0x0e}, {0x1a, 0x0e}, {0x1b, 0x0e},
+       {0x1c, 0x0e}, {0x1d, 0x0e}, {0x1e, 0x0e}, {0x1f, 0x0e},
+       /* 0xc0*/
+       {0x20, 0x0e}, {0x21, 0x0e}, {0x22, 0x0e}, {0x23, 0x0e},
+       {0x24, 0x0e}, {0x25, 0x0e}, {0x26, 0x0e}, {0x27, 0x0e},
+       {0x28, 0x0e}, {0x29, 0x0e}, {0x2a, 0x0e}, {0x2b, 0x0e},
+       {0x2c, 0x0e}, {0x2d, 0x0e}, {0x2e, 0x0e}, {0x2f, 0x0e},
+       /* 0xd0*/
+       {0x30, 0x0e}, {0x31, 0x0e}, {0x32, 0x0e}, {0x33, 0x0e},
+       {0x34, 0x0e}, {0x35, 0x0e}, {0x36, 0x0e}, {0x37, 0x0e},
+       {0x38, 0x0e}, {0x39, 0x0e}, {0x3a, 0x0e}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x3f, 0x0e},
+       /* 0xe0*/
+       {0x40, 0x0e}, {0x41, 0x0e}, {0x42, 0x0e}, {0x43, 0x0e},
+       {0x44, 0x0e}, {0x45, 0x0e}, {0x46, 0x0e}, {0x47, 0x0e},
+       {0x48, 0x0e}, {0x49, 0x0e}, {0x4a, 0x0e}, {0x4b, 0x0e},
+       {0x4c, 0x0e}, {0x4d, 0x0e}, {0x4e, 0x0e}, {0x4f, 0x0e},
+       /* 0xf0*/
+       {0x50, 0x0e}, {0x51, 0x0e}, {0x52, 0x0e}, {0x53, 0x0e},
+       {0x54, 0x0e}, {0x55, 0x0e}, {0x56, 0x0e}, {0x57, 0x0e},
+       {0x58, 0x0e}, {0x59, 0x0e}, {0x5a, 0x0e}, {0x5b, 0x0e},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+};
+
+static unsigned char page00[256] = {
+       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+       0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
+       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
+       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
+       0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+       0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */
+       0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */
+       0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */
+       0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page0e[256] = {
+       0x00, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, /* 0x00-0x07 */
+       0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0x08-0x0f */
+       0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0x10-0x17 */
+       0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* 0x18-0x1f */
+       0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0x20-0x27 */
+       0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0x28-0x2f */
+       0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0x30-0x37 */
+       0xd8, 0xd9, 0xda, 0x00, 0x00, 0x00, 0x00, 0xdf, /* 0x38-0x3f */
+       0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0x40-0x47 */
+       0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0x48-0x4f */
+       0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0x50-0x57 */
+       0xf8, 0xf9, 0xfa, 0xfb, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page20[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x96, 0x97, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x91, 0x92, 0x00, 0x00, 0x93, 0x94, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x85, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char *page_uni2charset[256] = {
+       page00, NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   page0e, NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       page20, NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+};
+
+#if 0
+static unsigned char charset2upper[256] = {
+       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+       0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
+       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
+       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
+       0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+       0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+       0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 0x80-0x87 */
+       0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, /* 0x88-0x8f */
+       0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, /* 0x90-0x97 */
+       0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, /* 0x98-0x9f */
+       0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, /* 0xa0-0xa7 */
+       0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
+       0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
+       0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* 0xb8-0xbf */
+       0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xc0-0xc7 */
+       0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
+       0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
+       0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, /* 0xd8-0xdf */
+       0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0xe0-0xe7 */
+       0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xe8-0xef */
+       0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
+       0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
+};
+#endif
+
+static struct unls_table table = {
+       "cp874",
+       page_uni2charset,
+       charset2uni,
+       NULL
+};
+
+int
+init_unls_cp874()
+{
+       return (register_unls(&table));
+}
diff --git a/libunls/nls_file.c b/libunls/nls_file.c
new file mode 100644 (file)
index 0000000..434679a
--- /dev/null
@@ -0,0 +1,189 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)nls_file.c      1.3 05/05/01 2000 J. Schilling */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/*
+ *     Modifications to make the code portable Copyright (c) 2000 J. Schilling
+ *
+ * nls_file: create a charset table from a input table file
+ * from the Unicode Organization (www.unicode.org).
+ * The Unicode to charset table has only exact mappings.
+ *
+ * Only reads single byte to word matches.
+ *
+ * James Pearson (j.pearson@ge.ucl.ac.uk) 16-Aug-2000
+ */
+
+#include <mconfig.h>
+#include <stdio.h>
+#include <stdxlib.h>
+#include <strdefs.h>
+#include <libport.h>
+#include "nls.h"
+
+#define        NUM     256
+
+static void    free_mem(struct unls_unicode *, unsigned char **);
+
+static void
+free_mem(struct unls_unicode *charset2uni, unsigned char **page_uni2charset)
+{
+       int     i;
+
+       if (charset2uni)
+               free(charset2uni);
+
+       if (page_uni2charset) {
+               for (i = 0; i < NUM; i++) {
+                       if (page_uni2charset[i]) {
+                               free(page_uni2charset[i]);
+                       }
+               }
+               free(page_uni2charset);
+       }
+}
+
+int
+init_unls_file(char *filename)
+{
+       FILE    *fp;
+       struct unls_unicode *charset2uni = NULL;
+       unsigned char **page_uni2charset = NULL;
+       char    buf[1024];
+       char    *p;
+       unsigned int    cp, uc;
+       struct unls_table *table;
+       int     i, ok = 0;
+
+       /* give up if no filename is given */
+       if (filename == NULL)
+               return (-1);
+
+       /*
+        * see if we already have a table with this name - built in tables
+        * have precedence of file tables - i.e. can't have the name of an
+        * existing table. Also, we may have already registered this file table
+        */
+       if (find_unls(filename) != NULL)
+               return (-1);
+
+       if ((fp = fopen(filename, "r")) == NULL)
+               return (-1);
+
+       /* allocate memory for the forward conversion table */
+       if ((charset2uni = (struct unls_unicode *)
+                       malloc(sizeof (struct unls_unicode) * NUM)) == NULL) {
+               free_mem(charset2uni, page_uni2charset);
+               return (-1);
+       }
+
+       /* any unknown character should be mapped to NULL */
+       memset(charset2uni, 0, sizeof (struct unls_unicode) * NUM);
+
+       /*
+        * some source files don't set the control characters 0x00 - 0x1f
+        * so set these by default
+        */
+       for (i = 0; i < 32; i++) {
+               charset2uni[i].unls_low = i;
+       }
+
+       /* also set DELETE (0x7f) by default */
+       charset2uni[0x7f].unls_low = 0x7f;
+
+       /* read each line of the file */
+       while (fgets(buf, sizeof (buf), fp) != NULL) {
+               /* cut off any comments */
+               if ((p = strchr(buf, '#')) != NULL)
+                       *p = '\0';
+
+               /* look for two hex values */
+               if (sscanf(buf, "%x%x", &cp, &uc) == 2) {
+                       /* if they are not in range - fail */
+                       if (cp > 0xff || uc > 0xffff) {
+                               continue;
+                       }
+
+                       /* set the Unicode value for the given code point */
+                       charset2uni[cp].unls_low  = uc & 0xff;
+                       charset2uni[cp].unls_high = (uc >> 8) & 0xff;
+
+                       /* make sure we find at least one pair ... */
+                       ok = 1;
+               }
+       }
+
+       fclose(fp);
+
+       if (!ok) {
+               /* we haven't found anything ... */
+               free_mem(charset2uni, page_uni2charset);
+               return (-1);
+       }
+
+       /* allocate memory for the reverse table */
+       if ((page_uni2charset = (unsigned char **)
+                       malloc(sizeof (unsigned char *) * NUM)) == NULL) {
+               free_mem(charset2uni, page_uni2charset);
+               return (-1);
+       }
+
+       memset(page_uni2charset, 0, sizeof (unsigned char *) * NUM);
+
+       /* loop through the forward table, setting the reverse value */
+       for (i = 0; i < NUM; i++) {
+               uc = charset2uni[i].unls_high;
+               cp = charset2uni[i].unls_low;
+               /* if the page doesn't exist, create a page */
+               if (page_uni2charset[uc] == NULL) {
+                       if ((page_uni2charset[uc] =
+                               (unsigned char *) malloc(NUM)) == NULL) {
+                               free_mem(charset2uni, page_uni2charset);
+                               return (-1);
+                       }
+                       memset(page_uni2charset[uc], 0, NUM);
+               }
+
+               /* set the reverse point in the page */
+               page_uni2charset[uc][cp] = i;
+       }
+
+       /* set up the table */
+       if ((table = (struct unls_table *)malloc(sizeof (struct unls_table)))
+                                                       == NULL) {
+               free_mem(charset2uni, page_uni2charset);
+               return (-1);
+       }
+
+       /* give the table the file name, so we can find it again if needed */
+       table->unls_name = strdup(filename);
+       table->unls_uni2cs = page_uni2charset;
+       table->unls_cs2uni = charset2uni;
+       table->unls_next = NULL;
+
+       /* register the table */
+       return (register_unls(table));
+}
diff --git a/libunls/nls_iconv.c b/libunls/nls_iconv.c
new file mode 100644 (file)
index 0000000..828e2af
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)nls_iconv.c     1.0 02/04/20 2002 J. Schilling  */
+/*
+ * 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; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/*
+ *     Modifications to make the code portable Copyright (c) 2000 J. Schilling
+ *
+ * nls_iconv: create a pseudo-charset table to use iconv() provided by C
+ * library or libiconv by Bruno Haible
+ * The Unicode to charset table has only exact mappings.
+ *
+ *
+ * Jungshik Shin (jshin@mailaps.org) 04-Feb-2002
+ */
+
+#ifdef USE_ICONV
+#include <mconfig.h>
+#include <stdio.h>
+#include <stdxlib.h>
+#include <strdefs.h>
+#include "nls.h"
+#include <iconv.h>
+
+static void    inc_use_count(void);
+static void    dec_use_count(void);
+
+
+static void
+inc_use_count()
+{
+       MOD_INC_USE_COUNT;
+}
+
+static void
+dec_use_count()
+{
+       MOD_DEC_USE_COUNT;
+}
+
+int
+init_nls_iconv(char *charset)
+{
+       iconv_t iconv_d;  /* iconv conversion descriptor */
+       struct unls_table *table;
+
+       /* give up if no charset is given */
+       if (charset == NULL)
+               return -1;
+
+       /* see if we already have a table with this name - built in tables
+          have precedence over iconv() - i.e. can't have the name of an
+          existing table. Also, we may have already registered this file
+          table */
+       if (find_unls(charset) != NULL)
+               return -1;
+
+       if ((iconv_d = iconv_open("UCS-2BE", charset)) == (iconv_t) -1)
+               return -1;
+
+
+       /* set up the table */
+       if ((table = (struct unls_table *)malloc(sizeof (struct unls_table)))
+                                                       == NULL) {
+               return -1;
+       }
+
+       /* give the table the file name, so we can find it again if needed */
+       table->unls_name = strdup(charset);
+       table->unls_uni2cs = NULL;
+       table->unls_cs2uni = NULL;
+       table->unls_next = NULL;
+       table->iconv_d = iconv_d;
+
+       /* register the table */
+       return register_unls(table);
+}
+#endif
diff --git a/libunls/nls_iso8859-1.c b/libunls/nls_iso8859-1.c
new file mode 100644 (file)
index 0000000..9b376cb
--- /dev/null
@@ -0,0 +1,216 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)nls_iso8859-1.c 1.2 05/05/01 2000 J. Schilling */
+/*
+ *     Modifications to make the code portable Copyright (c) 2000 J. Schilling
+ *
+ *     Code taken from the Linux kernel.
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/*
+ * linux/fs/nls_iso8859-1.c
+ *
+ * Charset iso8859-1 translation tables.
+ * Generated automatically from the Unicode and charset
+ * tables from the Unicode Organization (www.unicode.org).
+ * The Unicode to charset table has only exact mappings.
+ */
+
+#include <mconfig.h>
+#include "nls.h"
+
+static struct unls_unicode charset2uni[256] = {
+       /* 0x00*/
+       {0x00, 0x00}, {0x01, 0x00}, {0x02, 0x00}, {0x03, 0x00},
+       {0x04, 0x00}, {0x05, 0x00}, {0x06, 0x00}, {0x07, 0x00},
+       {0x08, 0x00}, {0x09, 0x00}, {0x0a, 0x00}, {0x0b, 0x00},
+       {0x0c, 0x00}, {0x0d, 0x00}, {0x0e, 0x00}, {0x0f, 0x00},
+       /* 0x10*/
+       {0x10, 0x00}, {0x11, 0x00}, {0x12, 0x00}, {0x13, 0x00},
+       {0x14, 0x00}, {0x15, 0x00}, {0x16, 0x00}, {0x17, 0x00},
+       {0x18, 0x00}, {0x19, 0x00}, {0x1a, 0x00}, {0x1b, 0x00},
+       {0x1c, 0x00}, {0x1d, 0x00}, {0x1e, 0x00}, {0x1f, 0x00},
+       /* 0x20*/
+       {0x20, 0x00}, {0x21, 0x00}, {0x22, 0x00}, {0x23, 0x00},
+       {0x24, 0x00}, {0x25, 0x00}, {0x26, 0x00}, {0x27, 0x00},
+       {0x28, 0x00}, {0x29, 0x00}, {0x2a, 0x00}, {0x2b, 0x00},
+       {0x2c, 0x00}, {0x2d, 0x00}, {0x2e, 0x00}, {0x2f, 0x00},
+       /* 0x30*/
+       {0x30, 0x00}, {0x31, 0x00}, {0x32, 0x00}, {0x33, 0x00},
+       {0x34, 0x00}, {0x35, 0x00}, {0x36, 0x00}, {0x37, 0x00},
+       {0x38, 0x00}, {0x39, 0x00}, {0x3a, 0x00}, {0x3b, 0x00},
+       {0x3c, 0x00}, {0x3d, 0x00}, {0x3e, 0x00}, {0x3f, 0x00},
+       /* 0x40*/
+       {0x40, 0x00}, {0x41, 0x00}, {0x42, 0x00}, {0x43, 0x00},
+       {0x44, 0x00}, {0x45, 0x00}, {0x46, 0x00}, {0x47, 0x00},
+       {0x48, 0x00}, {0x49, 0x00}, {0x4a, 0x00}, {0x4b, 0x00},
+       {0x4c, 0x00}, {0x4d, 0x00}, {0x4e, 0x00}, {0x4f, 0x00},
+       /* 0x50*/
+       {0x50, 0x00}, {0x51, 0x00}, {0x52, 0x00}, {0x53, 0x00},
+       {0x54, 0x00}, {0x55, 0x00}, {0x56, 0x00}, {0x57, 0x00},
+       {0x58, 0x00}, {0x59, 0x00}, {0x5a, 0x00}, {0x5b, 0x00},
+       {0x5c, 0x00}, {0x5d, 0x00}, {0x5e, 0x00}, {0x5f, 0x00},
+       /* 0x60*/
+       {0x60, 0x00}, {0x61, 0x00}, {0x62, 0x00}, {0x63, 0x00},
+       {0x64, 0x00}, {0x65, 0x00}, {0x66, 0x00}, {0x67, 0x00},
+       {0x68, 0x00}, {0x69, 0x00}, {0x6a, 0x00}, {0x6b, 0x00},
+       {0x6c, 0x00}, {0x6d, 0x00}, {0x6e, 0x00}, {0x6f, 0x00},
+       /* 0x70*/
+       {0x70, 0x00}, {0x71, 0x00}, {0x72, 0x00}, {0x73, 0x00},
+       {0x74, 0x00}, {0x75, 0x00}, {0x76, 0x00}, {0x77, 0x00},
+       {0x78, 0x00}, {0x79, 0x00}, {0x7a, 0x00}, {0x7b, 0x00},
+       {0x7c, 0x00}, {0x7d, 0x00}, {0x7e, 0x00}, {0x7f, 0x00},
+       /* 0x80*/
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       /* 0x90*/
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       /* 0xa0*/
+       {0xa0, 0x00}, {0xa1, 0x00}, {0xa2, 0x00}, {0xa3, 0x00},
+       {0xa4, 0x00}, {0xa5, 0x00}, {0xa6, 0x00}, {0xa7, 0x00},
+       {0xa8, 0x00}, {0xa9, 0x00}, {0xaa, 0x00}, {0xab, 0x00},
+       {0xac, 0x00}, {0xad, 0x00}, {0xae, 0x00}, {0xaf, 0x00},
+       /* 0xb0*/
+       {0xb0, 0x00}, {0xb1, 0x00}, {0xb2, 0x00}, {0xb3, 0x00},
+       {0xb4, 0x00}, {0xb5, 0x00}, {0xb6, 0x00}, {0xb7, 0x00},
+       {0xb8, 0x00}, {0xb9, 0x00}, {0xba, 0x00}, {0xbb, 0x00},
+       {0xbc, 0x00}, {0xbd, 0x00}, {0xbe, 0x00}, {0xbf, 0x00},
+       /* 0xc0*/
+       {0xc0, 0x00}, {0xc1, 0x00}, {0xc2, 0x00}, {0xc3, 0x00},
+       {0xc4, 0x00}, {0xc5, 0x00}, {0xc6, 0x00}, {0xc7, 0x00},
+       {0xc8, 0x00}, {0xc9, 0x00}, {0xca, 0x00}, {0xcb, 0x00},
+       {0xcc, 0x00}, {0xcd, 0x00}, {0xce, 0x00}, {0xcf, 0x00},
+       /* 0xd0*/
+       {0xd0, 0x00}, {0xd1, 0x00}, {0xd2, 0x00}, {0xd3, 0x00},
+       {0xd4, 0x00}, {0xd5, 0x00}, {0xd6, 0x00}, {0xd7, 0x00},
+       {0xd8, 0x00}, {0xd9, 0x00}, {0xda, 0x00}, {0xdb, 0x00},
+       {0xdc, 0x00}, {0xdd, 0x00}, {0xde, 0x00}, {0xdf, 0x00},
+       /* 0xe0*/
+       {0xe0, 0x00}, {0xe1, 0x00}, {0xe2, 0x00}, {0xe3, 0x00},
+       {0xe4, 0x00}, {0xe5, 0x00}, {0xe6, 0x00}, {0xe7, 0x00},
+       {0xe8, 0x00}, {0xe9, 0x00}, {0xea, 0x00}, {0xeb, 0x00},
+       {0xec, 0x00}, {0xed, 0x00}, {0xee, 0x00}, {0xef, 0x00},
+       /* 0xf0*/
+       {0xf0, 0x00}, {0xf1, 0x00}, {0xf2, 0x00}, {0xf3, 0x00},
+       {0xf4, 0x00}, {0xf5, 0x00}, {0xf6, 0x00}, {0xf7, 0x00},
+       {0xf8, 0x00}, {0xf9, 0x00}, {0xfa, 0x00}, {0xfb, 0x00},
+       {0xfc, 0x00}, {0xfd, 0x00}, {0xfe, 0x00}, {0xff, 0x00},
+};
+
+static unsigned char page00[256] = {
+       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+       0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
+       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
+       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
+       0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+       0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */
+       0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */
+       0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */
+       0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, /* 0xa0-0xa7 */
+       0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
+       0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
+       0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* 0xb8-0xbf */
+       0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xc0-0xc7 */
+       0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
+       0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
+       0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, /* 0xd8-0xdf */
+       0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0xe0-0xe7 */
+       0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xe8-0xef */
+       0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
+       0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
+};
+
+static unsigned char *page_uni2charset[256] = {
+       page00, NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+};
+
+#if 0
+static unsigned char charset2upper[256] = {
+       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+       0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
+       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
+       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
+       0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+       0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+       0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 0x80-0x87 */
+       0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, /* 0x88-0x8f */
+       0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, /* 0x90-0x97 */
+       0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, /* 0x98-0x9f */
+       0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, /* 0xa0-0xa7 */
+       0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
+       0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
+       0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* 0xb8-0xbf */
+       0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xc0-0xc7 */
+       0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
+       0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
+       0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf7, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+#endif
+
+static struct unls_table table = {
+       "iso8859-1",
+       page_uni2charset,
+       charset2uni,
+       NULL
+};
+
+int
+init_unls_iso8859_1()
+{
+       return (register_unls(&table));
+}
diff --git a/libunls/nls_iso8859-14.c b/libunls/nls_iso8859-14.c
new file mode 100644 (file)
index 0000000..ea7754e
--- /dev/null
@@ -0,0 +1,263 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)nls_iso8859-14.c        1.2 05/05/01 2000 J. Schilling */
+/*
+ *     Modifications to make the code portable Copyright (c) 2000 J. Schilling
+ *
+ *     Code taken from the Linux kernel.
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/*
+ * linux/fs/nls_iso8859-14.c
+ *
+ * Charset iso8859-14 translation tables.
+ *
+ * Generated automatically from the Unicode and charset table
+ * provided by the Unicode Organisation at
+ * http://www.unicode.org/
+ * The Unicode to charset table has only exact mappings.
+ *
+ * Rhys Jones, Swansea University Computer Society
+ * rhys@sucs.swan.ac.uk
+ */
+
+#include <mconfig.h>
+#include "nls.h"
+
+static struct unls_unicode charset2uni[256] = {
+       /* 0x00*/
+       {0x00, 0x00}, {0x01, 0x00}, {0x02, 0x00}, {0x03, 0x00},
+       {0x04, 0x00}, {0x05, 0x00}, {0x06, 0x00}, {0x07, 0x00},
+       {0x08, 0x00}, {0x09, 0x00}, {0x0a, 0x00}, {0x0b, 0x00},
+       {0x0c, 0x00}, {0x0d, 0x00}, {0x0e, 0x00}, {0x0f, 0x00},
+       /* 0x10*/
+       {0x10, 0x00}, {0x11, 0x00}, {0x12, 0x00}, {0x13, 0x00},
+       {0x14, 0x00}, {0x15, 0x00}, {0x16, 0x00}, {0x17, 0x00},
+       {0x18, 0x00}, {0x19, 0x00}, {0x1a, 0x00}, {0x1b, 0x00},
+       {0x1c, 0x00}, {0x1d, 0x00}, {0x1e, 0x00}, {0x1f, 0x00},
+       /* 0x20*/
+       {0x20, 0x00}, {0x21, 0x00}, {0x22, 0x00}, {0x23, 0x00},
+       {0x24, 0x00}, {0x25, 0x00}, {0x26, 0x00}, {0x27, 0x00},
+       {0x28, 0x00}, {0x29, 0x00}, {0x2a, 0x00}, {0x2b, 0x00},
+       {0x2c, 0x00}, {0x2d, 0x00}, {0x2e, 0x00}, {0x2f, 0x00},
+       /* 0x30*/
+       {0x30, 0x00}, {0x31, 0x00}, {0x32, 0x00}, {0x33, 0x00},
+       {0x34, 0x00}, {0x35, 0x00}, {0x36, 0x00}, {0x37, 0x00},
+       {0x38, 0x00}, {0x39, 0x00}, {0x3a, 0x00}, {0x3b, 0x00},
+       {0x3c, 0x00}, {0x3d, 0x00}, {0x3e, 0x00}, {0x3f, 0x00},
+       /* 0x40*/
+       {0x40, 0x00}, {0x41, 0x00}, {0x42, 0x00}, {0x43, 0x00},
+       {0x44, 0x00}, {0x45, 0x00}, {0x46, 0x00}, {0x47, 0x00},
+       {0x48, 0x00}, {0x49, 0x00}, {0x4a, 0x00}, {0x4b, 0x00},
+       {0x4c, 0x00}, {0x4d, 0x00}, {0x4e, 0x00}, {0x4f, 0x00},
+       /* 0x50*/
+       {0x50, 0x00}, {0x51, 0x00}, {0x52, 0x00}, {0x53, 0x00},
+       {0x54, 0x00}, {0x55, 0x00}, {0x56, 0x00}, {0x57, 0x00},
+       {0x58, 0x00}, {0x59, 0x00}, {0x5a, 0x00}, {0x5b, 0x00},
+       {0x5c, 0x00}, {0x5d, 0x00}, {0x5e, 0x00}, {0x5f, 0x00},
+       /* 0x60*/
+       {0x60, 0x00}, {0x61, 0x00}, {0x62, 0x00}, {0x63, 0x00},
+       {0x64, 0x00}, {0x65, 0x00}, {0x66, 0x00}, {0x67, 0x00},
+       {0x68, 0x00}, {0x69, 0x00}, {0x6a, 0x00}, {0x6b, 0x00},
+       {0x6c, 0x00}, {0x6d, 0x00}, {0x6e, 0x00}, {0x6f, 0x00},
+       /* 0x70*/
+       {0x70, 0x00}, {0x71, 0x00}, {0x72, 0x00}, {0x73, 0x00},
+       {0x74, 0x00}, {0x75, 0x00}, {0x76, 0x00}, {0x77, 0x00},
+       {0x78, 0x00}, {0x79, 0x00}, {0x7a, 0x00}, {0x7b, 0x00},
+       {0x7c, 0x00}, {0x7d, 0x00}, {0x7e, 0x00}, {0x7f, 0x00},
+       /* 0x80*/
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       /* 0x90*/
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       /* 0xa0*/
+       {0xa0, 0x00}, {0x02, 0x1e}, {0x03, 0x1e}, {0xa3, 0x00},
+       {0x0a, 0x01}, {0x0b, 0x01}, {0x0a, 0x1e}, {0xa7, 0x00},
+       {0x80, 0x1e}, {0xa9, 0x00}, {0x82, 0x1e}, {0x0b, 0x1e},
+       {0xf2, 0x1e}, {0xad, 0x00}, {0xae, 0x00}, {0x78, 0x01},
+       /* 0xb0*/
+       {0x1e, 0x1e}, {0x1f, 0x1e}, {0x20, 0x01}, {0x21, 0x01},
+       {0x40, 0x1e}, {0x41, 0x1e}, {0xb6, 0x00}, {0x56, 0x1e},
+       {0x81, 0x1e}, {0x57, 0x1e}, {0x83, 0x1e}, {0x60, 0x1e},
+       {0xf3, 0x1e}, {0x84, 0x1e}, {0x85, 0x1e}, {0x61, 0x1e},
+       /* 0xc0*/
+       {0xc0, 0x00}, {0xc1, 0x00}, {0xc2, 0x00}, {0xc3, 0x00},
+       {0xc4, 0x00}, {0xc5, 0x00}, {0xc6, 0x00}, {0xc7, 0x00},
+       {0xc8, 0x00}, {0xc9, 0x00}, {0xca, 0x00}, {0xcb, 0x00},
+       {0xcc, 0x00}, {0xcd, 0x00}, {0xce, 0x00}, {0xcf, 0x00},
+       /* 0xd0*/
+       {0x74, 0x01}, {0xd1, 0x00}, {0xd2, 0x00}, {0xd3, 0x00},
+       {0xd4, 0x00}, {0xd5, 0x00}, {0xd6, 0x00}, {0x6a, 0x1e},
+       {0xd8, 0x00}, {0xd9, 0x00}, {0xda, 0x00}, {0xdb, 0x00},
+       {0xdc, 0x00}, {0xdd, 0x00}, {0x76, 0x01}, {0xdf, 0x00},
+       /* 0xe0*/
+       {0xe0, 0x00}, {0xe1, 0x00}, {0xe2, 0x00}, {0xe3, 0x00},
+       {0xe4, 0x00}, {0xe5, 0x00}, {0xe6, 0x00}, {0xe7, 0x00},
+       {0xe8, 0x00}, {0xe9, 0x00}, {0xea, 0x00}, {0xeb, 0x00},
+       {0xec, 0x00}, {0xed, 0x00}, {0xee, 0x00}, {0xef, 0x00},
+       /* 0xf0*/
+       {0x75, 0x01}, {0xf1, 0x00}, {0xf2, 0x00}, {0xf3, 0x00},
+       {0xf4, 0x00}, {0xf5, 0x00}, {0xf6, 0x00}, {0x6b, 0x1e},
+       {0xf8, 0x00}, {0xf9, 0x00}, {0xfa, 0x00}, {0xfb, 0x00},
+       {0xfc, 0x00}, {0xfd, 0x00}, {0x77, 0x01}, {0xff, 0x00},
+};
+
+static unsigned char page00[256] = {
+       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+       0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
+       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
+       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
+       0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+       0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */
+       0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */
+       0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */
+       0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0xa0, 0x00, 0x00, 0xa3, 0x00, 0x00, 0x00, 0xa7, /* 0xa0-0xa7 */
+       0x00, 0xa9, 0x00, 0x00, 0x00, 0xad, 0xae, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb6, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xc0-0xc7 */
+       0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
+       0x00, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0x00, /* 0xd0-0xd7 */
+       0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0x00, 0xdf, /* 0xd8-0xdf */
+       0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0xe0-0xe7 */
+       0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xe8-0xef */
+       0x00, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0x00, /* 0xf0-0xf7 */
+       0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0x00, 0xff, /* 0xf8-0xff */
+};
+
+static unsigned char page01[256] = {
+       0x00, 0x00, 0xa1, 0xa2, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0xa6, 0xab, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0xb1, /* 0x18-0x1f */
+       0xb2, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0xb4, 0xb5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb7, 0xb9, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0xbb, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0xd7, 0xf7, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0xd0, 0xf0, 0xde, 0xfe, /* 0x70-0x77 */
+       0xaf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0xa8, 0xb8, 0xaa, 0xba, 0xbd, 0xbe, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0xac, 0xbc, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page1e[256] = {
+       0x00, 0x00, 0xa1, 0xa2, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0xa6, 0xab, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0xb1, /* 0x18-0x1f */
+       0xb2, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0xb4, 0xb5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb7, 0xb9, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0xbb, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0xd7, 0xf7, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0xd0, 0xf0, 0xde, 0xfe, /* 0x70-0x77 */
+       0xaf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0xa8, 0xb8, 0xaa, 0xba, 0xbd, 0xbe, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0xac, 0xbc, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char *page_uni2charset[256] = {
+       page00, page01, NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   page1e, NULL,
+
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+};
+
+static struct unls_table table = {
+       "iso8859-14",
+       page_uni2charset,
+       charset2uni,
+       NULL
+};
+
+int
+init_unls_iso8859_14()
+{
+       return (register_unls(&table));
+}
diff --git a/libunls/nls_iso8859-15.c b/libunls/nls_iso8859-15.c
new file mode 100644 (file)
index 0000000..8094f6c
--- /dev/null
@@ -0,0 +1,256 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)nls_iso8859-15.c        1.2 05/05/01 2000 J. Schilling */
+/*
+ *     Modifications to make the code portable Copyright (c) 2000 J. Schilling
+ *
+ *     Code taken from the Linux kernel.
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/*
+ * linux/fs/nls_iso8859-15.c
+ *
+ * Charset iso8859-15 translation tables.
+ * The Unicode to charset table has only exact mappings.
+ */
+
+#include <mconfig.h>
+#include "nls.h"
+
+static struct unls_unicode charset2uni[256] = {
+       /* 0x00*/
+       {0x00, 0x00}, {0x01, 0x00}, {0x02, 0x00}, {0x03, 0x00},
+       {0x04, 0x00}, {0x05, 0x00}, {0x06, 0x00}, {0x07, 0x00},
+       {0x08, 0x00}, {0x09, 0x00}, {0x0a, 0x00}, {0x0b, 0x00},
+       {0x0c, 0x00}, {0x0d, 0x00}, {0x0e, 0x00}, {0x0f, 0x00},
+       /* 0x10*/
+       {0x10, 0x00}, {0x11, 0x00}, {0x12, 0x00}, {0x13, 0x00},
+       {0x14, 0x00}, {0x15, 0x00}, {0x16, 0x00}, {0x17, 0x00},
+       {0x18, 0x00}, {0x19, 0x00}, {0x1a, 0x00}, {0x1b, 0x00},
+       {0x1c, 0x00}, {0x1d, 0x00}, {0x1e, 0x00}, {0x1f, 0x00},
+       /* 0x20*/
+       {0x20, 0x00}, {0x21, 0x00}, {0x22, 0x00}, {0x23, 0x00},
+       {0x24, 0x00}, {0x25, 0x00}, {0x26, 0x00}, {0x27, 0x00},
+       {0x28, 0x00}, {0x29, 0x00}, {0x2a, 0x00}, {0x2b, 0x00},
+       {0x2c, 0x00}, {0x2d, 0x00}, {0x2e, 0x00}, {0x2f, 0x00},
+       /* 0x30*/
+       {0x30, 0x00}, {0x31, 0x00}, {0x32, 0x00}, {0x33, 0x00},
+       {0x34, 0x00}, {0x35, 0x00}, {0x36, 0x00}, {0x37, 0x00},
+       {0x38, 0x00}, {0x39, 0x00}, {0x3a, 0x00}, {0x3b, 0x00},
+       {0x3c, 0x00}, {0x3d, 0x00}, {0x3e, 0x00}, {0x3f, 0x00},
+       /* 0x40*/
+       {0x40, 0x00}, {0x41, 0x00}, {0x42, 0x00}, {0x43, 0x00},
+       {0x44, 0x00}, {0x45, 0x00}, {0x46, 0x00}, {0x47, 0x00},
+       {0x48, 0x00}, {0x49, 0x00}, {0x4a, 0x00}, {0x4b, 0x00},
+       {0x4c, 0x00}, {0x4d, 0x00}, {0x4e, 0x00}, {0x4f, 0x00},
+       /* 0x50*/
+       {0x50, 0x00}, {0x51, 0x00}, {0x52, 0x00}, {0x53, 0x00},
+       {0x54, 0x00}, {0x55, 0x00}, {0x56, 0x00}, {0x57, 0x00},
+       {0x58, 0x00}, {0x59, 0x00}, {0x5a, 0x00}, {0x5b, 0x00},
+       {0x5c, 0x00}, {0x5d, 0x00}, {0x5e, 0x00}, {0x5f, 0x00},
+       /* 0x60*/
+       {0x60, 0x00}, {0x61, 0x00}, {0x62, 0x00}, {0x63, 0x00},
+       {0x64, 0x00}, {0x65, 0x00}, {0x66, 0x00}, {0x67, 0x00},
+       {0x68, 0x00}, {0x69, 0x00}, {0x6a, 0x00}, {0x6b, 0x00},
+       {0x6c, 0x00}, {0x6d, 0x00}, {0x6e, 0x00}, {0x6f, 0x00},
+       /* 0x70*/
+       {0x70, 0x00}, {0x71, 0x00}, {0x72, 0x00}, {0x73, 0x00},
+       {0x74, 0x00}, {0x75, 0x00}, {0x76, 0x00}, {0x77, 0x00},
+       {0x78, 0x00}, {0x79, 0x00}, {0x7a, 0x00}, {0x7b, 0x00},
+       {0x7c, 0x00}, {0x7d, 0x00}, {0x7e, 0x00}, {0x7f, 0x00},
+       /* 0x80*/
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       /* 0x90*/
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       /* 0xa0*/
+       {0xa0, 0x00}, {0xa1, 0x00}, {0xa2, 0x00}, {0xa3, 0x00},
+       {0xac, 0x20}, {0xa5, 0x00}, {0x60, 0x01}, {0xa7, 0x00},
+       {0x61, 0x01}, {0xa9, 0x00}, {0xaa, 0x00}, {0xab, 0x00},
+       {0xac, 0x00}, {0xad, 0x00}, {0xae, 0x00}, {0xaf, 0x00},
+       /* 0xb0*/
+       {0xb0, 0x00}, {0xb1, 0x00}, {0xb2, 0x00}, {0xb3, 0x00},
+       {0x7d, 0x01}, {0xb5, 0x00}, {0xb6, 0x00}, {0xb7, 0x00},
+       {0x7e, 0x01}, {0xb9, 0x00}, {0xba, 0x00}, {0xbb, 0x00},
+       {0x52, 0x01}, {0x53, 0x01}, {0x78, 0x01}, {0xbf, 0x00},
+       /* 0xc0*/
+       {0xc0, 0x00}, {0xc1, 0x00}, {0xc2, 0x00}, {0xc3, 0x00},
+       {0xc4, 0x00}, {0xc5, 0x00}, {0xc6, 0x00}, {0xc7, 0x00},
+       {0xc8, 0x00}, {0xc9, 0x00}, {0xca, 0x00}, {0xcb, 0x00},
+       {0xcc, 0x00}, {0xcd, 0x00}, {0xce, 0x00}, {0xcf, 0x00},
+       /* 0xd0*/
+       {0xd0, 0x00}, {0xd1, 0x00}, {0xd2, 0x00}, {0xd3, 0x00},
+       {0xd4, 0x00}, {0xd5, 0x00}, {0xd6, 0x00}, {0xd7, 0x00},
+       {0xd8, 0x00}, {0xd9, 0x00}, {0xda, 0x00}, {0xdb, 0x00},
+       {0xdc, 0x00}, {0xdd, 0x00}, {0xde, 0x00}, {0xdf, 0x00},
+       /* 0xe0*/
+       {0xe0, 0x00}, {0xe1, 0x00}, {0xe2, 0x00}, {0xe3, 0x00},
+       {0xe4, 0x00}, {0xe5, 0x00}, {0xe6, 0x00}, {0xe7, 0x00},
+       {0xe8, 0x00}, {0xe9, 0x00}, {0xea, 0x00}, {0xeb, 0x00},
+       {0xec, 0x00}, {0xed, 0x00}, {0xee, 0x00}, {0xef, 0x00},
+       /* 0xf0*/
+       {0xf0, 0x00}, {0xf1, 0x00}, {0xf2, 0x00}, {0xf3, 0x00},
+       {0xf4, 0x00}, {0xf5, 0x00}, {0xf6, 0x00}, {0xf7, 0x00},
+       {0xf8, 0x00}, {0xf9, 0x00}, {0xfa, 0x00}, {0xfb, 0x00},
+       {0xfc, 0x00}, {0xfd, 0x00}, {0xfe, 0x00}, {0xff, 0x00},
+};
+
+static unsigned char page00[256] = {
+       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+       0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
+       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
+       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
+       0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+       0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */
+       0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */
+       0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */
+       0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0xa0, 0xa1, 0xa2, 0xa3, 0x00, 0xa5, 0x00, 0xa7, /* 0xa0-0xa7 */
+       0x00, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
+       0xb0, 0xb1, 0xb2, 0xb3, 0x00, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
+       0x00, 0xb9, 0xba, 0xbb, 0x00, 0x00, 0x00, 0xbf, /* 0xb8-0xbf */
+       0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xc0-0xc7 */
+       0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
+       0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
+       0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, /* 0xd8-0xdf */
+       0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0xe0-0xe7 */
+       0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xe8-0xef */
+       0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
+       0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
+};
+
+static unsigned char page01[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0xbc, 0xbd, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0xa6, 0xa8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0xbe, 0x00, 0x00, 0x00, 0x00, 0xb4, 0xb8, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page20[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char *page_uni2charset[256] = {
+       page00, page01, NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+
+       page20, NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+};
+
+static struct unls_table table = {
+       "iso8859-15",
+       page_uni2charset,
+       charset2uni,
+       NULL
+};
+
+int
+init_unls_iso8859_15()
+{
+       return (register_unls(&table));
+}
diff --git a/libunls/nls_iso8859-2.c b/libunls/nls_iso8859-2.c
new file mode 100644 (file)
index 0000000..e0c1052
--- /dev/null
@@ -0,0 +1,288 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)nls_iso8859-2.c 1.2 05/05/01 2000 J. Schilling */
+/*
+ *     Modifications to make the code portable Copyright (c) 2000 J. Schilling
+ *
+ *     Code taken from the Linux kernel.
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/*
+ * linux/fs/nls_iso8859-2.c
+ *
+ * Charset iso8859-2 translation tables.
+ * Generated automatically from the Unicode and charset
+ * tables from the Unicode Organization (www.unicode.org).
+ * The Unicode to charset table has only exact mappings.
+ */
+
+#include <mconfig.h>
+#include "nls.h"
+
+static struct unls_unicode charset2uni[256] = {
+       /* 0x00*/
+       {0x00, 0x00}, {0x01, 0x00}, {0x02, 0x00}, {0x03, 0x00},
+       {0x04, 0x00}, {0x05, 0x00}, {0x06, 0x00}, {0x07, 0x00},
+       {0x08, 0x00}, {0x09, 0x00}, {0x0a, 0x00}, {0x0b, 0x00},
+       {0x0c, 0x00}, {0x0d, 0x00}, {0x0e, 0x00}, {0x0f, 0x00},
+       /* 0x10*/
+       {0x10, 0x00}, {0x11, 0x00}, {0x12, 0x00}, {0x13, 0x00},
+       {0x14, 0x00}, {0x15, 0x00}, {0x16, 0x00}, {0x17, 0x00},
+       {0x18, 0x00}, {0x19, 0x00}, {0x1a, 0x00}, {0x1b, 0x00},
+       {0x1c, 0x00}, {0x1d, 0x00}, {0x1e, 0x00}, {0x1f, 0x00},
+       /* 0x20*/
+       {0x20, 0x00}, {0x21, 0x00}, {0x22, 0x00}, {0x23, 0x00},
+       {0x24, 0x00}, {0x25, 0x00}, {0x26, 0x00}, {0x27, 0x00},
+       {0x28, 0x00}, {0x29, 0x00}, {0x2a, 0x00}, {0x2b, 0x00},
+       {0x2c, 0x00}, {0x2d, 0x00}, {0x2e, 0x00}, {0x2f, 0x00},
+       /* 0x30*/
+       {0x30, 0x00}, {0x31, 0x00}, {0x32, 0x00}, {0x33, 0x00},
+       {0x34, 0x00}, {0x35, 0x00}, {0x36, 0x00}, {0x37, 0x00},
+       {0x38, 0x00}, {0x39, 0x00}, {0x3a, 0x00}, {0x3b, 0x00},
+       {0x3c, 0x00}, {0x3d, 0x00}, {0x3e, 0x00}, {0x3f, 0x00},
+       /* 0x40*/
+       {0x40, 0x00}, {0x41, 0x00}, {0x42, 0x00}, {0x43, 0x00},
+       {0x44, 0x00}, {0x45, 0x00}, {0x46, 0x00}, {0x47, 0x00},
+       {0x48, 0x00}, {0x49, 0x00}, {0x4a, 0x00}, {0x4b, 0x00},
+       {0x4c, 0x00}, {0x4d, 0x00}, {0x4e, 0x00}, {0x4f, 0x00},
+       /* 0x50*/
+       {0x50, 0x00}, {0x51, 0x00}, {0x52, 0x00}, {0x53, 0x00},
+       {0x54, 0x00}, {0x55, 0x00}, {0x56, 0x00}, {0x57, 0x00},
+       {0x58, 0x00}, {0x59, 0x00}, {0x5a, 0x00}, {0x5b, 0x00},
+       {0x5c, 0x00}, {0x5d, 0x00}, {0x5e, 0x00}, {0x5f, 0x00},
+       /* 0x60*/
+       {0x60, 0x00}, {0x61, 0x00}, {0x62, 0x00}, {0x63, 0x00},
+       {0x64, 0x00}, {0x65, 0x00}, {0x66, 0x00}, {0x67, 0x00},
+       {0x68, 0x00}, {0x69, 0x00}, {0x6a, 0x00}, {0x6b, 0x00},
+       {0x6c, 0x00}, {0x6d, 0x00}, {0x6e, 0x00}, {0x6f, 0x00},
+       /* 0x70*/
+       {0x70, 0x00}, {0x71, 0x00}, {0x72, 0x00}, {0x73, 0x00},
+       {0x74, 0x00}, {0x75, 0x00}, {0x76, 0x00}, {0x77, 0x00},
+       {0x78, 0x00}, {0x79, 0x00}, {0x7a, 0x00}, {0x7b, 0x00},
+       {0x7c, 0x00}, {0x7d, 0x00}, {0x7e, 0x00}, {0x7f, 0x00},
+       /* 0x80*/
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       /* 0x90*/
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       /* 0xa0*/
+       {0xa0, 0x00}, {0x04, 0x01}, {0xd8, 0x02}, {0x41, 0x01},
+       {0xa4, 0x00}, {0x3d, 0x01}, {0x5a, 0x01}, {0xa7, 0x00},
+       {0xa8, 0x00}, {0x60, 0x01}, {0x5e, 0x01}, {0x64, 0x01},
+       {0x79, 0x01}, {0xad, 0x00}, {0x7d, 0x01}, {0x7b, 0x01},
+       /* 0xb0*/
+       {0xb0, 0x00}, {0x05, 0x01}, {0xdb, 0x02}, {0x42, 0x01},
+       {0xb4, 0x00}, {0x3e, 0x01}, {0x5b, 0x01}, {0xc7, 0x02},
+       {0xb8, 0x00}, {0x61, 0x01}, {0x5f, 0x01}, {0x65, 0x01},
+       {0x7a, 0x01}, {0xdd, 0x02}, {0x7e, 0x01}, {0x7c, 0x01},
+       /* 0xc0*/
+       {0x54, 0x01}, {0xc1, 0x00}, {0xc2, 0x00}, {0x02, 0x01},
+       {0xc4, 0x00}, {0x39, 0x01}, {0x06, 0x01}, {0xc7, 0x00},
+       {0x0c, 0x01}, {0xc9, 0x00}, {0x18, 0x01}, {0xcb, 0x00},
+       {0x1a, 0x01}, {0xcd, 0x00}, {0xce, 0x00}, {0x0e, 0x01},
+       /* 0xd0*/
+       {0x10, 0x01}, {0x43, 0x01}, {0x47, 0x01}, {0xd3, 0x00},
+       {0xd4, 0x00}, {0x50, 0x01}, {0xd6, 0x00}, {0xd7, 0x00},
+       {0x58, 0x01}, {0x6e, 0x01}, {0xda, 0x00}, {0x70, 0x01},
+       {0xdc, 0x00}, {0xdd, 0x00}, {0x62, 0x01}, {0xdf, 0x00},
+       /* 0xe0*/
+       {0x55, 0x01}, {0xe1, 0x00}, {0xe2, 0x00}, {0x03, 0x01},
+       {0xe4, 0x00}, {0x3a, 0x01}, {0x07, 0x01}, {0xe7, 0x00},
+       {0x0d, 0x01}, {0xe9, 0x00}, {0x19, 0x01}, {0xeb, 0x00},
+       {0x1b, 0x01}, {0xed, 0x00}, {0xee, 0x00}, {0x0f, 0x01},
+       /* 0xf0*/
+       {0x11, 0x01}, {0x44, 0x01}, {0x48, 0x01}, {0xf3, 0x00},
+       {0xf4, 0x00}, {0x51, 0x01}, {0xf6, 0x00}, {0xf7, 0x00},
+       {0x59, 0x01}, {0x6f, 0x01}, {0xfa, 0x00}, {0x71, 0x01},
+       {0xfc, 0x00}, {0xfd, 0x00}, {0x63, 0x01}, {0xd9, 0x02},
+};
+
+static unsigned char page00[256] = {
+       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+       0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
+       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
+       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
+       0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+       0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */
+       0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */
+       0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */
+       0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0xa0, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0xa7, /* 0xa0-0xa7 */
+       0xa8, 0x00, 0x00, 0x00, 0x00, 0xad, 0x00, 0x00, /* 0xa8-0xaf */
+       0xb0, 0x00, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0xc1, 0xc2, 0x00, 0xc4, 0x00, 0x00, 0xc7, /* 0xc0-0xc7 */
+       0x00, 0xc9, 0x00, 0xcb, 0x00, 0xcd, 0xce, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0xd3, 0xd4, 0x00, 0xd6, 0xd7, /* 0xd0-0xd7 */
+       0x00, 0x00, 0xda, 0x00, 0xdc, 0xdd, 0x00, 0xdf, /* 0xd8-0xdf */
+       0x00, 0xe1, 0xe2, 0x00, 0xe4, 0x00, 0x00, 0xe7, /* 0xe0-0xe7 */
+       0x00, 0xe9, 0x00, 0xeb, 0x00, 0xed, 0xee, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0xf3, 0xf4, 0x00, 0xf6, 0xf7, /* 0xf0-0xf7 */
+       0x00, 0x00, 0xfa, 0x00, 0xfc, 0xfd, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page01[256] = {
+       0x00, 0x00, 0xc3, 0xe3, 0xa1, 0xb1, 0xc6, 0xe6, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0xc8, 0xe8, 0xcf, 0xef, /* 0x08-0x0f */
+       0xd0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0xca, 0xea, 0xcc, 0xec, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0xc5, 0xe5, 0x00, 0x00, 0xa5, 0xb5, 0x00, /* 0x38-0x3f */
+       0x00, 0xa3, 0xb3, 0xd1, 0xf1, 0x00, 0x00, 0xd2, /* 0x40-0x47 */
+       0xf2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0xd5, 0xf5, 0x00, 0x00, 0xc0, 0xe0, 0x00, 0x00, /* 0x50-0x57 */
+       0xd8, 0xf8, 0xa6, 0xb6, 0x00, 0x00, 0xaa, 0xba, /* 0x58-0x5f */
+       0xa9, 0xb9, 0xde, 0xfe, 0xab, 0xbb, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd9, 0xf9, /* 0x68-0x6f */
+       0xdb, 0xfb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0xac, 0xbc, 0xaf, 0xbf, 0xae, 0xbe, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page02[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb7, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0xa2, 0xff, 0x00, 0xb2, 0x00, 0xbd, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char *page_uni2charset[256] = {
+       page00, page01, page02, NULL,   NULL,   NULL,   NULL,   NULL,
+};
+
+#if 0
+static unsigned char charset2upper[256] = {
+       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+       0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
+       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
+       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
+       0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+       0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+       0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 0x80-0x87 */
+       0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, /* 0x88-0x8f */
+       0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, /* 0x90-0x97 */
+       0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, /* 0x98-0x9f */
+       0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, /* 0xa0-0xa7 */
+       0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
+       0xb0, 0x00, 0xb2, 0x00, 0xb4, 0x00, 0x00, 0xb7, /* 0xb0-0xb7 */
+       0xb8, 0x00, 0x00, 0x00, 0x00, 0xbd, 0x00, 0x00, /* 0xb8-0xbf */
+       0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xc0-0xc7 */
+       0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
+       0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
+       0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf7, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, /* 0xf8-0xff */
+};
+#endif
+
+static struct unls_table table = {
+       "iso8859-2",
+       page_uni2charset,
+       charset2uni,
+       NULL
+};
+
+int
+init_unls_iso8859_2()
+{
+       return (register_unls(&table));
+}
diff --git a/libunls/nls_iso8859-3.c b/libunls/nls_iso8859-3.c
new file mode 100644 (file)
index 0000000..833b08c
--- /dev/null
@@ -0,0 +1,288 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)nls_iso8859-3.c 1.2 05/05/01 2000 J. Schilling */
+/*
+ *     Modifications to make the code portable Copyright (c) 2000 J. Schilling
+ *
+ *     Code taken from the Linux kernel.
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/*
+ * linux/fs/nls_iso8859-3.c
+ *
+ * Charset iso8859-3 translation tables.
+ * Generated automatically from the Unicode and charset
+ * tables from the Unicode Organization (www.unicode.org).
+ * The Unicode to charset table has only exact mappings.
+ */
+
+#include <mconfig.h>
+#include "nls.h"
+
+static struct unls_unicode charset2uni[256] = {
+       /* 0x00*/
+       {0x00, 0x00}, {0x01, 0x00}, {0x02, 0x00}, {0x03, 0x00},
+       {0x04, 0x00}, {0x05, 0x00}, {0x06, 0x00}, {0x07, 0x00},
+       {0x08, 0x00}, {0x09, 0x00}, {0x0a, 0x00}, {0x0b, 0x00},
+       {0x0c, 0x00}, {0x0d, 0x00}, {0x0e, 0x00}, {0x0f, 0x00},
+       /* 0x10*/
+       {0x10, 0x00}, {0x11, 0x00}, {0x12, 0x00}, {0x13, 0x00},
+       {0x14, 0x00}, {0x15, 0x00}, {0x16, 0x00}, {0x17, 0x00},
+       {0x18, 0x00}, {0x19, 0x00}, {0x1a, 0x00}, {0x1b, 0x00},
+       {0x1c, 0x00}, {0x1d, 0x00}, {0x1e, 0x00}, {0x1f, 0x00},
+       /* 0x20*/
+       {0x20, 0x00}, {0x21, 0x00}, {0x22, 0x00}, {0x23, 0x00},
+       {0x24, 0x00}, {0x25, 0x00}, {0x26, 0x00}, {0x27, 0x00},
+       {0x28, 0x00}, {0x29, 0x00}, {0x2a, 0x00}, {0x2b, 0x00},
+       {0x2c, 0x00}, {0x2d, 0x00}, {0x2e, 0x00}, {0x2f, 0x00},
+       /* 0x30*/
+       {0x30, 0x00}, {0x31, 0x00}, {0x32, 0x00}, {0x33, 0x00},
+       {0x34, 0x00}, {0x35, 0x00}, {0x36, 0x00}, {0x37, 0x00},
+       {0x38, 0x00}, {0x39, 0x00}, {0x3a, 0x00}, {0x3b, 0x00},
+       {0x3c, 0x00}, {0x3d, 0x00}, {0x3e, 0x00}, {0x3f, 0x00},
+       /* 0x40*/
+       {0x40, 0x00}, {0x41, 0x00}, {0x42, 0x00}, {0x43, 0x00},
+       {0x44, 0x00}, {0x45, 0x00}, {0x46, 0x00}, {0x47, 0x00},
+       {0x48, 0x00}, {0x49, 0x00}, {0x4a, 0x00}, {0x4b, 0x00},
+       {0x4c, 0x00}, {0x4d, 0x00}, {0x4e, 0x00}, {0x4f, 0x00},
+       /* 0x50*/
+       {0x50, 0x00}, {0x51, 0x00}, {0x52, 0x00}, {0x53, 0x00},
+       {0x54, 0x00}, {0x55, 0x00}, {0x56, 0x00}, {0x57, 0x00},
+       {0x58, 0x00}, {0x59, 0x00}, {0x5a, 0x00}, {0x5b, 0x00},
+       {0x5c, 0x00}, {0x5d, 0x00}, {0x5e, 0x00}, {0x5f, 0x00},
+       /* 0x60*/
+       {0x60, 0x00}, {0x61, 0x00}, {0x62, 0x00}, {0x63, 0x00},
+       {0x64, 0x00}, {0x65, 0x00}, {0x66, 0x00}, {0x67, 0x00},
+       {0x68, 0x00}, {0x69, 0x00}, {0x6a, 0x00}, {0x6b, 0x00},
+       {0x6c, 0x00}, {0x6d, 0x00}, {0x6e, 0x00}, {0x6f, 0x00},
+       /* 0x70*/
+       {0x70, 0x00}, {0x71, 0x00}, {0x72, 0x00}, {0x73, 0x00},
+       {0x74, 0x00}, {0x75, 0x00}, {0x76, 0x00}, {0x77, 0x00},
+       {0x78, 0x00}, {0x79, 0x00}, {0x7a, 0x00}, {0x7b, 0x00},
+       {0x7c, 0x00}, {0x7d, 0x00}, {0x7e, 0x00}, {0x7f, 0x00},
+       /* 0x80*/
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       /* 0x90*/
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       /* 0xa0*/
+       {0xa0, 0x00}, {0x26, 0x01}, {0xd8, 0x02}, {0xa3, 0x00},
+       {0xa4, 0x00}, {0x00, 0x00}, {0x24, 0x01}, {0xa7, 0x00},
+       {0xa8, 0x00}, {0x30, 0x01}, {0x5e, 0x01}, {0x1e, 0x01},
+       {0x34, 0x01}, {0xad, 0x00}, {0x00, 0x00}, {0x7b, 0x01},
+       /* 0xb0*/
+       {0xb0, 0x00}, {0x27, 0x01}, {0xb2, 0x00}, {0xb3, 0x00},
+       {0xb4, 0x00}, {0xb5, 0x00}, {0x25, 0x01}, {0xb7, 0x00},
+       {0xb8, 0x00}, {0x31, 0x01}, {0x5f, 0x01}, {0x1f, 0x01},
+       {0x35, 0x01}, {0xbd, 0x00}, {0x00, 0x00}, {0x7c, 0x01},
+       /* 0xc0*/
+       {0xc0, 0x00}, {0xc1, 0x00}, {0xc2, 0x00}, {0x00, 0x00},
+       {0xc4, 0x00}, {0x0a, 0x01}, {0x08, 0x01}, {0xc7, 0x00},
+       {0xc8, 0x00}, {0xc9, 0x00}, {0xca, 0x00}, {0xcb, 0x00},
+       {0xcc, 0x00}, {0xcd, 0x00}, {0xce, 0x00}, {0xcf, 0x00},
+       /* 0xd0*/
+       {0x00, 0x00}, {0xd1, 0x00}, {0xd2, 0x00}, {0xd3, 0x00},
+       {0xd4, 0x00}, {0x20, 0x01}, {0xd6, 0x00}, {0xd7, 0x00},
+       {0x1c, 0x01}, {0xd9, 0x00}, {0xda, 0x00}, {0xdb, 0x00},
+       {0xdc, 0x00}, {0x6c, 0x01}, {0x5c, 0x01}, {0xdf, 0x00},
+       /* 0xe0*/
+       {0xe0, 0x00}, {0xe1, 0x00}, {0xe2, 0x00}, {0x00, 0x00},
+       {0xe4, 0x00}, {0x0b, 0x01}, {0x09, 0x01}, {0xe7, 0x00},
+       {0xe8, 0x00}, {0xe9, 0x00}, {0xea, 0x00}, {0xeb, 0x00},
+       {0xec, 0x00}, {0xed, 0x00}, {0xee, 0x00}, {0xef, 0x00},
+       /* 0xf0*/
+       {0x00, 0x00}, {0xf1, 0x00}, {0xf2, 0x00}, {0xf3, 0x00},
+       {0xf4, 0x00}, {0x21, 0x01}, {0xf6, 0x00}, {0xf7, 0x00},
+       {0x1d, 0x01}, {0xf9, 0x00}, {0xfa, 0x00}, {0xfb, 0x00},
+       {0xfc, 0x00}, {0x6d, 0x01}, {0x5d, 0x01}, {0xd9, 0x02},
+};
+
+static unsigned char page00[256] = {
+       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+       0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
+       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
+       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
+       0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+       0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */
+       0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */
+       0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */
+       0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0xa0, 0x00, 0x00, 0xa3, 0xa4, 0x00, 0x00, 0xa7, /* 0xa0-0xa7 */
+       0xa8, 0x00, 0x00, 0x00, 0x00, 0xad, 0x00, 0x00, /* 0xa8-0xaf */
+       0xb0, 0x00, 0xb2, 0xb3, 0xb4, 0xb5, 0x00, 0xb7, /* 0xb0-0xb7 */
+       0xb8, 0x00, 0x00, 0x00, 0x00, 0xbd, 0x00, 0x00, /* 0xb8-0xbf */
+       0xc0, 0xc1, 0xc2, 0x00, 0xc4, 0x00, 0x00, 0xc7, /* 0xc0-0xc7 */
+       0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
+       0x00, 0xd1, 0xd2, 0xd3, 0xd4, 0x00, 0xd6, 0xd7, /* 0xd0-0xd7 */
+       0x00, 0xd9, 0xda, 0xdb, 0xdc, 0x00, 0x00, 0xdf, /* 0xd8-0xdf */
+       0xe0, 0xe1, 0xe2, 0x00, 0xe4, 0x00, 0x00, 0xe7, /* 0xe0-0xe7 */
+       0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xe8-0xef */
+       0x00, 0xf1, 0xf2, 0xf3, 0xf4, 0x00, 0xf6, 0xf7, /* 0xf0-0xf7 */
+       0x00, 0xf9, 0xfa, 0xfb, 0xfc, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page01[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0xc6, 0xe6, 0xc5, 0xe5, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0xd8, 0xf8, 0xab, 0xbb, /* 0x18-0x1f */
+       0xd5, 0xf5, 0x00, 0x00, 0xa6, 0xb6, 0xa1, 0xb1, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0xa9, 0xb9, 0x00, 0x00, 0xac, 0xbc, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0xde, 0xfe, 0xaa, 0xba, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0xdd, 0xfd, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0xaf, 0xbf, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page02[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0xa2, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char *page_uni2charset[256] = {
+       page00, page01, page02, NULL,   NULL,   NULL,   NULL,   NULL,
+};
+
+#if 0
+static unsigned char charset2upper[256] = {
+       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+       0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
+       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
+       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
+       0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+       0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+       0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 0x80-0x87 */
+       0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, /* 0x88-0x8f */
+       0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, /* 0x90-0x97 */
+       0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, /* 0x98-0x9f */
+       0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, /* 0xa0-0xa7 */
+       0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
+       0xb0, 0x00, 0xb2, 0xb3, 0xb4, 0xb5, 0x00, 0xb7, /* 0xb0-0xb7 */
+       0xb8, 0x00, 0x00, 0x00, 0x00, 0xbd, 0xbe, 0x00, /* 0xb8-0xbf */
+       0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xc0-0xc7 */
+       0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
+       0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
+       0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0xe3, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf7, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, /* 0xf8-0xff */
+};
+#endif
+
+static struct unls_table table = {
+       "iso8859-3",
+       page_uni2charset,
+       charset2uni,
+       NULL
+};
+
+int
+init_unls_iso8859_3()
+{
+       return (register_unls(&table));
+}
diff --git a/libunls/nls_iso8859-4.c b/libunls/nls_iso8859-4.c
new file mode 100644 (file)
index 0000000..20a7744
--- /dev/null
@@ -0,0 +1,288 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)nls_iso8859-4.c 1.2 05/05/01 2000 J. Schilling */
+/*
+ *     Modifications to make the code portable Copyright (c) 2000 J. Schilling
+ *
+ *     Code taken from the Linux kernel.
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/*
+ * linux/fs/nls_iso8859-4.c
+ *
+ * Charset iso8859-4 translation tables.
+ * Generated automatically from the Unicode and charset
+ * tables from the Unicode Organization (www.unicode.org).
+ * The Unicode to charset table has only exact mappings.
+ */
+
+#include <mconfig.h>
+#include "nls.h"
+
+static struct unls_unicode charset2uni[256] = {
+       /* 0x00*/
+       {0x00, 0x00}, {0x01, 0x00}, {0x02, 0x00}, {0x03, 0x00},
+       {0x04, 0x00}, {0x05, 0x00}, {0x06, 0x00}, {0x07, 0x00},
+       {0x08, 0x00}, {0x09, 0x00}, {0x0a, 0x00}, {0x0b, 0x00},
+       {0x0c, 0x00}, {0x0d, 0x00}, {0x0e, 0x00}, {0x0f, 0x00},
+       /* 0x10*/
+       {0x10, 0x00}, {0x11, 0x00}, {0x12, 0x00}, {0x13, 0x00},
+       {0x14, 0x00}, {0x15, 0x00}, {0x16, 0x00}, {0x17, 0x00},
+       {0x18, 0x00}, {0x19, 0x00}, {0x1a, 0x00}, {0x1b, 0x00},
+       {0x1c, 0x00}, {0x1d, 0x00}, {0x1e, 0x00}, {0x1f, 0x00},
+       /* 0x20*/
+       {0x20, 0x00}, {0x21, 0x00}, {0x22, 0x00}, {0x23, 0x00},
+       {0x24, 0x00}, {0x25, 0x00}, {0x26, 0x00}, {0x27, 0x00},
+       {0x28, 0x00}, {0x29, 0x00}, {0x2a, 0x00}, {0x2b, 0x00},
+       {0x2c, 0x00}, {0x2d, 0x00}, {0x2e, 0x00}, {0x2f, 0x00},
+       /* 0x30*/
+       {0x30, 0x00}, {0x31, 0x00}, {0x32, 0x00}, {0x33, 0x00},
+       {0x34, 0x00}, {0x35, 0x00}, {0x36, 0x00}, {0x37, 0x00},
+       {0x38, 0x00}, {0x39, 0x00}, {0x3a, 0x00}, {0x3b, 0x00},
+       {0x3c, 0x00}, {0x3d, 0x00}, {0x3e, 0x00}, {0x3f, 0x00},
+       /* 0x40*/
+       {0x40, 0x00}, {0x41, 0x00}, {0x42, 0x00}, {0x43, 0x00},
+       {0x44, 0x00}, {0x45, 0x00}, {0x46, 0x00}, {0x47, 0x00},
+       {0x48, 0x00}, {0x49, 0x00}, {0x4a, 0x00}, {0x4b, 0x00},
+       {0x4c, 0x00}, {0x4d, 0x00}, {0x4e, 0x00}, {0x4f, 0x00},
+       /* 0x50*/
+       {0x50, 0x00}, {0x51, 0x00}, {0x52, 0x00}, {0x53, 0x00},
+       {0x54, 0x00}, {0x55, 0x00}, {0x56, 0x00}, {0x57, 0x00},
+       {0x58, 0x00}, {0x59, 0x00}, {0x5a, 0x00}, {0x5b, 0x00},
+       {0x5c, 0x00}, {0x5d, 0x00}, {0x5e, 0x00}, {0x5f, 0x00},
+       /* 0x60*/
+       {0x60, 0x00}, {0x61, 0x00}, {0x62, 0x00}, {0x63, 0x00},
+       {0x64, 0x00}, {0x65, 0x00}, {0x66, 0x00}, {0x67, 0x00},
+       {0x68, 0x00}, {0x69, 0x00}, {0x6a, 0x00}, {0x6b, 0x00},
+       {0x6c, 0x00}, {0x6d, 0x00}, {0x6e, 0x00}, {0x6f, 0x00},
+       /* 0x70*/
+       {0x70, 0x00}, {0x71, 0x00}, {0x72, 0x00}, {0x73, 0x00},
+       {0x74, 0x00}, {0x75, 0x00}, {0x76, 0x00}, {0x77, 0x00},
+       {0x78, 0x00}, {0x79, 0x00}, {0x7a, 0x00}, {0x7b, 0x00},
+       {0x7c, 0x00}, {0x7d, 0x00}, {0x7e, 0x00}, {0x7f, 0x00},
+       /* 0x80*/
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       /* 0x90*/
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       /* 0xa0*/
+       {0xa0, 0x00}, {0x04, 0x01}, {0x38, 0x01}, {0x56, 0x01},
+       {0xa4, 0x00}, {0x28, 0x01}, {0x3b, 0x01}, {0xa7, 0x00},
+       {0xa8, 0x00}, {0x60, 0x01}, {0x12, 0x01}, {0x22, 0x01},
+       {0x66, 0x01}, {0xad, 0x00}, {0x7d, 0x01}, {0xaf, 0x00},
+       /* 0xb0*/
+       {0xb0, 0x00}, {0x05, 0x01}, {0xdb, 0x02}, {0x57, 0x01},
+       {0xb4, 0x00}, {0x29, 0x01}, {0x3c, 0x01}, {0xc7, 0x02},
+       {0xb8, 0x00}, {0x61, 0x01}, {0x13, 0x01}, {0x23, 0x01},
+       {0x67, 0x01}, {0x4a, 0x01}, {0x7e, 0x01}, {0x4b, 0x01},
+       /* 0xc0*/
+       {0x00, 0x01}, {0xc1, 0x00}, {0xc2, 0x00}, {0xc3, 0x00},
+       {0xc4, 0x00}, {0xc5, 0x00}, {0xc6, 0x00}, {0x2e, 0x01},
+       {0x0c, 0x01}, {0xc9, 0x00}, {0x18, 0x01}, {0xcb, 0x00},
+       {0x16, 0x01}, {0xcd, 0x00}, {0xce, 0x00}, {0x2a, 0x01},
+       /* 0xd0*/
+       {0x10, 0x01}, {0x45, 0x01}, {0x4c, 0x01}, {0x36, 0x01},
+       {0xd4, 0x00}, {0xd5, 0x00}, {0xd6, 0x00}, {0xd7, 0x00},
+       {0xd8, 0x00}, {0x72, 0x01}, {0xda, 0x00}, {0xdb, 0x00},
+       {0xdc, 0x00}, {0x68, 0x01}, {0x6a, 0x01}, {0xdf, 0x00},
+       /* 0xe0*/
+       {0x01, 0x01}, {0xe1, 0x00}, {0xe2, 0x00}, {0xe3, 0x00},
+       {0xe4, 0x00}, {0xe5, 0x00}, {0xe6, 0x00}, {0x2f, 0x01},
+       {0x0d, 0x01}, {0xe9, 0x00}, {0x19, 0x01}, {0xeb, 0x00},
+       {0x17, 0x01}, {0xed, 0x00}, {0xee, 0x00}, {0x2b, 0x01},
+       /* 0xf0*/
+       {0x11, 0x01}, {0x46, 0x01}, {0x4d, 0x01}, {0x37, 0x01},
+       {0xf4, 0x00}, {0xf5, 0x00}, {0xf6, 0x00}, {0xf7, 0x00},
+       {0xf8, 0x00}, {0x73, 0x01}, {0xfa, 0x00}, {0xfb, 0x00},
+       {0xfc, 0x00}, {0x69, 0x01}, {0x6b, 0x01}, {0xd9, 0x02},
+};
+
+static unsigned char page00[256] = {
+       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+       0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
+       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
+       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
+       0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+       0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */
+       0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */
+       0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */
+       0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0xa0, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0xa7, /* 0xa0-0xa7 */
+       0xa8, 0x00, 0x00, 0x00, 0x00, 0xad, 0x00, 0xaf, /* 0xa8-0xaf */
+       0xb0, 0x00, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0x00, /* 0xc0-0xc7 */
+       0x00, 0xc9, 0x00, 0xcb, 0x00, 0xcd, 0xce, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
+       0xd8, 0x00, 0xda, 0xdb, 0xdc, 0x00, 0x00, 0xdf, /* 0xd8-0xdf */
+       0x00, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0x00, /* 0xe0-0xe7 */
+       0x00, 0xe9, 0x00, 0xeb, 0x00, 0xed, 0xee, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
+       0xf8, 0x00, 0xfa, 0xfb, 0xfc, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page01[256] = {
+       0xc0, 0xe0, 0x00, 0x00, 0xa1, 0xb1, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0xc8, 0xe8, 0x00, 0x00, /* 0x08-0x0f */
+       0xd0, 0xf0, 0xaa, 0xba, 0x00, 0x00, 0xcc, 0xec, /* 0x10-0x17 */
+       0xca, 0xea, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0xab, 0xbb, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0xa5, 0xb5, 0xcf, 0xef, 0x00, 0x00, 0xc7, 0xe7, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd3, 0xf3, /* 0x30-0x37 */
+       0xa2, 0x00, 0x00, 0xa6, 0xb6, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0xd1, 0xf1, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0xbd, 0xbf, 0xd2, 0xf2, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa3, 0xb3, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0xa9, 0xb9, 0x00, 0x00, 0x00, 0x00, 0xac, 0xbc, /* 0x60-0x67 */
+       0xdd, 0xfd, 0xde, 0xfe, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0xd9, 0xf9, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0xae, 0xbe, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page02[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb7, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0xff, 0x00, 0xb2, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char *page_uni2charset[256] = {
+       page00, page01, page02, NULL,   NULL,   NULL,   NULL,   NULL,
+};
+
+#if 0
+static unsigned char charset2upper[256] = {
+       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+       0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
+       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
+       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
+       0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+       0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+       0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 0x80-0x87 */
+       0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, /* 0x88-0x8f */
+       0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, /* 0x90-0x97 */
+       0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, /* 0x98-0x9f */
+       0xa0, 0xa1, 0x00, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, /* 0xa0-0xa7 */
+       0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
+       0xb0, 0x00, 0xb2, 0x00, 0xb4, 0x00, 0x00, 0xb7, /* 0xb0-0xb7 */
+       0xb8, 0x00, 0x00, 0x00, 0x00, 0xbd, 0x00, 0x00, /* 0xb8-0xbf */
+       0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xc0-0xc7 */
+       0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
+       0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
+       0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf7, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, /* 0xf8-0xff */
+};
+#endif
+
+static struct unls_table table = {
+       "iso8859-4",
+       page_uni2charset,
+       charset2uni,
+       NULL
+};
+
+int
+init_unls_iso8859_4()
+{
+       return (register_unls(&table));
+}
diff --git a/libunls/nls_iso8859-5.c b/libunls/nls_iso8859-5.c
new file mode 100644 (file)
index 0000000..8b84ea8
--- /dev/null
@@ -0,0 +1,292 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)nls_iso8859-5.c 1.2 05/05/01 2000 J. Schilling */
+/*
+ *     Modifications to make the code portable Copyright (c) 2000 J. Schilling
+ *
+ *     Code taken from the Linux kernel.
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/*
+ * linux/fs/nls_iso8859-5.c
+ *
+ * Charset iso8859-5 translation tables.
+ * Generated automatically from the Unicode and charset
+ * tables from the Unicode Organization (www.unicode.org).
+ * The Unicode to charset table has only exact mappings.
+ */
+
+#include <mconfig.h>
+#include "nls.h"
+
+static struct unls_unicode charset2uni[256] = {
+       /* 0x00*/
+       {0x00, 0x00}, {0x01, 0x00}, {0x02, 0x00}, {0x03, 0x00},
+       {0x04, 0x00}, {0x05, 0x00}, {0x06, 0x00}, {0x07, 0x00},
+       {0x08, 0x00}, {0x09, 0x00}, {0x0a, 0x00}, {0x0b, 0x00},
+       {0x0c, 0x00}, {0x0d, 0x00}, {0x0e, 0x00}, {0x0f, 0x00},
+       /* 0x10*/
+       {0x10, 0x00}, {0x11, 0x00}, {0x12, 0x00}, {0x13, 0x00},
+       {0x14, 0x00}, {0x15, 0x00}, {0x16, 0x00}, {0x17, 0x00},
+       {0x18, 0x00}, {0x19, 0x00}, {0x1a, 0x00}, {0x1b, 0x00},
+       {0x1c, 0x00}, {0x1d, 0x00}, {0x1e, 0x00}, {0x1f, 0x00},
+       /* 0x20*/
+       {0x20, 0x00}, {0x21, 0x00}, {0x22, 0x00}, {0x23, 0x00},
+       {0x24, 0x00}, {0x25, 0x00}, {0x26, 0x00}, {0x27, 0x00},
+       {0x28, 0x00}, {0x29, 0x00}, {0x2a, 0x00}, {0x2b, 0x00},
+       {0x2c, 0x00}, {0x2d, 0x00}, {0x2e, 0x00}, {0x2f, 0x00},
+       /* 0x30*/
+       {0x30, 0x00}, {0x31, 0x00}, {0x32, 0x00}, {0x33, 0x00},
+       {0x34, 0x00}, {0x35, 0x00}, {0x36, 0x00}, {0x37, 0x00},
+       {0x38, 0x00}, {0x39, 0x00}, {0x3a, 0x00}, {0x3b, 0x00},
+       {0x3c, 0x00}, {0x3d, 0x00}, {0x3e, 0x00}, {0x3f, 0x00},
+       /* 0x40*/
+       {0x40, 0x00}, {0x41, 0x00}, {0x42, 0x00}, {0x43, 0x00},
+       {0x44, 0x00}, {0x45, 0x00}, {0x46, 0x00}, {0x47, 0x00},
+       {0x48, 0x00}, {0x49, 0x00}, {0x4a, 0x00}, {0x4b, 0x00},
+       {0x4c, 0x00}, {0x4d, 0x00}, {0x4e, 0x00}, {0x4f, 0x00},
+       /* 0x50*/
+       {0x50, 0x00}, {0x51, 0x00}, {0x52, 0x00}, {0x53, 0x00},
+       {0x54, 0x00}, {0x55, 0x00}, {0x56, 0x00}, {0x57, 0x00},
+       {0x58, 0x00}, {0x59, 0x00}, {0x5a, 0x00}, {0x5b, 0x00},
+       {0x5c, 0x00}, {0x5d, 0x00}, {0x5e, 0x00}, {0x5f, 0x00},
+       /* 0x60*/
+       {0x60, 0x00}, {0x61, 0x00}, {0x62, 0x00}, {0x63, 0x00},
+       {0x64, 0x00}, {0x65, 0x00}, {0x66, 0x00}, {0x67, 0x00},
+       {0x68, 0x00}, {0x69, 0x00}, {0x6a, 0x00}, {0x6b, 0x00},
+       {0x6c, 0x00}, {0x6d, 0x00}, {0x6e, 0x00}, {0x6f, 0x00},
+       /* 0x70*/
+       {0x70, 0x00}, {0x71, 0x00}, {0x72, 0x00}, {0x73, 0x00},
+       {0x74, 0x00}, {0x75, 0x00}, {0x76, 0x00}, {0x77, 0x00},
+       {0x78, 0x00}, {0x79, 0x00}, {0x7a, 0x00}, {0x7b, 0x00},
+       {0x7c, 0x00}, {0x7d, 0x00}, {0x7e, 0x00}, {0x7f, 0x00},
+       /* 0x80*/
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       /* 0x90*/
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       /* 0xa0*/
+       {0xa0, 0x00}, {0x01, 0x04}, {0x02, 0x04}, {0x03, 0x04},
+       {0x04, 0x04}, {0x05, 0x04}, {0x06, 0x04}, {0x07, 0x04},
+       {0x08, 0x04}, {0x09, 0x04}, {0x0a, 0x04}, {0x0b, 0x04},
+       {0x0c, 0x04}, {0xad, 0x00}, {0x0e, 0x04}, {0x0f, 0x04},
+       /* 0xb0*/
+       {0x10, 0x04}, {0x11, 0x04}, {0x12, 0x04}, {0x13, 0x04},
+       {0x14, 0x04}, {0x15, 0x04}, {0x16, 0x04}, {0x17, 0x04},
+       {0x18, 0x04}, {0x19, 0x04}, {0x1a, 0x04}, {0x1b, 0x04},
+       {0x1c, 0x04}, {0x1d, 0x04}, {0x1e, 0x04}, {0x1f, 0x04},
+       /* 0xc0*/
+       {0x20, 0x04}, {0x21, 0x04}, {0x22, 0x04}, {0x23, 0x04},
+       {0x24, 0x04}, {0x25, 0x04}, {0x26, 0x04}, {0x27, 0x04},
+       {0x28, 0x04}, {0x29, 0x04}, {0x2a, 0x04}, {0x2b, 0x04},
+       {0x2c, 0x04}, {0x2d, 0x04}, {0x2e, 0x04}, {0x2f, 0x04},
+       /* 0xd0*/
+       {0x30, 0x04}, {0x31, 0x04}, {0x32, 0x04}, {0x33, 0x04},
+       {0x34, 0x04}, {0x35, 0x04}, {0x36, 0x04}, {0x37, 0x04},
+       {0x38, 0x04}, {0x39, 0x04}, {0x3a, 0x04}, {0x3b, 0x04},
+       {0x3c, 0x04}, {0x3d, 0x04}, {0x3e, 0x04}, {0x3f, 0x04},
+       /* 0xe0*/
+       {0x40, 0x04}, {0x41, 0x04}, {0x42, 0x04}, {0x43, 0x04},
+       {0x44, 0x04}, {0x45, 0x04}, {0x46, 0x04}, {0x47, 0x04},
+       {0x48, 0x04}, {0x49, 0x04}, {0x4a, 0x04}, {0x4b, 0x04},
+       {0x4c, 0x04}, {0x4d, 0x04}, {0x4e, 0x04}, {0x4f, 0x04},
+       /* 0xf0*/
+       {0x16, 0x21}, {0x51, 0x04}, {0x52, 0x04}, {0x53, 0x04},
+       {0x54, 0x04}, {0x55, 0x04}, {0x56, 0x04}, {0x57, 0x04},
+       {0x58, 0x04}, {0x59, 0x04}, {0x5a, 0x04}, {0x5b, 0x04},
+       {0x5c, 0x04}, {0xa7, 0x00}, {0x5e, 0x04}, {0x5f, 0x04},
+};
+
+static unsigned char page00[256] = {
+       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+       0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
+       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
+       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
+       0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+       0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */
+       0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */
+       0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */
+       0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfd, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0xad, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page04[256] = {
+       0x00, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, /* 0x00-0x07 */
+       0xa8, 0xa9, 0xaa, 0xab, 0xac, 0x00, 0xae, 0xaf, /* 0x08-0x0f */
+       0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0x10-0x17 */
+       0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* 0x18-0x1f */
+       0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0x20-0x27 */
+       0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0x28-0x2f */
+       0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0x30-0x37 */
+       0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, /* 0x38-0x3f */
+       0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0x40-0x47 */
+       0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0x48-0x4f */
+       0x00, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0x50-0x57 */
+       0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0x00, 0xfe, 0xff, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page21[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char *page_uni2charset[256] = {
+       page00, NULL,   NULL,   NULL,   page04, NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   page21, NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+};
+
+#if 0
+static unsigned char charset2upper[256] = {
+       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+       0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
+       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
+       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
+       0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+       0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+       0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 0x80-0x87 */
+       0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, /* 0x88-0x8f */
+       0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, /* 0x90-0x97 */
+       0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, /* 0x98-0x9f */
+       0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, /* 0xa0-0xa7 */
+       0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
+       0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
+       0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* 0xb8-0xbf */
+       0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xc0-0xc7 */
+       0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x00, /* 0xf8-0xff */
+};
+#endif
+
+static struct unls_table table = {
+       "iso8859-5",
+       page_uni2charset,
+       charset2uni,
+       NULL
+};
+
+int
+init_unls_iso8859_5()
+{
+       return (register_unls(&table));
+}
diff --git a/libunls/nls_iso8859-6.c b/libunls/nls_iso8859-6.c
new file mode 100644 (file)
index 0000000..44e259b
--- /dev/null
@@ -0,0 +1,252 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)nls_iso8859-6.c 1.2 05/05/01 2000 J. Schilling */
+/*
+ *     Modifications to make the code portable Copyright (c) 2000 J. Schilling
+ *
+ *     Code taken from the Linux kernel.
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/*
+ * linux/fs/nls_iso8859-6.c
+ *
+ * Charset iso8859-6 translation tables.
+ * Generated automatically from the Unicode and charset
+ * tables from the Unicode Organization (www.unicode.org).
+ * The Unicode to charset table has only exact mappings.
+ */
+
+#include <mconfig.h>
+#include "nls.h"
+
+static struct unls_unicode charset2uni[256] = {
+       /* 0x00*/
+       {0x00, 0x00}, {0x01, 0x00}, {0x02, 0x00}, {0x03, 0x00},
+       {0x04, 0x00}, {0x05, 0x00}, {0x06, 0x00}, {0x07, 0x00},
+       {0x08, 0x00}, {0x09, 0x00}, {0x0a, 0x00}, {0x0b, 0x00},
+       {0x0c, 0x00}, {0x0d, 0x00}, {0x0e, 0x00}, {0x0f, 0x00},
+       /* 0x10*/
+       {0x10, 0x00}, {0x11, 0x00}, {0x12, 0x00}, {0x13, 0x00},
+       {0x14, 0x00}, {0x15, 0x00}, {0x16, 0x00}, {0x17, 0x00},
+       {0x18, 0x00}, {0x19, 0x00}, {0x1a, 0x00}, {0x1b, 0x00},
+       {0x1c, 0x00}, {0x1d, 0x00}, {0x1e, 0x00}, {0x1f, 0x00},
+       /* 0x20*/
+       {0x20, 0x00}, {0x21, 0x00}, {0x22, 0x00}, {0x23, 0x00},
+       {0x24, 0x00}, {0x25, 0x00}, {0x26, 0x00}, {0x27, 0x00},
+       {0x28, 0x00}, {0x29, 0x00}, {0x2a, 0x00}, {0x2b, 0x00},
+       {0x2c, 0x00}, {0x2d, 0x00}, {0x2e, 0x00}, {0x2f, 0x00},
+       /* 0x30*/
+       {0x60, 0x06}, {0x61, 0x06}, {0x62, 0x06}, {0x63, 0x06},
+       {0x64, 0x06}, {0x65, 0x06}, {0x66, 0x06}, {0x67, 0x06},
+       {0x68, 0x06}, {0x69, 0x06}, {0x3a, 0x00}, {0x3b, 0x00},
+       {0x3c, 0x00}, {0x3d, 0x00}, {0x3e, 0x00}, {0x3f, 0x00},
+       /* 0x40*/
+       {0x40, 0x00}, {0x41, 0x00}, {0x42, 0x00}, {0x43, 0x00},
+       {0x44, 0x00}, {0x45, 0x00}, {0x46, 0x00}, {0x47, 0x00},
+       {0x48, 0x00}, {0x49, 0x00}, {0x4a, 0x00}, {0x4b, 0x00},
+       {0x4c, 0x00}, {0x4d, 0x00}, {0x4e, 0x00}, {0x4f, 0x00},
+       /* 0x50*/
+       {0x50, 0x00}, {0x51, 0x00}, {0x52, 0x00}, {0x53, 0x00},
+       {0x54, 0x00}, {0x55, 0x00}, {0x56, 0x00}, {0x57, 0x00},
+       {0x58, 0x00}, {0x59, 0x00}, {0x5a, 0x00}, {0x5b, 0x00},
+       {0x5c, 0x00}, {0x5d, 0x00}, {0x5e, 0x00}, {0x5f, 0x00},
+       /* 0x60*/
+       {0x60, 0x00}, {0x61, 0x00}, {0x62, 0x00}, {0x63, 0x00},
+       {0x64, 0x00}, {0x65, 0x00}, {0x66, 0x00}, {0x67, 0x00},
+       {0x68, 0x00}, {0x69, 0x00}, {0x6a, 0x00}, {0x6b, 0x00},
+       {0x6c, 0x00}, {0x6d, 0x00}, {0x6e, 0x00}, {0x6f, 0x00},
+       /* 0x70*/
+       {0x70, 0x00}, {0x71, 0x00}, {0x72, 0x00}, {0x73, 0x00},
+       {0x74, 0x00}, {0x75, 0x00}, {0x76, 0x00}, {0x77, 0x00},
+       {0x78, 0x00}, {0x79, 0x00}, {0x7a, 0x00}, {0x7b, 0x00},
+       {0x7c, 0x00}, {0x7d, 0x00}, {0x7e, 0x00}, {0x7f, 0x00},
+       /* 0x80*/
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       /* 0x90*/
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       /* 0xa0*/
+       {0xa0, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0xa4, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x0c, 0x06}, {0xad, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       /* 0xb0*/
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x1b, 0x06},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x1f, 0x06},
+       /* 0xc0*/
+       {0x00, 0x00}, {0x21, 0x06}, {0x22, 0x06}, {0x23, 0x06},
+       {0x24, 0x06}, {0x25, 0x06}, {0x26, 0x06}, {0x27, 0x06},
+       {0x28, 0x06}, {0x29, 0x06}, {0x2a, 0x06}, {0x2b, 0x06},
+       {0x2c, 0x06}, {0x2d, 0x06}, {0x2e, 0x06}, {0x2f, 0x06},
+       /* 0xd0*/
+       {0x30, 0x06}, {0x31, 0x06}, {0x32, 0x06}, {0x33, 0x06},
+       {0x34, 0x06}, {0x35, 0x06}, {0x36, 0x06}, {0x37, 0x06},
+       {0x38, 0x06}, {0x39, 0x06}, {0x3a, 0x06}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       /* 0xe0*/
+       {0x40, 0x06}, {0x41, 0x06}, {0x42, 0x06}, {0x43, 0x06},
+       {0x44, 0x06}, {0x45, 0x06}, {0x46, 0x06}, {0x47, 0x06},
+       {0x48, 0x06}, {0x49, 0x06}, {0x4a, 0x06}, {0x4b, 0x06},
+       {0x4c, 0x06}, {0x4d, 0x06}, {0x4e, 0x06}, {0x4f, 0x06},
+       /* 0xf0*/
+       {0x50, 0x06}, {0x51, 0x06}, {0x52, 0x06}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+};
+
+static unsigned char page00[256] = {
+       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+       0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
+       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
+       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
+       0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+       0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */
+       0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */
+       0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */
+       0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0xa0, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0xad, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page06[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0xac, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0xbb, 0x00, 0x00, 0x00, 0xbf, /* 0x18-0x1f */
+       0x00, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0x20-0x27 */
+       0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0x28-0x2f */
+       0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0x30-0x37 */
+       0xd8, 0xd9, 0xda, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0x40-0x47 */
+       0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0x48-0x4f */
+       0xf0, 0xf1, 0xf2, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x60-0x67 */
+       0x38, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char *page_uni2charset[256] = {
+       page00, NULL,   NULL,   NULL,   NULL,   NULL,   page06, NULL,
+};
+
+#if 0
+static unsigned char charset2upper[256] = {
+       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+       0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
+       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
+       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
+       0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+       0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+       0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 0x80-0x87 */
+       0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, /* 0x88-0x8f */
+       0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, /* 0x90-0x97 */
+       0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, /* 0x98-0x9f */
+       0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, /* 0xa0-0xa7 */
+       0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
+       0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
+       0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* 0xb8-0xbf */
+       0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xc0-0xc7 */
+       0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
+       0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
+       0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, /* 0xd8-0xdf */
+       0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0xe0-0xe7 */
+       0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xe8-0xef */
+       0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
+       0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
+};
+#endif
+
+static struct unls_table table = {
+       "iso8859-6",
+       page_uni2charset,
+       charset2uni,
+       NULL
+};
+
+int
+init_unls_iso8859_6()
+{
+       return (register_unls(&table));
+}
diff --git a/libunls/nls_iso8859-7.c b/libunls/nls_iso8859-7.c
new file mode 100644 (file)
index 0000000..cc1438a
--- /dev/null
@@ -0,0 +1,328 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)nls_iso8859-7.c 1.2 05/05/01 2000 J. Schilling */
+/*
+ *     Modifications to make the code portable Copyright (c) 2000 J. Schilling
+ *
+ *     Code taken from the Linux kernel.
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/*
+ * linux/fs/nls_iso8859-7.c
+ *
+ * Charset iso8859-7 translation tables.
+ * Generated automatically from the Unicode and charset
+ * tables from the Unicode Organization (www.unicode.org).
+ * The Unicode to charset table has only exact mappings.
+ */
+
+#include <mconfig.h>
+#include "nls.h"
+
+static struct unls_unicode charset2uni[256] = {
+       /* 0x00*/
+       {0x00, 0x00}, {0x01, 0x00}, {0x02, 0x00}, {0x03, 0x00},
+       {0x04, 0x00}, {0x05, 0x00}, {0x06, 0x00}, {0x07, 0x00},
+       {0x08, 0x00}, {0x09, 0x00}, {0x0a, 0x00}, {0x0b, 0x00},
+       {0x0c, 0x00}, {0x0d, 0x00}, {0x0e, 0x00}, {0x0f, 0x00},
+       /* 0x10*/
+       {0x10, 0x00}, {0x11, 0x00}, {0x12, 0x00}, {0x13, 0x00},
+       {0x14, 0x00}, {0x15, 0x00}, {0x16, 0x00}, {0x17, 0x00},
+       {0x18, 0x00}, {0x19, 0x00}, {0x1a, 0x00}, {0x1b, 0x00},
+       {0x1c, 0x00}, {0x1d, 0x00}, {0x1e, 0x00}, {0x1f, 0x00},
+       /* 0x20*/
+       {0x20, 0x00}, {0x21, 0x00}, {0x22, 0x00}, {0x23, 0x00},
+       {0x24, 0x00}, {0x25, 0x00}, {0x26, 0x00}, {0x27, 0x00},
+       {0x28, 0x00}, {0x29, 0x00}, {0x2a, 0x00}, {0x2b, 0x00},
+       {0x2c, 0x00}, {0x2d, 0x00}, {0x2e, 0x00}, {0x2f, 0x00},
+       /* 0x30*/
+       {0x30, 0x00}, {0x31, 0x00}, {0x32, 0x00}, {0x33, 0x00},
+       {0x34, 0x00}, {0x35, 0x00}, {0x36, 0x00}, {0x37, 0x00},
+       {0x38, 0x00}, {0x39, 0x00}, {0x3a, 0x00}, {0x3b, 0x00},
+       {0x3c, 0x00}, {0x3d, 0x00}, {0x3e, 0x00}, {0x3f, 0x00},
+       /* 0x40*/
+       {0x40, 0x00}, {0x41, 0x00}, {0x42, 0x00}, {0x43, 0x00},
+       {0x44, 0x00}, {0x45, 0x00}, {0x46, 0x00}, {0x47, 0x00},
+       {0x48, 0x00}, {0x49, 0x00}, {0x4a, 0x00}, {0x4b, 0x00},
+       {0x4c, 0x00}, {0x4d, 0x00}, {0x4e, 0x00}, {0x4f, 0x00},
+       /* 0x50*/
+       {0x50, 0x00}, {0x51, 0x00}, {0x52, 0x00}, {0x53, 0x00},
+       {0x54, 0x00}, {0x55, 0x00}, {0x56, 0x00}, {0x57, 0x00},
+       {0x58, 0x00}, {0x59, 0x00}, {0x5a, 0x00}, {0x5b, 0x00},
+       {0x5c, 0x00}, {0x5d, 0x00}, {0x5e, 0x00}, {0x5f, 0x00},
+       /* 0x60*/
+       {0x60, 0x00}, {0x61, 0x00}, {0x62, 0x00}, {0x63, 0x00},
+       {0x64, 0x00}, {0x65, 0x00}, {0x66, 0x00}, {0x67, 0x00},
+       {0x68, 0x00}, {0x69, 0x00}, {0x6a, 0x00}, {0x6b, 0x00},
+       {0x6c, 0x00}, {0x6d, 0x00}, {0x6e, 0x00}, {0x6f, 0x00},
+       /* 0x70*/
+       {0x70, 0x00}, {0x71, 0x00}, {0x72, 0x00}, {0x73, 0x00},
+       {0x74, 0x00}, {0x75, 0x00}, {0x76, 0x00}, {0x77, 0x00},
+       {0x78, 0x00}, {0x79, 0x00}, {0x7a, 0x00}, {0x7b, 0x00},
+       {0x7c, 0x00}, {0x7d, 0x00}, {0x7e, 0x00}, {0x7f, 0x00},
+       /* 0x80*/
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       /* 0x90*/
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       /* 0xa0*/
+       {0xa0, 0x00}, {0xbd, 0x02}, {0xbc, 0x02}, {0xa3, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0xa6, 0x00}, {0xa7, 0x00},
+       {0xa8, 0x00}, {0xa9, 0x00}, {0x00, 0x00}, {0xab, 0x00},
+       {0xac, 0x00}, {0xad, 0x00}, {0x00, 0x00}, {0x15, 0x20},
+       /* 0xb0*/
+       {0xb0, 0x00}, {0xb1, 0x00}, {0xb2, 0x00}, {0xb3, 0x00},
+       {0x84, 0x03}, {0x85, 0x03}, {0x86, 0x03}, {0xb7, 0x00},
+       {0x88, 0x03}, {0x89, 0x03}, {0x8a, 0x03}, {0xbb, 0x00},
+       {0x8c, 0x03}, {0xbd, 0x00}, {0x8e, 0x03}, {0x8f, 0x03},
+       /* 0xc0*/
+       {0x90, 0x03}, {0x91, 0x03}, {0x92, 0x03}, {0x93, 0x03},
+       {0x94, 0x03}, {0x95, 0x03}, {0x96, 0x03}, {0x97, 0x03},
+       {0x98, 0x03}, {0x99, 0x03}, {0x9a, 0x03}, {0x9b, 0x03},
+       {0x9c, 0x03}, {0x9d, 0x03}, {0x9e, 0x03}, {0x9f, 0x03},
+       /* 0xd0*/
+       {0xa0, 0x03}, {0xa1, 0x03}, {0x00, 0x00}, {0xa3, 0x03},
+       {0xa4, 0x03}, {0xa5, 0x03}, {0xa6, 0x03}, {0xa7, 0x03},
+       {0xa8, 0x03}, {0xa9, 0x03}, {0xaa, 0x03}, {0xab, 0x03},
+       {0xac, 0x03}, {0xad, 0x03}, {0xae, 0x03}, {0xaf, 0x03},
+       /* 0xe0*/
+       {0xb0, 0x03}, {0xb1, 0x03}, {0xb2, 0x03}, {0xb3, 0x03},
+       {0xb4, 0x03}, {0xb5, 0x03}, {0xb6, 0x03}, {0xb7, 0x03},
+       {0xb8, 0x03}, {0xb9, 0x03}, {0xba, 0x03}, {0xbb, 0x03},
+       {0xbc, 0x03}, {0xbd, 0x03}, {0xbe, 0x03}, {0xbf, 0x03},
+       /* 0xf0*/
+       {0xc0, 0x03}, {0xc1, 0x03}, {0xc2, 0x03}, {0xc3, 0x03},
+       {0xc4, 0x03}, {0xc5, 0x03}, {0xc6, 0x03}, {0xc7, 0x03},
+       {0xc8, 0x03}, {0xc9, 0x03}, {0xca, 0x03}, {0xcb, 0x03},
+       {0xcc, 0x03}, {0xcd, 0x03}, {0xce, 0x03}, {0x00, 0x00},
+};
+
+static unsigned char page00[256] = {
+       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+       0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
+       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
+       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
+       0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+       0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */
+       0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */
+       0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */
+       0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0xa0, 0x00, 0x00, 0xa3, 0x00, 0x00, 0xa6, 0xa7, /* 0xa0-0xa7 */
+       0xa8, 0xa9, 0x00, 0xab, 0xac, 0xad, 0x00, 0x00, /* 0xa8-0xaf */
+       0xb0, 0xb1, 0xb2, 0xb3, 0x00, 0x00, 0x00, 0xb7, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0xbb, 0x00, 0xbd, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page02[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0xa2, 0xa1, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page03[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0xb4, 0xb5, 0xb6, 0x00, /* 0x80-0x87 */
+       0xb8, 0xb9, 0xba, 0x00, 0xbc, 0x00, 0xbe, 0xbf, /* 0x88-0x8f */
+       0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0x90-0x97 */
+       0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0x98-0x9f */
+       0xd0, 0xd1, 0x00, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xa0-0xa7 */
+       0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, /* 0xa8-0xaf */
+       0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0xb0-0xb7 */
+       0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xb8-0xbf */
+       0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xc0-0xc7 */
+       0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page20[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0xaf, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char *page_uni2charset[256] = {
+       page00, NULL,   page02, page03, NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       page20, NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+};
+
+#if 0
+static unsigned char charset2upper[256] = {
+       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+       0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
+       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
+       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
+       0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+       0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+       0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 0x80-0x87 */
+       0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, /* 0x88-0x8f */
+       0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, /* 0x90-0x97 */
+       0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, /* 0x98-0x9f */
+       0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, /* 0xa0-0xa7 */
+       0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
+       0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
+       0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* 0xb8-0xbf */
+       0x00, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xc0-0xc7 */
+       0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
+       0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
+       0xd8, 0xd9, 0xda, 0xdb, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, /* 0xf8-0xff */
+};
+#endif
+
+static struct unls_table table = {
+       "iso8859-7",
+       page_uni2charset,
+       charset2uni,
+       NULL
+};
+
+int
+init_unls_iso8859_7()
+{
+       return (register_unls(&table));
+}
diff --git a/libunls/nls_iso8859-8.c b/libunls/nls_iso8859-8.c
new file mode 100644 (file)
index 0000000..6b69d32
--- /dev/null
@@ -0,0 +1,292 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)nls_iso8859-8.c 1.2 05/05/01 2000 J. Schilling */
+/*
+ *     Modifications to make the code portable Copyright (c) 2000 J. Schilling
+ *
+ *     Code taken from the Linux kernel.
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/*
+ * linux/fs/nls_iso8859-8.c
+ *
+ * Charset iso8859-8 translation tables.
+ * Generated automatically from the Unicode and charset
+ * tables from the Unicode Organization (www.unicode.org).
+ * The Unicode to charset table has only exact mappings.
+ */
+
+#include <mconfig.h>
+#include "nls.h"
+
+static struct unls_unicode charset2uni[256] = {
+       /* 0x00*/
+       {0x00, 0x00}, {0x01, 0x00}, {0x02, 0x00}, {0x03, 0x00},
+       {0x04, 0x00}, {0x05, 0x00}, {0x06, 0x00}, {0x07, 0x00},
+       {0x08, 0x00}, {0x09, 0x00}, {0x0a, 0x00}, {0x0b, 0x00},
+       {0x0c, 0x00}, {0x0d, 0x00}, {0x0e, 0x00}, {0x0f, 0x00},
+       /* 0x10*/
+       {0x10, 0x00}, {0x11, 0x00}, {0x12, 0x00}, {0x13, 0x00},
+       {0x14, 0x00}, {0x15, 0x00}, {0x16, 0x00}, {0x17, 0x00},
+       {0x18, 0x00}, {0x19, 0x00}, {0x1a, 0x00}, {0x1b, 0x00},
+       {0x1c, 0x00}, {0x1d, 0x00}, {0x1e, 0x00}, {0x1f, 0x00},
+       /* 0x20*/
+       {0x20, 0x00}, {0x21, 0x00}, {0x22, 0x00}, {0x23, 0x00},
+       {0x24, 0x00}, {0x25, 0x00}, {0x26, 0x00}, {0x27, 0x00},
+       {0x28, 0x00}, {0x29, 0x00}, {0x2a, 0x00}, {0x2b, 0x00},
+       {0x2c, 0x00}, {0x2d, 0x00}, {0x2e, 0x00}, {0x2f, 0x00},
+       /* 0x30*/
+       {0x30, 0x00}, {0x31, 0x00}, {0x32, 0x00}, {0x33, 0x00},
+       {0x34, 0x00}, {0x35, 0x00}, {0x36, 0x00}, {0x37, 0x00},
+       {0x38, 0x00}, {0x39, 0x00}, {0x3a, 0x00}, {0x3b, 0x00},
+       {0x3c, 0x00}, {0x3d, 0x00}, {0x3e, 0x00}, {0x3f, 0x00},
+       /* 0x40*/
+       {0x40, 0x00}, {0x41, 0x00}, {0x42, 0x00}, {0x43, 0x00},
+       {0x44, 0x00}, {0x45, 0x00}, {0x46, 0x00}, {0x47, 0x00},
+       {0x48, 0x00}, {0x49, 0x00}, {0x4a, 0x00}, {0x4b, 0x00},
+       {0x4c, 0x00}, {0x4d, 0x00}, {0x4e, 0x00}, {0x4f, 0x00},
+       /* 0x50*/
+       {0x50, 0x00}, {0x51, 0x00}, {0x52, 0x00}, {0x53, 0x00},
+       {0x54, 0x00}, {0x55, 0x00}, {0x56, 0x00}, {0x57, 0x00},
+       {0x58, 0x00}, {0x59, 0x00}, {0x5a, 0x00}, {0x5b, 0x00},
+       {0x5c, 0x00}, {0x5d, 0x00}, {0x5e, 0x00}, {0x5f, 0x00},
+       /* 0x60*/
+       {0x60, 0x00}, {0x61, 0x00}, {0x62, 0x00}, {0x63, 0x00},
+       {0x64, 0x00}, {0x65, 0x00}, {0x66, 0x00}, {0x67, 0x00},
+       {0x68, 0x00}, {0x69, 0x00}, {0x6a, 0x00}, {0x6b, 0x00},
+       {0x6c, 0x00}, {0x6d, 0x00}, {0x6e, 0x00}, {0x6f, 0x00},
+       /* 0x70*/
+       {0x70, 0x00}, {0x71, 0x00}, {0x72, 0x00}, {0x73, 0x00},
+       {0x74, 0x00}, {0x75, 0x00}, {0x76, 0x00}, {0x77, 0x00},
+       {0x78, 0x00}, {0x79, 0x00}, {0x7a, 0x00}, {0x7b, 0x00},
+       {0x7c, 0x00}, {0x7d, 0x00}, {0x7e, 0x00}, {0x7f, 0x00},
+       /* 0x80*/
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       /* 0x90*/
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       /* 0xa0*/
+       {0xa0, 0x00}, {0x00, 0x00}, {0xa2, 0x00}, {0xa3, 0x00},
+       {0xa4, 0x00}, {0xa5, 0x00}, {0xa6, 0x00}, {0xa7, 0x00},
+       {0xa8, 0x00}, {0xa9, 0x00}, {0xd7, 0x00}, {0xab, 0x00},
+       {0xac, 0x00}, {0xad, 0x00}, {0xae, 0x00}, {0x3e, 0x20},
+       /* 0xb0*/
+       {0xb0, 0x00}, {0xb1, 0x00}, {0xb2, 0x00}, {0xb3, 0x00},
+       {0xb4, 0x00}, {0xb5, 0x00}, {0xb6, 0x00}, {0xb7, 0x00},
+       {0xb8, 0x00}, {0xb9, 0x00}, {0xf7, 0x00}, {0xbb, 0x00},
+       {0xbc, 0x00}, {0xbd, 0x00}, {0xbe, 0x00}, {0x00, 0x00},
+       /* 0xc0*/
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       /* 0xd0*/
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x17, 0x20},
+       /* 0xe0*/
+       {0xd0, 0x05}, {0xd1, 0x05}, {0xd2, 0x05}, {0xd3, 0x05},
+       {0xd4, 0x05}, {0xd5, 0x05}, {0xd6, 0x05}, {0xd7, 0x05},
+       {0xd8, 0x05}, {0xd9, 0x05}, {0xda, 0x05}, {0xdb, 0x05},
+       {0xdc, 0x05}, {0xdd, 0x05}, {0xde, 0x05}, {0xdf, 0x05},
+       /* 0xf0*/
+       {0xe0, 0x05}, {0xe1, 0x05}, {0xe2, 0x05}, {0xe3, 0x05},
+       {0xe4, 0x05}, {0xe5, 0x05}, {0xe6, 0x05}, {0xe7, 0x05},
+       {0xe8, 0x05}, {0xe9, 0x05}, {0xea, 0x05}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+};
+
+static unsigned char page00[256] = {
+       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+       0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
+       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
+       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
+       0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+       0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */
+       0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */
+       0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */
+       0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0xa0, 0x00, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, /* 0xa0-0xa7 */
+       0xa8, 0xa9, 0x00, 0xab, 0xac, 0xad, 0xae, 0x00, /* 0xa8-0xaf */
+       0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
+       0xb8, 0xb9, 0x00, 0xbb, 0xbc, 0xbd, 0xbe, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xba, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page05[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0xd0-0xd7 */
+       0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xd8-0xdf */
+       0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xe0-0xe7 */
+       0xf8, 0xf9, 0xfa, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page20[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdf, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaf, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char *page_uni2charset[256] = {
+       page00, NULL,   NULL,   NULL,   NULL,   page05, NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       page20, NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+};
+
+#if 0
+static unsigned char charset2upper[256] = {
+       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+       0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
+       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
+       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
+       0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+       0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+       0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 0x80-0x87 */
+       0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, /* 0x88-0x8f */
+       0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, /* 0x90-0x97 */
+       0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, /* 0x98-0x9f */
+       0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, /* 0xa0-0xa7 */
+       0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
+       0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
+       0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* 0xb8-0xbf */
+       0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xc0-0xc7 */
+       0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
+       0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
+       0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, /* 0xd8-0xdf */
+       0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0xe0-0xe7 */
+       0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xe8-0xef */
+       0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
+       0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
+};
+#endif
+
+static struct unls_table table = {
+       "iso8859-8",
+       page_uni2charset,
+       charset2uni,
+       NULL
+};
+
+int
+init_unls_iso8859_8()
+{
+       return (register_unls(&table));
+}
diff --git a/libunls/nls_iso8859-9.c b/libunls/nls_iso8859-9.c
new file mode 100644 (file)
index 0000000..8229922
--- /dev/null
@@ -0,0 +1,252 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)nls_iso8859-9.c 1.2 05/05/01 2000 J. Schilling */
+/*
+ *     Modifications to make the code portable Copyright (c) 2000 J. Schilling
+ *
+ *     Code taken from the Linux kernel.
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/*
+ * linux/fs/nls_iso8859-9.c
+ *
+ * Charset iso8859-9 translation tables.
+ * Generated automatically from the Unicode and charset
+ * tables from the Unicode Organization (www.unicode.org).
+ * The Unicode to charset table has only exact mappings.
+ */
+
+#include <mconfig.h>
+#include "nls.h"
+
+static struct unls_unicode charset2uni[256] = {
+       /* 0x00*/
+       {0x00, 0x00}, {0x01, 0x00}, {0x02, 0x00}, {0x03, 0x00},
+       {0x04, 0x00}, {0x05, 0x00}, {0x06, 0x00}, {0x07, 0x00},
+       {0x08, 0x00}, {0x09, 0x00}, {0x0a, 0x00}, {0x0b, 0x00},
+       {0x0c, 0x00}, {0x0d, 0x00}, {0x0e, 0x00}, {0x0f, 0x00},
+       /* 0x10*/
+       {0x10, 0x00}, {0x11, 0x00}, {0x12, 0x00}, {0x13, 0x00},
+       {0x14, 0x00}, {0x15, 0x00}, {0x16, 0x00}, {0x17, 0x00},
+       {0x18, 0x00}, {0x19, 0x00}, {0x1a, 0x00}, {0x1b, 0x00},
+       {0x1c, 0x00}, {0x1d, 0x00}, {0x1e, 0x00}, {0x1f, 0x00},
+       /* 0x20*/
+       {0x20, 0x00}, {0x21, 0x00}, {0x22, 0x00}, {0x23, 0x00},
+       {0x24, 0x00}, {0x25, 0x00}, {0x26, 0x00}, {0x27, 0x00},
+       {0x28, 0x00}, {0x29, 0x00}, {0x2a, 0x00}, {0x2b, 0x00},
+       {0x2c, 0x00}, {0x2d, 0x00}, {0x2e, 0x00}, {0x2f, 0x00},
+       /* 0x30*/
+       {0x30, 0x00}, {0x31, 0x00}, {0x32, 0x00}, {0x33, 0x00},
+       {0x34, 0x00}, {0x35, 0x00}, {0x36, 0x00}, {0x37, 0x00},
+       {0x38, 0x00}, {0x39, 0x00}, {0x3a, 0x00}, {0x3b, 0x00},
+       {0x3c, 0x00}, {0x3d, 0x00}, {0x3e, 0x00}, {0x3f, 0x00},
+       /* 0x40*/
+       {0x40, 0x00}, {0x41, 0x00}, {0x42, 0x00}, {0x43, 0x00},
+       {0x44, 0x00}, {0x45, 0x00}, {0x46, 0x00}, {0x47, 0x00},
+       {0x48, 0x00}, {0x49, 0x00}, {0x4a, 0x00}, {0x4b, 0x00},
+       {0x4c, 0x00}, {0x4d, 0x00}, {0x4e, 0x00}, {0x4f, 0x00},
+       /* 0x50*/
+       {0x50, 0x00}, {0x51, 0x00}, {0x52, 0x00}, {0x53, 0x00},
+       {0x54, 0x00}, {0x55, 0x00}, {0x56, 0x00}, {0x57, 0x00},
+       {0x58, 0x00}, {0x59, 0x00}, {0x5a, 0x00}, {0x5b, 0x00},
+       {0x5c, 0x00}, {0x5d, 0x00}, {0x5e, 0x00}, {0x5f, 0x00},
+       /* 0x60*/
+       {0x60, 0x00}, {0x61, 0x00}, {0x62, 0x00}, {0x63, 0x00},
+       {0x64, 0x00}, {0x65, 0x00}, {0x66, 0x00}, {0x67, 0x00},
+       {0x68, 0x00}, {0x69, 0x00}, {0x6a, 0x00}, {0x6b, 0x00},
+       {0x6c, 0x00}, {0x6d, 0x00}, {0x6e, 0x00}, {0x6f, 0x00},
+       /* 0x70*/
+       {0x70, 0x00}, {0x71, 0x00}, {0x72, 0x00}, {0x73, 0x00},
+       {0x74, 0x00}, {0x75, 0x00}, {0x76, 0x00}, {0x77, 0x00},
+       {0x78, 0x00}, {0x79, 0x00}, {0x7a, 0x00}, {0x7b, 0x00},
+       {0x7c, 0x00}, {0x7d, 0x00}, {0x7e, 0x00}, {0x7f, 0x00},
+       /* 0x80*/
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       /* 0x90*/
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+       /* 0xa0*/
+       {0xa0, 0x00}, {0xa1, 0x00}, {0xa2, 0x00}, {0xa3, 0x00},
+       {0xa4, 0x00}, {0xa5, 0x00}, {0xa6, 0x00}, {0xa7, 0x00},
+       {0xa8, 0x00}, {0xa9, 0x00}, {0xaa, 0x00}, {0xab, 0x00},
+       {0xac, 0x00}, {0xad, 0x00}, {0xae, 0x00}, {0xaf, 0x00},
+       /* 0xb0*/
+       {0xb0, 0x00}, {0xb1, 0x00}, {0xb2, 0x00}, {0xb3, 0x00},
+       {0xb4, 0x00}, {0xb5, 0x00}, {0xb6, 0x00}, {0xb7, 0x00},
+       {0xb8, 0x00}, {0xb9, 0x00}, {0xba, 0x00}, {0xbb, 0x00},
+       {0xbc, 0x00}, {0xbd, 0x00}, {0xbe, 0x00}, {0xbf, 0x00},
+       /* 0xc0*/
+       {0xc0, 0x00}, {0xc1, 0x00}, {0xc2, 0x00}, {0xc3, 0x00},
+       {0xc4, 0x00}, {0xc5, 0x00}, {0xc6, 0x00}, {0xc7, 0x00},
+       {0xc8, 0x00}, {0xc9, 0x00}, {0xca, 0x00}, {0xcb, 0x00},
+       {0xcc, 0x00}, {0xcd, 0x00}, {0xce, 0x00}, {0xcf, 0x00},
+       /* 0xd0*/
+       {0x1e, 0x01}, {0xd1, 0x00}, {0xd2, 0x00}, {0xd3, 0x00},
+       {0xd4, 0x00}, {0xd5, 0x00}, {0xd6, 0x00}, {0xd7, 0x00},
+       {0xd8, 0x00}, {0xd9, 0x00}, {0xda, 0x00}, {0xdb, 0x00},
+       {0xdc, 0x00}, {0x30, 0x01}, {0x5e, 0x01}, {0xdf, 0x00},
+       /* 0xe0*/
+       {0xe0, 0x00}, {0xe1, 0x00}, {0xe2, 0x00}, {0xe3, 0x00},
+       {0xe4, 0x00}, {0xe5, 0x00}, {0xe6, 0x00}, {0xe7, 0x00},
+       {0xe8, 0x00}, {0xe9, 0x00}, {0xea, 0x00}, {0xeb, 0x00},
+       {0xec, 0x00}, {0xed, 0x00}, {0xee, 0x00}, {0xef, 0x00},
+       /* 0xf0*/
+       {0x1f, 0x01}, {0xf1, 0x00}, {0xf2, 0x00}, {0xf3, 0x00},
+       {0xf4, 0x00}, {0xf5, 0x00}, {0xf6, 0x00}, {0xf7, 0x00},
+       {0xf8, 0x00}, {0xf9, 0x00}, {0xfa, 0x00}, {0xfb, 0x00},
+       {0xfc, 0x00}, {0x31, 0x01}, {0x5f, 0x01}, {0xff, 0x00},
+};
+
+static unsigned char page00[256] = {
+       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+       0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
+       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
+       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
+       0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+       0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */
+       0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */
+       0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */
+       0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, /* 0xa0-0xa7 */
+       0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
+       0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
+       0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* 0xb8-0xbf */
+       0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xc0-0xc7 */
+       0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
+       0x00, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
+       0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0x00, 0x00, 0xdf, /* 0xd8-0xdf */
+       0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0xe0-0xe7 */
+       0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xe8-0xef */
+       0x00, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
+       0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0x00, 0x00, 0xff, /* 0xf8-0xff */
+};
+
+static unsigned char page01[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0xf0, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0xdd, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xde, 0xfe, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char *page_uni2charset[256] = {
+       page00, page01, NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+};
+
+#if 0
+static unsigned char charset2upper[256] = {
+       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+       0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
+       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
+       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
+       0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+       0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+       0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 0x80-0x87 */
+       0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, /* 0x88-0x8f */
+       0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, /* 0x90-0x97 */
+       0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, /* 0x98-0x9f */
+       0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, /* 0xa0-0xa7 */
+       0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
+       0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
+       0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* 0xb8-0xbf */
+       0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xc0-0xc7 */
+       0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
+       0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
+       0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf7, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+#endif
+
+static struct unls_table table = {
+       "iso8859-9",
+       page_uni2charset,
+       charset2uni,
+       NULL
+};
+
+int
+init_unls_iso8859_9()
+{
+       return (register_unls(&table));
+}
diff --git a/libunls/nls_koi8-r.c b/libunls/nls_koi8-r.c
new file mode 100644 (file)
index 0000000..6be6933
--- /dev/null
@@ -0,0 +1,364 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)nls_koi8-r.c    1.2 05/05/01 2000 J. Schilling */
+/*
+ *     Modifications to make the code portable Copyright (c) 2000 J. Schilling
+ *
+ *     Code taken from the Linux kernel.
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/*
+ * linux/fs/nls_koi8-r.c
+ *
+ * Charset koi8-r translation tables.
+ * Generated automatically from the Unicode and charset
+ * tables from the Unicode Organization (www.unicode.org).
+ * The Unicode to charset table has only exact mappings.
+ */
+
+#include <mconfig.h>
+#include "nls.h"
+
+static struct unls_unicode charset2uni[256] = {
+       /* 0x00*/
+       {0x00, 0x00}, {0x01, 0x00}, {0x02, 0x00}, {0x03, 0x00},
+       {0x04, 0x00}, {0x05, 0x00}, {0x06, 0x00}, {0x07, 0x00},
+       {0x08, 0x00}, {0x09, 0x00}, {0x0a, 0x00}, {0x0b, 0x00},
+       {0x0c, 0x00}, {0x0d, 0x00}, {0x0e, 0x00}, {0x0f, 0x00},
+       /* 0x10*/
+       {0x10, 0x00}, {0x11, 0x00}, {0x12, 0x00}, {0x13, 0x00},
+       {0x14, 0x00}, {0x15, 0x00}, {0x16, 0x00}, {0x17, 0x00},
+       {0x18, 0x00}, {0x19, 0x00}, {0x1a, 0x00}, {0x1b, 0x00},
+       {0x1c, 0x00}, {0x1d, 0x00}, {0x1e, 0x00}, {0x1f, 0x00},
+       /* 0x20*/
+       {0x20, 0x00}, {0x21, 0x00}, {0x22, 0x00}, {0x23, 0x00},
+       {0x24, 0x00}, {0x25, 0x00}, {0x26, 0x00}, {0x27, 0x00},
+       {0x28, 0x00}, {0x29, 0x00}, {0x2a, 0x00}, {0x2b, 0x00},
+       {0x2c, 0x00}, {0x2d, 0x00}, {0x2e, 0x00}, {0x2f, 0x00},
+       /* 0x30*/
+       {0x30, 0x00}, {0x31, 0x00}, {0x32, 0x00}, {0x33, 0x00},
+       {0x34, 0x00}, {0x35, 0x00}, {0x36, 0x00}, {0x37, 0x00},
+       {0x38, 0x00}, {0x39, 0x00}, {0x3a, 0x00}, {0x3b, 0x00},
+       {0x3c, 0x00}, {0x3d, 0x00}, {0x3e, 0x00}, {0x3f, 0x00},
+       /* 0x40*/
+       {0x40, 0x00}, {0x41, 0x00}, {0x42, 0x00}, {0x43, 0x00},
+       {0x44, 0x00}, {0x45, 0x00}, {0x46, 0x00}, {0x47, 0x00},
+       {0x48, 0x00}, {0x49, 0x00}, {0x4a, 0x00}, {0x4b, 0x00},
+       {0x4c, 0x00}, {0x4d, 0x00}, {0x4e, 0x00}, {0x4f, 0x00},
+       /* 0x50*/
+       {0x50, 0x00}, {0x51, 0x00}, {0x52, 0x00}, {0x53, 0x00},
+       {0x54, 0x00}, {0x55, 0x00}, {0x56, 0x00}, {0x57, 0x00},
+       {0x58, 0x00}, {0x59, 0x00}, {0x5a, 0x00}, {0x5b, 0x00},
+       {0x5c, 0x00}, {0x5d, 0x00}, {0x5e, 0x00}, {0x5f, 0x00},
+       /* 0x60*/
+       {0x60, 0x00}, {0x61, 0x00}, {0x62, 0x00}, {0x63, 0x00},
+       {0x64, 0x00}, {0x65, 0x00}, {0x66, 0x00}, {0x67, 0x00},
+       {0x68, 0x00}, {0x69, 0x00}, {0x6a, 0x00}, {0x6b, 0x00},
+       {0x6c, 0x00}, {0x6d, 0x00}, {0x6e, 0x00}, {0x6f, 0x00},
+       /* 0x70*/
+       {0x70, 0x00}, {0x71, 0x00}, {0x72, 0x00}, {0x73, 0x00},
+       {0x74, 0x00}, {0x75, 0x00}, {0x76, 0x00}, {0x77, 0x00},
+       {0x78, 0x00}, {0x79, 0x00}, {0x7a, 0x00}, {0x7b, 0x00},
+       {0x7c, 0x00}, {0x7d, 0x00}, {0x7e, 0x00}, {0x7f, 0x00},
+       /* 0x80*/
+       {0x00, 0x25}, {0x02, 0x25}, {0x0c, 0x25}, {0x10, 0x25},
+       {0x14, 0x25}, {0x18, 0x25}, {0x1c, 0x25}, {0x24, 0x25},
+       {0x2c, 0x25}, {0x34, 0x25}, {0x3c, 0x25}, {0x80, 0x25},
+       {0x84, 0x25}, {0x88, 0x25}, {0x8c, 0x25}, {0x90, 0x25},
+       /* 0x90*/
+       {0x91, 0x25}, {0x92, 0x25}, {0x93, 0x25}, {0x20, 0x23},
+       {0xa0, 0x25}, {0x19, 0x22}, {0x1a, 0x22}, {0x48, 0x22},
+       {0x64, 0x22}, {0x65, 0x22}, {0xa0, 0x00}, {0x21, 0x23},
+       {0xb0, 0x00}, {0xb2, 0x00}, {0xb7, 0x00}, {0xf7, 0x00},
+       /* 0xa0*/
+       {0x50, 0x25}, {0x51, 0x25}, {0x52, 0x25}, {0x51, 0x04},
+       {0x53, 0x25}, {0x54, 0x25}, {0x55, 0x25}, {0x56, 0x25},
+       {0x57, 0x25}, {0x58, 0x25}, {0x59, 0x25}, {0x5a, 0x25},
+       {0x5b, 0x25}, {0x5c, 0x25}, {0x5d, 0x25}, {0x5e, 0x25},
+       /* 0xb0*/
+       {0x5f, 0x25}, {0x60, 0x25}, {0x61, 0x25}, {0x01, 0x04},
+       {0x62, 0x25}, {0x63, 0x25}, {0x64, 0x25}, {0x65, 0x25},
+       {0x66, 0x25}, {0x67, 0x25}, {0x68, 0x25}, {0x69, 0x25},
+       {0x6a, 0x25}, {0x6b, 0x25}, {0x6c, 0x25}, {0xa9, 0x00},
+       /* 0xc0*/
+       {0x4e, 0x04}, {0x30, 0x04}, {0x31, 0x04}, {0x46, 0x04},
+       {0x34, 0x04}, {0x35, 0x04}, {0x44, 0x04}, {0x33, 0x04},
+       {0x45, 0x04}, {0x38, 0x04}, {0x39, 0x04}, {0x3a, 0x04},
+       {0x3b, 0x04}, {0x3c, 0x04}, {0x3d, 0x04}, {0x3e, 0x04},
+       /* 0xd0*/
+       {0x3f, 0x04}, {0x4f, 0x04}, {0x40, 0x04}, {0x41, 0x04},
+       {0x42, 0x04}, {0x43, 0x04}, {0x36, 0x04}, {0x32, 0x04},
+       {0x4c, 0x04}, {0x4b, 0x04}, {0x37, 0x04}, {0x48, 0x04},
+       {0x4d, 0x04}, {0x49, 0x04}, {0x47, 0x04}, {0x4a, 0x04},
+       /* 0xe0*/
+       {0x2e, 0x04}, {0x10, 0x04}, {0x11, 0x04}, {0x26, 0x04},
+       {0x14, 0x04}, {0x15, 0x04}, {0x24, 0x04}, {0x13, 0x04},
+       {0x25, 0x04}, {0x18, 0x04}, {0x19, 0x04}, {0x1a, 0x04},
+       {0x1b, 0x04}, {0x1c, 0x04}, {0x1d, 0x04}, {0x1e, 0x04},
+       /* 0xf0*/
+       {0x1f, 0x04}, {0x2f, 0x04}, {0x20, 0x04}, {0x21, 0x04},
+       {0x22, 0x04}, {0x23, 0x04}, {0x16, 0x04}, {0x12, 0x04},
+       {0x2c, 0x04}, {0x2b, 0x04}, {0x17, 0x04}, {0x28, 0x04},
+       {0x2d, 0x04}, {0x29, 0x04}, {0x27, 0x04}, {0x2a, 0x04},
+};
+
+static unsigned char page00[256] = {
+       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+       0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
+       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
+       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
+       0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+       0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */
+       0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */
+       0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */
+       0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x9a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x9c, 0x00, 0x9d, 0x00, 0x00, 0x00, 0x00, 0x9e, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9f, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page04[256] = {
+       0x00, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0xe1, 0xe2, 0xf7, 0xe7, 0xe4, 0xe5, 0xf6, 0xfa, /* 0x10-0x17 */
+       0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, /* 0x18-0x1f */
+       0xf2, 0xf3, 0xf4, 0xf5, 0xe6, 0xe8, 0xe3, 0xfe, /* 0x20-0x27 */
+       0xfb, 0xfd, 0xff, 0xf9, 0xf8, 0xfc, 0xe0, 0xf1, /* 0x28-0x2f */
+       0xc1, 0xc2, 0xd7, 0xc7, 0xc4, 0xc5, 0xd6, 0xda, /* 0x30-0x37 */
+       0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, /* 0x38-0x3f */
+       0xd2, 0xd3, 0xd4, 0xd5, 0xc6, 0xc8, 0xc3, 0xde, /* 0x40-0x47 */
+       0xdb, 0xdd, 0xdf, 0xd9, 0xd8, 0xdc, 0xc0, 0xd1, /* 0x48-0x4f */
+       0x00, 0xa3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page22[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x95, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x98, 0x99, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page23[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x93, 0x9b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page25[256] = {
+       0x80, 0x00, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x82, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x83, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x85, 0x00, 0x00, 0x00, 0x86, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x87, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x89, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x8a, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0xa0, 0xa1, 0xa2, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, /* 0x50-0x57 */
+       0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, /* 0x58-0x5f */
+       0xb1, 0xb2, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, /* 0x60-0x67 */
+       0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x8b, 0x00, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x8d, 0x00, 0x00, 0x00, 0x8e, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x8f, 0x90, 0x91, 0x92, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char *page_uni2charset[256] = {
+       page00, NULL,   NULL,   NULL,   page04, NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   page22, page23, NULL,   page25, NULL,   NULL,
+};
+
+#if 0
+static unsigned char charset2upper[256] = {
+       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+       0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
+       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
+       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
+       0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+       0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+       0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 0x80-0x87 */
+       0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, /* 0x88-0x8f */
+       0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, /* 0x90-0x97 */
+       0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, /* 0x98-0x9f */
+       0xa0, 0xa1, 0xa2, 0x00, 0xa4, 0xa5, 0xa6, 0xa7, /* 0xa0-0xa7 */
+       0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
+       0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
+       0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0xe0-0xe7 */
+       0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xe8-0xef */
+       0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
+       0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
+};
+#endif
+
+static struct unls_table table = {
+       "koi8-r",
+       page_uni2charset,
+       charset2uni,
+       NULL
+};
+
+int
+init_unls_koi8_r()
+{
+       return (register_unls(&table));
+}
diff --git a/libunls/nls_koi8-u.c b/libunls/nls_koi8-u.c
new file mode 100644 (file)
index 0000000..2623236
--- /dev/null
@@ -0,0 +1,364 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)nls_koi8-u.c    1.2 05/05/01 2002 J. Schilling by Andy Shevchenko */
+/*
+ *     Modifications to make the code portable Copyright (c) 2000 J. Schilling
+ *
+ *     Code taken from the Linux kernel.
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/*
+ * linux/fs/nls_koi8-u.c
+ *
+ * Charset koi8-u translation tables.
+ * Generated automatically from the Unicode and charset
+ * tables from the Unicode Organization (www.unicode.org).
+ * The Unicode to charset table has only exact mappings.
+ */
+
+#include <mconfig.h>
+#include "nls.h"
+
+static struct unls_unicode charset2uni[256] = {
+       /* 0x00*/
+       {0x00, 0x00}, {0x01, 0x00}, {0x02, 0x00}, {0x03, 0x00},
+       {0x04, 0x00}, {0x05, 0x00}, {0x06, 0x00}, {0x07, 0x00},
+       {0x08, 0x00}, {0x09, 0x00}, {0x0a, 0x00}, {0x0b, 0x00},
+       {0x0c, 0x00}, {0x0d, 0x00}, {0x0e, 0x00}, {0x0f, 0x00},
+       /* 0x10*/
+       {0x10, 0x00}, {0x11, 0x00}, {0x12, 0x00}, {0x13, 0x00},
+       {0x14, 0x00}, {0x15, 0x00}, {0x16, 0x00}, {0x17, 0x00},
+       {0x18, 0x00}, {0x19, 0x00}, {0x1a, 0x00}, {0x1b, 0x00},
+       {0x1c, 0x00}, {0x1d, 0x00}, {0x1e, 0x00}, {0x1f, 0x00},
+       /* 0x20*/
+       {0x20, 0x00}, {0x21, 0x00}, {0x22, 0x00}, {0x23, 0x00},
+       {0x24, 0x00}, {0x25, 0x00}, {0x26, 0x00}, {0x27, 0x00},
+       {0x28, 0x00}, {0x29, 0x00}, {0x2a, 0x00}, {0x2b, 0x00},
+       {0x2c, 0x00}, {0x2d, 0x00}, {0x2e, 0x00}, {0x2f, 0x00},
+       /* 0x30*/
+       {0x30, 0x00}, {0x31, 0x00}, {0x32, 0x00}, {0x33, 0x00},
+       {0x34, 0x00}, {0x35, 0x00}, {0x36, 0x00}, {0x37, 0x00},
+       {0x38, 0x00}, {0x39, 0x00}, {0x3a, 0x00}, {0x3b, 0x00},
+       {0x3c, 0x00}, {0x3d, 0x00}, {0x3e, 0x00}, {0x3f, 0x00},
+       /* 0x40*/
+       {0x40, 0x00}, {0x41, 0x00}, {0x42, 0x00}, {0x43, 0x00},
+       {0x44, 0x00}, {0x45, 0x00}, {0x46, 0x00}, {0x47, 0x00},
+       {0x48, 0x00}, {0x49, 0x00}, {0x4a, 0x00}, {0x4b, 0x00},
+       {0x4c, 0x00}, {0x4d, 0x00}, {0x4e, 0x00}, {0x4f, 0x00},
+       /* 0x50*/
+       {0x50, 0x00}, {0x51, 0x00}, {0x52, 0x00}, {0x53, 0x00},
+       {0x54, 0x00}, {0x55, 0x00}, {0x56, 0x00}, {0x57, 0x00},
+       {0x58, 0x00}, {0x59, 0x00}, {0x5a, 0x00}, {0x5b, 0x00},
+       {0x5c, 0x00}, {0x5d, 0x00}, {0x5e, 0x00}, {0x5f, 0x00},
+       /* 0x60*/
+       {0x60, 0x00}, {0x61, 0x00}, {0x62, 0x00}, {0x63, 0x00},
+       {0x64, 0x00}, {0x65, 0x00}, {0x66, 0x00}, {0x67, 0x00},
+       {0x68, 0x00}, {0x69, 0x00}, {0x6a, 0x00}, {0x6b, 0x00},
+       {0x6c, 0x00}, {0x6d, 0x00}, {0x6e, 0x00}, {0x6f, 0x00},
+       /* 0x70*/
+       {0x70, 0x00}, {0x71, 0x00}, {0x72, 0x00}, {0x73, 0x00},
+       {0x74, 0x00}, {0x75, 0x00}, {0x76, 0x00}, {0x77, 0x00},
+       {0x78, 0x00}, {0x79, 0x00}, {0x7a, 0x00}, {0x7b, 0x00},
+       {0x7c, 0x00}, {0x7d, 0x00}, {0x7e, 0x00}, {0x7f, 0x00},
+       /* 0x80*/
+       {0x00, 0x25}, {0x02, 0x25}, {0x0c, 0x25}, {0x10, 0x25},
+       {0x14, 0x25}, {0x18, 0x25}, {0x1c, 0x25}, {0x24, 0x25},
+       {0x2c, 0x25}, {0x34, 0x25}, {0x3c, 0x25}, {0x80, 0x25},
+       {0x84, 0x25}, {0x88, 0x25}, {0x8c, 0x25}, {0x90, 0x25},
+       /* 0x90*/
+       {0x91, 0x25}, {0x92, 0x25}, {0x93, 0x25}, {0x20, 0x23},
+       {0xa0, 0x25}, {0x19, 0x22}, {0x1a, 0x22}, {0x48, 0x22},
+       {0x64, 0x22}, {0x65, 0x22}, {0xa0, 0x00}, {0x21, 0x23},
+       {0xb0, 0x00}, {0xb2, 0x00}, {0xb7, 0x00}, {0xf7, 0x00},
+       /* 0xa0*/
+       {0x50, 0x25}, {0x51, 0x25}, {0x52, 0x25}, {0x51, 0x04},
+       {0x54, 0x04}, {0x54, 0x25}, {0x56, 0x04}, {0x57, 0x04},
+       {0x57, 0x25}, {0x58, 0x25}, {0x59, 0x25}, {0x5a, 0x25},
+       {0x5b, 0x25}, {0x91, 0x04}, {0x5d, 0x25}, {0x5e, 0x25},
+       /* 0xb0*/
+       {0x5f, 0x25}, {0x60, 0x25}, {0x61, 0x25}, {0x01, 0x04},
+       {0x04, 0x04}, {0x63, 0x25}, {0x06, 0x04}, {0x07, 0x04},
+       {0x66, 0x25}, {0x67, 0x25}, {0x68, 0x25}, {0x69, 0x25},
+       {0x6a, 0x25}, {0x90, 0x04}, {0x6c, 0x25}, {0xa9, 0x00},
+       /* 0xc0*/
+       {0x4e, 0x04}, {0x30, 0x04}, {0x31, 0x04}, {0x46, 0x04},
+       {0x34, 0x04}, {0x35, 0x04}, {0x44, 0x04}, {0x33, 0x04},
+       {0x45, 0x04}, {0x38, 0x04}, {0x39, 0x04}, {0x3a, 0x04},
+       {0x3b, 0x04}, {0x3c, 0x04}, {0x3d, 0x04}, {0x3e, 0x04},
+       /* 0xd0*/
+       {0x3f, 0x04}, {0x4f, 0x04}, {0x40, 0x04}, {0x41, 0x04},
+       {0x42, 0x04}, {0x43, 0x04}, {0x36, 0x04}, {0x32, 0x04},
+       {0x4c, 0x04}, {0x4b, 0x04}, {0x37, 0x04}, {0x48, 0x04},
+       {0x4d, 0x04}, {0x49, 0x04}, {0x47, 0x04}, {0x4a, 0x04},
+       /* 0xe0*/
+       {0x2e, 0x04}, {0x10, 0x04}, {0x11, 0x04}, {0x26, 0x04},
+       {0x14, 0x04}, {0x15, 0x04}, {0x24, 0x04}, {0x13, 0x04},
+       {0x25, 0x04}, {0x18, 0x04}, {0x19, 0x04}, {0x1a, 0x04},
+       {0x1b, 0x04}, {0x1c, 0x04}, {0x1d, 0x04}, {0x1e, 0x04},
+       /* 0xf0*/
+       {0x1f, 0x04}, {0x2f, 0x04}, {0x20, 0x04}, {0x21, 0x04},
+       {0x22, 0x04}, {0x23, 0x04}, {0x16, 0x04}, {0x12, 0x04},
+       {0x2c, 0x04}, {0x2b, 0x04}, {0x17, 0x04}, {0x28, 0x04},
+       {0x2d, 0x04}, {0x29, 0x04}, {0x27, 0x04}, {0x2a, 0x04},
+};
+
+static unsigned char page00[256] = {
+       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+       0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
+       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
+       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
+       0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+       0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */
+       0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */
+       0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */
+       0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x9a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x9c, 0x00, 0x9d, 0x00, 0x00, 0x00, 0x00, 0x9e, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9f, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page04[256] = {
+       0x00, 0xb3, 0x00, 0x00, 0xb4, 0x00, 0xb6, 0xb7, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0xe1, 0xe2, 0xf7, 0xe7, 0xe4, 0xe5, 0xf6, 0xfa, /* 0x10-0x17 */
+       0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, /* 0x18-0x1f */
+       0xf2, 0xf3, 0xf4, 0xf5, 0xe6, 0xe8, 0xe3, 0xfe, /* 0x20-0x27 */
+       0xfb, 0xfd, 0xff, 0xf9, 0xf8, 0xfc, 0xe0, 0xf1, /* 0x28-0x2f */
+       0xc1, 0xc2, 0xd7, 0xc7, 0xc4, 0xc5, 0xd6, 0xda, /* 0x30-0x37 */
+       0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, /* 0x38-0x3f */
+       0xd2, 0xd3, 0xd4, 0xd5, 0xc6, 0xc8, 0xc3, 0xde, /* 0x40-0x47 */
+       0xdb, 0xdd, 0xdf, 0xd9, 0xd8, 0xdc, 0xc0, 0xd1, /* 0x48-0x4f */
+       0x00, 0xa3, 0x00, 0x00, 0xa4, 0x00, 0xa6, 0xa7, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0xbd, 0xad, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page22[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x95, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x98, 0x99, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page23[256] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x93, 0x9b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page25[256] = {
+       0x80, 0x00, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+       0x00, 0x00, 0x00, 0x00, 0x82, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+       0x83, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+       0x85, 0x00, 0x00, 0x00, 0x86, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+       0x00, 0x00, 0x00, 0x00, 0x87, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+       0x00, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+       0x00, 0x00, 0x00, 0x00, 0x89, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+       0x00, 0x00, 0x00, 0x00, 0x8a, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+       0xa0, 0xa1, 0xa2, 0x00, 0xa5, 0x00, 0x00, 0xa8, /* 0x50-0x57 */
+       0xa9, 0xaa, 0xab, 0xac, 0x00, 0xae, 0xaf, 0xb0, /* 0x58-0x5f */
+       0xb1, 0xb2, 0x00, 0xb5, 0x00, 0x00, 0xb8, 0xb9, /* 0x60-0x67 */
+       0xba, 0xbb, 0xbc, 0x00, 0xbe, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+       0x8b, 0x00, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+       0x8d, 0x00, 0x00, 0x00, 0x8e, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+       0x8f, 0x90, 0x91, 0x92, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+       0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char *page_uni2charset[256] = {
+       page00, NULL,   NULL,   NULL,   page04, NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,
+       NULL,   NULL,   page22, page23, NULL,   page25, NULL,   NULL,
+};
+
+#if 0
+static unsigned char charset2upper[256] = {
+       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+       0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
+       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
+       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
+       0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+       0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+       0x00, 0x00, 0x00, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+       0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 0x80-0x87 */
+       0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, /* 0x88-0x8f */
+       0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, /* 0x90-0x97 */
+       0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, /* 0x98-0x9f */
+       0xa0, 0xa1, 0xa2, 0xb3, 0xa4, 0xa5, 0xb6, 0xb7, /* 0xa0-0xa7 */
+       0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xbd, 0xae, 0xaf, /* 0xa8-0xaf */
+       0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
+       0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* 0xb8-0xbf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+       0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0xe0-0xe7 */
+       0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xe8-0xef */
+       0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
+       0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
+};
+#endif
+
+static struct unls_table table = {
+       "koi8-u",
+       page_uni2charset,
+       charset2uni,
+       NULL
+};
+
+int
+init_unls_koi8_u()
+{
+       return (register_unls(&table));
+}
diff --git a/libusal/CMakeLists.txt b/libusal/CMakeLists.txt
new file mode 100644 (file)
index 0000000..b6fc8e4
--- /dev/null
@@ -0,0 +1,10 @@
+PROJECT (LIBSCG C)
+INCLUDE_DIRECTORIES(../include ${CMAKE_BINARY_DIR} ${CMAKE_BINARY_DIR}/include)
+include(../include/AddScgBits.cmake)
+ADD_DEFINITIONS(-DUSE_RCMD_RSH)
+
+#SET(LIBSCG_SRCS rdummy.c usalsettarget.c usaltimes.c scsi-linux-ata.c scsi-linux-pg.c scsi-linux-sg.c scsierrs.c scsihack.c scsihelp.c scsiopen.c scsitransp.c)
+SET(LIBSCG_SRCS usalsettarget.c usaltimes.c scsierrs.c scsihack.c scsihelp.c scsiopen.c scsitransp.c scsi-remote.c)
+LINK_DIRECTORIES(../librols)
+ADD_LIBRARY (usal STATIC ${LIBSCG_SRCS})
+TARGET_LINK_LIBRARIES(usal ${SCG_SELF_LIBS})
diff --git a/libusal/pg.h b/libusal/pg.h
new file mode 100644 (file)
index 0000000..8e8bf18
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/*     pg.h (c) 1998  Grant R. Guenther <grant@torque.net>
+                      Under the terms of the GNU public license
+
+
+       pg.h defines the user interface to the generic ATAPI packet
+        command driver for parallel port ATAPI devices (pg). The
+       driver is loosely modelled after the generic SCSI driver, sg,
+       although the actual interface is different.
+
+       The pg driver provides a simple character device interface for
+        sending ATAPI commands to a device.  With the exception of the
+       ATAPI reset operation, all operations are performed by a pair
+        of read and write operations to the appropriate /dev/pgN device.
+       A write operation delivers a command and any outbound data in
+        a single buffer.  Normally, the write will succeed unless the
+        device is offline or malfunctioning, or there is already another
+       command pending.  If the write succeeds, it should be followed
+        immediately by a read operation, to obtain any returned data and
+        status information.  A read will fail if there is no operation
+        in progress.
+
+       As a special case, the device can be reset with a write operation,
+        and in this case, no following read is expected, or permitted.
+
+       There are no ioctl() operations.  Any single operation
+       may transfer at most PG_MAX_DATA bytes.  Note that the driver must
+        copy the data through an internal buffer.  In keeping with all
+       current ATAPI devices, command packets are assumed to be exactly
+       12 bytes in length.
+
+       To permit future changes to this interface, the headers in the
+       read and write buffers contain a single character "magic" flag.
+        Currently this flag must be the character "P".
+
+*/
+
+#define PG_MAGIC       'P'
+#define PG_RESET       'Z'
+#define PG_COMMAND     'C'
+
+#define PG_MAX_DATA    32768
+
+struct pg_write_hdr {
+
+       char    magic;          /* == PG_MAGIC */
+       char    func;           /* PG_RESET or PG_COMMAND */
+       int     dlen;           /* number of bytes expected to transfer */
+       int     timeout;        /* number of seconds before timeout */
+       char    packet[12];     /* packet command */
+
+};
+
+struct pg_read_hdr {
+
+       char    magic;          /* == PG_MAGIC */
+       char    scsi;           /* "scsi" status == sense key */
+       int     dlen;           /* size of device transfer request */
+       int     duration;       /* time in seconds command took */
+       char    pad[12];        /* not used */
+
+};
+
+/* end of pg.h */
diff --git a/libusal/rdummy.c b/libusal/rdummy.c
new file mode 100644 (file)
index 0000000..4457e00
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)rdummy.c        1.1 00/08/26 Copyright 2000 J. Schilling */
+/*
+ *     usal Library 
+ *     dummy remote ops
+ *
+ *     Copyright (c) 2000 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <mconfig.h>
+#include <standard.h>
+#include <schily.h>
+
+#include <usal/scsitransp.h>
+
+usal_ops_t *usal_remote(void);
+
+EXPORT usal_ops_t *
+usal_remote()
+{
+extern usal_ops_t usal_remote_ops;
+
+       return (&usal_remote_ops);
+}
diff --git a/libusal/scsi-aix.c b/libusal/scsi-aix.c
new file mode 100644 (file)
index 0000000..a7b4be6
--- /dev/null
@@ -0,0 +1,428 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)scsi-aix.c      1.36 04/01/14 Copyright 1997 J. Schilling */
+/*
+ *     Interface for the AIX generic SCSI implementation.
+ *
+ *     This is a hack, that tries to emulate the functionality
+ *     of the usal driver.
+ *
+ *     Warning: you may change this source, but if you do that
+ *     you need to change the _usal_version and _usal_auth* string below.
+ *     You may not return "schily" for an SCG_AUTHOR request anymore.
+ *     Choose your name instead of "schily" and make clear that the version
+ *     string is related to a modified source.
+ *
+ *     Copyright (c) 1997 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <sys/scdisk.h>
+
+/*
+ *     Warning: you may change this source, but if you do that
+ *     you need to change the _usal_version and _usal_auth* string below.
+ *     You may not return "schily" for an SCG_AUTHOR request anymore.
+ *     Choose your name instead of "schily" and make clear that the version
+ *     string is related to a modified source.
+ */
+static char    _usal_trans_version[] = "scsi-aix.c-1.36";      /* The version for this transport*/
+
+
+#define        MAX_SCG         16      /* Max # of SCSI controllers */
+#define        MAX_TGT         16
+#define        MAX_LUN         8
+
+struct usal_local{
+       short   usalfiles[MAX_SCG][MAX_TGT][MAX_LUN];
+};
+#define        usallocal(p)    ((struct usal_local*)((p)->local))
+
+#define        MAX_DMA_AIX (64*1024)
+
+static int     do_usal_cmd(SCSI *usalp, struct usal_cmd *sp);
+static int     do_usal_sense(SCSI *usalp, struct usal_cmd *sp);
+
+/*
+ * Return version information for the low level SCSI transport code.
+ * This has been introduced to make it easier to trace down problems
+ * in applications.
+ */
+static char *
+usalo_version(SCSI *usalp, int what)
+{
+       if (usalp != (SCSI *)0) {
+               switch (what) {
+
+               case SCG_VERSION:
+                       return (_usal_trans_version);
+               /*
+                * If you changed this source, you are not allowed to
+                * return "schily" for the SCG_AUTHOR request.
+                */
+               case SCG_AUTHOR:
+                       return (_usal_auth_cdrkit);
+               case SCG_SCCS_ID:
+                       return (__sccsid);
+               }
+       }
+       return ((char *)0);
+}
+
+static int
+usalo_help(SCSI *usalp, FILE *f)
+{
+       __usal_help(f, "DKIOCMD", "SCSI transport for targets known by AIX drivers",
+               "", "bus,target,lun or UNIX device", "1,2,0 or /dev/rcd0@", FALSE, TRUE);
+       return (0);
+}
+
+static int
+usalo_open(SCSI *usalp, char *device)
+{
+               int     busno   = usal_scsibus(usalp);
+               int     tgt     = usal_target(usalp);
+               int     tlun    = usal_lun(usalp);
+       register int    f;
+       register int    b;
+       register int    t;
+       register int    l;
+       register int    nopen = 0;
+       char            devname[32];
+
+       if (busno >= MAX_SCG || tgt >= MAX_TGT || tlun >= MAX_LUN) {
+               errno = EINVAL;
+               if (usalp->errstr)
+                       snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                               "Illegal value for busno, target or lun '%d,%d,%d'",
+                               busno, tgt, tlun);
+               return (-1);
+       }
+
+       if (usalp->local == NULL) {
+               usalp->local = malloc(sizeof (struct usal_local));
+               if (usalp->local == NULL)
+                       return (0);
+
+               for (b = 0; b < MAX_SCG; b++) {
+                       for (t = 0; t < MAX_TGT; t++) {
+                               for (l = 0; l < MAX_LUN; l++)
+                                       usallocal(usalp)->usalfiles[b][t][l] = (short)-1;
+                       }
+               }
+       }
+
+       if ((device != NULL && *device != '\0') || (busno == -2 && tgt == -2))
+               goto openbydev;
+
+       if (busno >= 0 && tgt >= 0 && tlun >= 0) {
+
+               snprintf(devname, sizeof (devname), "/dev/rcd%d", tgt);
+               f = openx(devname, 0, 0, SC_DIAGNOSTIC);
+               if (f < 0) {
+                       if (usalp->errstr)
+                               snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                                       "Cannot open '%s'. Specify device number (1 for cd1) as target (1,0)",
+                                       devname);
+                       return (0);
+               }
+               usallocal(usalp)->usalfiles[busno][tgt][tlun] = f;
+               return (1);
+       } else {
+               if (usalp->errstr)
+                       snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                               "Unable to scan on AIX");
+               return (0);
+       }
+openbydev:
+       if (device != NULL && *device != '\0' && busno >= 0 && tgt >= 0 && tlun >= 0) {
+               f = openx(device, 0, 0, SC_DIAGNOSTIC);
+               if (f < 0) {
+                       if (usalp->errstr)
+                               snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                                       "Cannot open '%s'",
+                                       devname);
+                       return (0);
+               }
+
+               usallocal(usalp)->usalfiles[busno][tgt][tlun] = f;
+               usal_settarget(usalp, busno, tgt, tlun);
+
+               return (++nopen);
+       }
+       return (nopen);
+}
+
+static int
+usalo_close(SCSI *usalp)
+{
+       register int    f;
+       register int    b;
+       register int    t;
+       register int    l;
+
+       if (usalp->local== NULL)
+               return (-1);
+
+       for (b = 0; b < MAX_SCG; b++) {
+               for (t = 0; t < MAX_TGT; t++) {
+                       for (l = 0; l < MAX_LUN; l++) {
+                               f = usallocal(usalp)->usalfiles[b][t][l];
+                               if (f >= 0)
+                                       close(f);
+                               usallocal(usalp)->usalfiles[b][t][l] = (short)-1;
+                       }
+               }
+       }
+       return (0);
+}
+
+static long
+usalo_maxdma(SCSI *usalp, long amt)
+{
+       return (MAX_DMA_AIX);
+}
+
+#define        palign(x, a)    (((char *)(x)) + ((a) - 1 - (((UIntptr_t)((x)-1))%(a))))
+
+static void *
+usalo_getbuf(SCSI *usalp, long amt)
+{
+/* assume having a modern AIX here */
+#ifdef HAVE_ALLOCA_H
+    usalp->bufbase = (void *)valloc((size_t)amt);
+    return (usalp->bufbase);
+#else
+       void    *ret;
+       int     pagesize = getpagesize();
+
+       if (usalp->debug > 0) {
+               fprintf((FILE *)usalp->errfile,
+                               "usalo_getbuf: %ld bytes\n", amt);
+       }
+       /*
+        * Damn AIX is a paged system but has no valloc()
+        */
+       usalp->bufbase = ret = malloc((size_t)(amt+pagesize));
+       if (ret == NULL)
+               return (ret);
+       ret = palign(ret, pagesize);
+       return (ret);
+#endif
+}
+
+static void
+usalo_freebuf(SCSI *usalp)
+{
+       if (usalp->bufbase)
+               free(usalp->bufbase);
+       usalp->bufbase = NULL;
+}
+
+static BOOL
+usalo_havebus(SCSI *usalp, int busno)
+{
+       register int    t;
+       register int    l;
+
+       if (busno < 0 || busno >= MAX_SCG)
+               return (FALSE);
+
+       if (usalp->local == NULL)
+               return (FALSE);
+
+       for (t = 0; t < MAX_TGT; t++) {
+               for (l = 0; l < MAX_LUN; l++)
+                       if (usallocal(usalp)->usalfiles[busno][t][l] >= 0)
+                               return (TRUE);
+       }
+       return (FALSE);
+}
+
+static int
+usalo_fileno(SCSI *usalp, int busno, int tgt, int tlun)
+{
+       if (busno < 0 || busno >= MAX_SCG ||
+           tgt < 0 || tgt >= MAX_TGT ||
+           tlun < 0 || tlun >= MAX_LUN)
+               return (-1);
+
+       if (usalp->local == NULL)
+               return (-1);
+
+       return ((int)usallocal(usalp)->usalfiles[busno][tgt][tlun]);
+}
+
+static int
+usalo_initiator_id(SCSI *usalp)
+{
+       return (-1);
+}
+
+static int
+usalo_isatapi(SCSI *usalp)
+{
+       return (FALSE);
+}
+
+static int
+usalo_reset(SCSI *usalp, int what)
+{
+       if (what == SCG_RESET_NOP)
+               return (0);
+       if (what != SCG_RESET_BUS) {
+               errno = EINVAL;
+               return (-1);
+       }
+       /*
+        * XXX Does this reset TGT or BUS ???
+        */
+       return (ioctl(usalp->fd, SCIORESET, IDLUN(usal_target(usalp), usal_lun(usalp))));
+}
+
+static int
+do_usal_cmd(SCSI *usalp, struct usal_cmd *sp)
+{
+       struct sc_iocmd req;
+       int     ret;
+
+       if (sp->cdb_len > 12)
+               comerrno(EX_BAD, "Can't do %d byte command.\n", sp->cdb_len);
+
+       fillbytes(&req, sizeof (req), '\0');
+
+       req.flags = SC_ASYNC;
+       if (sp->flags & SCG_RECV_DATA) {
+               req.flags |= B_READ;
+       } else if (sp->size > 0) {
+               req.flags |= B_WRITE;
+       }
+       req.data_length = sp->size;
+       req.buffer = sp->addr;
+       req.timeout_value = sp->timeout;
+       req.command_length = sp->cdb_len;
+
+       movebytes(&sp->cdb, req.scsi_cdb, 12);
+       errno = 0;
+       ret = ioctl(usalp->fd, DKIOCMD, &req);
+
+       if (usalp->debug > 0) {
+               fprintf((FILE *)usalp->errfile, "ret: %d errno: %d (%s)\n", ret, errno, errmsgstr(errno));
+               fprintf((FILE *)usalp->errfile, "data_length:     %d\n", req.data_length);
+               fprintf((FILE *)usalp->errfile, "buffer:          0x%X\n", req.buffer);
+               fprintf((FILE *)usalp->errfile, "timeout_value:   %d\n", req.timeout_value);
+               fprintf((FILE *)usalp->errfile, "status_validity: %d\n", req.status_validity);
+               fprintf((FILE *)usalp->errfile, "scsi_bus_status: 0x%X\n", req.scsi_bus_status);
+               fprintf((FILE *)usalp->errfile, "adapter_status:  0x%X\n", req.adapter_status);
+               fprintf((FILE *)usalp->errfile, "adap_q_status:   0x%X\n", req.adap_q_status);
+               fprintf((FILE *)usalp->errfile, "q_tag_msg:       0x%X\n", req.q_tag_msg);
+               fprintf((FILE *)usalp->errfile, "flags:           0X%X\n", req.flags);
+       }
+       if (ret < 0) {
+               sp->ux_errno = geterrno();
+               /*
+                * Check if SCSI command cound not be send at all.
+                */
+               if (sp->ux_errno == ENOTTY || sp->ux_errno == ENXIO ||
+                   sp->ux_errno == EINVAL || sp->ux_errno == EACCES) {
+                       return (-1);
+               }
+       } else {
+               sp->ux_errno = 0;
+       }
+       ret = 0;
+       sp->sense_count = 0;
+       sp->resid = 0;          /* AIX is the same rubbish as Linux here */
+
+       fillbytes(&sp->scb, sizeof (sp->scb), '\0');
+       fillbytes(&sp->u_sense.cmd_sense, sizeof (sp->u_sense.cmd_sense), '\0');
+
+       if (req.status_validity == 0) {
+               sp->error = SCG_NO_ERROR;
+               return (0);
+       }
+       if (req.status_validity & 1) {
+               sp->u_scb.cmd_scb[0] = req.scsi_bus_status;
+               sp->error = SCG_RETRYABLE;
+       }
+       if (req.status_validity & 2) {
+               if (req.adapter_status & SC_NO_DEVICE_RESPONSE) {
+                       sp->error = SCG_FATAL;
+
+               } else if (req.adapter_status & SC_CMD_TIMEOUT) {
+                       sp->error = SCG_TIMEOUT;
+
+               } else if (req.adapter_status != 0) {
+                       sp->error = SCG_RETRYABLE;
+               }
+       }
+
+       return (ret);
+}
+
+static int
+do_usal_sense(SCSI *usalp, struct usal_cmd *sp)
+{
+       int             ret;
+       struct usal_cmd s_cmd;
+
+       fillbytes((caddr_t)&s_cmd, sizeof (s_cmd), '\0');
+       s_cmd.addr = sp->u_sense.cmd_sense;
+       s_cmd.size = sp->sense_len;
+       s_cmd.flags = SCG_RECV_DATA|SCG_DISRE_ENA;
+       s_cmd.cdb_len = SC_G0_CDBLEN;
+       s_cmd.sense_len = CCS_SENSE_LEN;
+       s_cmd.cdb.g0_cdb.cmd = SC_REQUEST_SENSE;
+       s_cmd.cdb.g0_cdb.lun = sp->cdb.g0_cdb.lun;
+       s_cmd.cdb.g0_cdb.count = sp->sense_len;
+       ret = do_usal_cmd(usalp, &s_cmd);
+
+       if (ret < 0)
+               return (ret);
+       if (s_cmd.u_scb.cmd_scb[0] & 02) {
+               /* XXX ??? Check condition on request Sense ??? */
+       }
+       sp->sense_count = sp->sense_len - s_cmd.resid;
+       return (ret);
+}
+
+static int
+usalo_send(SCSI *usalp)
+{
+       struct usal_cmd *sp = usalp->scmd;
+       int     ret;
+
+       if (usalp->fd < 0) {
+               sp->error = SCG_FATAL;
+               return (0);
+       }
+       ret = do_usal_cmd(usalp, sp);
+       if (ret < 0)
+               return (ret);
+       if (sp->u_scb.cmd_scb[0] & 02)
+               ret = do_usal_sense(usalp, sp);
+       return (ret);
+}
diff --git a/libusal/scsi-amigaos.c b/libusal/scsi-amigaos.c
new file mode 100644 (file)
index 0000000..991a4ab
--- /dev/null
@@ -0,0 +1,771 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)scsi-amigaos.c  1.6 04/01/14 Copyright 1997,2000-2003 J. Schilling */
+/*
+ *     Interface for the AmigaOS generic SCSI implementation.
+ *
+ *     Warning: you may change this source, but if you do that
+ *     you need to change the _usal_version and _usal_auth* string below.
+ *     You may not return "schily" for an SCG_AUTHOR request anymore.
+ *     Choose your name instead of "schily" and make clear that the version
+ *     string is related to a modified source.
+ *
+ *     Copyright (c) 1997, 2000-2003 J. Schilling
+ *     AmigaOS support code written by T. Langer
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#define        BOOL    int
+
+#include <strdefs.h>
+#include <exec/ports.h>
+#include <exec/io.h>
+#include <exec/errors.h>
+#include <devices/scsidisk.h>
+#include <devices/timer.h>
+#include <exec/semaphores.h>
+#include <exec/memory.h>
+#include <exec/execbase.h>
+#include <clib/exec_protos.h>
+#include <clib/alib_protos.h>
+
+/*
+ *     Warning: you may change this source, but if you do that
+ *     you need to change the _usal_version and _usal_auth* string below.
+ *     You may not return "schily" for an SCG_AUTHOR request anymore.
+ *     Choose your name instead of "schily" and make clear that the version
+ *     string is related to a modified source.
+ */
+static char    _usal_trans_version[] = "scsi-amigaos.c-1.6";   /* The version for this transport */
+static char    _usal_auth[] = "T. Langer";
+
+#define        MAX_SCG         8       /* Max # of SCSI controllers */
+#define        MAX_TGT         8
+#define        MAX_LUN         8
+#define        MAX_DEV         MAX_SCG*MAX_TGT*MAX_LUN
+
+struct usal_local{
+       int     usalfiles[MAX_SCG][MAX_TGT][MAX_LUN];
+};
+
+#define        usallocal(p)    ((struct usal_local*)((p)->local))
+
+#define        MAX_DMA_AMIGAOS (64*1024)
+
+static struct IOReq {
+       struct IOStdReq *ioReq;
+       int             ref_count;
+} request[MAX_DEV];
+
+static char                                    *devs[MAX_SCG];
+static struct MsgPort          *ioMsgPort = NULL;
+static struct timerequest      *timer_io = NULL;
+static struct MsgPort          *timerMsgPort = NULL;
+static int                     initialized = 0;
+static int                     last_bus = -1;
+/* my private var: for debug purpose only */
+static int                     ami_debug = 0;
+
+extern struct ExecBase         *SysBase;
+#define        IOERR_TIMEOUT           (-8)
+#define        CHECK_CONDITION         0x02
+#define        DUNIT(b, t, l)          (100 * b) + (10 * (l < 0 ? 0:l)) + t
+
+static void    amiga_init(void);
+static int     amiga_open_scsi(int bus, int tgt, int lun, SCSI *usalp);
+static void    amiga_close_scsi(int fd);
+static void    amiga_close_scsi_all(void);
+static void    amiga_scan_devices(void);
+static int     amiga_find_device(char *device);
+static int     amiga_open_timer(void);
+static void    amiga_close_timer(void);
+static int     amiga_get_scsi_bus(char *device);
+
+/*
+ * Return version information for the low level SCSI transport code.
+ * This has been introduced to make it easier to trace down problems
+ * in applications.
+ */
+static char *
+usalo_version(SCSI *usalp, int what)
+{
+       if (usalp != (SCSI *)0) {
+               switch (what) {
+
+               case SCG_VERSION:
+                       return (_usal_trans_version);
+               /*
+                * If you changed this source, you are not allowed to
+                * return "schily" for the SCG_AUTHOR request.
+                */
+               case SCG_AUTHOR:
+/*                     return (_usal_auth_cdrkit);*/
+                       return (_usal_auth);
+               case SCG_SCCS_ID:
+                       return (__sccsid);
+               }
+       }
+       return ((char *)0);
+}
+
+static int
+usalo_help(SCSI *usalp, FILE *f)
+{
+       __usal_help(f, "Amiga SCSI", "Generic SCSI",
+               "", "bus,target,lun or xxx.device:b,t,l", "1,2,0 or scsi.device:1,2,0", TRUE, FALSE);
+       return (0);
+}
+
+static int
+usalo_open(SCSI *usalp, char *device)
+{
+               int     busno   = usal_scsibus(usalp);
+               int     tgt     = usal_target(usalp);
+               int     tlun    = usal_lun(usalp);
+       register int    f;
+       register int    b;
+       register int    t;
+       register int    l;
+       register int    nopen = 0;
+
+       if (initialized == 0) {
+               amiga_init();
+               initialized = 1;
+       }
+
+       if (busno >= MAX_SCG || tgt >= MAX_TGT || tlun >= MAX_LUN) {
+               errno = EINVAL;
+               if (usalp->errstr) {
+                       snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                               "Illegal value for busno, target or lun '%d,%d,%d'",
+                               busno, tgt, tlun);
+               }
+               return (-1);
+       }
+       if (usalp->local == NULL) {
+               usalp->local = malloc(sizeof (struct usal_local));
+               if (usalp->local == NULL)
+                       return (0);
+
+               for (b = 0; b < MAX_SCG; b++) {
+                       for (t = 0; t < MAX_TGT; t++) {
+                               for (l = 0; l < MAX_LUN; l++) {
+                                       usallocal(usalp)->usalfiles[b][t][l] = -1;
+                               }
+                       }
+               }
+       }
+
+       if (device == NULL || *device == '\0') {
+
+               if (last_bus == -1) {
+                       snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                               "No scsi device found");
+                       return (-1);
+               }
+               if (busno < 0 && tgt < 0 && tlun < 0) {
+                       /* cdrecord -scanbus */
+                       for (b = 0; b <= last_bus; b++) {
+                               for (t = 0; t < MAX_TGT; t++) {
+                                       for (l = 0; l < MAX_LUN; l++) {
+                                               f = amiga_open_scsi(b, t, l, usalp);
+                                               if (f != -1) {
+                                                       usallocal(usalp)->usalfiles[b][t][l] = f;
+                                                       nopen++;
+                                               }
+                                       }
+                               }
+                       }
+               } else {
+                       /* cdrecord [-scanbus] dev=b,t,l */
+                       f = amiga_open_scsi(busno, tgt, tlun, usalp);
+                       if (f != -1) {
+                               usallocal(usalp)->usalfiles[busno][tgt][tlun] = f;
+                               nopen++;
+                       }
+               }
+       } else {
+               if (busno < 0 && tgt < 0 && tlun < 0) {
+                       /* cdrecord -scanbus dev=xxx.device */
+                       b = amiga_get_scsi_bus(device);
+                       if (b != -1) {
+                               for (t = 0; t < MAX_TGT; t++) {
+                                       for (l = 0; l < MAX_LUN; l++) {
+                                               f = amiga_open_scsi(b, t, l, usalp);
+                                               if (f != -1) {
+                                                       usallocal(usalp)->usalfiles[b][t][l] = f;
+                                                       nopen++;
+                                               }
+                                       }
+                               }
+                       } else {
+                               snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                                       "Scsi device %s not found", device);
+                       }
+               } else {
+                       /* cdrecord [-scanbus] dev=xxx.device:b,t,l */
+                       /*
+                        * this is a special case, in which the scsi device is accessed just by
+                        * name, bus parameter from the command is ignored.
+                        */
+                       b = amiga_get_scsi_bus(device);
+                       if (b != -1) {
+                               f = amiga_open_scsi(b, tgt, tlun, usalp);
+                               if (f != -1) {
+                                       usallocal(usalp)->usalfiles[busno][tgt][tlun] = f;
+                                       nopen++;
+                               }
+                       } else {
+                               snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                                       "Scsi device %s not found", device);
+                       }
+               }
+       }
+
+       return (nopen);
+}
+
+static int
+usalo_close(SCSI *usalp)
+{
+       register int    b;
+       register int    t;
+       register int    l;
+
+       if (usalp->local == NULL)
+               return (-1);
+
+       for (b = 0; b < MAX_SCG; b++) {
+               for (t = 0; t < MAX_TGT; t++) {
+                       for (l = 0; l < MAX_LUN; l++) {
+                               if (usallocal(usalp)->usalfiles[b][t][l] >= 0)
+                                       amiga_close_scsi(usallocal(usalp)->usalfiles[b][t][l]);
+                               usallocal(usalp)->usalfiles[b][t][l] = -1;
+                       }
+               }
+       }
+       return (0);
+}
+
+static long
+usalo_maxdma(SCSI *usalp, long amt)
+{
+       return (MAX_DMA_AMIGAOS);
+}
+
+static void *
+usalo_getbuf(SCSI *usalp, long amt)
+{
+       if (usalp->debug > 0) {
+               fprintf((FILE *)usalp->errfile,
+                       "usalo_getbuf: %ld bytes\n", amt);
+       }
+       usalp->bufbase = valloc((size_t)(amt));
+       return (usalp->bufbase);
+}
+
+static void
+usalo_freebuf(SCSI *usalp)
+{
+       if (usalp->bufbase)
+               free(usalp->bufbase);
+       usalp->bufbase = NULL;
+}
+
+static BOOL
+usalo_havebus(SCSI *usalp, int busno)
+{
+       register int    t;
+       register int    l;
+
+       if (busno < 0 || busno >= MAX_SCG)
+               return (FALSE);
+
+       if (usalp->local == NULL)
+               return (FALSE);
+
+       for (t = 0; t < MAX_TGT; t++) {
+               for (l = 0; l < MAX_LUN; l++)
+                       if (usallocal(usalp)->usalfiles[busno][t][l] != -1)
+                               return (TRUE);
+       }
+       return (FALSE);
+}
+
+static int
+usalo_fileno(SCSI *usalp, int busno, int tgt, int tlun)
+{
+       if (busno < 0 || busno >= MAX_SCG ||
+           tgt < 0 || tgt >= MAX_TGT ||
+           tlun < 0 || tlun >= MAX_LUN)
+               return (-1);
+
+       if (usalp->local == NULL)
+               return (-1);
+
+       return ((int)usallocal(usalp)->usalfiles[busno][tgt][tlun]);
+}
+
+static int
+usalo_initiator_id(SCSI *usalp)
+{
+       return (-1);
+}
+
+static int
+usalo_isatapi(SCSI *usalp)
+{
+       return (FALSE);
+}
+
+static int
+usalo_reset(SCSI *usalp, int what)
+{
+       /* XXX Is there really no reset function on AmigaOS? */
+       errno = EINVAL;
+       return (-1);
+}
+
+static int
+usalo_send(SCSI *usalp)
+{
+       register struct IOStdReq *ioreq = NULL;
+       struct SCSICmd  Cmd;
+       int             ret = 0;
+       struct usal_cmd *sp = usalp->scmd;
+
+       sp->error = SCG_NO_ERROR;
+       sp->sense_count = 0;
+       sp->u_scb.cmd_scb[0] = 0;
+       sp->resid = 0;
+
+       if (usalp->fd < 0) {
+               sp->error = SCG_FATAL;
+               return (0);
+       }
+       ioreq = request[usalp->fd].ioReq;
+       if (ioreq == NULL) {
+               sp->error = SCG_FATAL;
+               return (0);
+       }
+       ioreq->io_Length = sizeof (struct SCSICmd);
+       ioreq->io_Data = &Cmd;
+       ioreq->io_Command = HD_SCSICMD;
+
+       Cmd.scsi_Flags = SCSIF_AUTOSENSE;       /* We set the SCSI cmd len */
+       if (sp->flags & SCG_RECV_DATA)
+               Cmd.scsi_Flags |= SCSIF_READ;
+       else if (sp->size > 0)
+               Cmd.scsi_Flags |= SCSIF_WRITE;
+
+       Cmd.scsi_Command = sp->cdb.cmd_cdb;
+       Cmd.scsi_CmdLength = sp->cdb_len;
+       Cmd.scsi_Data = (UWORD *) sp->addr;
+       Cmd.scsi_Length = sp->size;
+       Cmd.scsi_Actual = 0;
+
+       Cmd.scsi_SenseData = sp->u_sense.cmd_sense;
+       Cmd.scsi_SenseLength = sp->sense_len;
+       Cmd.scsi_SenseActual = 0;
+       Cmd.scsi_Status = 0;
+
+       do_scsi_cmd(ioreq, sp->timeout);
+
+       fillbytes(&sp->scb, sizeof (sp->scb), '\0');
+       sp->resid = Cmd.scsi_Length - Cmd.scsi_Actual;
+
+       if (sp->resid < 0)
+               sp->resid = 0;
+       sp->sense_count = Cmd.scsi_SenseActual;
+       if (sp->sense_count < 0)
+               sp->sense_count;
+
+       if (sp->sense_count > SCG_MAX_SENSE)
+               sp->sense_count = SCG_MAX_SENSE;
+       sp->u_scb.cmd_scb[0] = Cmd.scsi_Status;
+
+       if (ioreq->io_Error)
+               sp->ux_errno = EIO;
+
+       if (ami_debug)
+               printf("ioreq->io_Error: %ld; status %ld\n", ioreq->io_Error, Cmd.scsi_Status);
+
+       switch (ioreq->io_Error) {
+               case 0:
+                       sp->error = SCG_NO_ERROR;
+                       break;
+               case IOERR_TIMEOUT:
+                       sp->error = SCG_TIMEOUT;
+                       break;
+               case HFERR_DMA:
+               case IOERR_UNITBUSY:
+               case HFERR_Phase:
+               case HFERR_Parity:
+               case HFERR_BadStatus:
+                       if (Cmd.scsi_Status == CHECK_CONDITION) {
+                               sp->error = SCG_NO_ERROR;
+                       } else {
+                               sp->error = SCG_RETRYABLE;
+                       }
+                       break;
+               default:
+                       /* XXX was kann sonst noch passieren? */
+                       sp->error = SCG_FATAL;
+                       break;
+       }
+
+       return (ret);
+}
+
+static int
+do_scsi_cmd(struct IOStdReq *scsi_io, int timeout)
+{
+       ULONG   scsi_flag = 0;
+       ULONG   timer_flag = 0;
+       ULONG   wait_sigs = 0;
+       ULONG   wait_ret = 0;
+       int             ret = 0;
+
+       scsi_flag = 1L<<scsi_io->io_Message.mn_ReplyPort->mp_SigBit;
+       wait_sigs = scsi_flag;
+
+       SetSignal(0L, scsi_flag);
+       SendIO((struct IORequest *)scsi_io);
+       if (timer_io) {
+               timer_flag = 1L<<timerMsgPort->mp_SigBit;
+               wait_sigs |= timer_flag;
+               timer_io->tr_time.tv_secs = timeout;
+               SetSignal(0L, timer_flag);
+               SendIO((struct IORequest *)timer_io);
+       }
+
+       wait_ret = Wait(wait_sigs);
+
+       if (wait_ret & scsi_flag) {
+               WaitIO((struct IORequest *)scsi_io);
+               if (timer_io) {
+                       if (!CheckIO((struct IORequest *) timer_io)) {
+                               AbortIO((struct IORequest *)timer_io);
+                               WaitIO((struct IORequest *)timer_io);
+                       }
+               }
+       } else if (wait_ret & timer_flag) {
+               WaitIO((struct IORequest *)timer_io);
+               if (!CheckIO((struct IORequest *) scsi_io)) {
+                       AbortIO((struct IORequest *)scsi_io);
+                       if (scsi_io->io_Error == IOERR_ABORTED) {
+                               WaitIO((struct IORequest *)scsi_io);
+                       }
+               }
+               scsi_io->io_Error = IOERR_TIMEOUT;
+       }
+
+       return (scsi_io->io_Error);
+}
+
+/*--------------------------------------------------------------------------*/
+
+/* strlwr: seems not to be implemented in ixemul */
+static char *
+strlwr(char *s)
+{
+       unsigned char *s1;
+
+       s1 = (unsigned char *)s;
+       while (*s1) {
+               if ((*s1 > ('A'-1)) && (*s1 < ('Z'+1)))
+                       *s1 += 'a'-'A';
+               s1++;
+       }
+       return (s);
+}
+
+/*
+ * amiga specific functions
+ */
+static void
+amiga_init()
+{
+       memset(request, 0, sizeof (request));
+       amiga_scan_devices();
+       if (ami_debug)
+               printf("scanning bus. %ld device(s) found\n", last_bus + 1);
+
+       atexit(amiga_close_scsi_all);
+}
+
+static void
+amiga_scan_devices()
+{
+       /*
+        * searching all known scsi devices
+        * for first there is only a (full) support for scsi.device and amithlon.device.
+        * This are devices i tested.
+        * All the other devices have to be specified by name (i.e. cdrecord dev=blabla.device:0,0,0)
+        * but didn't appear in the scanbus list. Later they should/may be also added to the
+        * main_dev_list (after testing).
+        */
+       const char      *main_dev_list[] = { "scsi.device", "amithlon.device", NULL };
+
+       int     i;
+       char    **main_dev;
+
+       main_dev = (char **)main_dev_list;
+       while (*main_dev) {
+               if (last_bus == MAX_SCG - 1)
+                       break;
+               if (amiga_find_device(*main_dev)) {
+                       last_bus++;
+                       devs[last_bus] = strdup(*main_dev);
+                       for (i = 2; i < MAX_SCG; i++) {
+                               char tmp[256];
+                               if (last_bus == MAX_SCG - 1)
+                                       break;
+                               if (i == 2) {
+                                       sprintf(tmp, "2nd.%s", *main_dev);
+                               } else if (i == 3) {
+                                       sprintf(tmp, "3rd.%s", *main_dev);
+                               } else {
+                                       sprintf(tmp, "%ldth.%s", i, *main_dev);
+                               }
+                               if (amiga_find_device(tmp)) {
+                                       last_bus++;
+                                       devs[last_bus] = strdup(tmp);
+                               } else {
+                                       break;
+                               }
+                       }
+               }
+               main_dev++;
+       }
+}
+
+static void
+amiga_close_scsi(int fd)
+{
+       if (request[fd].ref_count > 0) {
+               request[fd].ref_count--;
+               if (request[fd].ref_count == 0) {
+                       CloseDevice((struct IORequest *) request[fd].ioReq);
+                       DeleteStdIO(request[fd].ioReq);
+                       request[fd].ioReq = NULL;
+                       if (ami_debug) {
+                               printf("closing device fd %ld\n", fd);
+                       }
+               }
+       }
+}
+
+static void
+amiga_close_scsi_all()
+{
+       int     i;
+
+       for (i = 0; i < MAX_DEV; i++) {
+               if (request[i].ioReq != NULL) {
+                       if (ami_debug) {
+                               printf("closing device fd %ld\n", i);
+                       }
+                       CloseDevice((struct IORequest *) request[i].ioReq);
+                       DeleteStdIO(request[i].ioReq);
+                       request[i].ioReq = NULL;
+               }
+       }
+
+       if (ioMsgPort) {
+               DeletePort(ioMsgPort);
+               ioMsgPort = NULL;
+       }
+       amiga_close_timer();
+
+       for (i = 0; i < MAX_SCG; i++) {
+               free(devs[i]);
+       }
+}
+
+static int
+amiga_open_scsi(int bus, int tgt, int lun, SCSI *usalp)
+{
+       int     fd = bus * MAX_TGT * MAX_LUN + tgt * MAX_LUN + lun;
+       int     unit = DUNIT(bus, tgt, lun);
+       char    *dev = devs[bus];
+
+       if (dev == NULL) {
+               if (usalp->errstr) {
+                       snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                               "No scsi device found at bus %ld\n", bus);
+               }
+               return (-1);
+       }
+
+       if (ioMsgPort == NULL) {
+               ioMsgPort = CreatePort(NULL, 0);
+       }
+
+       if (ioMsgPort != NULL) {
+               if (request[fd].ioReq == NULL) {
+                       request[fd].ioReq = CreateStdIO(ioMsgPort);
+               }
+
+               if (request[fd].ioReq != NULL) {
+                       if (ami_debug)
+                               printf("trying %s, unit %ld\n", dev, unit);
+                       if (OpenDevice(dev, unit, (struct IORequest *)request[fd].ioReq, 0L)) {
+                               if (usalp->errstr) {
+                                       snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                                               "Cannot open %s\n",     dev);
+                               }
+                               if (request[fd].ref_count == 0) {
+                                       DeleteStdIO(request[fd].ioReq);
+                                       request[fd].ioReq = NULL;
+                               }
+                               fd = -1;
+                       } else {
+                               request[fd].ref_count++;
+                               if (ami_debug)
+                                       printf("opening %s, unit %ld as fd %ld count %ld\n", dev, unit, fd, request[fd].ref_count);
+                       }
+               } else {
+                       if (usalp->errstr) {
+                               snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                                       "Cannot create IOReq");
+                       }
+               }
+       } else {
+               if (usalp->errstr) {
+                       snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                               "Cannot open Message Port");
+               }
+       }
+
+       return (fd);
+}
+
+static int
+amiga_open_timer()
+{
+       int     ret = 0;
+
+       /* we need the timer to catch scsi timeouts */
+       if (timer_io == NULL) {
+               if (ami_debug)
+                       printf("opening timer\n");
+
+               timerMsgPort = CreatePort(NULL, 0);
+               if (timerMsgPort) {
+                       timer_io = (struct timerequest *)CreateExtIO(timerMsgPort, sizeof (struct timerequest));
+                       if (timer_io) {
+                               if (OpenDevice("timer.device", UNIT_MICROHZ, (struct IORequest *)timer_io, 0)) {
+                                       printf("Warning: can't open timer device\n");
+                                       DeleteExtIO((struct IORequest *) timer_io);
+                                       DeletePort(timerMsgPort);
+                                       timer_io = NULL;
+                                       timerMsgPort = NULL;
+                                       ret = 1;
+                               } else {
+                                       timer_io->tr_node.io_Command = TR_ADDREQUEST;
+                                       timer_io->tr_time.tv_micro = 0;
+                               }
+                       } else {
+                               printf("Warning: can't create timer request\n");
+                               DeletePort(timerMsgPort);
+                               timerMsgPort = NULL;
+                               ret = 1;
+                       }
+               } else {
+                       printf("Warning: can't create timer port\n");
+                       ret = 1;
+               }
+       }
+       return (ret);
+}
+
+static void
+amiga_close_timer()
+{
+       if (timer_io) {
+               if (ami_debug)
+                       printf("closing timer\n");
+
+               AbortIO((struct IORequest *) timer_io);
+               WaitIO((struct IORequest *) timer_io);
+               CloseDevice((struct IORequest *)timer_io);
+               DeleteExtIO((struct IORequest *) timer_io);
+               DeletePort(timerMsgPort);
+               timer_io = NULL;
+               timerMsgPort = NULL;
+       }
+}
+
+static int
+amiga_get_scsi_bus(char *device)
+{
+       int     i;
+       char    *tmp = strdup(device);
+
+       strlwr(tmp);
+       for (i = 0; i <= last_bus; i++) {
+               if (strcmp(devs[i], tmp) == 0) {
+                       return (i);
+               }
+       }
+
+       if (amiga_find_device(tmp)) {
+               devs[i] = tmp;
+               last_bus = i;
+               return (i);
+       }
+
+       return (-1);
+}
+
+static int
+amiga_find_device(char *device)
+{
+       char            tmp[256];
+       struct Node     *DeviceLibNode = SysBase->DeviceList.lh_Head;
+
+       if (ami_debug)
+               printf("looking for %s ", device);
+
+       Forbid();
+       while (DeviceLibNode->ln_Succ) {
+               DeviceLibNode = DeviceLibNode->ln_Succ;
+               strcpy(tmp, DeviceLibNode->ln_Name);
+               strlwr(tmp);
+               if (strcmp(tmp, device) == 0) {
+                       if (ami_debug)
+                               printf(" ... found\n");
+                       return (1);
+               }
+       }
+       Permit();
+
+       if (ami_debug)
+               printf(" ... not found\n");
+
+       return (0);
+}
diff --git a/libusal/scsi-apollo.c b/libusal/scsi-apollo.c
new file mode 100644 (file)
index 0000000..c368468
--- /dev/null
@@ -0,0 +1,550 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)scsi-apollo.c   1.5 04/01/14 Copyright 1997,2000 J. Schilling */
+/*
+ *     Code to support Apollo Domain/OS 10.4.1
+ *
+ *     Copyright (c) 1997,2000 J. Schilling
+ *     Apollo support code written by Paul Walker.
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <apollo/base.h>
+#include <apollo/scsi.h>
+#include <assert.h>
+#define        DomainScsiTimeout       100000
+
+/*
+ *     Warning: you may change this source, but if you do that
+ *     you need to change the _usal_version and _usal_auth* string below.
+ *     You may not return "schily" for an SCG_AUTHOR request anymore.
+ *     Choose your name instead of "schily" and make clear that the version
+ *     string is related to a modified source.
+ */
+static char    _usal_trans_version[] = "scsi-apollo.c-1.5";    /* The version for this transport */
+
+
+#define        MAX_SCG         1       /* Max # of SCSI controllers */
+#define        MAX_TGT         1       /* Max # of SCSI targets */
+#define        MAX_LUN         1       /* Max # of SCSI logical units */
+
+struct usal_local {
+       scsi_$handle_t  handle;
+       unsigned char   *DomainSensePointer;
+       short           usalfiles[MAX_SCG][MAX_TGT][MAX_LUN];
+};
+
+#define        usallocal(p)    ((struct usal_local *)((p)->local))
+
+#ifndef        SG_MAX_SENSE
+#define        SG_MAX_SENSE    16      /* Too small for CCS / SCSI-2    */
+#endif                         /* But cannot be changed         */
+
+/*
+ * Return version information for the low level SCSI transport code.
+ * This has been introduced to make it easier to trace down problems
+ * in applications.
+ */
+static char *
+usalo_version(SCSI *usalp, int what)
+{
+       if (usalp != (SCSI *)0) {
+               switch (what) {
+
+               case SCG_VERSION:
+                       return (_usal_trans_version);
+               /*
+                * If you changed this source, you are not allowed to
+                * return "schily" for the SCG_AUTHOR request.
+                */
+               case SCG_AUTHOR:
+                       return ("Paul Walker");
+               case SCG_SCCS_ID:
+                       return (__sccsid);
+               }
+       }
+       return ((char *)0);
+}
+
+static int
+usalo_help(SCSI *usalp, FILE *f)
+{
+       __usal_help(f, "scsi_$do_command_2", "SCSI transport from Apollo DomainOS drivers",
+               "", "DomainOS driver name", "A DomainOS device node name", FALSE, TRUE);
+       return (0);
+}
+
+static int
+usalo_open(SCSI *usalp, char *device)
+{
+       register int    nopen = 0;
+       status_$t       status;
+
+       if (usalp->debug > 1)
+               printf("Entered scsi_open, usalp=%p, device='%s'\n", usalp, device);
+       if (usalp->local == NULL) {
+               usalp->local = malloc(sizeof (struct usal_local));
+               if (usalp->local == NULL)
+                       return (0);
+       }
+       if (device == NULL || *device == '\0') {
+               snprintf(usalp->errstr, SCSI_ERRSTR_SIZE, "Must give device name");
+               return (0);
+       }
+
+       scsi_$acquire(device, strlen(device), &usallocal(usalp)->handle, &status);
+       if (status.all) {
+               if (usalp->errstr)
+                       snprintf(usalp->errstr, SCSI_ERRSTR_SIZE, "Cannot open '%s', status %08x", device, status.all);
+               return (0);
+       }
+       /*
+        * Allocate the sense buffer
+        */
+       usallocal(usalp)->DomainSensePointer = (Uchar *)valloc((size_t) (SCG_MAX_SENSE + getpagesize()));
+       assert(status.all == 0);
+       /*
+        * Wire the sense buffer
+        */
+       scsi_$wire(usallocal(usalp)->handle, (caddr_t)(usallocal(usalp)->DomainSensePointer), SCG_MAX_SENSE, &status);
+       assert(status.all == 0);
+
+       if (usallocal(usalp)->usalfiles[0][0][0] == -1)
+               usallocal(usalp)->usalfiles[0][0][0] = 1;
+       usal_settarget(usalp, 0, 0, 0);
+       return (++nopen);
+}
+
+static int
+usalo_close(SCSI *usalp)
+{
+       status_$t       status;
+
+       if (usalp->debug > 1)
+               printf("Entering scsi_close\n");
+       scsi_$release(usallocal(usalp)->handle, &status);
+       /*
+        * should also unwire the sense buffer
+        */
+       return (status.all);
+}
+
+
+static long
+usalo_maxdma(SCSI *usalp, long amt)
+{
+       status_$t       status;
+       scsi_$info_t    info;
+
+       scsi_$get_info(usallocal(usalp)->handle, sizeof (info), &info, &status);
+       if (status.all) {
+               /*
+                * Should have some better error handling here
+                */
+               printf("scsi_$get_info returned %08x\n", status.all);
+               return (0);
+       }
+       return (info.max_xfer);
+}
+
+
+static void *
+usalo_getbuf(SCSI *usalp, long amt)
+{
+       void    *ret;
+
+       if (usalp->debug > 1)
+               printf("scsi_getbuf: %ld bytes\n", amt);
+       ret = valloc((size_t)amt);
+       if (ret == NULL)
+               return (ret);
+       usalp->bufbase = ret;
+       return (ret);
+}
+
+static void
+usalo_freebuf(SCSI *usalp)
+{
+       if (usalp->debug > 1)
+               printf("Entering scsi_freebuf\n");
+
+       if (usalp->bufbase)
+               free(usalp->bufbase);
+       usalp->bufbase = NULL;
+}
+
+static BOOL
+usalo_havebus(SCSI *usalp, int busno)
+{
+       register int    t;
+       register int    l;
+
+       if (usalp->debug > 1)
+               printf("Entered scsi_havebus:  usalp=%p, busno=%d\n", usalp, busno);
+
+       if (busno < 0 || busno >= MAX_SCG)
+               return (FALSE);
+
+       if (usalp->local == NULL)
+               return (FALSE);
+
+       for (t = 0; t < MAX_TGT; t++) {
+               for (l = 0; l < MAX_LUN; l++)
+                       if (usallocal(usalp)->usalfiles[busno][t][l] >= 0)
+                               return (TRUE);
+       }
+       return (FALSE);
+}
+
+static int
+usalo_fileno(SCSI *usalp, int busno, int tgt, int tlun)
+{
+       if (usalp->debug > 1)
+               printf("Entered scsi_fileno:  usalp=%p, busno=%d, tgt=%d, tlun=%d\n", usalp, busno, tgt, tlun);
+       if (busno < 0 || busno >= MAX_SCG ||
+               tgt < 0 || tgt >= MAX_TGT ||
+               tlun < 0 || tlun >= MAX_LUN)
+               return (-1);
+
+       if (usalp->local == NULL)
+               return (-1);
+       if (usalp->debug > 1)
+               printf("exiting scsi_fileno, returning %d\n", usallocal(usalp)->usalfiles[busno][tgt][tlun]);
+       return ((int) usallocal(usalp)->usalfiles[busno][tgt][tlun]);
+}
+
+static int
+usalo_initiator_id(SCSI *usalp)
+{
+       if (usalp->debug > 1)
+               printf("Entering scsi_initiator\n");
+
+       return (-1);
+}
+
+static int
+usalo_isatapi(SCSI *usalp)
+{
+       return (FALSE);
+}
+
+static int
+usalo_reset(SCSI *usalp, int what)
+{
+       status_$t       status;
+
+       if (usalp->debug > 0)
+               printf("Entering scsi_reset\n");
+
+       if (what == SCG_RESET_NOP)
+               return (0);
+
+       if (what == SCG_RESET_TGT) {
+               scsi_$reset_device(usallocal(usalp)->handle, &status);
+               if (status.all)
+                       printf("Error - scsi_$reset_device failed, status is 0x%08x\n", status.all);
+               return (status.all);
+       } else {
+               errno = EINVAL;
+               return (-1);
+       }
+}
+
+static void
+scsi_do_sense(SCSI *usalp, struct usal_cmd *sp)
+{
+       scsi_$op_status_t       op_status;
+       static scsi_$cdb_t      sense_cdb;
+       static linteger         sense_cdb_size;
+       static linteger         sense_buffer_size;
+       static scsi_$operation_id_t sense_op_id;
+       static status_$t        sense_status;
+       static pinteger         sense_return_count;
+               int             i;
+
+       /*
+        * Issue the sense command (wire, issue, wait, unwire
+        */
+       sense_buffer_size = sp->sense_len;
+       sense_cdb_size = SC_G0_CDBLEN;
+       memset(sense_cdb.all, 0, sense_cdb_size);       /* Assuming Apollo sense */
+                                                       /* structure is correct */
+                                                       /* size */
+       sense_cdb.g0.cmd = SC_REQUEST_SENSE;
+       sense_cdb.g0.lun = sp->cdb.g0_cdb.lun;
+       sense_cdb.g0.len = sp->sense_len;
+       scsi_$do_command_2(usallocal(usalp)->handle, sense_cdb, sense_cdb_size, (caddr_t) (usallocal(usalp)->DomainSensePointer), sense_buffer_size, scsi_read, &sense_op_id, &sense_status);
+       if (sense_status.all) {
+               printf("Error executing sense command, status is 0x%08x\n", sense_status.all);
+       }
+       scsi_$wait(usallocal(usalp)->handle, DomainScsiTimeout, true, sense_op_id, 1, &op_status, &sense_return_count, &sense_status);
+       /*
+        * Print the sense information if debug is on, or if the information is
+        * "unusual"
+        */
+       if (usalp->debug > 0 ||
+               /*
+                * I don't prinqqt info for sense codes 0, 2, 5, 6 because
+                * they aren't interesting
+                */
+               (((u_char *) usallocal(usalp)->DomainSensePointer)[2] == 1) ||
+               (((u_char *) usallocal(usalp)->DomainSensePointer)[2] == 3) ||
+               (((u_char *) usallocal(usalp)->DomainSensePointer)[2] == 4) ||
+               (((u_char *) usallocal(usalp)->DomainSensePointer)[2] >= 7)) {
+               printf(" Sense dump:\n");
+               for (i = 0; i < sp->sense_len; i++)
+                       printf(" %02x", ((u_char *) usallocal(usalp)->DomainSensePointer)[i]);
+               printf("\n");
+       }
+       if (((u_char *) usallocal(usalp)->DomainSensePointer)[2] == 5) {
+               /*
+                * Illegal command
+                */
+               printf("Illegal command detected, ASC=0x%02x, ASQ=0x%02x\n", ((u_char *) usallocal(usalp)->DomainSensePointer)[12], ((u_char *) usallocal(usalp)->DomainSensePointer)[13]);
+       }
+       /*
+        * Copy the sense information to the driver
+        */
+       memcpy(sp->u_sense.cmd_sense, usallocal(usalp)->DomainSensePointer, sp->sense_len);
+       sp->sense_count = sp->sense_len;
+}
+
+
+static int
+usalo_send(SCSI *usalp)
+{
+       linteger        buffer_length;
+       linteger        cdb_len;
+       scsi_$operation_id_t operation;
+       scsi_$wait_index_t wait_index;
+       scsi_$op_status_t op_status;
+       pinteger        return_count;
+       status_$t       status;
+       char    *ascii_wait_status;
+       int             i;
+       struct usal_cmd *sp = usalp->scmd;
+
+       if (usalp->fd < 0) {
+               sp->error = SCG_FATAL;
+               return (0);
+       }
+
+       if (usalp->debug > 0) {
+               printf("Entered usalo_send, usalp=%p, sp=%p\n", usalp, sp);
+               printf("usalcmd dump:\n");
+               printf("  addr=%p\n", sp->addr);
+               printf("  size=0x%x\n", sp->size);
+               printf("  flags=0x%x\n", sp->flags);
+               printf("  cdb_len=%d\n", sp->cdb_len);
+               printf("  sense_len=%d\n", sp->sense_len);
+               printf("  timeout=%d\n", sp->timeout);
+               printf("  kdebug=%d\n", sp->kdebug);
+               printf("  CDB:");
+               for (i = 0; i < sp->cdb_len; i++)
+                               printf(" %02x", sp->cdb.cmd_cdb[i]);
+               printf("\n");
+       }
+
+       /*
+        * Assume complete transfer, so residual count = 0
+        */
+       sp->resid = 0;
+       buffer_length = sp->size;
+       if (sp->addr) {
+               if (usalp->debug > 0)
+                       printf(" wiring 0x%x bytes at 0x%x\n", buffer_length, sp->addr);
+               scsi_$wire(usallocal(usalp)->handle, sp->addr, buffer_length, &status);
+               if (status.all) {
+                       /*
+                        * Need better error handling
+                        */
+                       printf("scsi_$wire failed, 0x%08x\n", status.all);
+               }
+       }
+       cdb_len = sp->cdb_len;
+       scsi_$do_command_2(usallocal(usalp)->handle,            /* device handle*/
+                       *(scsi_$cdb_t *) &(sp->cdb.cmd_cdb[0]), /* SCSI CDB     */
+                       cdb_len,                                /* CDB len      */
+                       sp->addr,                               /* DMA buf      */
+                       buffer_length,                          /* DMA len      */
+                       (sp->flags & SCG_RECV_DATA) ? scsi_read : scsi_write,
+                       &operation,                             /* OP ID        */
+                       &status);                               /* Status ret   */
+
+       if (status.all) {
+               /*
+                * Need better error handling
+                */
+               printf("scsi_$do_command failed, 0x%08x\n", status.all);
+               sp->error = SCG_FATAL;
+               sp->ux_errno = EIO;
+               return (0);
+       } else if (usalp->debug > 0) {
+               printf("Command submitted, operation=0x%x\n", operation);
+       }
+       wait_index = scsi_$wait(usallocal(usalp)->handle,               /* device handle*/
+                               sp->timeout * 1000,             /* timeout      */
+                               0,                              /* async enable */
+                               operation,                      /* OP ID        */
+                               1,                              /* max count    */
+                               &op_status,                     /* status list  */
+                               &return_count,                  /* count ret    */
+                               &status);                       /* Status ret   */
+       if (status.all) {
+               /*
+                * Need better error handling
+                */
+               printf("scsi_$wait failed, 0x%08x\n", status.all);
+               sp->error = SCG_FATAL;
+               sp->ux_errno = EIO;
+               return (0);
+       } else {
+               if (usalp->debug > 0) {
+                       printf("wait_index=%d, return_count=%d, op_status: op=0x%x, cmd_status=0x%x, op_status=0x%x\n",
+                               wait_index, return_count, op_status.op, op_status.cmd_status, op_status.op_status);
+               }
+               switch (wait_index) {
+
+               case scsi_device_advance:
+                       ascii_wait_status = "scsi_device_advance";
+                       break;
+               case scsi_timeout:
+                       ascii_wait_status = "scsi_timeout";
+                       break;
+               case scsi_async_fault:
+                       ascii_wait_status = "scsi_async_fault";
+                       break;
+               default:
+                       ascii_wait_status = "unknown";
+                       break;
+               }
+               /*
+                * See if the scsi_$wait terminated "abnormally"
+                */
+               if (wait_index != scsi_device_advance) {
+                       printf("scsi_$wait terminated abnormally, status='%s'\n", ascii_wait_status);
+                       sp->error = SCG_FATAL;
+                       sp->ux_errno = EIO;
+                       return (0);
+               }
+               /*
+                * Normal termination, what's the scoop?
+                */
+               assert(return_count == 1);
+               switch (op_status.cmd_status.all) {
+
+               case status_$ok:
+                       switch (op_status.op_status) {
+
+                       case scsi_good_status:
+                               sp->error = SCG_NO_ERROR;
+                               sp->ux_errno = 0;
+                               break;
+                       case scsi_busy:
+                               sp->error = SCG_NO_ERROR;
+                               sp->ux_errno = 0;
+                               break;
+                       case scsi_check_condition:
+                               if (usalp->debug > 0)
+                                       printf("SCSI ERROR - CheckCondition\n");
+                               scsi_do_sense(usalp, sp);
+                               /*
+                                * If this was a media error, then call it retryable,
+                                * instead of no error
+                                */
+                               if ((((u_char *) usallocal(usalp)->DomainSensePointer)[0] == 0xf0) &&
+                                       (((u_char *) usallocal(usalp)->DomainSensePointer)[2] == 0x03)) {
+                                       if (usalp->debug > 0)
+                                               printf("  (retryable)\n");
+                                       sp->error = SCG_RETRYABLE;
+                                       sp->ux_errno = EIO;
+                               } else {
+                               /* printf("  (no error)\n"); */
+                                       sp->error = SCG_NO_ERROR;
+                                       sp->ux_errno = 0;
+                               }
+                               break;
+                       default:
+                               /*
+                                * I fault out in this case because I want to know
+                                * about this error, and this guarantees that it will
+                                * get attention.
+                                */
+                               printf("Unhandled Domain/OS op_status error:  status=%08x\n",
+                                                                       op_status.op_status);
+                               exit(EXIT_FAILURE);
+                       }
+                       break;
+               /*
+                * Handle recognized error conditions by copying the error
+                * code over
+                */
+               case scsi_$operation_timeout:
+                       printf("SCSI ERROR - Timeout\n");
+                       scsi_do_sense(usalp, sp);
+                       sp->error = SCG_TIMEOUT;
+                       sp->ux_errno = EIO;
+                       break;
+               case scsi_$dma_underrun:
+                       /*
+                        * This condition seems to occur occasionaly.  I no longer
+                        *  complain because it doesn't seem to matter.
+                        */
+                       if (usalp->debug > 0)
+                               printf("SCSI ERROR - Underrun\n");
+                       scsi_do_sense(usalp, sp);
+                       sp->resid = sp->size;   /* We don't have the right number */
+                       sp->error = SCG_RETRYABLE;
+                       sp->ux_errno = EIO;
+                       break;
+               case scsi_$hdwr_failure:        /* received when both scanners were active */
+                       printf("SCSI ERROR - Hardware Failure\n");
+                       scsi_do_sense(usalp, sp);
+                       sp->error = SCG_RETRYABLE;
+                       sp->ux_errno = EIO;
+                       break;
+               default:
+                       printf("\nUnhandled Domain/OS cmd_status error:  status=%08x\n", op_status.cmd_status.all);
+                       error_$print(op_status.cmd_status);
+                       exit(EXIT_FAILURE);
+               }
+       }
+       if (sp->addr) {
+               if (usalp->debug > 0)
+                       printf(" unwiring buffer\n");
+               scsi_$unwire(usallocal(usalp)->handle, sp->addr, buffer_length, sp->flags & SCG_RECV_DATA, &status);
+               if (status.all) {
+                       /*
+                        * Need better error handling
+                        */
+                       printf("scsi_$unwire failed, 0x%08x\n", status.all);
+                       sp->error = SCG_FATAL;
+                       sp->ux_errno = EIO;
+                       return (0);
+               }
+       }
+       return (0);
+}
diff --git a/libusal/scsi-beos.c b/libusal/scsi-beos.c
new file mode 100644 (file)
index 0000000..78b649e
--- /dev/null
@@ -0,0 +1,414 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)scsi-beos.c     1.23 06/02/05 Copyright 1998 J. Schilling */
+/*
+ *     Interface for the BeOS user-land raw SCSI implementation.
+ *
+ *     This is a hack, that tries to emulate the functionality
+ *     of the usal driver.
+ *
+ *     First version done by swetland@be.com
+ *
+ *     Warning: you may change this source, but if you do that
+ *     you need to change the _usal_version and _usal_auth* string below.
+ *     You may not return "schily" for an SCG_AUTHOR request anymore.
+ *     Choose your name instead of "schily" and make clear that the version
+ *     string is related to a modified source.
+ *
+ *     Copyright (c) 1998 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+/*
+ *     Warning: you may change this source, but if you do that
+ *     you need to change the _usal_version and _usal_auth* string below.
+ *     You may not return "schily" for an SCG_AUTHOR request anymore.
+ *     Choose your name instead of "schily" and make clear that the version
+ *     string is related to a modified source.
+ */
+static char    _usal_trans_version[] = "scsi-beos.c-1.23";     /* The version for this transport*/
+
+/*
+ * There are also defines for:
+ *     B_BEOS_VERSION_4
+ *     B_BEOS_VERSION_4_5
+ *
+ * in BeOS 5
+ */
+#ifndef        B_BEOS_VERSION_5
+/*
+ * New BeOS seems to include <be/kernel/OS.h> from device/scsi.h
+ */
+
+/* nasty hack to avoid broken def of bool in SupportDefs.h */
+#define        _SUPPORT_DEFS_H
+
+#ifndef _SYS_TYPES_H
+typedef unsigned long                  ulong;
+typedef unsigned int                   uint;
+typedef unsigned short                 ushort;
+#endif /* _SYS_TYPES_H */
+
+#include <BeBuild.h>
+#include <sys/types.h>
+#include <Errors.h>
+
+
+/*-------------------------------------------------------------*/
+/*----- Shorthand type formats --------------------------------*/
+
+typedef        signed char                     int8;
+typedef unsigned char                  uint8;
+typedef volatile signed char           vint8;
+typedef volatile unsigned char         vuint8;
+
+typedef        short                           int16;
+typedef unsigned short                 uint16;
+typedef volatile short                 vint16;
+typedef volatile unsigned short                vuint16;
+
+typedef        long                            int32;
+typedef unsigned long                  uint32;
+typedef volatile long                  vint32;
+typedef volatile unsigned long         vuint32;
+
+typedef        long long                       int64;
+typedef unsigned long long             uint64;
+typedef volatile long long             vint64;
+typedef volatile unsigned long long    vuint64;
+
+typedef volatile long                  vlong;
+typedef volatile int                   vint;
+typedef volatile short                 vshort;
+typedef volatile char                  vchar;
+
+typedef volatile unsigned long         vulong;
+typedef volatile unsigned int          vuint;
+typedef volatile unsigned short                vushort;
+typedef volatile unsigned char         vuchar;
+
+typedef unsigned char                  uchar;
+typedef unsigned short                 unichar;
+
+
+
+/*-------------------------------------------------------------*/
+/*----- Descriptive formats -----------------------------------*/
+typedef int32                                  status_t;
+typedef int64                                  bigtime_t;
+typedef uint32                                 type_code;
+typedef uint32                                 perform_code;
+
+/* end nasty hack */
+
+#endif /* ! B_BEOS_VERSION_5 */
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <usal/usalio.h>
+
+/* this is really really dumb (tm) */
+/*#undef sense*/
+/*#undef scb*/
+#include <device/scsi.h>
+
+#undef bool
+#include <drivers/CAM.h>
+
+struct _fdmap_ {
+       struct _fdmap_ *next;
+       int bus;
+       int targ;
+       int lun;
+       int fd;
+};
+
+/*
+ * Return version information for the low level SCSI transport code.
+ * This has been introduced to make it easier to trace down problems
+ * in applications.
+ */
+static char *
+usalo_version(SCSI *usalp, int what)
+{
+       if (usalp != (SCSI *)0) {
+               switch (what) {
+
+               case SCG_VERSION:
+                       return (_usal_trans_version);
+               /*
+                * If you changed this source, you are not allowed to
+                * return "schily" for the SCG_AUTHOR request.
+                */
+               case SCG_AUTHOR:
+                       return (_usal_auth_cdrkit);
+               case SCG_SCCS_ID:
+                       return (__sccsid);
+               }
+       }
+       return ((char *)0);
+}
+
+static int
+usalo_help(SCSI *usalp, FILE *f)
+{
+       __usal_help(f, "CAM", "Generic transport independent SCSI (BeOS CAM variant)",
+               "", "bus,target,lun", "1,2,0", TRUE, FALSE);
+       return (0);
+}
+
+static int
+usalo_open(SCSI *usalp, char *device)
+{
+       int     busno   = usal_scsibus(usalp);
+       int     tgt     = usal_target(usalp);
+#ifdef nonono
+       int     tlun    = usal_lun(usalp);
+#endif
+
+#ifdef nonono
+       if (busno >= MAX_SCG || tgt >= MAX_TGT || tlun >= MAX_LUN) {
+               errno = EINVAL;
+               if (usalp->errstr)
+                       snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                               "Illegal value for busno, target or lun '%d,%d,%d'",
+                               busno, tgt, tlun);
+               return (-1);
+       }
+#endif
+
+       if ((device != NULL && *device != '\0') || (busno == -2 && tgt == -2)) {
+               errno = EINVAL;
+               if (usalp->errstr)
+                       snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                               "Open by 'devname' not supported on this OS");
+               return (-1);
+       }
+       return (1);
+}
+
+static int
+usalo_close(SCSI *usalp)
+{
+       struct _fdmap_  *f;
+       struct _fdmap_  *fnext;
+
+       for (f = (struct _fdmap_ *)usalp->local; f; f = fnext) {
+               usalp->local = 0;
+               fnext = f->next;
+               close(f->fd);
+               free(f);
+       }
+       return (0);
+}
+
+static long
+usalo_maxdma(SCSI *usalp, long amt)
+{
+       return (128*1024);
+       return (256*1024);
+}
+
+static void *
+usalo_getbuf(SCSI *usalp, long amt)
+{
+       if (usalp->debug > 0) {
+               fprintf((FILE *)usalp->errfile,
+                       "usalo_getbuf: %ld bytes\n", amt);
+       }
+       usalp->bufbase = malloc((size_t)(amt));
+       return (usalp->bufbase);
+}
+
+static void
+usalo_freebuf(SCSI *usalp)
+{
+       if (usalp->bufbase)
+               free(usalp->bufbase);
+       usalp->bufbase = NULL;
+}
+
+static BOOL
+usalo_havebus(SCSI *usalp, int busno)
+{
+       struct stat     sb;
+       char            buf[128];
+
+       if (busno < 8)
+               snprintf(buf, sizeof (buf), "/dev/bus/scsi/%d", busno);
+       else
+               snprintf(buf, sizeof (buf), "/dev/disk/ide/atapi/%d", busno-8);
+       if (stat(buf, &sb))
+               return (FALSE);
+       return (TRUE);
+}
+
+static int
+usalo_fileno(SCSI *usalp, int busno, int tgt, int tlun)
+{
+       struct _fdmap_  *f;
+       char            buf[128];
+       int             fd;
+
+       for (f = (struct _fdmap_ *)usalp->local; f; f = f->next) {
+               if (f->bus == busno && f->targ == tgt && f->lun == tlun)
+                       return (f->fd);
+       }
+       if (busno < 8) {
+               snprintf(buf, sizeof (buf),
+                                       "/dev/bus/scsi/%d/%d/%d/raw",
+                                       busno, tgt, tlun);
+       } else {
+               char *tgtstr = (tgt == 0) ? "master" : (tgt == 1) ? "slave" : "dummy";
+               snprintf(buf, sizeof (buf),
+                                       "/dev/disk/ide/atapi/%d/%s/%d/raw",
+                                       busno-8, tgtstr, tlun);
+       }
+       fd = open(buf, 0);
+
+       if (fd >= 0) {
+               f = (struct _fdmap_ *) malloc(sizeof (struct _fdmap_));
+               f->bus = busno;
+               f->targ = tgt;
+               f->lun = tlun;
+               f->fd = fd;
+               f->next = (struct _fdmap_ *)usalp->local;
+               usalp->local = f;
+       }
+       return (fd);
+}
+
+static int
+usalo_initiator_id(SCSI *usalp)
+{
+       return (-1);
+}
+
+static int
+usalo_isatapi(SCSI *usalp)
+{
+       /*
+        * XXX Should check for ATAPI
+        */
+       return (-1);
+}
+
+static int
+usalo_reset(SCSI *usalp, int what)
+{
+       errno = EINVAL;
+       return (-1);
+}
+
+static int
+usalo_send(SCSI *usalp)
+{
+       struct usal_cmd         *sp = usalp->scmd;
+       int                     e;
+       int                     scsi_error;
+       int                     cam_error;
+       raw_device_command      rdc;
+
+       if (usalp->fd < 0) {
+               sp->error = SCG_FATAL;
+               return (0);
+       }
+
+       memcpy(rdc.command, &(sp->cdb), 12);
+       rdc.command_length = sp->cdb_len;
+       rdc.data = sp->addr;
+       rdc.data_length = sp->size;
+       rdc.sense_data_length = sp->sense_len;
+       rdc.sense_data = sp->u_sense.cmd_sense;
+       rdc.flags = sp->flags & SCG_RECV_DATA ? B_RAW_DEVICE_DATA_IN : 0;
+       if (sp->size > 0)
+               rdc.flags |= B_RAW_DEVICE_REPORT_RESIDUAL;
+       rdc.timeout = sp->timeout * 1000000;
+
+       sp->error               = SCG_NO_ERROR;
+       sp->sense_count         = 0;
+       sp->u_scb.cmd_scb[0]    = 0;
+       sp->resid               = 0;
+
+       if (usalp->debug > 0) {
+               fprintf(stderr, "SEND(%d): cmd %02x, cdblen = %d, datalen = %ld, senselen = %ld\n",
+                       usalp->fd, rdc.command[0], rdc.command_length,
+                       rdc.data_length, rdc.sense_data_length);
+       }
+       e = ioctl(usalp->fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof (rdc));
+       if (usalp->debug > 0) {
+               fprintf(stderr, "SEND(%d): -> %d CAM Status %02X SCSI status %02X\n", e, rdc.cam_status, rdc.scsi_status);
+       }
+       sp->ux_errno = 0;
+#ifdef DEBUG
+       fprintf(stderr, "err %d errno %x CAM %X SL %d DL %d/%d FL %X\n",
+               e, geterrno(), rdc.cam_status,
+               rdc.sense_data_length, rdc.data_length, sp->size, rdc.flags);
+#endif
+       if (!e) {
+               cam_error = rdc.cam_status;
+               scsi_error = rdc.scsi_status;
+               sp->u_scb.cmd_scb[0] = scsi_error;
+               if (sp->size > 0)
+                       sp->resid = sp->size - rdc.data_length;
+
+               switch (cam_error & CAM_STATUS_MASK) {
+
+               case CAM_REQ_CMP:
+                       sp->error = SCG_NO_ERROR;
+                       break;
+
+               case CAM_REQ_CMP_ERR:
+                       sp->sense_count = sp->sense_len; /* XXX */
+                       sp->error = SCG_NO_ERROR;
+                       sp->ux_errno = EIO;
+                       break;
+
+               case CAM_CMD_TIMEOUT:
+                       sp->error = SCG_TIMEOUT;
+                       sp->ux_errno = EIO;
+
+               case CAM_SEL_TIMEOUT:
+                       sp->error = SCG_FATAL;
+                       sp->ux_errno = EIO;
+                       break;
+
+               default:
+                       sp->error = SCG_RETRYABLE;
+                       sp->ux_errno = EIO;
+               }
+       } else {
+               sp->error = SCG_FATAL;
+               sp->ux_errno = geterrno();
+               sp->resid = sp->size;
+       }
+       return (0);
+}
diff --git a/libusal/scsi-bsd-os.c b/libusal/scsi-bsd-os.c
new file mode 100644 (file)
index 0000000..5719505
--- /dev/null
@@ -0,0 +1,443 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)scsi-bsd-os.c   1.28 04/01/15 Copyright 1997 J. Schilling */
+/*
+ *     Interface for the BSD/OS user-land raw SCSI implementation.
+ *
+ *     This is a hack, that tries to emulate the functionality
+ *     of the usal driver.
+ *
+ *     Warning: you may change this source, but if you do that
+ *     you need to change the _usal_version and _usal_auth* string below.
+ *     You may not return "schily" for an SCG_AUTHOR request anymore.
+ *     Choose your name instead of "schily" and make clear that the version
+ *     string is related to a modified source.
+ *
+ *     Copyright (c) 1997 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#undef sense
+
+#define        scsi_sense      bsdi_scsi_sense
+#define        scsi_inquiry    bsdi_scsi_inquiry
+
+/*
+ * Must use -I/sys...
+ * The next two files are in /sys/dev/scsi
+ */
+#include <dev/scsi/scsi.h>
+#include <dev/scsi/scsi_ioctl.h>
+
+/*
+ *     Warning: you may change this source, but if you do that
+ *     you need to change the _usal_version and _usal_auth* string below.
+ *     You may not return "schily" for an SCG_AUTHOR request anymore.
+ *     Choose your name instead of "schily" and make clear that the version
+ *     string is related to a modified source.
+ */
+static char    _usal_trans_version[] = "scsi-bsd-os.c-1.28";   /* The version for this transport*/
+
+#define        MAX_SCG         16      /* Max # of SCSI controllers */
+#define        MAX_TGT         16
+#define        MAX_LUN         8
+
+struct usal_local {
+       short   usalfiles[MAX_SCG][MAX_TGT][MAX_LUN];
+};
+#define        usallocal(p)    ((struct usal_local *)((p)->local))
+
+#include <machine/param.h>
+
+#define        MAX_DMA_BSDI    MAXPHYS         /* More makes problems */
+
+
+static BOOL    usal_setup(SCSI *usalp, int f, int busno, int tgt, int tlun);
+
+/*
+ * Return version information for the low level SCSI transport code.
+ * This has been introduced to make it easier to trace down problems
+ * in applications.
+ */
+static char *
+usalo_version(SCSI *usalp, int what)
+{
+       if (usalp != (SCSI *)0) {
+               switch (what) {
+
+               case SCG_VERSION:
+                       return (_usal_trans_version);
+               /*
+                * If you changed this source, you are not allowed to
+                * return "schily" for the SCG_AUTHOR request.
+                */
+               case SCG_AUTHOR:
+                       return (_usal_auth_cdrkit);
+               case SCG_SCCS_ID:
+                       return (__sccsid);
+               }
+       }
+       return ((char *)0);
+}
+
+static int
+usalo_help(SCSI *usalp, FILE *f)
+{
+       __usal_help(f, "SCSIRAWCDB", "Generic SCSI for devices known by BSDi",
+               "", "devname:@,lun", "/dev/rsr0a:@,0", FALSE, TRUE);
+       return (0);
+}
+
+static int
+usalo_open(SCSI *usalp, char *device)
+{
+               int     busno   = usal_scsibus(usalp);
+               int     tgt     = usal_target(usalp);
+               int     tlun    = usal_lun(usalp);
+       register int    f;
+       register int    b;
+       register int    t;
+       register int    l;
+       register int    nopen = 0;
+       char            devname[64];
+
+       if (busno >= MAX_SCG || tgt >= MAX_TGT || tlun >= MAX_LUN) {
+               errno = EINVAL;
+               if (usalp->errstr)
+                       snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                               "Illegal value for busno, target or lun '%d,%d,%d'",
+                               busno, tgt, tlun);
+               return (-1);
+       }
+
+       if (usalp->local == NULL) {
+               usalp->local = malloc(sizeof (struct usal_local));
+               if (usalp->local == NULL)
+                       return (0);
+
+               for (b = 0; b < MAX_SCG; b++) {
+                       for (t = 0; t < MAX_TGT; t++) {
+                               for (l = 0; l < MAX_LUN; l++)
+                                       usallocal(usalp)->usalfiles[b][t][l] = (short)-1;
+                       }
+               }
+       }
+
+       if ((device != NULL && *device != '\0') || (busno == -2 && tgt == -2))
+               goto openbydev;
+
+       if (busno >= 0 && tgt >= 0 && tlun >= 0) {
+
+               snprintf(devname, sizeof (devname),
+                                       "/dev/su%d-%d-%d", busno, tgt, tlun);
+               f = open(devname, O_RDWR|O_NONBLOCK);
+               if (f < 0) {
+                       goto openbydev;
+               }
+               usallocal(usalp)->usalfiles[busno][tgt][tlun] = f;
+               return (1);
+
+       } else for (b = 0; b < MAX_SCG; b++) {
+               for (t = 0; t < MAX_TGT; t++) {
+                       for (l = 0; l < MAX_LUN; l++) {
+                               snprintf(devname, sizeof (devname),
+                                               "/dev/su%d-%d-%d", b, t, l);
+                               f = open(devname, O_RDWR|O_NONBLOCK);
+/*                             fprintf(stderr, "open (%s) = %d\n", devname, f);*/
+
+                               if (f < 0) {
+                                       if (errno != ENOENT &&
+                                           errno != ENXIO &&
+                                           errno != ENODEV) {
+                                               if (usalp->errstr)
+                                                       snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                                                               "Cannot open '%s'",
+                                                               devname);
+                                               return (0);
+                                       }
+                               } else {
+                                       if (usal_setup(usalp, f, b, t, l))
+                                               nopen++;
+                               }
+                       }
+               }
+       }
+       /*
+        * Could not open /dev/su-* or got dev=devname:b,l,l / dev=devname:@,l
+        * We do the apropriate tests and try our best.
+        */
+openbydev:
+       if (nopen == 0) {
+               if (device == NULL || device[0] == '\0')
+                       return (0);
+               f = open(device, O_RDWR|O_NONBLOCK);
+               if (f < 0) {
+                       if (usalp->errstr)
+                               snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                                       "Cannot open '%s'",
+                                       device);
+                       return (0);
+               }
+               if (tlun == -2) {       /* If 'lun' is not known, we reject */
+                       close(f);
+                       errno = EINVAL;
+                       return (0);
+               }
+               busno = 0;              /* use fake number, we cannot get it */
+               tgt   = 0;              /* use fake number, we cannot get it */
+               usal_settarget(usalp, busno, tgt, tlun);
+               /* 'lun' has been specified on command line */
+               if (usal_setup(usalp, f, busno, tgt, tlun))
+                       nopen++;
+       }
+       return (nopen);
+}
+
+static int
+usalo_close(SCSI *usalp)
+{
+       register int    f;
+       register int    b;
+       register int    t;
+       register int    l;
+
+       if (usalp->local == NULL)
+               return (-1);
+
+       for (b = 0; b < MAX_SCG; b++) {
+               for (t = 0; t < MAX_TGT; t++) {
+                       for (l = 0; l < MAX_LUN; l++) {
+                               f = usallocal(usalp)->usalfiles[b][t][l];
+                               if (f >= 0)
+                                       close(f);
+                               usallocal(usalp)->usalfiles[b][t][l] = (short)-1;
+                       }
+               }
+       }
+       return (0);
+}
+
+static BOOL
+usal_setup(SCSI *usalp, int f, int busno, int tgt, int tlun)
+{
+       int     Bus;
+       int     Target;
+       int     Lun;
+       BOOL    onetarget = FALSE;
+
+       if (usal_scsibus(usalp) >= 0 && usal_target(usalp) >= 0 && usal_lun(usalp) >= 0)
+               onetarget = TRUE;
+
+       /*
+        * Unfortunately there is no way to get the right values from kernel.
+        */
+       Bus     = busno;
+       Target  = tgt;
+       Lun     = tlun;
+
+       if (usalp->debug > 0) {
+               fprintf((FILE *)usalp->errfile,
+                       "Bus: %d Target: %d Lun: %d\n", Bus, Target, Lun);
+       }
+
+       if (Bus >= MAX_SCG || Target >= MAX_TGT || Lun >= MAX_LUN) {
+               close(f);
+               return (FALSE);
+       }
+
+       if (usallocal(usalp)->usalfiles[Bus][Target][Lun] == (short)-1)
+               usallocal(usalp)->usalfiles[Bus][Target][Lun] = (short)f;
+
+       if (onetarget) {
+               if (Bus == busno && Target == tgt && Lun == tlun) {
+                       return (TRUE);
+               } else {
+                       usallocal(usalp)->usalfiles[Bus][Target][Lun] = (short)-1;
+                       close(f);
+               }
+       }
+       return (FALSE);
+}
+
+static long
+usalo_maxdma(SCSI *usalp, long amt)
+{
+       long maxdma = MAX_DMA_BSDI;
+
+       return (maxdma);
+}
+
+static void *
+usalo_getbuf(SCSI *usalp, long amt)
+{
+       if (usalp->debug > 0) {
+               fprintf((FILE *)usalp->errfile,
+                       "usalo_getbuf: %ld bytes\n", amt);
+       }
+       usalp->bufbase = malloc((size_t)(amt));
+       return (usalp->bufbase);
+}
+
+static void
+usalo_freebuf(SCSI *usalp)
+{
+       if (usalp->bufbase)
+               free(usalp->bufbase);
+       usalp->bufbase = NULL;
+}
+
+static BOOL
+usalo_havebus(SCSI *usalp, int busno)
+{
+       register int    t;
+       register int    l;
+
+       if (busno < 0 || busno >= MAX_SCG)
+               return (FALSE);
+
+       if (usalp->local == NULL)
+               return (FALSE);
+
+       for (t = 0; t < MAX_TGT; t++) {
+               for (l = 0; l < MAX_LUN; l++)
+                       if (usallocal(usalp)->usalfiles[busno][t][l] >= 0)
+                               return (TRUE);
+       }
+       return (FALSE);
+}
+
+static int
+usalo_fileno(SCSI *usalp, int busno, int tgt, int tlun)
+{
+       if (busno < 0 || busno >= MAX_SCG ||
+           tgt < 0 || tgt >= MAX_TGT ||
+           tlun < 0 || tlun >= MAX_LUN)
+               return (-1);
+
+       if (usalp->local == NULL)
+               return (-1);
+
+       return ((int)usallocal(usalp)->usalfiles[busno][tgt][tlun]);
+}
+
+static int
+usalo_initiator_id(SCSI *usalp)
+{
+       return (-1);
+}
+
+static int
+usalo_isatapi(SCSI *usalp)
+{
+       return (FALSE);
+}
+
+static int
+usalo_reset(SCSI *usalp, int what)
+{
+       /*
+        * Cannot reset on BSD/OS
+        */
+       errno = EINVAL;
+       return (-1);
+}
+
+static int
+usalo_send(SCSI *usalp)
+{
+       struct usal_cmd *sp = usalp->scmd;
+       scsi_user_cdb_t suc;
+       int             ret = 0;
+
+/*     fprintf((FILE *)usalp->errfile, "f: %d\n", f);*/
+       if (usalp->fd < 0) {
+               sp->error = SCG_FATAL;
+               return (0);
+       }
+
+       /* Zero the structure... */
+       fillbytes(&suc, sizeof (suc), '\0');
+
+       /* Read or write? */
+       if (sp->flags & SCG_RECV_DATA) {
+               suc.suc_flags |= SUC_READ;
+       } else if (sp->size > 0) {
+               suc.suc_flags |= SUC_WRITE;
+       }
+
+       suc.suc_timeout = sp->timeout;
+
+       suc.suc_cdblen = sp->cdb_len;
+       movebytes(sp->cdb.cmd_cdb, suc.suc_cdb, suc.suc_cdblen);
+
+       suc.suc_datalen = sp->size;
+       suc.suc_data = sp->addr;
+
+       if (ioctl(usalp->fd, SCSIRAWCDB, &suc) < 0) {
+               ret  = -1;
+               sp->ux_errno = geterrno();
+               if (sp->ux_errno != ENOTTY)
+                       ret = 0;
+       } else {
+               sp->ux_errno = 0;
+               if (suc.suc_sus.sus_status != STS_GOOD)
+                       sp->ux_errno = EIO;
+       }
+       fillbytes(&sp->scb, sizeof (sp->scb), '\0');
+       fillbytes(&sp->u_sense.cmd_sense, sizeof (sp->u_sense.cmd_sense), '\0');
+#if 0
+       /*
+        * Unfortunalety, BSD/OS has no idea of DMA residual count.
+        */
+       sp->resid = req.datalen - req.datalen_used;
+       sp->sense_count = req.senselen_used;
+#else
+       sp->resid = 0;
+       sp->sense_count = sizeof (suc.suc_sus.sus_sense);
+#endif
+       if (sp->sense_count > SCG_MAX_SENSE)
+               sp->sense_count = SCG_MAX_SENSE;
+       movebytes(suc.suc_sus.sus_sense, sp->u_sense.cmd_sense, sp->sense_count);
+       sp->u_scb.cmd_scb[0] = suc.suc_sus.sus_status;
+
+       switch (suc.suc_sus.sus_status) {
+
+       case STS_GOOD:
+                               sp->error = SCG_NO_ERROR;       break;
+       case STS_CMD_TERMINATED:sp->error = SCG_TIMEOUT;        break;
+       case STS_BUSY:          sp->error = SCG_RETRYABLE;      break;
+       case STS_CHECKCOND:     sp->error = SCG_RETRYABLE;      break;
+       case STS_QUEUE_FULL:    sp->error = SCG_RETRYABLE;      break;
+       default:                sp->error = SCG_FATAL;          break;
+       }
+
+       return (ret);
+}
+
+#define        sense   u_sense.Sense
+
+#undef scsi_sense
+#undef scsi_inquiry
diff --git a/libusal/scsi-bsd.c b/libusal/scsi-bsd.c
new file mode 100644 (file)
index 0000000..6e6c240
--- /dev/null
@@ -0,0 +1,992 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)scsi-bsd.c      1.42 04/01/15 Copyright 1997 J. Schilling */
+/*
+ *     Interface for the NetBSD/FreeBSD/OpenBSD generic SCSI implementation.
+ *
+ *     This is a hack, that tries to emulate the functionality
+ *     of the usal driver.
+ *     The SCSI tranport of the generic *BSD implementation is very
+ *     similar to the SCSI command transport of the
+ *     6 years older usal driver.
+ *
+ *     Warning: you may change this source, but if you do that
+ *     you need to change the _usal_version and _usal_auth* string below.
+ *     You may not return "schily" for an SCG_AUTHOR request anymore.
+ *     Choose your name instead of "schily" and make clear that the version
+ *     string is related to a modified source.
+ *
+ *     Copyright (c) 1997 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef HAVE_CAMLIB_H
+
+#undef sense
+#include <sys/scsiio.h>
+
+/*
+ *     Warning: you may change this source, but if you do that
+ *     you need to change the _usal_version and _usal_auth* string below.
+ *     You may not return "schily" for an SCG_AUTHOR request anymore.
+ *     Choose your name instead of "schily" and make clear that the version
+ *     string is related to a modified source.
+ */
+static char    _usal_trans_version[] = "scsi-bsd.c-1.42";      /* The version for this transport*/
+
+#define        MAX_SCG         16      /* Max # of SCSI controllers */
+#define        MAX_TGT         16
+#define        MAX_LUN         8
+
+struct usal_local {
+       short   usalfiles[MAX_SCG][MAX_TGT][MAX_LUN];
+};
+#define        usallocal(p)    ((struct usal_local *)((p)->local))
+
+/*#define      MAX_DMA_BSD     (32*1024)*/
+#define        MAX_DMA_BSD     (60*1024)       /* More seems to make problems */
+
+#if    defined(__NetBSD__) && defined(TYPE_ATAPI)
+/*
+ * NetBSD 1.3 has a merged SCSI/ATAPI system, so this structure
+ * is slightly different.
+ */
+#define        MAYBE_ATAPI
+#define        SADDR_ISSCSI(a) ((a).type == TYPE_SCSI)
+
+#define        SADDR_BUS(a)    (SADDR_ISSCSI(a)?(a).addr.scsi.scbus:(MAX_SCG-1))
+#define        SADDR_TARGET(a) (SADDR_ISSCSI(a)?(a).addr.scsi.target:(a).addr.atapi.atbus*2+(a).addr.atapi.drive)
+#define        SADDR_LUN(a)    (SADDR_ISSCSI(a)?(a).addr.scsi.lun:0)
+#else
+
+#if    defined(__OpenBSD__) && defined(TYPE_ATAPI)
+#define        SADDR_ISSCSI(a) ((a).type == TYPE_SCSI)
+#else
+#define        SADDR_ISSCSI(a) (1)
+#endif
+
+#define        SADDR_BUS(a)    (a).scbus
+#define        SADDR_TARGET(a) (a).target
+#define        SADDR_LUN(a)    (a).lun
+#endif /* __NetBSD__ && TYPE_ATAPI */
+
+static BOOL    usal_setup(SCSI *usalp, int f, int busno, int tgt, int tlun);
+
+/*
+ * Return version information for the low level SCSI transport code.
+ * This has been introduced to make it easier to trace down problems
+ * in applications.
+ */
+static char *
+usalo_version(SCSI *usalp, int what)
+{
+       if (usalp != (SCSI *)0) {
+               switch (what) {
+
+               case SCG_VERSION:
+                       return (_usal_trans_version);
+               /*
+                * If you changed this source, you are not allowed to
+                * return "schily" for the SCG_AUTHOR request.
+                */
+               case SCG_AUTHOR:
+                       return (_usal_auth_cdrkit);
+               case SCG_SCCS_ID:
+                       return (__sccsid);
+               }
+       }
+       return ((char *)0);
+}
+
+static int
+usalo_help(SCSI *usalp, FILE *f)
+{
+       __usal_help(f, "SCIOCCOMMAND", "SCSI for devices known by *BSD",
+               "", "device or bus,target,lun", "/dev/rcd0a:@ or 1,2,0", FALSE, TRUE);
+       return (0);
+}
+
+static int
+usalo_open(SCSI *usalp, char *device)
+{
+               int     busno   = usal_scsibus(usalp);
+               int     tgt     = usal_target(usalp);
+               int     tlun    = usal_lun(usalp);
+       register int    f;
+       register int    b;
+       register int    t;
+       register int    l;
+       register int    nopen = 0;
+       char            devname[64];
+
+       if (busno >= MAX_SCG || tgt >= MAX_TGT || tlun >= MAX_LUN) {
+               errno = EINVAL;
+               if (usalp->errstr)
+                       snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                               "Illegal value for busno, target or lun '%d,%d,%d'",
+                               busno, tgt, tlun);
+               return (-1);
+       }
+
+       if (usalp->local == NULL) {
+               usalp->local = malloc(sizeof (struct usal_local));
+               if (usalp->local == NULL)
+                       return (0);
+
+               for (b = 0; b < MAX_SCG; b++) {
+                       for (t = 0; t < MAX_TGT; t++) {
+                               for (l = 0; l < MAX_LUN; l++)
+                                       usallocal(usalp)->usalfiles[b][t][l] = (short)-1;
+                       }
+               }
+       }
+
+       if ((device != NULL && *device != '\0') || (busno == -2 && tgt == -2))
+               goto openbydev;
+
+       if (busno >= 0 && tgt >= 0 && tlun >= 0) {
+
+               snprintf(devname, sizeof (devname),
+                               "/dev/su%d-%d-%d", busno, tgt, tlun);
+               f = open(devname, O_RDWR);
+               if (f < 0) {
+                       goto openbydev;
+               }
+               usallocal(usalp)->usalfiles[busno][tgt][tlun] = f;
+               return (1);
+
+       } else for (b = 0; b < MAX_SCG; b++) {
+               for (t = 0; t < MAX_TGT; t++) {
+                       for (l = 0; l < MAX_LUN; l++) {
+                               snprintf(devname, sizeof (devname),
+                                                       "/dev/su%d-%d-%d", b, t, l);
+                               f = open(devname, O_RDWR);
+/*                             fprintf(stderr, "open (%s) = %d\n", devname, f);*/
+
+                               if (f < 0) {
+                                       if (errno != ENOENT &&
+                                           errno != ENXIO &&
+                                           errno != ENODEV) {
+                                               if (usalp->errstr)
+                                                       snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                                                               "Cannot open '%s'",
+                                                               devname);
+                                               return (0);
+                                       }
+                               } else {
+                                       if (usal_setup(usalp, f, b, t, l))
+                                               nopen++;
+                               }
+                       }
+               }
+       }
+       /*
+        * Could not open /dev/su-* or got dev=devname:b,l,l / dev=devname:@,l
+        * We do the apropriate tests and try our best.
+        */
+openbydev:
+       if (nopen == 0) {
+               struct scsi_addr saddr;
+
+               if (device == NULL || device[0] == '\0')
+                       return (0);
+               f = open(device, O_RDWR);
+               if (f < 0) {
+                       if (usalp->errstr)
+                               snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                                       "Cannot open '%s'",
+                                       device);
+                       return (0);
+               }
+               if (tgt == -2) {
+                       if (ioctl(f, SCIOCIDENTIFY, &saddr) < 0) {
+                               close(f);
+                               errno = EINVAL;
+                               return (0);
+                       }
+                       busno   = SADDR_BUS(saddr);
+                       tgt     = SADDR_TARGET(saddr);
+                       if ((tlun >= 0) && (tlun != SADDR_LUN(saddr))) {
+                               close(f);
+                               errno = EINVAL;
+                               return (0);
+                       }
+                       tlun    = SADDR_LUN(saddr);
+                       usal_settarget(usalp, busno, tgt, tlun);
+               }
+               if (usal_setup(usalp, f, busno, tgt, tlun))
+                       nopen++;
+       }
+       return (nopen);
+}
+
+static int
+usalo_close(SCSI *usalp)
+{
+       register int    f;
+       register int    b;
+       register int    t;
+       register int    l;
+
+       if (usalp->local == NULL)
+               return (-1);
+
+       for (b = 0; b < MAX_SCG; b++) {
+               for (t = 0; t < MAX_TGT; t++) {
+                       for (l = 0; l < MAX_LUN; l++) {
+                               f = usallocal(usalp)->usalfiles[b][t][l];
+                               if (f >= 0)
+                                       close(f);
+                               usallocal(usalp)->usalfiles[b][t][l] = (short)-1;
+                       }
+               }
+       }
+       return (0);
+}
+
+static BOOL
+usal_setup(SCSI *usalp, int f, int busno, int tgt, int tlun)
+{
+       struct scsi_addr saddr;
+       int     Bus;
+       int     Target;
+       int     Lun;
+       BOOL    onetarget = FALSE;
+
+       if (usal_scsibus(usalp) >= 0 && usal_target(usalp) >= 0 && usal_lun(usalp) >= 0)
+               onetarget = TRUE;
+
+       if (ioctl(f, SCIOCIDENTIFY, &saddr) < 0) {
+               errmsg("Cannot get SCSI addr.\n");
+               close(f);
+               return (FALSE);
+       }
+       Bus     = SADDR_BUS(saddr);
+       Target  = SADDR_TARGET(saddr);
+       Lun     = SADDR_LUN(saddr);
+
+       if (usalp->debug > 0) {
+               fprintf((FILE *)usalp->errfile,
+                       "Bus: %d Target: %d Lun: %d\n", Bus, Target, Lun);
+       }
+
+       if (Bus >= MAX_SCG || Target >= MAX_TGT || Lun >= MAX_LUN) {
+               close(f);
+               return (FALSE);
+       }
+
+       if (usallocal(usalp)->usalfiles[Bus][Target][Lun] == (short)-1)
+               usallocal(usalp)->usalfiles[Bus][Target][Lun] = (short)f;
+
+       if (onetarget) {
+               if (Bus == busno && Target == tgt && Lun == tlun) {
+                       return (TRUE);
+               } else {
+                       usallocal(usalp)->usalfiles[Bus][Target][Lun] = (short)-1;
+                       close(f);
+               }
+       }
+       return (FALSE);
+}
+
+static long
+usalo_maxdma(SCSI *usalp, long amt)
+{
+       long maxdma = MAX_DMA_BSD;
+
+       return (maxdma);
+}
+
+static void *
+usalo_getbuf(SCSI *usalp, long amt)
+{
+       if (usalp->debug > 0) {
+               fprintf((FILE *)usalp->errfile,
+                       "usalo_getbuf: %ld bytes\n", amt);
+       }
+       usalp->bufbase = valloc((size_t)(amt));
+       return (usalp->bufbase);
+}
+
+static void
+usalo_freebuf(SCSI *usalp)
+{
+       if (usalp->bufbase)
+               free(usalp->bufbase);
+       usalp->bufbase = NULL;
+}
+
+static BOOL
+usalo_havebus(SCSI *usalp, int busno)
+{
+       register int    t;
+       register int    l;
+
+       if (busno < 0 || busno >= MAX_SCG)
+               return (FALSE);
+
+       if (usalp->local == NULL)
+               return (FALSE);
+
+       for (t = 0; t < MAX_TGT; t++) {
+               for (l = 0; l < MAX_LUN; l++)
+                       if (usallocal(usalp)->usalfiles[busno][t][l] >= 0)
+                               return (TRUE);
+       }
+       return (FALSE);
+}
+
+static int
+usalo_fileno(SCSI *usalp, int busno, int tgt, int tlun)
+{
+       if (busno < 0 || busno >= MAX_SCG ||
+           tgt < 0 || tgt >= MAX_TGT ||
+           tlun < 0 || tlun >= MAX_LUN)
+               return (-1);
+
+       if (usalp->local == NULL)
+               return (-1);
+
+       return ((int)usallocal(usalp)->usalfiles[busno][tgt][tlun]);
+}
+
+static int
+usalo_initiator_id(SCSI *usalp)
+{
+       return (-1);
+}
+
+static int
+usalo_isatapi(SCSI *usalp)
+{
+#ifdef MAYBE_ATAPI
+       struct scsi_addr saddr;
+
+       if (ioctl(usalp->fd, SCIOCIDENTIFY, &saddr) < 0)
+               return (-1);
+
+       if (!SADDR_ISSCSI(saddr))
+               return (TRUE);
+#endif
+       return (FALSE);
+}
+
+static int
+usalo_reset(SCSI *usalp, int what)
+{
+       if (what == SCG_RESET_NOP)
+               return (0);
+       if (what != SCG_RESET_BUS) {
+               errno = EINVAL;
+               return (-1);
+       }
+       /*
+        * XXX Does this reset TGT or BUS ???
+        */
+       return (ioctl(usalp->fd, SCIOCRESET, 0));
+}
+
+static int
+usalo_send(SCSI *usalp)
+{
+       struct usal_cmd *sp = usalp->scmd;
+       scsireq_t       req;
+       register long   *lp1;
+       register long   *lp2;
+       int             ret = 0;
+
+/*     fprintf((FILE *)usalp->errfile, "fd: %d\n", usalp->fd);*/
+       if (usalp->fd < 0) {
+               sp->error = SCG_FATAL;
+               return (0);
+       }
+       req.flags = SCCMD_ESCAPE;       /* We set the SCSI cmd len */
+       if (sp->flags & SCG_RECV_DATA)
+               req.flags |= SCCMD_READ;
+       else if (sp->size > 0)
+               req.flags |= SCCMD_WRITE;
+
+       req.timeout = sp->timeout * 1000;
+       lp1 = (long *)sp->cdb.cmd_cdb;
+       lp2 = (long *)req.cmd;
+       *lp2++ = *lp1++;
+       *lp2++ = *lp1++;
+       *lp2++ = *lp1++;
+       *lp2++ = *lp1++;
+       req.cmdlen = sp->cdb_len;
+       req.databuf = sp->addr;
+       req.datalen = sp->size;
+       req.datalen_used = 0;
+       fillbytes(req.sense, sizeof (req.sense), '\0');
+       if (sp->sense_len > sizeof (req.sense))
+               req.senselen = sizeof (req.sense);
+       else if (sp->sense_len < 0)
+               req.senselen = 0;
+       else
+               req.senselen = sp->sense_len;
+       req.senselen_used = 0;
+       req.status = 0;
+       req.retsts = 0;
+       req.error = 0;
+
+       if (ioctl(usalp->fd, SCIOCCOMMAND, (void *)&req) < 0) {
+               ret  = -1;
+               sp->ux_errno = geterrno();
+               if (sp->ux_errno != ENOTTY)
+                       ret = 0;
+       } else {
+               sp->ux_errno = 0;
+               if (req.retsts != SCCMD_OK)
+                       sp->ux_errno = EIO;
+       }
+       fillbytes(&sp->scb, sizeof (sp->scb), '\0');
+       fillbytes(&sp->u_sense.cmd_sense, sizeof (sp->u_sense.cmd_sense), '\0');
+       sp->resid = req.datalen - req.datalen_used;
+       sp->sense_count = req.senselen_used;
+       if (sp->sense_count > SCG_MAX_SENSE)
+               sp->sense_count = SCG_MAX_SENSE;
+       movebytes(req.sense, sp->u_sense.cmd_sense, sp->sense_count);
+       sp->u_scb.cmd_scb[0] = req.status;
+
+       switch (req.retsts) {
+
+       case SCCMD_OK:
+#ifdef BSD_SCSI_SENSE_BUG
+                               sp->u_scb.cmd_scb[0] = 0;
+                               sp->ux_errno = 0;
+#endif
+                               sp->error = SCG_NO_ERROR;       break;
+       case SCCMD_TIMEOUT:     sp->error = SCG_TIMEOUT;        break;
+       default:
+       case SCCMD_BUSY:        sp->error = SCG_RETRYABLE;      break;
+       case SCCMD_SENSE:       sp->error = SCG_RETRYABLE;      break;
+       case SCCMD_UNKNOWN:     sp->error = SCG_FATAL;          break;
+       }
+
+       return (ret);
+}
+#define        sense   u_sense.Sense
+
+#else /* BSD_CAM */
+/*
+ *     Interface for the FreeBSD CAM passthrough device.
+ *
+ * Copyright (c) 1998 Michael Smith <msmith@freebsd.org>
+ * Copyright (c) 1998 Kenneth D. Merry <ken@kdm.org>
+ * Copyright (c) 1998 Joerg Schilling <schilling@fokus.gmd.de>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#undef sense
+#define        scsi_sense CAM_scsi_sense
+#define        scsi_inquiry CAM_scsi_inquiry
+#include <sys/param.h>
+#include <cam/cam.h>
+#include <cam/cam_ccb.h>
+#include <cam/scsi/scsi_message.h>
+#include <cam/scsi/scsi_pass.h>
+#include <camlib.h>
+
+/*
+ *     Warning: you may change this source, but if you do that
+ *     you need to change the _usal_version and _usal_auth* string below.
+ *     You may not return "schily" for an SCG_AUTHOR request anymore.
+ *     Choose your name instead of "schily" and make clear that the version
+ *     string is related to a modified source.
+ */
+static char    _usal_trans_version[] = "scsi-bsd.c-1.42";      /* The version for this transport*/
+
+#define        CAM_MAXDEVS     128
+struct usal_local {
+       struct cam_device *cam_devices[CAM_MAXDEVS + 1];
+};
+#define        usallocal(p)    ((struct usal_local *)((p)->local))
+
+/*
+ * Return version information for the low level SCSI transport code.
+ * This has been introduced to make it easier to trace down problems
+ * in applications.
+ */
+static char *
+usalo_version(SCSI *usalp, int what)
+{
+       if (usalp != (SCSI *)0) {
+               switch (what) {
+
+               case SCG_VERSION:
+                       return (_usal_trans_version);
+               /*
+                * If you changed this source, you are not allowed to
+                * return "schily" for the SCG_AUTHOR request.
+                */
+               case SCG_AUTHOR:
+                       return (_usal_auth_cdrkit);
+               case SCG_SCCS_ID:
+                       return (__sccsid);
+               }
+       }
+       return ((char *)0);
+}
+
+static int
+usalo_help(SCSI *usalp, FILE *f)
+{
+       __usal_help(f, "CAM", "Generic transport independent SCSI (Common Access Method)",
+               "", "bus,target,lun", "1,2,0", TRUE, FALSE);
+       return (0);
+}
+
+/*
+ * Build a list of everything we can find.
+ */
+static int
+usalo_open(SCSI *usalp, char *device)
+{
+       int                             busno   = usal_scsibus(usalp);
+       int                             tgt     = usal_target(usalp);
+       int                             tlun    = usal_lun(usalp);
+       char                            name[16];
+       int                             unit;
+       int                             nopen = 0;
+       union ccb                       ccb;
+       int                             bufsize;
+       struct periph_match_pattern     *match_pat;
+       int                             fd;
+
+       if ((device != NULL && *device != '\0') || (busno == -2 && tgt == -2)) {
+               errno = EINVAL;
+               if (usalp->errstr)
+                       snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                               "Open by 'devname' not supported on this OS");
+               return (-1);
+       }
+
+       if (usalp->local == NULL) {
+               usalp->local = malloc(sizeof (struct usal_local));
+               if (usalp->local == NULL)
+                       return (0);
+
+               for (unit = 0; unit <= CAM_MAXDEVS; unit++) {
+                       usallocal(usalp)->cam_devices[unit] = (struct cam_device *)-1;
+               }
+       }
+
+
+       /*
+        * If we're not scanning the bus, just open one device.
+        */
+       if (busno >= 0 && tgt >= 0 && tlun >= 0) {
+               usallocal(usalp)->cam_devices[0] = cam_open_btl(busno, tgt, tlun, O_RDWR, NULL);
+               if (usallocal(usalp)->cam_devices[0] == NULL)
+                       return (-1);
+               nopen++;
+               return (nopen);
+       }
+
+       /*
+        * First open the transport layer device.  There's no point in the
+        * rest of this if we can't open it.
+        */
+
+       if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
+               if (usalp->errstr)
+                       snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                               "Open of %s failed", XPT_DEVICE);
+               return (-1);
+       }
+       fillbytes(&ccb, sizeof (union ccb), '\0');
+
+       /*
+        * Get a list of up to CAM_MAXDEVS passthrough devices in the
+        * system.
+        */
+       ccb.ccb_h.func_code = XPT_DEV_MATCH;
+
+       /*
+        * Setup the result buffer.
+        */
+       bufsize = sizeof (struct dev_match_result) * CAM_MAXDEVS;
+       ccb.cdm.match_buf_len = bufsize;
+       ccb.cdm.matches = (struct dev_match_result *)malloc(bufsize);
+       if (ccb.cdm.matches == NULL) {
+               if (usalp->errstr)
+                       snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                               "Couldn't malloc match buffer");
+               close(fd);
+               return (-1);
+       }
+       ccb.cdm.num_matches = 0;
+
+       /*
+        * Setup the pattern buffer.  We're matching against all
+        * peripherals named "pass".
+        */
+       ccb.cdm.num_patterns = 1;
+       ccb.cdm.pattern_buf_len = sizeof (struct dev_match_pattern);
+       ccb.cdm.patterns = (struct dev_match_pattern *)malloc(
+               sizeof (struct dev_match_pattern));
+       if (ccb.cdm.patterns == NULL) {
+               if (usalp->errstr)
+                       snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                               "Couldn't malloc pattern buffer");
+               close(fd);
+               free(ccb.cdm.matches);
+               return (-1);
+       }
+       ccb.cdm.patterns[0].type = DEV_MATCH_PERIPH;
+       match_pat = &ccb.cdm.patterns[0].pattern.periph_pattern;
+       snprintf(match_pat->periph_name, sizeof (match_pat->periph_name),
+                                                               "pass");
+       match_pat->flags = PERIPH_MATCH_NAME;
+
+       if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
+               if (usalp->errstr)
+                       snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                               "CAMIOCOMMAND ioctl failed");
+               close(fd);
+               free(ccb.cdm.matches);
+               free(ccb.cdm.patterns);
+               return (-1);
+       }
+
+       if ((ccb.ccb_h.status != CAM_REQ_CMP) ||
+           ((ccb.cdm.status != CAM_DEV_MATCH_LAST) &&
+           (ccb.cdm.status != CAM_DEV_MATCH_MORE))) {
+/*             errmsgno(EX_BAD, "Got CAM error 0x%X, CDM error %d.\n",*/
+               if (usalp->errstr)
+                       snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                               "Got CAM error 0x%X, CDM error %d",
+                       ccb.ccb_h.status, ccb.cdm.status);
+               close(fd);
+               free(ccb.cdm.matches);
+               free(ccb.cdm.patterns);
+               return (-1);
+       }
+
+       free(ccb.cdm.patterns);
+       close(fd);
+
+       for (unit = 0; unit < MIN(CAM_MAXDEVS, ccb.cdm.num_matches); unit++) {
+               struct periph_match_result *periph_result;
+
+               /*
+                * We shouldn't have anything other than peripheral
+                * matches in here.  If we do, it means an error in the
+                * device matching code in the transport layer.
+                */
+               if (ccb.cdm.matches[unit].type != DEV_MATCH_PERIPH) {
+/*                     errmsgno(EX_BAD, "Kernel error! got periph match type %d!!\n",*/
+                       if (usalp->errstr)
+                               snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                                       "Kernel error! got periph match type %d!!",
+                                       ccb.cdm.matches[unit].type);
+                       free(ccb.cdm.matches);
+                       return (-1);
+               }
+               periph_result = &ccb.cdm.matches[unit].result.periph_result;
+
+               snprintf(name, sizeof (name),
+                               "/dev/%s%d", periph_result->periph_name,
+                       periph_result->unit_number);
+
+               /*
+                * cam_open_pass() avoids all lookup and translation from
+                * "regular device name" to passthrough unit number and
+                * just opens the device in question as a passthrough device.
+                */
+               usallocal(usalp)->cam_devices[unit] = cam_open_pass(name, O_RDWR, NULL);
+
+               /*
+                * If we get back NULL from the open routine, it wasn't
+                * able to open the given passthrough device for one reason
+                * or another.
+                */
+               if (usallocal(usalp)->cam_devices[unit] == NULL) {
+#ifdef OLD
+                       errmsgno(EX_BAD, "Error opening /dev/%s%d\n",
+                               periph_result->periph_name,
+                               periph_result->unit_number);
+                       errmsgno(EX_BAD, "%s\n", cam_errbuf);
+#endif
+                       if (usalp->errstr)
+                               snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                                       "Error opening /dev/%s%d Cam error '%s'",
+                                       periph_result->periph_name,
+                                       periph_result->unit_number,
+                                       cam_errbuf);
+                       break;
+               }
+               nopen++;
+       }
+
+       free(ccb.cdm.matches);
+       return (nopen);
+}
+
+static int
+usalo_close(SCSI *usalp)
+{
+       register int    i;
+
+       if (usalp->local == NULL)
+               return (-1);
+
+       for (i = 0; i <= CAM_MAXDEVS; i++) {
+               if (usallocal(usalp)->cam_devices[i] != (struct cam_device *)-1)
+                       cam_close_device(usallocal(usalp)->cam_devices[i]);
+               usallocal(usalp)->cam_devices[i] = (struct cam_device *)-1;
+       }
+       return (0);
+}
+
+static long
+usalo_maxdma(SCSI *usalp, long amt)
+{
+#ifdef DFLTPHYS
+       return (DFLTPHYS);
+#else
+       return (MAXPHYS);
+#endif
+}
+
+static void *
+usalo_getbuf(SCSI *usalp, long amt)
+{
+       if (usalp->debug > 0) {
+               fprintf((FILE *)usalp->errfile,
+                       "usalo_getbuf: %ld bytes\n", amt);
+       }
+       usalp->bufbase = valloc((size_t)(amt));
+       return (usalp->bufbase);
+}
+
+static void
+usalo_freebuf(SCSI *usalp)
+{
+       if (usalp->bufbase)
+               free(usalp->bufbase);
+       usalp->bufbase = NULL;
+}
+
+static BOOL
+usalo_havebus(SCSI *usalp, int busno)
+{
+       int             unit;
+
+       if (usalp->local == NULL)
+               return (FALSE);
+
+       /*
+        * There's a "cleaner" way to do this, using the matching code, but
+        * it would involve more code than this solution...
+        */
+       for (unit = 0; usallocal(usalp)->cam_devices[unit] != (struct cam_device *)-1; unit++) {
+               if (usallocal(usalp)->cam_devices[unit] == NULL)
+                       continue;
+               if (usallocal(usalp)->cam_devices[unit]->path_id == busno)
+                       return (TRUE);
+       }
+       return (FALSE);
+}
+
+static int
+usalo_fileno(SCSI *usalp, int busno, int unit, int tlun)
+{
+       int             i;
+
+       if (usalp->local == NULL)
+               return (-1);
+
+       for (i = 0; usallocal(usalp)->cam_devices[i] != (struct cam_device *)-1; i++) {
+               if (usallocal(usalp)->cam_devices[i] == NULL)
+                       continue;
+               if ((usallocal(usalp)->cam_devices[i]->path_id == busno) &&
+                   (usallocal(usalp)->cam_devices[i]->target_id == unit) &&
+                   (usallocal(usalp)->cam_devices[i]->target_lun == tlun))
+                       return (i);
+       }
+       return (-1);
+}
+
+static int
+usalo_initiator_id(SCSI *usalp)
+{
+       return (-1);
+}
+
+static int
+usalo_isatapi(SCSI *usalp)
+{
+       return (FALSE);
+}
+
+static int
+usalo_reset(SCSI *usalp, int what)
+{
+       /* XXX synchronous reset command - is this wise? */
+       errno = EINVAL;
+       return (-1);
+}
+
+static int
+usalo_send(SCSI *usalp)
+{
+       struct usal_cmd         *sp = usalp->scmd;
+       struct cam_device       *dev;
+       union ccb               ccb_space;
+       union ccb               *ccb = &ccb_space;
+       int                     rv, result;
+       u_int32_t               ccb_flags;
+
+       if (usalp->fd < 0) {
+#if 0
+               fprintf((FILE *)usalp->errfile,
+                       "attempt to reference invalid unit %d\n", usalp->fd);
+#endif
+               sp->error = SCG_FATAL;
+               return (0);
+       }
+
+       dev = usallocal(usalp)->cam_devices[usalp->fd];
+       fillbytes(&ccb->ccb_h, sizeof (struct ccb_hdr), '\0');
+       ccb->ccb_h.path_id = dev->path_id;
+       ccb->ccb_h.target_id = dev->target_id;
+       ccb->ccb_h.target_lun = dev->target_lun;
+
+       /* Build the CCB */
+       fillbytes(&(&ccb->ccb_h)[1], sizeof (struct ccb_scsiio), '\0');
+       movebytes(sp->cdb.cmd_cdb, &ccb->csio.cdb_io.cdb_bytes, sp->cdb_len);
+
+       /*
+        * Set the data direction flags.
+        */
+       if (sp->size != 0) {
+               ccb_flags = (sp->flags & SCG_RECV_DATA) ?   CAM_DIR_IN :
+                                                           CAM_DIR_OUT;
+       } else {
+               ccb_flags = CAM_DIR_NONE;
+       }
+
+       ccb_flags |= CAM_DEV_QFRZDIS;
+
+       /*
+        * If you don't want to bother with sending tagged commands under CAM,
+        * we don't need to do anything to cdrecord.  If you want to send
+        * tagged commands to those devices that support it, we'll need to set
+        * the tag action valid field like this in usalo_send():
+        *
+        *      ccb_flags |= CAM_DEV_QFRZDIS | CAM_TAG_ACTION_VALID;
+        */
+
+       cam_fill_csio(&ccb->csio,
+                       /* retries */   1,
+                       /* cbfncp */    NULL,
+                       /* flags */     ccb_flags,
+                       /* tag_action */ MSG_SIMPLE_Q_TAG,
+                       /* data_ptr */  (u_int8_t *)sp->addr,
+                       /* dxfer_len */ sp->size,
+                       /* sense_len */ SSD_FULL_SIZE,
+                       /* cdb_len */   sp->cdb_len,
+                       /* timeout */   sp->timeout * 1000);
+
+       /* Run the command */
+       errno = 0;
+       if ((rv = cam_send_ccb(dev, ccb)) == -1) {
+               return (rv);
+       } else {
+               /*
+                * Check for command status.  Selection timeouts are fatal.
+                * For command timeouts, we pass back the appropriate
+                * error.  If we completed successfully, there's (obviously)
+                * no error.  We declare anything else "retryable".
+                */
+               switch (ccb->ccb_h.status & CAM_STATUS_MASK) {
+                       case CAM_SEL_TIMEOUT:
+                               result = SCG_FATAL;
+                               break;
+                       case CAM_CMD_TIMEOUT:
+                               result = SCG_TIMEOUT;
+                               break;
+                       case CAM_REQ_CMP:
+                               result = SCG_NO_ERROR;
+                               break;
+                       default:
+                               result = SCG_RETRYABLE;
+                               break;
+               }
+       }
+
+       sp->error = result;
+       if (result != SCG_NO_ERROR)
+               sp->ux_errno = EIO;
+
+       /* Pass the result back up */
+       fillbytes(&sp->scb, sizeof (sp->scb), '\0');
+       fillbytes(&sp->u_sense.cmd_sense, sizeof (sp->u_sense.cmd_sense), '\0');
+       sp->resid = ccb->csio.resid;
+       sp->sense_count = SSD_FULL_SIZE - ccb->csio.sense_resid;
+
+       /*
+        * Determine how much room we have for sense data.
+        */
+       if (sp->sense_count > SCG_MAX_SENSE)
+               sp->sense_count = SCG_MAX_SENSE;
+
+       /* Copy the sense data out */
+       movebytes(&ccb->csio.sense_data, &sp->u_sense.cmd_sense, sp->sense_count);
+
+       sp->u_scb.cmd_scb[0] = ccb->csio.scsi_status;
+
+       return (0);
+}
+
+#undef scsi_sense
+#undef scsi_inquiry
+#define        sense u_sense.Sense
+
+#endif /* BSD_CAM */
diff --git a/libusal/scsi-dos.c b/libusal/scsi-dos.c
new file mode 100644 (file)
index 0000000..ecf36ce
--- /dev/null
@@ -0,0 +1,562 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)scsi-dos.c      1.11 03/12/10 Copyright 1998-2003 J. Schilling, 2003 Alex Kopylov reanimatolog@yandex.ru */
+/*
+ *     Interface for the MS-DOS ASPI managers.
+ *     You need ASPI manager installed in your config.sys:
+ *             aspi*.sys for SCSI devices
+ *             oakaspi.sys for ATAPI devices
+ *             usbaspi.sys for USB devices
+ *
+ *     Made from Win32 ASPI library template.
+ *
+ *     Warning: you may change this source, but if you do that
+ *     you need to change the _usal_version and _usal_auth* string below.
+ *     You may not return "schily" for an SCG_AUTHOR request anymore.
+ *     Choose your name instead of "schily" and make clear that the version
+ *     string is related to a modified source.
+ *
+ *     Copyright (c) 1998-2003 J. Schilling
+ *     Copyright (c) 1999 A.L. Faber for the first implementation
+ *                        of this interface.
+ *     Copyright (c) 2003 Alex Kopylov reanimatolog@yandex.ru
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <dos.h>
+#include <dpmi.h>
+#include <go32.h>
+#include <usal/aspi-dos.h>
+
+/*
+ *     Warning: you may change this source, but if you do that
+ *     you need to change the _usal_version and _usal_auth* string below.
+ *     You may not return "schily" for an SCG_AUTHOR request anymore.
+ *     Choose your name instead of "schily" and make clear that the version
+ *     string is related to a modified source.
+ */
+static char    _usal_trans_version[] = "scsi-dos.c-1.11";      /* The version for this transport*/
+
+#define        MAX_SCG 8
+#define        MAX_TGT 8
+#define        MAX_LUN 8
+
+struct usal_local {
+       int     dummy;
+};
+#define        usallocal(p)    ((struct usal_local *)((p)->local))
+
+#define        MAX_DMA_DOS     (63L*1024L)
+
+static BYTE    busses          = 1;
+static DWORD   SCSIMgrEntry    = 0;
+static int     AspiLoaded      = 0;
+
+static BOOL    _callback_flag;
+static _go32_dpmi_seginfo _callback_info;
+static _go32_dpmi_registers _callback_regs;
+
+static BOOL    SCSIMgrOpen(SCSI *);
+static void    SCSIMgrClose(void);
+static int     SCSIMgrSendSRB(SRB *, time_t);
+static void    SCSIMgrCallBack(_go32_dpmi_registers *regs);
+
+static char *
+usalo_version(SCSI *usalp, int what)
+{
+       if (usalp != (SCSI *)0) {
+               switch (what) {
+
+               case SCG_VERSION:
+                       return (_usal_trans_version);
+               case SCG_AUTHOR:
+                       return (_usal_auth_cdrkit);
+               case SCG_SCCS_ID:
+                       return (__sccsid);
+               }
+       }
+       return ((char *)0);
+}
+
+static int
+usalo_help(SCSI *usalp, FILE *f)
+{
+       __usal_help(f, "ASPI", "Generic transport independent SCSI",
+               "", "bus,target,lun", "1,2,0", TRUE, FALSE);
+       return (0);
+}
+
+static int
+usalo_open(SCSI *usalp, char *device)
+{
+       int     busno   = usal_scsibus(usalp);
+       int     tgt     = usal_target(usalp);
+       int     tlun    = usal_lun(usalp);
+
+       if (busno >= MAX_SCG || tgt >= MAX_TGT || tlun >= MAX_LUN) {
+               errno = EINVAL;
+               if (usalp->errstr)
+                       snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                               "Illegal value for busno, target or lun '%d,%d,%d'",
+                               busno, tgt, tlun);
+               return (-1);
+       }
+
+       if ((device != NULL && *device != '\0') || (busno == -2 && tgt == -2)) {
+               errno = EINVAL;
+               if (usalp->errstr)
+                       snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                               "Open by 'devname' not supported on this OS");
+               return (-1);
+       }
+
+       /*
+        *  Check if variables are within the range
+        */
+       if (tgt >= 0 && tgt >= 0 && tlun >= 0) {
+               /*
+                * This is the non -scanbus case.
+                */
+               ;
+       } else if (tgt != -1 || tgt != -1 || tlun != -1) {
+               errno = EINVAL;
+               return (-1);
+       }
+
+       if (usalp->local == NULL) {
+               usalp->local = malloc(sizeof (struct usal_local));
+               if (usalp->local == NULL)
+                       return (0);
+       }
+       /*
+        * Try to open ASPI-Router
+        */
+       if (!SCSIMgrOpen(usalp))
+               return (-1);
+
+       /*
+        * More than we have ...
+        */
+       if (busno >= busses) {
+               SCSIMgrClose();
+               return (-1);
+       }
+
+       /*
+        * Install Exit Function which closes the ASPI-Router
+        */
+       atexit(SCSIMgrClose);
+
+       /*
+        * Success after all
+        */
+       return (1);
+}
+
+static int
+usalo_close(SCSI *usalp)
+{
+       SCSIMgrClose();
+       return (0);
+}
+
+static long
+usalo_maxdma(SCSI *usalp, long amt)
+{
+       return (MAX_DMA_DOS);
+}
+
+static void *
+usalo_getbuf(SCSI *usalp, long amt)
+{
+       if (usalp->debug > 0) {
+               fprintf((FILE *)usalp->errfile,
+                               "usalo_getbuf: %ld bytes\n", amt);
+       }
+       usalp->bufbase = malloc((size_t)(amt));
+       return (usalp->bufbase);
+}
+
+static void
+usalo_freebuf(SCSI *usalp)
+{
+       if (usalp->bufbase)
+               free(usalp->bufbase);
+       usalp->bufbase = NULL;
+}
+
+static __SBOOL
+usalo_havebus(SCSI *usalp, int busno)
+{
+       if (busno < 0 || busno >= busses)
+               return (FALSE);
+
+       return (TRUE);
+}
+
+static int
+usalo_fileno(SCSI *usalp, int busno, int tgt, int tlun)
+{
+       if (busno < 0 || busno >= busses ||
+           tgt < 0 || tgt >= MAX_TGT ||
+           tlun < 0 || tlun >= MAX_LUN)
+               return (-1);
+
+       /*
+        * Return fake
+        */
+       return (1);
+}
+
+static int
+usalo_initiator_id(SCSI *usalp)
+{
+       return (-1);
+}
+
+static int
+usalo_isatapi(SCSI *usalp)
+{
+       return (-1);
+}
+
+static int
+usalo_reset(SCSI *usalp, int what)
+{
+       errno = EINVAL;
+       return (-1);
+}
+
+static int
+usalo_send(SCSI *usalp)
+{
+       struct usal_cmd *sp = usalp->scmd;
+       SRB             Srb;
+       int             dos_memory_data_seg;
+       int             dos_memory_data_sel;
+       DWORD           dos_memory_data_ptr;
+
+       /*
+        * Check if ASPI library is loaded
+        */
+       if (!SCSIMgrEntry) {
+               errmsgno(EX_BAD, "error in usalo_send: ASPI driver not loaded.\n");
+               sp->error = SCG_FATAL;
+               return (-1);
+       }
+
+       if (usalp->fd < 0) {
+               sp->error = SCG_FATAL;
+               return (0);
+       }
+
+       /*
+        * Initialize variables
+        */
+       sp->error               = SCG_NO_ERROR;
+       sp->sense_count         = 0;
+       sp->u_scb.cmd_scb[0]    = 0;
+       sp->resid               = 0;
+
+       memset(&Srb, 0, sizeof (Srb));
+
+       switch (sp->cdb_len) {
+
+       case 6:
+               movebytes(&sp->cdb, &(Srb.Type.ExecSCSICmd.CmdLen._6.CDBByte), sp->cdb_len);
+               break;
+       case 10:
+               movebytes(&sp->cdb, &(Srb.Type.ExecSCSICmd.CmdLen._10.CDBByte), sp->cdb_len);
+               break;
+       case 12:
+               movebytes(&sp->cdb, &(Srb.Type.ExecSCSICmd.CmdLen._12.CDBByte), sp->cdb_len);
+               break;
+       default:
+               sp->error = SCG_FATAL;
+               sp->ux_errno = EINVAL;
+               fprintf((FILE *)usalp->errfile,
+                       "Unsupported sp->cdb_len: %u. Fatal error in usalo_send, exiting...\n", sp->cdb_len);
+               return (-1);
+       }
+
+       if ((dos_memory_data_seg = __dpmi_allocate_dos_memory((sp->size>>4)+1, &dos_memory_data_sel)) == -1) {
+               sp->error = SCG_FATAL;
+               return (-1);
+       }
+       dos_memory_data_ptr = dos_memory_data_seg<<16;
+
+       _dosmemputb(sp->addr, sp->size, dos_memory_data_seg<<4);
+
+       Srb.Cmd = SC_EXEC_SCSI_CMD;
+       Srb.HaId = usal_scsibus(usalp);
+       Srb.Type.ExecSCSICmd.Target = usal_target(usalp);
+       Srb.Type.ExecSCSICmd.Lun = usal_lun(usalp);
+       Srb.Type.ExecSCSICmd.BufLen = sp->size;
+       Srb.Type.ExecSCSICmd.BufPointer = (void *)dos_memory_data_ptr;
+       Srb.Type.ExecSCSICmd.CDBLen = sp->cdb_len;
+       if (sp->sense_len <= (SENSE_LEN+2))
+               Srb.Type.ExecSCSICmd.SenseLen = sp->sense_len;
+       else
+               Srb.Type.ExecSCSICmd.SenseLen = (SENSE_LEN+2);
+
+       /*
+        * Enable SCSIMgrCallBack()
+        */
+       Srb.Flags |= SRB_POSTING;
+       Srb.Type.ExecSCSICmd.PostProc = (void *)(_callback_info.rm_offset|(_callback_info.rm_segment<<16));
+
+       /*
+        * Do we receive data from this ASPI command?
+        */
+       if (sp->flags & SCG_RECV_DATA) {
+
+               Srb.Flags |= SRB_DIR_IN;
+       } else {
+               /*
+                * Set direction to output
+                */
+               if (sp->size > 0) {
+                       Srb.Flags |= SRB_DIR_OUT;
+               }
+       }
+
+       SCSIMgrSendSRB(&Srb, usalp->scmd->timeout);
+       Srb.Type.ExecSCSICmd.BufPointer = sp->addr;
+       _dosmemgetb(dos_memory_data_seg<<4, sp->size, sp->addr);
+       __dpmi_free_dos_memory(dos_memory_data_sel);
+
+       if (Srb.Status == SS_PENDING) { /* Check if we got a timeout*/
+               if (usalp->debug > 0) {
+                       fprintf((FILE *)usalp->errfile,
+                                       "Timeout....\n");
+               }
+                       sp->error = SCG_TIMEOUT;
+               return (1);             /* Return error             */
+       }
+
+       /*
+        * Check ASPI command status
+        */
+       if (Srb.Status != SS_COMP) {
+
+               if (usalp->debug > 0) {
+                       fprintf((FILE *)usalp->errfile,
+                               "Error in usalo_send: Srb.Status is 0x%x\n", Srb.Status);
+               }
+
+               switch (Srb.Status) {
+
+                       case SS_COMP:                   /* 0x01 SRB completed without error */
+                               sp->error = SCG_NO_ERROR;
+                               sp->ux_errno = 0;
+                               break;
+
+                       case SS_PENDING:                /* 0x00 SRB being processed         */
+                       case SS_ABORTED:                /* 0x02 SRB aborted                 */
+                       case SS_ABORT_FAIL:             /* 0x03 Unable to abort SRB         */
+                       default:
+                               sp->error = SCG_RETRYABLE;
+                               sp->ux_errno = EIO;
+                               break;
+
+                       case SS_ERR:                    /* 0x04 SRB completed with error    */
+                               /*
+                                * If the SCSI Status byte is != 0, we definitely could send
+                                * the command to the target. We signal NO transport error.
+                                */
+                               sp->error = SCG_NO_ERROR;
+                               sp->ux_errno = EIO;
+                               if (Srb.Type.ExecSCSICmd.TargStat)
+                                       break;
+
+                       case SS_INVALID_CMD:            /* 0x80 Invalid ASPI command        */
+                       case SS_INVALID_HA:             /* 0x81 Invalid host adapter number */
+                       case SS_NO_DEVICE:              /* 0x82 SCSI device not installed   */
+                               sp->error = SCG_FATAL;
+                               sp->ux_errno = EINVAL;
+                               break;
+               }
+
+               sp->sense_count = Srb.Type.ExecSCSICmd.SenseLen;
+               if (sp->sense_count > sp->sense_len)
+                       sp->sense_count = sp->sense_len;
+
+               memset(&sp->u_sense.Sense, 0x00, sizeof (sp->u_sense.Sense));
+
+               switch (sp->cdb_len) {
+
+               case 6:
+                       memcpy(&sp->u_sense.Sense, Srb.Type.ExecSCSICmd.CmdLen._6.SenseArea, sp->sense_count);
+                       break;
+               case 10:
+                       memcpy(&sp->u_sense.Sense, Srb.Type.ExecSCSICmd.CmdLen._10.SenseArea, sp->sense_count);
+                       break;
+               case 12:
+                       memcpy(&sp->u_sense.Sense, Srb.Type.ExecSCSICmd.CmdLen._12.SenseArea, sp->sense_count);
+                       break;
+               }
+               sp->u_scb.cmd_scb[0] = Srb.Type.ExecSCSICmd.TargStat;
+
+               if (usalp->debug > 0) {
+                       fprintf((FILE *)usalp->errfile,
+                               "Mapped to: error %d errno: %d\n", sp->error, sp->ux_errno);
+               }
+               return (1);
+       }
+
+       return (0);
+}
+
+static BOOL
+SCSIMgrOpen(SCSI *usalp)
+{
+       int             hSCSIMgr;
+       int             dos_memory_seg;
+       int             dos_memory_sel;
+       __dpmi_regs     _regs;
+       SRB             Srb;
+
+       if (SCSIMgrEntry) {
+               AspiLoaded++;
+               return (TRUE);
+       }
+
+       /*
+        * Open "SCSIMRG$"
+        */
+       if (!_dos_open("SCSIMGR$", 0, &hSCSIMgr)) {
+
+               /* Alloc 16 bytes DOS memory */
+               if ((dos_memory_seg = __dpmi_allocate_dos_memory(1, &dos_memory_sel)) != -1) {
+
+                       /* Look for SCSIMgr entry point */
+                       memset(&_regs, 0, sizeof (_regs));
+                       _regs.x.ax = 0x4402;
+                       _regs.x.bx = hSCSIMgr;
+                       _regs.x.cx = 0x0004;
+                       _regs.x.ds = dos_memory_seg;
+                       _regs.x.dx = 0x0000;
+                       if (!__dpmi_simulate_real_mode_interrupt(0x21,  &_regs)) {
+                               _dosmemgetb(dos_memory_seg<<4, 4, &SCSIMgrEntry);
+                       }
+
+                       /* Free DOS memory */
+                       __dpmi_free_dos_memory(dos_memory_sel);
+               }
+
+               /* Close "SCSIMRG$" */
+               _dos_close(hSCSIMgr);
+
+               /* Allocate real mode callback */
+               _callback_info.pm_offset = (unsigned long)&SCSIMgrCallBack;
+               if (_go32_dpmi_allocate_real_mode_callback_retf(&_callback_info, &_callback_regs) == -1) {
+                       fprintf((FILE *)usalp->errfile, "Cannot allocate callback address!\n");
+                       SCSIMgrEntry = 0;
+               }
+       }
+
+       /* SCSIMgr entry point founded? */
+       if (!SCSIMgrEntry) {
+               fprintf((FILE *)usalp->errfile, "Cannot open ASPI manager! Try to get one from http://bootcd.narod.ru/\n");
+               return (FALSE);
+       }
+
+       memset(&Srb, 0, sizeof (Srb));
+       Srb.Cmd = SC_HA_INQUIRY;
+
+       SCSIMgrSendSRB(&Srb, 10);
+
+       if (usalp->debug) {
+               fprintf((FILE *)usalp->errfile, "Status : %ld\n", Srb.Status);
+               fprintf((FILE *)usalp->errfile, "hacount: %d\n", Srb.Type.HAInquiry.Count);
+               fprintf((FILE *)usalp->errfile, "SCSI id: %d\n", Srb.Type.HAInquiry.SCSI_ID);
+               fprintf((FILE *)usalp->errfile, "Manager: '%.16s'\n", Srb.Type.HAInquiry.ManagerId);
+               fprintf((FILE *)usalp->errfile, "Identif: '%.16s'\n", Srb.Type.HAInquiry.Identifier);
+               usal_prbytes("Unique:", Srb.Type.HAInquiry.Unique, 16);
+       }
+
+       AspiLoaded++;
+       return (TRUE);
+}
+
+static void
+SCSIMgrClose()
+{
+       if (--AspiLoaded > 0)
+               return;
+       if (SCSIMgrEntry) {
+               _go32_dpmi_free_real_mode_callback(&_callback_info);
+               SCSIMgrEntry = 0;
+       }
+}
+
+static int
+SCSIMgrSendSRB(SRB *Srb, time_t timeout)
+{
+       int             dos_memory_srb_seg;
+       int             dos_memory_srb_sel;
+       DWORD           dos_memory_srb_ptr;
+       struct timeval  st;
+       struct timeval  cr;
+       __dpmi_regs     _regs;
+
+       /* Alloc DOS memory */
+       if ((dos_memory_srb_seg = __dpmi_allocate_dos_memory((sizeof (SRB) >> 4) + 1, &dos_memory_srb_sel)) == -1) {
+               Srb->Status = SS_NO_DEVICE; /* ??? fatal error */
+               return (Srb->Status);
+       }
+       dos_memory_srb_ptr = dos_memory_srb_seg<<16;
+
+       /* Copy SRB to DOS memory */
+       _dosmemputb((void *)Srb, sizeof (SRB), dos_memory_srb_seg<<4);
+
+       /* Reset callback flag */
+       _callback_flag = 0;
+
+       /* Call SCSIMgr */
+       memset(&_regs, 0, sizeof (_regs));
+       _regs.x.ip = SCSIMgrEntry & 0xffff;
+       _regs.x.cs = SCSIMgrEntry >> 16;
+       __dpmi_simulate_real_mode_procedure_retf_stack(&_regs, 2, &dos_memory_srb_ptr);
+
+       /* Wait 'timeout' seconds for Srb->Status != SS_PENDING */
+       gettimeofday(&st, NULL);
+       do {
+               _dosmemgetb(dos_memory_srb_seg << 4, sizeof (SRB), (void *)Srb);
+               gettimeofday(&cr, NULL);
+       } while ((Srb->Status == SS_PENDING) && (cr.tv_sec - st.tv_sec < timeout));
+
+       /* Free DOS memory */
+       __dpmi_free_dos_memory(dos_memory_srb_sel);
+
+       return (Srb->Status);
+}
+
+static void
+SCSIMgrCallBack(_go32_dpmi_registers *regs)
+{
+       _callback_flag = 1;
+}
diff --git a/libusal/scsi-hpux.c b/libusal/scsi-hpux.c
new file mode 100644 (file)
index 0000000..f7eb553
--- /dev/null
@@ -0,0 +1,363 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)scsi-hpux.c     1.31 04/01/15 Copyright 1997 J. Schilling */
+/*
+ *     Interface for the HP-UX generic SCSI implementation.
+ *
+ *     Warning: you may change this source, but if you do that
+ *     you need to change the _usal_version and _usal_auth* string below.
+ *     You may not return "schily" for an SCG_AUTHOR request anymore.
+ *     Choose your name instead of "schily" and make clear that the version
+ *     string is related to a modified source.
+ *
+ *     Copyright (c) 1997 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#undef sense
+#include <sys/scsi.h>
+
+/*
+ *     Warning: you may change this source, but if you do that
+ *     you need to change the _usal_version and _usal_auth* string below.
+ *     You may not return "schily" for an SCG_AUTHOR request anymore.
+ *     Choose your name instead of "schily" and make clear that the version
+ *     string is related to a modified source.
+ */
+static char    _usal_trans_version[] = "scsi-hpux.c-1.31";     /* The version for this transport*/
+
+#define        MAX_SCG         16      /* Max # of SCSI controllers */
+#define        MAX_TGT         16
+#define        MAX_LUN         8
+
+struct usal_local {
+       short   usalfiles[MAX_SCG][MAX_TGT][MAX_LUN];
+};
+#define        usallocal(p)    ((struct usal_local *)((p)->local))
+
+#ifdef SCSI_MAXPHYS
+#      define  MAX_DMA_HP      SCSI_MAXPHYS
+#else
+#      define  MAX_DMA_HP      (63*1024)       /* Check if this is not too big */
+#endif
+
+
+/*
+ * Return version information for the low level SCSI transport code.
+ * This has been introduced to make it easier to trace down problems
+ * in applications.
+ */
+static char *
+usalo_version(SCSI *usalp, int what)
+{
+       if (usalp != (SCSI *)0) {
+               switch (what) {
+
+               case SCG_VERSION:
+                       return (_usal_trans_version);
+               /*
+                * If you changed this source, you are not allowed to
+                * return "schily" for the SCG_AUTHOR request.
+                */
+               case SCG_AUTHOR:
+                       return (_usal_auth_cdrkit);
+               case SCG_SCCS_ID:
+                       return (__sccsid);
+               }
+       }
+       return ((char *)0);
+}
+
+static int
+usalo_help(SCSI *usalp, FILE *f)
+{
+       __usal_help(f, "SIOC", "Generic SCSI",
+               "", "bus,target,lun", "1,2,0", TRUE, FALSE);
+       return (0);
+}
+
+static int
+usalo_open(SCSI *usalp, char *device)
+{
+               int     busno   = usal_scsibus(usalp);
+               int     tgt     = usal_target(usalp);
+               int     tlun    = usal_lun(usalp);
+       register int    f;
+       register int    b;
+       register int    t;
+       register int    l;
+       register int    nopen = 0;
+       char            devname[64];
+
+       if (busno >= MAX_SCG || tgt >= MAX_TGT || tlun >= MAX_LUN) {
+               errno = EINVAL;
+               if (usalp->errstr)
+                       snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                               "Illegal value for busno, target or lun '%d,%d,%d'",
+                               busno, tgt, tlun);
+               return (-1);
+       }
+
+       if ((device != NULL && *device != '\0') || (busno == -2 && tgt == -2)) {
+               errno = EINVAL;
+               if (usalp->errstr)
+                       snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                               "Open by 'devname' not supported on this OS");
+               return (-1);
+       }
+
+       if (usalp->local == NULL) {
+               usalp->local = malloc(sizeof (struct usal_local));
+               if (usalp->local == NULL)
+                       return (0);
+
+               for (b = 0; b < MAX_SCG; b++) {
+                       for (t = 0; t < MAX_TGT; t++) {
+                               for (l = 0; l < MAX_LUN; l++)
+                                       usallocal(usalp)->usalfiles[b][t][l] = (short)-1;
+                       }
+               }
+       }
+
+       if (busno >= 0 && tgt >= 0 && tlun >= 0) {
+
+               snprintf(devname, sizeof (devname),
+                               "/dev/rscsi/c%xt%xl%x", busno, tgt, tlun);
+               f = open(devname, O_RDWR);
+               if (f < 0)
+                       return (-1);
+               usallocal(usalp)->usalfiles[busno][tgt][tlun] = f;
+               return (1);
+       } else {
+               for (b = 0; b < MAX_SCG; b++) {
+                       for (t = 0; t < MAX_TGT; t++) {
+/*                             for (l = 0; l < MAX_LUN; l++) {*/
+                               for (l = 0; l < 1; l++) {
+                                       snprintf(devname, sizeof (devname),
+                                                       "/dev/rscsi/c%xt%xl%x", b, t, l);
+/*fprintf(stderr, "name: '%s'\n", devname);*/
+                                       f = open(devname, O_RDWR);
+                                       if (f >= 0) {
+                                               usallocal(usalp)->usalfiles[b][t][l] = (short)f;
+                                               nopen++;
+                                       } else if (usalp->debug > 0) {
+                                               errmsg("open '%s'\n", devname);
+                                       }
+                               }
+                       }
+               }
+       }
+       return (nopen);
+}
+
+static int
+usalo_close(SCSI *usalp)
+{
+       register int    f;
+       register int    b;
+       register int    t;
+       register int    l;
+
+       if (usalp->local == NULL)
+               return (-1);
+
+       for (b = 0; b < MAX_SCG; b++) {
+               for (t = 0; t < MAX_TGT; t++) {
+                       for (l = 0; l < MAX_LUN; l++) {
+                               f = usallocal(usalp)->usalfiles[b][t][l];
+                               if (f >= 0)
+                                       close(f);
+                               usallocal(usalp)->usalfiles[b][t][l] = (short)-1;
+                       }
+               }
+       }
+       return (0);
+}
+
+static long
+usalo_maxdma(SCSI *usalp, long amt)
+{
+       return  (MAX_DMA_HP);
+}
+
+static void *
+usalo_getbuf(SCSI *usalp, long amt)
+{
+       if (usalp->debug > 0) {
+               fprintf((FILE *)usalp->errfile,
+                       "usalo_getbuf: %ld bytes\n", amt);
+       }
+       usalp->bufbase = valloc((size_t)(amt));
+       return (usalp->bufbase);
+}
+
+static void
+usalo_freebuf(SCSI *usalp)
+{
+       if (usalp->bufbase)
+               free(usalp->bufbase);
+       usalp->bufbase = NULL;
+}
+
+static BOOL
+usalo_havebus(SCSI *usalp, int busno)
+{
+       register int    t;
+       register int    l;
+
+       if (busno < 0 || busno >= MAX_SCG)
+               return (FALSE);
+
+       if (usalp->local == NULL)
+               return (FALSE);
+
+       for (t = 0; t < MAX_TGT; t++) {
+               for (l = 0; l < MAX_LUN; l++)
+                       if (usallocal(usalp)->usalfiles[busno][t][l] >= 0)
+                               return (TRUE);
+       }
+       return (FALSE);
+}
+
+static int
+usalo_fileno(SCSI *usalp, int busno, int tgt, int tlun)
+{
+       if (busno < 0 || busno >= MAX_SCG ||
+           tgt < 0 || tgt >= MAX_TGT ||
+           tlun < 0 || tlun >= MAX_LUN)
+               return (-1);
+
+       if (usalp->local == NULL)
+               return (-1);
+
+       return ((int)usallocal(usalp)->usalfiles[busno][tgt][tlun]);
+}
+
+static int
+usalo_initiator_id(SCSI *usalp)
+{
+       return (-1);
+}
+
+static int
+usalo_isatapi(SCSI *usalp)
+{
+       return (FALSE);
+}
+
+static int
+usalo_reset(SCSI *usalp, int what)
+{
+       if (what == SCG_RESET_NOP)
+               return (0);
+       if (what != SCG_RESET_BUS) {
+               errno = EINVAL;
+               return (-1);
+       }
+       return (ioctl(usalp->fd, SIOC_RESET_BUS, 0));
+}
+
+static int
+usalo_send(SCSI *usalp)
+{
+       struct usal_cmd *sp = usalp->scmd;
+       int             ret;
+       int             flags;
+       struct sctl_io  sctl_io;
+
+       if ((usalp->fd < 0) || (sp->cdb_len > sizeof (sctl_io.cdb))) {
+               sp->error = SCG_FATAL;
+               return (0);
+       }
+
+       fillbytes((caddr_t)&sctl_io, sizeof (sctl_io), '\0');
+
+       flags = 0;
+/*     flags = SCTL_INIT_WDTR|SCTL_INIT_SDTR;*/
+       if (sp->flags & SCG_RECV_DATA)
+               flags |= SCTL_READ;
+       if ((sp->flags & SCG_DISRE_ENA) == 0)
+               flags |= SCTL_NO_ATN;
+
+       sctl_io.flags           = flags;
+
+       movebytes(&sp->cdb, sctl_io.cdb, sp->cdb_len);
+       sctl_io.cdb_length      = sp->cdb_len;
+
+       sctl_io.data_length     = sp->size;
+       sctl_io.data            = sp->addr;
+
+       if (sp->timeout == 0)
+               sctl_io.max_msecs = 0;
+       else
+               sctl_io.max_msecs = (sp->timeout * 1000) + 500;
+
+       errno           = 0;
+       sp->error       = SCG_NO_ERROR;
+       sp->sense_count = 0;
+       sp->u_scb.cmd_scb[0] = 0;
+       sp->resid       = 0;
+
+       ret = ioctl(usalp->fd, SIOC_IO, &sctl_io);
+       if (ret < 0) {
+               sp->error = SCG_FATAL;
+               sp->ux_errno = errno;
+               return (ret);
+       }
+if (usalp->debug > 0)
+fprintf(stderr, "cdb_status: %X, size: %d xfer: %d\n", sctl_io.cdb_status, sctl_io.data_length, sctl_io.data_xfer);
+
+       if (sctl_io.cdb_status == 0 || sctl_io.cdb_status == 0x02)
+               sp->resid = sp->size - sctl_io.data_xfer;
+
+       if (sctl_io.cdb_status & SCTL_SELECT_TIMEOUT ||
+                       sctl_io.cdb_status & SCTL_INVALID_REQUEST) {
+               sp->error = SCG_FATAL;
+       } else if (sctl_io.cdb_status & SCTL_INCOMPLETE) {
+               sp->error = SCG_TIMEOUT;
+       } else if (sctl_io.cdb_status > 0xFF) {
+               errmsgno(EX_BAD, "SCSI problems: cdb_status: %X\n", sctl_io.cdb_status);
+
+       } else if ((sctl_io.cdb_status & 0xFF) != 0) {
+               sp->error = SCG_RETRYABLE;
+               sp->ux_errno = EIO;
+
+               sp->u_scb.cmd_scb[0] = sctl_io.cdb_status & 0xFF;
+
+               sp->sense_count = sctl_io.sense_xfer;
+               if (sp->sense_count > SCG_MAX_SENSE)
+                       sp->sense_count = SCG_MAX_SENSE;
+
+               if (sctl_io.sense_status != S_GOOD) {
+                       sp->sense_count = 0;
+               } else {
+                       movebytes(sctl_io.sense, sp->u_sense.cmd_sense, sp->sense_count);
+               }
+
+       }
+       return (ret);
+}
+#define        sense   u_sense.Sense
diff --git a/libusal/scsi-linux-ata.c b/libusal/scsi-linux-ata.c
new file mode 100644 (file)
index 0000000..3ec18b7
--- /dev/null
@@ -0,0 +1,1188 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)scsi-linux-ata.c        1.7 04/06/12 Copyright 2002 J. Schilling */
+/*
+ *     Interface for Linux generic SCSI implementation (sg).
+ *
+ *     This is the interface for the broken Linux SCSI generic driver.
+ *     This is a hack, that tries to emulate the functionality
+ *     of the usal driver.
+ *
+ *     Warning: you may change this source, but if you do that
+ *     you need to change the _usal_version and _usal_auth* string below.
+ *     You may not return "schily" for an SCG_AUTHOR request anymore.
+ *     Choose your name instead of "schily" and make clear that the version
+ *     string is related to a modified source.
+ *
+ *     Copyright (c) 2002 J. Schilling
+ *
+ *     Thanks to Alexander Kern <alex.kern@gmx.de> for the idea and first
+ *     code fragments for supporting the CDROM_SEND_PACKET ioctl() from
+ *     the cdrom.c kernel driver. Please note that this interface in priciple
+ *     is completely unneeded but the Linux kernel is just a cluster of
+ *     code and does not support planned orthogonal interface systems.
+ *     For this reason we need CDROM_SEND_PACKET in order to work around a
+ *     bug in the linux kernel that prevents to use PCATA drives because
+ *     the kernel panics if you try to put ide-scsi on top of the PCATA
+ *     driver.
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef USE_OLD_ATAPI
+
+#define ata_sccsid "obsolete ATAPI driver in cdrkit"
+
+static char    _usal_atrans_version[] = "scsi-linux-ata.c-1.7";        /* The version for ATAPI transport*/
+
+static char *usalo_aversion(SCSI *usalp, int what);
+static int     usalo_ahelp(SCSI *usalp, FILE *f);
+static int     usalo_aopen(SCSI *usalp, char *device);
+static int     usalo_aclose(SCSI *usalp);
+static long    usalo_amaxdma(SCSI *usalp, long amt);
+static BOOL    usalo_ahavebus(SCSI *usalp, int);
+static int     usalo_afileno(SCSI *usalp, int, int, int);
+static int     usalo_ainitiator_id(SCSI *usalp);
+static int     usalo_aisatapi(SCSI *usalp);
+static int     usalo_areset(SCSI *usalp, int what);
+static int     usalo_asend(SCSI *usalp);
+
+static usal_ops_t ata_ops = {
+       usalo_asend,
+       usalo_aversion,
+       usalo_ahelp,
+       usalo_aopen,
+       usalo_aclose,
+       usalo_amaxdma,
+       usalo_getbuf,           /* Shared with SG driver */
+       usalo_freebuf,          /* Shared with SG driver */
+       usalo_ahavebus,
+       usalo_afileno,
+       usalo_ainitiator_id,
+       usalo_aisatapi,
+       usalo_areset,
+};
+
+#define        HOST_EMPTY      0xF
+#define        HOST_SCSI       0x0
+#define        HOST_IDE        0x1
+#define        HOST_USB        0x2
+#define        HOST_IEEE1389   0x3
+#define        HOST_PARALLEL   0x4
+#define        HOST_OTHER      0xE
+
+
+#define        typlocal(p, schillybus)         usallocal(p)->bc[schillybus].typ
+#define        buslocal(p, schillybus)         usallocal(p)->bc[schillybus].bus
+#define        hostlocal(p, schillybus)        usallocal(p)->bc[schillybus].host
+
+#define        MAX_DMA_ATA (131072-1)  /* EINVAL (hart) ENOMEM (weich) bei mehr ... */
+                               /* Bei fehlerhaftem Sense Pointer kommt EFAULT */
+
+static int usalo_send(SCSI * usalp);
+static BOOL sg_amapdev(SCSI * usalp, int f, char *device, int *bus, 
+                                                         int *target, int *lun);
+static BOOL sg_amapdev_scsi(SCSI * usalp, int f, int *busp, int *tgtp,
+                                                                        int *lunp, int *chanp, int *inop);
+static int usalo_aget_first_free_shillybus(SCSI * usalp, int subsystem,
+                                                                                                               int host, int bus);
+static int usalo_amerge(char *path, char *readedlink, char *buffer, int buflen);
+
+/*
+ * uncomment this when you will get a debug file #define DEBUG
+ */
+#ifdef DEBUG
+#define        LOGFILE "scsi-linux-ata.log"
+#define        log(a)  sglog a
+
+static void    sglog(const char *fmt, ...);
+
+#include <vadefs.h>
+
+/* VARARGS1 */
+static void
+sglog(const char *fmt, ...)
+{
+       va_list args;
+       FILE    *f       = fopen(LOGFILE, "a");
+
+       if (f == NULL)
+               return;
+
+       va_start(args, fmt);
+       vfprintf(f, fmt, args);
+       va_end(args);
+       fclose(f);
+}
+#else
+#define        log(a)
+#endif /* DEBUG */
+
+static int     scan_internal(SCSI * usalp, int *fatal);
+
+/*
+ * Return version information for the low level SCSI transport code.
+ * This has been introduced to make it easier to trace down problems
+ * in applications.
+ */
+static char *
+usalo_aversion(SCSI *usalp, int what)
+{
+       if (usalp != (SCSI *)0) {
+               switch (what) {
+
+               case SCG_VERSION:
+                       return (_usal_atrans_version);
+               /*
+                * If you changed this source, you are not allowed to
+                * return "schily" for the SCG_AUTHOR request.
+                */
+               case SCG_AUTHOR:
+                       return (_usal_auth_cdrkit);
+               case SCG_SCCS_ID:
+                       return (ata_sccsid);
+               }
+       }
+       return ((char *)0);
+}
+
+static int
+usalo_ahelp(SCSI *usalp, FILE *f)
+{
+       __usal_help(f, "ATA", "ATA Packet specific SCSI transport",
+               "ATAPI:", "bus,target,lun", "ATAPI:1,2,0", TRUE, FALSE);
+       return (0);
+}
+
+static int
+usalo_aopen(SCSI *usalp, char *device)
+{
+       int     bus = usal_scsibus(usalp);
+       int     target = usal_target(usalp);
+       int     lun = usal_lun(usalp);
+
+       register int    f;
+       register int    b;
+       register int    t;
+       register int    l;
+               int     nopen = 0;
+
+       if (usalp->overbose)
+               fprintf(stderr, "Warning: Using ATA Packet interface.\n");
+       if (usalp->overbose) {
+               fprintf(stderr, "Warning: The related Linux kernel interface code seems to be unmaintained.\n");
+               fprintf(stderr, "Warning: There is absolutely NO DMA, operations thus are slow.\n");
+       }
+
+       log(("\n<<<<<<<<<<<<<<<<  LOGGING ON >>>>>>>>>>>>>>>>>\n"));
+       if (bus >= MAX_SCHILLY_HOSTS || target >= MAX_TGT || lun >= MAX_LUN) {
+               errno = EINVAL;
+               if (usalp->errstr)
+                       snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                               "Illegal value for bus, target or lun '%d,%d,%d'",
+                               bus, target, lun);
+
+               return (-1);
+       }
+
+       if (usalp->local == NULL) {
+               usalp->local = malloc(sizeof (struct usal_local));
+               if (usalp->local == NULL) {
+                       return (0);
+               }
+
+               usallocal(usalp)->usalfile = -1;
+               usallocal(usalp)->pgbus = -2;
+               usallocal(usalp)->SCSIbuf = (char *)-1;
+               usallocal(usalp)->pack_id = 5;
+               usallocal(usalp)->drvers = -1;
+               usallocal(usalp)->isold = -1;
+               usallocal(usalp)->xbufsize = 0L;
+               usallocal(usalp)->xbuf = NULL;
+
+
+               for (b = 0; b < MAX_SCHILLY_HOSTS; b++) {
+                       typlocal(usalp, b) = HOST_EMPTY;
+                       for (t = 0; t < MAX_TGT; t++) {
+                               for (l = 0; l < MAX_LUN; l++)
+                                       usallocal(usalp)->usalfiles[b][t][l] = (short) -1;
+                       }
+               }
+       }
+
+       if (device != NULL && strcmp(device, "ATAPI") == 0)
+               goto atascan;
+
+       /* if not scanning */
+       if ((device != NULL && *device != '\0') || (bus == -2 && target == -2))
+               goto openbydev;
+
+atascan:
+       if (scan_internal(usalp, &nopen)) {
+               if (usalp->errstr)
+                       printf(usalp->errstr, "INFO: scan_internal(...) failed");
+               return (-1);
+       }
+       return (nopen);
+
+openbydev:
+       if (device != NULL && strncmp(device, "ATAPI:", 6) == 0)
+               device += 6;
+       if (usalp->debug > 3) {
+               fprintf((FILE *) usalp->errfile, "INFO: do usalo_open openbydev");
+       }
+       if (device != NULL && *device != '\0') {
+               int     schilly_bus,
+                       starget,
+                       slun;
+
+               f = sg_open_excl(device, O_RDONLY | O_NONBLOCK, FALSE);
+
+               if (f < 0) {
+                       if (usalp->errstr)
+                               snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                                       "Cannot open '%s'", device);
+                       return (0);
+               }
+               if (sg_amapdev(usalp, f, device, &schilly_bus, &starget, &slun)) {
+                       usal_settarget(usalp, schilly_bus, starget, slun);
+                       return (++nopen);
+               }
+       }
+       return (nopen);
+}
+
+static int
+scan_internal(SCSI *usalp, int *nopen)
+{
+       int     i,
+               f;
+       int     schilly_bus,
+               target,
+               lun;
+       char    device[128];
+       /*
+        * try always with devfs
+        * unfortunatelly the solution with test of existing
+        * of '/dev/.devfsd' don't work, because it root.root 700
+        * and i don't like run suid root
+        */
+       BOOL    DEVFS = TRUE;
+
+       if (DEVFS) {
+               for (i = 0; ; i++) {
+                       sprintf(device, "/dev/cdroms/cdrom%i", i);
+                       if ((f = open(device, O_RDONLY | O_NONBLOCK)) < 0) {
+                               if (errno != ENOENT && errno != ENXIO && errno != ENODEV && errno != EACCES) {
+                                       if (usalp->debug > 4) {
+                                               fprintf((FILE *) usalp->errfile,
+                                               "try open(%s) return %i, errno %i, cancel\n", device, f, errno);
+                                       }
+                                       return (-2);
+                               } else if (errno == ENOENT || errno == ENODEV) {
+                                       if (usalp->debug > 4) {
+                                               fprintf((FILE *) usalp->errfile,
+                                               "try open(%s) return %i, errno %i\n", device, f, errno);
+                                       }
+                                       if (0 == i) {
+                                               DEVFS = FALSE;
+                                               if (usalp->debug > 4) {
+                                                       fprintf((FILE *) usalp->errfile,
+                                                       "DEVFS not detected, continuing with old dev\n");
+                                               }
+                                       }
+                                       break;
+                               }
+                               if (usalp->debug > 4) {
+                                       if (errno == EACCES) {
+                                               fprintf((FILE *) usalp->errfile,
+                                               "errno (EACCESS), you don't have the needed rights for %s\n",
+                                               device);
+                                       }
+                                       fprintf((FILE *) usalp->errfile,
+                                       "try open(%s) return %i, errno %i, trying next cdrom\n",
+                                       device, f, errno);
+                               }
+                       } else {
+                               if (usalp->debug > 4) {
+                                       fprintf((FILE *) usalp->errfile,
+                                       "try open(%s) return %i errno %i calling sg_mapdev(...)\n",
+                                       device, f, errno);
+                               }
+                               if (sg_amapdev(usalp, f, device, &schilly_bus, &target, &lun)) {
+                                       (++(*nopen));
+                               } else {
+                                       close(f);
+                               }
+                       }
+               }
+       }
+       if (!DEVFS) {
+               /* for /dev/sr0 - /dev/sr? */
+               for (i = 0; i<16 ; i++) {
+                       sprintf(device, "/dev/sr%i", i);
+                       if ((f = open(device, O_RDONLY | O_NONBLOCK)) < 0) {
+                               if (errno != ENOENT && errno != ENXIO && errno != ENODEV && errno != EACCES) {
+                                       if (usalp->debug > 4) {
+                                               fprintf((FILE *) usalp->errfile,
+                                               "try open(%s) return %i, errno %i, cancel\n",
+                                               device, f, errno);
+                                       }
+                                       return (-2);
+        }
+                       } else {
+                               if (sg_amapdev(usalp, f, device, &schilly_bus, &target, &lun)) {
+                                       (++(*nopen));
+                               } else {
+                                       close(f);
+                               }
+                       }
+               }
+
+               /* for /dev/hda - /dev/hdz */
+               for (i = 'a'; i <= 'z'; i++) {
+                       sprintf(device, "/dev/hd%c", i);
+                       if ((f = open(device, O_RDONLY | O_NONBLOCK)) < 0) {
+                               if (errno != ENOENT && errno != ENXIO && errno != EACCES) {
+                                       if (usalp->debug > 4) {
+                                               fprintf((FILE *) usalp->errfile,
+                                               "try open(%s) return %i, errno %i, cancel\n",
+                                               device, f, errno);
+                                       }
+                                       return (-2);
+        }
+                       } else {
+                               /* ugly hack, make better, when you can. Alex */
+                               if (0 > ioctl(f, CDROM_DRIVE_STATUS, CDSL_CURRENT)) {
+                                       if (usalp->debug > 4) {
+                                               fprintf((FILE *) usalp->errfile,
+                                               "%s is not a cdrom, skipping\n",
+                                               device);
+                                       }
+                                       close(f);
+                               } else if (sg_amapdev(usalp, f, device, &schilly_bus, &target, &lun)) {
+                                       (++(*nopen));
+                               } else {
+                                       close(f);
+                               }
+                       }
+               }
+       }
+       return (0);
+}
+
+static int
+usalo_aclose(SCSI *usalp)
+{
+       register int    f;
+       register int    h;
+       register int    t;
+       register int    l;
+
+       if (usalp->local == NULL)
+               return (-1);
+
+       for (h = 0; h < MAX_SCHILLY_HOSTS; h++) {
+               typlocal(usalp, h) = (HOST_EMPTY);
+               for (t = 0; t < MAX_TGT; t++) {
+                       for (l = 0; l < MAX_LUN; l++) {
+                               f = usallocal(usalp)->usalfiles[h][t][l];
+                               if (f >= 0)
+                                       close(f);
+                               usallocal(usalp)->usalfiles[h][t][l] = (short) -1;
+                       }
+               }
+       }
+
+       if (usallocal(usalp)->xbuf != NULL) {
+               free(usallocal(usalp)->xbuf);
+               usallocal(usalp)->xbufsize = 0L;
+               usallocal(usalp)->xbuf = NULL;
+       }
+       log(("<<<<<<<<<<<<<<<<  LOGGING OFF >>>>>>>>>>>>>>>>>\n\n"));
+       return (0);
+}
+
+static int
+usalo_aget_first_free_shillybus(SCSI *usalp, int subsystem, int host, int bus)
+{
+       int     first_free_schilly_bus;
+
+       for (first_free_schilly_bus = 0;
+                       first_free_schilly_bus < MAX_SCHILLY_HOSTS;
+                                               first_free_schilly_bus++) {
+
+               if (typlocal(usalp, first_free_schilly_bus) == HOST_EMPTY ||
+                   (typlocal(usalp, first_free_schilly_bus) == subsystem &&
+                   hostlocal(usalp, first_free_schilly_bus) == host &&
+                   buslocal(usalp, first_free_schilly_bus) == bus))
+                       break;
+       }
+
+       if (first_free_schilly_bus >= MAX_SCHILLY_HOSTS) {
+               errmsgno(EX_BAD, "ERROR: in usalo_get_first_free_shillybus(...). Too many CDROMs, more than %i",
+                       MAX_SCHILLY_HOSTS);
+               errmsgno(EX_BAD, "Increase MAX_SCHILLY_HOSTS in scsi-linux-ata.c and recompile!");
+               return (-1);
+       }
+       return (first_free_schilly_bus);
+}
+
+static int
+usalo_amerge(char *path, char *readedlink, char *buffer, int buflen)
+{
+       char    *aa;
+
+#define        TOKEN_ARRAY             20
+#define        LAST_CHAR(x)            (x)[strlen((x))-1]
+#define        ONE_CHAR_BACK(x)        (x)[strlen((x))-1] = '\0'
+       char    *ppa[TOKEN_ARRAY];
+       char    *pa;
+
+       int     i;
+       int     len;
+       char    seps[] = "/";
+       char    *last_slash;
+
+       if (!path || !readedlink || !buffer)
+               return (-EINVAL);
+
+       if ('/' == readedlink[0]) {
+               aa = (char *) malloc(strlen(readedlink) + 1);
+               if (!aa)
+                       return (-ENOMEM);
+
+               strcpy(aa, readedlink);
+       } else {
+               aa = (char *) malloc(strlen(path) + strlen(readedlink) + 1);
+               if (!aa)
+                       return (-ENOMEM);
+
+               strcpy(aa, path);
+               if (LAST_CHAR(aa) == '/') {
+                       ONE_CHAR_BACK(aa);
+               }
+               last_slash = strrchr(aa, '/');
+               if (last_slash == NULL)
+                       strcpy(aa, "/");
+               else
+                       *(++last_slash) = '\0';
+               strcat(aa, readedlink);
+       }
+       memset(ppa, 0x00, sizeof (ppa));
+
+       for (i = 0, pa = strtok(aa, seps);
+               i < TOKEN_ARRAY && pa != NULL;
+               ++i, pa = strtok(NULL, seps)) {
+               ppa[i] = pa;
+       }
+
+       if (i == TOKEN_ARRAY) {
+               free(aa);
+               return (-ENOMEM);
+       }
+       for (i = 0; i < TOKEN_ARRAY && ppa[i]; i++) {
+               if (strcmp(ppa[i], "..") == 0) {
+                       ppa[i] = NULL;
+                       if (i > 1)
+                               ppa[i - 1] = NULL;
+               }
+       }
+
+       /* dry run */
+       len = 0;
+       for (i = 0; i < TOKEN_ARRAY; i++) {
+               if (ppa[i]) {
+                       len += 1;
+                       len += strlen(ppa[i]);
+               }
+       }
+       if (0 == len)
+               len = 1;
+
+       if (len + 1 <= buflen) {
+               strcpy(buffer, "");
+               for (i = 0; i < TOKEN_ARRAY; i++) {
+                       if (ppa[i]) {
+                               strcat(buffer, "/");
+                               strcat(buffer, ppa[i]);
+                       }
+               }
+
+               if (strlen(buffer) == 0)
+                       strcpy(buffer, "/");
+       }
+       free(aa);
+
+       return (len + 1);
+}
+
+/*
+ *     /dev/cdroms/cdrom0      first CD-ROM
+ *     /dev/cdroms/cdrom1      second CD-ROM
+ *
+ *
+ *     SCSI Devices
+ *
+ *     To uniquely identify any SCSI device requires the following information:
+ *
+ *     controller      (host adapter)
+ *     bus             (SCSI channel)
+ *     target          (SCSI ID)
+ *     unit            (Logical Unit Number)
+ *
+ *     All SCSI devices are placed under /dev/scsi (assuming devfs is mounted on /dev).
+ *     Hence, a SCSI device with the following parameters:
+ *             c=1,b=2,t=3,u=4 would appear as:
+ *
+ *             /dev/scsi/host1/bus2/target3/lun4       device directory
+ *
+ *     Inside this directory, a number of device entries may be created,
+ *     depending on which SCSI device-type drivers were installed.
+ *
+ *     See the section on the disc naming scheme to see what entries
+ *     the SCSI disc driver creates.
+ *
+ *     See the section on the tape naming scheme to see what entries
+ *     the SCSI tape driver creates.
+ *
+ *     The SCSI CD-ROM driver creates:  cd
+ *     The SCSI generic driver creates: generic
+ *
+ *     IDE Devices
+ *
+ *     To uniquely identify any IDE device requires the following information:
+ *
+ *     controller
+ *     bus             (0/1 aka. primary/secondary)
+ *     target          (0/1 aka. master/slave)
+ *     unit
+ *
+ *     All IDE devices are placed under /dev/ide, and uses a similar
+ *     naming scheme to the SCSI subsystem.
+ *
+ *
+ *     Example /dev/cdroms/cdrom0 ->  /dev/scsi/host1/bus2/target3/lun4/cd
+ *     Example /dev/cdroms/cdrom1 ->  /dev/ide/host1/bus0/target1/lun4/cd
+ *
+ */
+static BOOL
+sg_amapdev(SCSI *usalp, int f, char *device, int *schillybus, int *target, 
+                         int *lun)
+{
+       struct host {
+               char    host[4];
+               char    host_no;
+       };
+       struct bus {
+               char    bus[3];
+               char    bus_no;
+       };
+       struct target {
+               char    target[6];
+               char    target_no;
+       };
+       struct lun {
+               char    lun[3];
+               char    lun_no;
+       };
+
+       int     h,
+               b,
+               t,
+               l;
+
+#define        TOKEN_DEV               "dev"
+#define        TOKEN_SUBSYSTEM_SCSI    "scsi"
+#define        TOKEN_SUBSYSTEM_IDE     "ide"
+#define        TOKEN_HOST              "host"
+#define        TOKEN_BUS               "bus"
+#define        TOKEN_TARGET            "target"
+#define        TOKEN_LUN               "lun"
+#define        TOKEN_CD                "cd"
+
+#define        ID_TOKEN_DEV            0
+#define        ID_TOKEN_SUBSYSTEM      1
+#define        ID_TOKEN_HOST           2
+#define        ID_TOKEN_BUS            3
+#define        ID_TOKEN_TARGET         4
+#define        ID_TOKEN_LUN            5
+#define        ID_TOKEN_CD             6
+#define        ID_TOKEN_LAST           ID_TOKEN_CD
+#define        ID_TOKEN_MAX            ID_TOKEN_LAST + 2
+#define        CHARTOINT(x)            (abs(atoi(&x)))
+
+       char            *token[ID_TOKEN_MAX],
+                       *seps = "/";
+       int             i,
+                       result;
+       struct stat     buf;
+
+#ifndef MAX_PATH
+#define        MAX_PATH 260
+#endif
+#define        LOCAL_MAX_PATH MAX_PATH
+       char            tmp[LOCAL_MAX_PATH],
+                       tmp1[LOCAL_MAX_PATH];
+       int             first_free_schilly_bus;
+       int             subsystem = HOST_EMPTY;
+
+       /* old DEV */
+       typedef struct {
+               char            prefix[2];
+               char            device;
+       } old_dev;
+       /* strtok need char* instead of const char* */
+       result = stat(device, &buf);
+       if (result || !S_ISBLK(buf.st_mode))
+               return (FALSE);
+
+       result = lstat(device, &buf);
+       if (!result && S_ISLNK(buf.st_mode)) {
+               result = readlink(device, tmp, LOCAL_MAX_PATH);
+               if (result > 0 && result < LOCAL_MAX_PATH) {
+                       tmp[result] = '\0';
+
+                       result = usalo_amerge(device, tmp, tmp1, LOCAL_MAX_PATH);
+                       if (result > 0 && result < LOCAL_MAX_PATH) {
+                               tmp1[result] = '\0';
+                               strcpy(tmp, tmp1);
+                       } else {
+                               errmsgno(EX_BAD,
+                               "ERROR: with link merging! base %s link %s, result of merging %i\n",
+                                       device, tmp, result);
+                               return (FALSE);
+                       }
+               } else {
+                       errmsgno(EX_BAD,
+                       "ERROR: with link reading! link %s, result of readlink %i\n",
+                               device, result);
+                       return (FALSE);
+               }
+       } else {
+               strncpy(tmp, device, sizeof (tmp));
+       }
+       if (usalp->debug > 3) {
+               fprintf((FILE *) usalp->errfile, "INFO: %s -> %s\n", device, tmp);
+       }
+       memset(token, 0x00, sizeof (token));
+       i = 0;
+       token[i] = strtok(tmp, seps);
+       while (token[i] != NULL && (++i) && i < ID_TOKEN_MAX) {
+               token[i] = strtok(NULL, seps);
+       }
+
+       if (i == ID_TOKEN_MAX ||
+               !(token[ID_TOKEN_DEV]) ||
+               strcmp(token[ID_TOKEN_DEV], TOKEN_DEV)) {
+
+               errmsgno(EX_BAD, "ERROR: unknown format\n");
+               errmsgno(EX_BAD, "EXAMPLE: /dev/scsi/host1/bus2/target3/lun4/cd\n");
+               errmsgno(EX_BAD, "EXAMPLE: /dev/ide/host0/bus0/target1/lun0/cd\n");
+               errmsgno(EX_BAD, "EXAMPLE: /dev/hda or /dev/sr0\n");
+               return (FALSE);
+       }
+       if (!(strcmp(token[ID_TOKEN_SUBSYSTEM], TOKEN_SUBSYSTEM_SCSI)) ||
+           !(strcmp(token[ID_TOKEN_SUBSYSTEM], TOKEN_SUBSYSTEM_IDE))) {
+               h = CHARTOINT(((struct host *) token[ID_TOKEN_HOST])->host_no);
+               b = CHARTOINT(((struct bus *) token[ID_TOKEN_BUS])->bus_no);
+               t = CHARTOINT(((struct target *) token[ID_TOKEN_TARGET])->target_no);
+               l = CHARTOINT(((struct lun *) token[ID_TOKEN_LUN])->lun_no);
+#ifdef PARANOID
+               if (strncmp(token[ID_TOKEN_HOST], TOKEN_HOST, strlen(TOKEN_HOST))) {
+                       log(("ERROR: invalid host specified\n"));
+                       return (FALSE);
+               }
+               if (strncmp(token[ID_TOKEN_BUS], TOKEN_BUS, strlen(TOKEN_BUS))) {
+                       log(("ERROR: invalid bus specified\n"));
+                       return (FALSE);
+               }
+               if (strncmp(token[ID_TOKEN_TARGET], TOKEN_TARGET, strlen(TOKEN_TARGET))) {
+                       log(("ERROR: invalid target specified\n"));
+                       return (FALSE);
+               }
+               if (strncmp(token[ID_TOKEN_LUN], TOKEN_LUN, strlen(TOKEN_LUN))) {
+                       log(("ERROR: invalid lun specified\n"));
+                       return (FALSE);
+               }
+               if (!(strcmp(token[ID_TOKEN_SUBSYSTEM], TOKEN_SUBSYSTEM_IDE))) {
+                       if (b > 1 || t > 1) {
+                               log(("ERROR: invalid bus or target for IDE specified\n"));
+                               return (FALSE);
+                       }
+               }
+#endif /* PARANOID */
+
+               if (!(strcmp(token[ID_TOKEN_SUBSYSTEM], TOKEN_SUBSYSTEM_IDE))) {
+                       subsystem = HOST_IDE;
+               } else if (!(strcmp(token[ID_TOKEN_SUBSYSTEM], TOKEN_SUBSYSTEM_SCSI))) {
+                       subsystem = HOST_SCSI;
+               } else {
+                       subsystem = HOST_OTHER;
+               }
+       } else if (!token[ID_TOKEN_HOST] &&
+               strlen(token[ID_TOKEN_SUBSYSTEM]) == sizeof (old_dev)) {
+               char    j;
+
+               old_dev *pDev = (old_dev *) token[ID_TOKEN_SUBSYSTEM];
+
+               if (strncmp(pDev->prefix, "hd", 2) == 0) {
+                       j = pDev->device - ('a');
+
+                       subsystem = HOST_IDE;
+                       h = j / 4;
+                       b = (j % 4) / 2;
+                       t = (j % 4) % 2;
+                       l = 0;
+               } else if (strncmp(pDev->prefix, "sr", 2) == 0) {
+#ifdef nonono
+                       if (pDev->device >= '0' && pDev->device <= '9')
+                               j = pDev->device - ('0');
+                       else
+                               j = pDev->device - ('a');
+
+
+                       h = j / 4;
+                       b = (j % 4) / 2;
+                       t = (j % 4) % 2;
+                       l = 0;
+#endif /* nonono */
+                       /* other solution, with ioctl */
+                       int     Chan = 0,
+                               Ino = 0,
+                               Bus = 0,
+                               Target = 0,
+                               Lun = 0;
+
+                       subsystem = HOST_SCSI;
+                       sg_amapdev_scsi(usalp, f, &Bus, &Target, &Lun, &Chan, &Ino);
+
+                       /* For old kernels try to make the best guess. */
+#ifdef nonono
+                               int     n;
+                               Ino |= Chan << 8;
+                               n = sg_mapbus(usalp, Bus, Ino);
+                               if (Bus == -1) {
+                                       Bus = n;
+                                       if (usalp->debug > 0) {
+                                               fprintf((FILE *)usalp->errfile,
+                                                       "SCSI Bus: %d (mapped from %d)\n",
+                                                       Bus, Ino);
+                                       }
+                               }
+/*                             It is me too high ;-()*/
+#endif /* nonono */
+                       h = Ino;
+                       b = Chan;
+                       t = Target;
+                       l = Lun;
+               } else {
+                       errmsgno(EX_BAD, "ERROR: unknow subsystem (%s) in (%s)\n",
+                               token[ID_TOKEN_SUBSYSTEM], device);
+                       return (FALSE);
+               }
+       } else {
+               errmsgno(EX_BAD, "ERROR: unknow subsystem (%s) in (%s)\n",
+                       token[ID_TOKEN_SUBSYSTEM], device);
+               return (FALSE);
+       }
+
+       if (usalp->verbose)
+               printf(usalp->errstr, "INFO: subsystem %s: h %i, b %i, t %i, l %i",
+                       token[ID_TOKEN_SUBSYSTEM], h, b, t, l);
+
+       first_free_schilly_bus = usalo_aget_first_free_shillybus(usalp, subsystem, h, b);
+       if (-1 == first_free_schilly_bus) {
+               return (FALSE);
+       }
+       if (usallocal(usalp)->usalfiles[first_free_schilly_bus][t][l] != (-1)) {
+               errmsgno(EX_BAD, "ERROR: this cdrom is already mapped %s(%d,%d,%d)\n",
+                       device, first_free_schilly_bus, t, l);
+               return (FALSE);
+       } else {
+               usallocal(usalp)->usalfiles[first_free_schilly_bus][t][l] = f;
+               typlocal(usalp, first_free_schilly_bus) = subsystem;
+               hostlocal(usalp, first_free_schilly_bus) = h;
+               buslocal(usalp, first_free_schilly_bus) = b;
+               *schillybus = first_free_schilly_bus;
+               *target = t;
+               *lun = l;
+
+               if (usalp->debug > 1) {
+                       fprintf((FILE *) usalp->errfile,
+                               "INFO: /dev/%s, (host%d/bus%d/target%d/lun%d) will be mapped on the schilly bus No %d (%d,%d,%d)\n",
+                               token[ID_TOKEN_SUBSYSTEM], h, b, t, l,
+                               first_free_schilly_bus, first_free_schilly_bus, t, l);
+               }
+       }
+       return (TRUE);
+}
+
+static BOOL
+sg_amapdev_scsi(SCSI *usalp, int f, int *busp, int *tgtp, int *lunp, 
+                                        int *chanp, int *inop)
+{
+       struct sg_id {
+               long    l1;     /* target | lun << 8 | channel << 16 | low_ino << 24 */
+               long    l2;     /* Unique id */
+       } sg_id;
+       int     Chan;
+       int     Ino;
+       int     Bus;
+       int     Target;
+       int     Lun;
+
+       if (ioctl(f, SCSI_IOCTL_GET_IDLUN, &sg_id))
+               return (FALSE);
+
+       if (usalp->debug > 0) {
+               fprintf((FILE *) usalp->errfile,
+                       "INFO: l1: 0x%lX l2: 0x%lX\n", sg_id.l1, sg_id.l2);
+       }
+       if (ioctl(f, SCSI_IOCTL_GET_BUS_NUMBER, &Bus) < 0) {
+               Bus = -1;
+       }
+       Target = sg_id.l1 & 0xFF;
+       Lun = (sg_id.l1 >> 8) & 0xFF;
+       Chan = (sg_id.l1 >> 16) & 0xFF;
+       Ino = (sg_id.l1 >> 24) & 0xFF;
+       if (usalp->debug > 0) {
+               fprintf((FILE *) usalp->errfile,
+                       "INFO: Bus: %d Target: %d Lun: %d Chan: %d Ino: %d\n",
+                       Bus, Target, Lun, Chan, Ino);
+       }
+       *busp = Bus;
+       *tgtp = Target;
+       *lunp = Lun;
+       if (chanp)
+               *chanp = Chan;
+       if (inop)
+               *inop = Ino;
+       return (TRUE);
+}
+
+static long
+usalo_amaxdma(SCSI *usalp, long amt)
+{
+       /*
+        * EINVAL (hart) ENOMEM (weich) bei mehr ...
+        * Bei fehlerhaftem Sense Pointer kommt EFAULT
+        */
+       return (MAX_DMA_ATA);
+}
+
+static BOOL
+usalo_ahavebus(SCSI *usalp, int busno)
+{
+       register int    t;
+       register int    l;
+
+       if (busno < 0 || busno >= MAX_SCHILLY_HOSTS)
+               return (FALSE);
+
+       if (usalp->local == NULL)
+               return (FALSE);
+
+       for (t = 0; t < MAX_TGT; t++) {
+               for (l = 0; l < MAX_LUN; l++)
+                       if (usallocal(usalp)->usalfiles[busno][t][l] >= 0)
+                               return (TRUE);
+       }
+       return (FALSE);
+}
+
+static int
+usalo_afileno(SCSI *usalp, int busno, int tgt, int tlun)
+{
+       if (busno < 0 || busno >= MAX_SCHILLY_HOSTS ||
+               tgt < 0 || tgt >= MAX_TGT ||
+               tlun < 0 || tlun >= MAX_LUN)
+               return (-1);
+
+       if (usalp->local == NULL)
+               return (-1);
+
+       return ((int) usallocal(usalp)->usalfiles[busno][tgt][tlun]);
+}
+
+static int
+usalo_ainitiator_id(SCSI *usalp)
+{
+       printf(usalp->errstr, "NOT IMPELEMENTED: usalo_initiator_id");
+       return (-1);
+}
+
+static int
+usalo_aisatapi(SCSI *usalp)
+{
+       int schillybus = usalp->addr.scsibus;
+       int typ = typlocal(usalp, schillybus);
+       if (typ == HOST_EMPTY)
+               return (-1);
+       if (typ != HOST_SCSI)
+               return (1);
+       else
+               return (0);
+}
+
+static int
+usalo_areset(SCSI *usalp, int what)
+{
+       if (what == SCG_RESET_NOP)
+               return (0);
+
+       if (what == SCG_RESET_TGT || what == SCG_RESET_BUS)
+               return (ioctl(what, CDROMRESET));
+
+       return (-1);
+}
+
+static int
+usalo_asend(SCSI *usalp)
+{
+       struct usal_cmd *sp = usalp->scmd;
+       int             ret,
+                       i;
+       struct cdrom_generic_command sg_cgc;
+       struct request_sense sense_cgc;
+
+#ifdef DEBUG
+       char            tmp_send[340],
+                       tmp_read[340],
+                       tmp_sense[340],
+                       tmp1[30];
+       int             j;
+       char            *p;
+#endif
+
+       if (usalp->fd < 0) {
+               sp->error = SCG_FATAL;
+               sp->ux_errno = EIO;
+               return (0);
+       }
+       if (sp->cdb_len > CDROM_PACKET_SIZE) {
+               sp->error = SCG_FATAL;
+               sp->ux_errno = EIO;
+               return (0);
+       }
+       /* initialize */
+       fillbytes((caddr_t) & sg_cgc, sizeof (sg_cgc), '\0');
+       fillbytes((caddr_t) & sense_cgc, sizeof (sense_cgc), '\0');
+
+       if (sp->flags & SCG_RECV_DATA) {
+               sg_cgc.data_direction = CGC_DATA_READ;
+       } else if (sp->size > 0) {
+               sg_cgc.data_direction = CGC_DATA_WRITE;
+       } else {
+               sg_cgc.data_direction = CGC_DATA_NONE;
+       }
+#if LINUX_VERSION_CODE >= 0x020403
+       if (sp->flags & SCG_SILENT) {
+               sg_cgc.quiet = 1;
+       }
+#endif
+       for (i = 0; i < sp->cdb_len; i++) {
+               sg_cgc.cmd[i] = sp->cdb.cmd_cdb[i];
+       }
+
+       sg_cgc.buflen = sp->size;
+       sg_cgc.buffer = (unsigned char *)sp->addr;
+
+       if (sp->sense_len > sizeof (sense_cgc))
+               sense_cgc.add_sense_len = sizeof (sense_cgc) - 8;
+       else
+               sense_cgc.add_sense_len = sp->sense_len - 8;
+
+       sg_cgc.sense = &sense_cgc;
+#if LINUX_VERSION_CODE >= 0x020403
+       sg_cgc.timeout = sp->timeout * 1000;
+#endif
+#ifdef DEBUG
+       strcpy(tmp_send, "send cmd:\n");
+       for (j = 0; j < sp->cdb_len; j++) {
+               sprintf(tmp1, " %02X", sp->cdb.cmd_cdb[j]);
+               strcat(tmp_send, tmp1);
+       }
+       strcat(tmp_send, "\n");
+
+       if (sg_cgc.data_direction == CGC_DATA_WRITE) {
+               int     z;
+
+               sprintf(tmp1, "data_write: %i bytes\n", sp->size);
+               strcat(tmp_send, tmp1);
+               for (j = 0, z = 1; j < 80 && j < sp->size; j++, z++) {
+                       if (z > 16) {
+                               z = 1;
+                               strcat(tmp_send, "\n");
+                       }
+                       sprintf(tmp1, " %02X", (unsigned char) (sp->addr[j]));
+                       strcat(tmp_send, tmp1);
+               }
+               strcat(tmp_send, "\n");
+
+               if (sp->size > 80) {
+                       strcat(tmp_send, "...\n");
+               }
+       }
+#endif /* DEBUG */
+       if ((ret = ioctl(usalp->fd, CDROM_SEND_PACKET, &sg_cgc)) < 0)
+               sp->ux_errno = geterrno();
+
+       if (ret < 0 && usalp->debug > 4) {
+               fprintf((FILE *) usalp->errfile,
+                       "ioctl(CDROM_SEND_PACKET) ret: %d\n", ret);
+       }
+       /*
+        * copy scsi data back
+        */
+       if (sp->flags & SCG_RECV_DATA && ((void *) sp->addr != (void *) sg_cgc.buffer)) {
+               memcpy(sp->addr, sg_cgc.buffer, (sp->size < sg_cgc.buflen) ? sp->size : sg_cgc.buflen);
+               if (sg_cgc.buflen > sp->size)
+                       sp->resid = sg_cgc.buflen - sp->size;
+       }
+       sp->error = SCG_NO_ERROR;
+#ifdef DEBUG
+       if (ret < 0) {
+               switch (sp->ux_errno) {
+               case ENOTTY:
+                       p = "ENOTTY";
+                       break;
+               case EINVAL:
+                       p = "EINVAL";
+                       break;
+               case ENXIO:
+                       p = "ENXIO";
+                       break;
+               case EACCES:
+                       p = "EACCES";
+                       break;
+               case EIO:
+                       p = "EIO";
+                       break;
+               case ENOMEDIUM:
+                       p = "ENOMEDIUM";
+                       break;
+               case EDRIVE_CANT_DO_THIS:
+                       p = "EDRIVE_CANT_DO_THIS";
+                       break;
+               default:
+                       p = "UNKNOW";
+               };
+               log(("%s", tmp_send));
+               log(("ERROR: returns %i errno %i(%s)\n", ret, sp->ux_errno, p));
+       }
+#endif /* DEBUG */
+       if (ret < 0) {
+               /*
+                * Check if SCSI command cound not be send at all.
+                * Linux usually returns EINVAL for an unknoen ioctl.
+                * In case somebody from the Linux kernel team learns that the
+                * corect errno would be ENOTTY, we check for this errno too.
+                */
+               if (sp->ux_errno == EINVAL) {
+                       /*
+                        * Try to work around broken Linux kernel design...
+                        * If SCSI Sense Key is 0x05 (Illegal request), Linux
+                        * returns a useless EINVAL making it close to
+                        * impossible distinct from "Illegal ioctl()" or
+                        * "Invalid parameter".
+                        */
+                       if ((((Uchar *)sg_cgc.sense)[0] != 0) ||
+                           (((Uchar *)sg_cgc.sense)[2] != 0))
+                               sp->ux_errno = EIO;
+
+               } else if ((sp->ux_errno == ENOTTY || sp->ux_errno == EINVAL)) {
+                       /*
+                        * May be "Illegal ioctl()".
+                        */
+                       return (-1);
+               }
+               if (sp->ux_errno == ENXIO || sp->ux_errno == EACCES) {
+                       return (-1);
+               }
+       } else if (ret == 0) {
+#ifdef DEBUG
+               if (sg_cgc.data_direction == CGC_DATA_READ) {
+                       int     z;
+
+                       sprintf(tmp_read, "data_read: %i bytes\n", sp->size);
+                       for (j = 0, z = 1; j < 80 && j < sp->size; j++, z++) {
+                               if (z > 16) {
+                                       z = 1;
+                                       strcat(tmp_read, "\n");
+                               }
+                               sprintf(tmp1, " %02X", (unsigned char) (sp->addr[j]));
+                               strcat(tmp_read, tmp1);
+                       }
+                       strcat(tmp_read, "\n");
+                       if (sp->size > 80) {
+                               strcat(tmp_read, "...\n");
+                       }
+               }
+#endif /* DEBUG */
+       }
+       /*
+        * copy sense back
+        */
+       if (ret < 0 && sg_cgc.sense->error_code) {
+               sp->sense_count = sense_cgc.add_sense_len + 8;
+#ifdef DEBUG
+               sprintf(tmp_sense, "sense_data: length %i\n", sp->sense_count);
+               for (j = 0; j < sp->sense_count; j++) {
+                       sprintf(tmp1, " %02X", (((unsigned char *) (&sense_cgc))[j]));
+                       strcat(tmp_sense, tmp1);
+               }
+               log(("%s\n", tmp_sense));
+
+               sprintf(tmp_sense, "sense_data: error code 0x%02X, sense key 0x%02X,"
+                       " additional length %i, ASC 0x%02X, ASCQ 0x%02X\n",
+                       sg_cgc.sense->error_code, sg_cgc.sense->sense_key,
+                       sg_cgc.sense->add_sense_len, sg_cgc.sense->asc,
+                       sg_cgc.sense->ascq);
+
+               log(("%s\n", tmp_sense));
+#endif /* DEBUG */
+               memcpy(sp->u_sense.cmd_sense, /* (caddr_t) */ &sense_cgc, SCG_MAX_SENSE);
+               sp->u_scb.cmd_scb[0] = ST_CHK_COND;
+
+               switch (sg_cgc.sense->sense_key) {
+               case SC_UNIT_ATTENTION:
+               case SC_NOT_READY:
+                       sp->error = SCG_RETRYABLE;      /* may be BUS_BUSY */
+                       sp->u_scb.cmd_scb[0] |= ST_BUSY;
+                       break;
+               case SC_ILLEGAL_REQUEST:
+                       break;
+               default:
+                       break;
+               }
+       } else {
+               sp->u_scb.cmd_scb[0] = 0x00;
+       }
+
+       sp->resid = 0;
+       return (0);
+}
+#endif /* USE_OLD_ATAPI */
diff --git a/libusal/scsi-linux-pg.c b/libusal/scsi-linux-pg.c
new file mode 100644 (file)
index 0000000..00edf5d
--- /dev/null
@@ -0,0 +1,587 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)scsi-linux-pg.c 1.43 04/01/15 Copyright 1997 J. Schilling */
+/*
+ *     Interface for the Linux PARIDE implementation.
+ *
+ *     We emulate the functionality of the usal driver, via the pg driver.
+ *
+ *     Warning: you may change this source, but if you do that
+ *     you need to change the _usal_version and _usal_auth* string below.
+ *     You may not return "schily" for an SCG_AUTHOR request anymore.
+ *     Choose your name instead of "schily" and make clear that the version
+ *     string is related to a modified source.
+ *
+ *     Copyright (c) 1997  J. Schilling
+ *     Copyright (c) 1998  Grant R. Guenther   <grant@torque.net>
+ *                         Under the terms of the GNU public license.
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <string.h>
+#ifdef HAVE_LINUX_PG_H
+#include <linux/pg.h>
+#else
+#include "pg.h"                /* Use local version as Linux sometimes doesn't have */
+#endif                 /* installed. Now libusal always supports PP SCSI    */
+
+/*
+ *     Warning: you may change this source, but if you do that
+ *     you need to change the _usal_version and _usal_auth* string below.
+ *     You may not return "schily" for an SCG_AUTHOR request anymore.
+ *     Choose your name instead of "schily" and make clear that the version
+ *     string is related to a modified source.
+ */
+static char    _usal_trans_version_pg[] = "scsi-linux-pg.c-1.43";      /* The version for this transport*/
+
+#ifdef USE_PG_ONLY
+
+#define        MAX_SCG         1       /* Max # of SCSI controllers */
+#define        MAX_TGT         8
+#define        MAX_LUN         8
+
+struct usal_local {
+       short   usalfiles[MAX_SCG][MAX_TGT][MAX_LUN];
+       short   buscookies[MAX_SCG];
+       int     pgbus;
+       char    *SCSIbuf;
+};
+#define        usallocal(p)    ((struct usal_local *)((p)->local))
+
+#else
+
+#define        usalo_version   pg_version
+#define        usalo_help      pg_help
+#define        usalo_open      pg_open
+#define        usalo_close     pg_close
+#define        usalo_send      pg_send
+#define        usalo_maxdma    pg_maxdma
+#define        usalo_initiator_id pg_initiator_id
+#define        usalo_isatapi   pg_isatapi
+#define        usalo_reset     pg_reset
+
+static char    *pg_version(SCSI *usalp, int what);
+static int     pg_help(SCSI *usalp, FILE *f);
+static int     pg_open(SCSI *usalp, char *device);
+static int     pg_close(SCSI *usalp);
+static long    pg_maxdma(SCSI *usalp, long amt);
+static int     pg_initiator_id(SCSI *usalp);
+static int     pg_isatapi(SCSI *usalp);
+static int     pg_reset(SCSI *usalp, int what);
+static int     pg_send(SCSI *usalp);
+
+#endif
+
+static int     do_usal_cmd(SCSI *usalp, struct usal_cmd *sp);
+static int     do_usal_sense(SCSI *usalp, struct usal_cmd *sp);
+
+
+/*
+ * Return version information for the low level SCSI transport code.
+ * This has been introduced to make it easier to trace down problems
+ * in applications.
+ */
+static char *
+usalo_version(SCSI *usalp, int what)
+{
+       if (usalp != (SCSI *)0) {
+               switch (what) {
+
+               case SCG_VERSION:
+                       return (_usal_trans_version_pg);
+               /*
+                * If you changed this source, you are not allowed to
+                * return "schily" for the SCG_AUTHOR request.
+                */
+               case SCG_AUTHOR:
+                       return (_usal_auth_cdrkit);
+               case SCG_SCCS_ID:
+                       return (___sccsid);
+               }
+       }
+       return ((char *)0);
+}
+
+static int
+usalo_help(SCSI *usalp, FILE *f)
+{
+       __usal_help(f, "pg", "SCSI transport for ATAPI over Parallel Port",
+               "", "bus,target,lun", "1,2,0", TRUE, FALSE);
+       return (0);
+}
+
+static int
+usalo_open(SCSI *usalp, char *device)
+{
+               int     busno   = usal_scsibus(usalp);
+               int     tgt     = usal_target(usalp);
+               int     tlun    = usal_lun(usalp);
+       register int    f;
+       register int    b;
+#ifdef USE_PG_ONLY
+       register int    t;
+       register int    l;
+#endif
+       register int    nopen = 0;
+       char            devname[32];
+
+       if (busno >= MAX_SCG || tgt >= MAX_TGT || tlun >= MAX_LUN) {
+               errno = EINVAL;
+               if (usalp->errstr)
+                       snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                               "Illegal value for busno, target or lun '%d,%d,%d'",
+                               busno, tgt, tlun);
+               return (-1);
+       }
+
+#ifndef        USE_PG_ONLY
+       /*
+        * We need to find a fake bus number for the parallel port interface.
+        * Unfortunatly, the buscookie array may contain holes if
+        * SCSI_IOCTL_GET_BUS_NUMBER works, so we are searching backwards
+        * for some place for us.
+        * XXX Should add extra space in buscookies for a "PP bus".
+        */
+
+       if (usallocal(usalp)->buscookies[MAX_SCG-1] != (short)-1)
+               return (0);                     /* No space for pgbus */
+
+       for (b = MAX_SCG-1; b >= 0; b--) {
+               if (usallocal(usalp)->buscookies[b] != (short)-1) {
+                       usallocal(usalp)->pgbus = ++b;
+                       break;
+               }
+       }
+       if (usalp->debug > 0) {
+               fprintf((FILE *)usalp->errfile,
+                       "PP Bus: %d\n", usallocal(usalp)->pgbus);
+       }
+#else
+       if (usalp->local == NULL) {
+               usalp->local = malloc(sizeof (struct usal_local));
+               if (usalp->local == NULL)
+                       return (0);
+
+               usallocal(usalp)->pgbus = -2;
+               usallocal(usalp)->SCSIbuf = (char *)-1;
+
+               for (b = 0; b < MAX_SCG; b++) {
+                       for (t = 0; t < MAX_TGT; t++) {
+                               for (l = 0; l < MAX_LUN; l++)
+                                       usallocal(usalp)->usalfiles[b][t][l] = (short)-1;
+                       }
+               }
+       }
+#endif
+       if (usallocal(usalp)->pgbus < 0)
+               usallocal(usalp)->pgbus = 0;
+
+       if ((device != NULL && *device != '\0') || (busno == -2 && tgt == -2))
+               goto openbydev;
+
+       if (busno >= 0 && tgt >= 0 && tlun >= 0) {
+#ifndef        USE_PG_ONLY
+               if (usallocal(usalp)->pgbus != busno)
+                       return (0);
+#endif
+               snprintf(devname, sizeof (devname), "/dev/pg%d", tgt);
+               f = sg_open_excl(devname, O_RDWR | O_NONBLOCK);
+               if (f < 0) {
+                       if (usalp->errstr)
+                               snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                                               "Cannot open '%s'", devname);
+                       return (0);
+               }
+               usallocal(usalp)->usalfiles[busno][tgt][tlun] = f;
+               return (1);
+       } else {
+               tlun = 0;
+               for (tgt = 0; tgt < MAX_TGT; tgt++) {
+                       snprintf(devname, sizeof (devname), "/dev/pg%d", tgt);
+                       f = sg_open_excl(devname, O_RDWR | O_NONBLOCK);
+                       if (f < 0) {
+                               /*
+                                * Set up error string but let us clear it later
+                                * if at least one open succeeded.
+                                */
+                               if (usalp->errstr)
+                                       snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                                                       "Cannot open '/dev/pg*'");
+                               if (errno != ENOENT && errno != ENXIO && errno != ENODEV) {
+                                       if (usalp->errstr)
+                                               snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                                                       "Cannot open '%s'", devname);
+                                       return (0);
+                               }
+                       } else {
+                               usallocal(usalp)->usalfiles[usallocal(usalp)->pgbus][tgt][tlun] = f;
+                               nopen++;
+                       }
+               }
+       }
+       if (nopen > 0 && usalp->errstr)
+               usalp->errstr[0] = '\0';
+
+openbydev:
+       if (device != NULL && *device != '\0') {
+               char    *p;
+
+               if (tlun < 0)
+                       return (0);
+               f = open(device, O_RDWR | O_NONBLOCK);
+/*             if (f < 0 && errno == ENOENT) {*/
+               if (f < 0) {
+                       if (usalp->errstr)
+                               snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                                       "Cannot open '%s'",
+                                       device);
+                       return (0);
+               }
+
+               p = device + strlen(device) -1;
+               tgt = *p - '0';
+               if (tgt < 0 || tgt > 9)
+                       return (0);
+               usallocal(usalp)->usalfiles[usallocal(usalp)->pgbus][tgt][tlun] = f;
+               usal_settarget(usalp, usallocal(usalp)->pgbus, tgt, tlun);
+
+               return (++nopen);
+       }
+       return (nopen);
+}
+
+static int
+usalo_close(SCSI *usalp)
+{
+       register int    f;
+       register int    b;
+       register int    t;
+       register int    l;
+
+       if (usalp->local == NULL)
+               return (-1);
+       if (usallocal(usalp)->pgbus < 0)
+               return (0);
+       b = usallocal(usalp)->pgbus;
+       usallocal(usalp)->buscookies[b] = (short)-1;
+
+       for (t = 0; t < MAX_TGT; t++) {
+               for (l = 0; l < MAX_LUN; l++) {
+                       f = usallocal(usalp)->usalfiles[b][t][l];
+                       if (f >= 0)
+                               close(f);
+                       usallocal(usalp)->usalfiles[b][t][l] = (short)-1;
+               }
+       }
+       return (0);
+}
+
+static long
+usalo_maxdma(SCSI *usalp, long amt)
+{
+       return (PG_MAX_DATA);
+}
+
+#ifdef USE_PG_ONLY
+
+static void *
+usalo_getbuf(SCSI *usalp, long amt)
+{
+       char    *ret;
+
+       if (usalp->debug > 0) {
+               fprintf((FILE *)usalp->errfile,
+                       "usalo_getbuf: %ld bytes\n", amt);
+       }
+       ret = valloc((size_t)(amt+getpagesize()));
+       if (ret == NULL)
+               return (ret);
+       usalp->bufbase = ret;
+       ret += getpagesize();
+       usallocal(usalp)->SCSIbuf = ret;
+       return ((void *)ret);
+
+}
+
+static void
+usalo_freebuf(SCSI *usalp)
+{
+       if (usalp->bufbase)
+               free(usalp->bufbase);
+       usalp->bufbase = NULL;
+}
+
+static BOOL
+usalo_havebus(SCSI *usalp, int busno)
+{
+       register int    t;
+       register int    l;
+
+       if (busno < 0 || busno >= MAX_SCG)
+               return (FALSE);
+
+       if (usalp->local == NULL)
+               return (FALSE);
+
+       for (t = 0; t < MAX_TGT; t++) {
+               for (l = 0; l < MAX_LUN; l++)
+                       if (usallocal(usalp)->usalfiles[busno][t][l] >= 0)
+                               return (TRUE);
+       }
+       return (FALSE);
+}
+
+static int
+usalo_fileno(SCSI *usalp, int busno, int tgt, int tlun)
+{
+       if (busno < 0 || busno >= MAX_SCG ||
+           tgt < 0 || tgt >= MAX_TGT ||
+           tlun < 0 || tlun >= MAX_LUN)
+               return (-1);
+
+       if (usalp->local == NULL)
+               return (-1);
+
+       return ((int)usallocal(usalp)->usalfiles[busno][tgt][tlun]);
+}
+#endif /* USE_PG_ONLY */
+
+static int
+usalo_initiator_id(SCSI *usalp)
+{
+       return (-1);
+}
+
+static int
+usalo_isatapi(SCSI *usalp)
+{
+       return (TRUE);
+}
+
+static int
+usalo_reset(SCSI *usalp, int what)
+{
+       struct pg_write_hdr hdr = {PG_MAGIC, PG_RESET, 0};
+
+       if (what == SCG_RESET_NOP)
+               return (0);
+       if (what != SCG_RESET_BUS) {
+               errno = EINVAL;
+               return (-1);
+       }
+       /*
+        * XXX Does this reset TGT or BUS ???
+        */
+       return (write(usalp->fd, (char *)&hdr, sizeof (hdr)));
+
+}
+
+#ifndef MAX
+#define        MAX(a, b)       ((a) > (b) ? (a):(b))
+#endif
+
+#define        RHSIZE  sizeof (struct pg_read_hdr)
+#define        WHSIZE  sizeof (struct pg_write_hdr)
+#define        LEAD    MAX(RHSIZE, WHSIZE)
+
+static int
+do_usal_cmd(SCSI *usalp, struct usal_cmd *sp)
+{
+
+       char    local[LEAD+PG_MAX_DATA];
+       int     use_local, i, r;
+       int     inward = (sp->flags & SCG_RECV_DATA);
+
+       struct pg_write_hdr *whp;
+       struct pg_read_hdr  *rhp;
+       char                *dbp;
+
+       if (sp->cdb_len > 12)
+               comerrno(EX_BAD, "Can't do %d byte command.\n", sp->cdb_len);
+
+       if (sp->addr == usallocal(usalp)->SCSIbuf) {
+               use_local = 0;
+               dbp = sp->addr;
+       } else {
+               use_local = 1;
+               dbp = &local[LEAD];
+               if (!inward)
+                       movebytes(sp->addr, dbp, sp->size);
+       }
+
+       whp = (struct pg_write_hdr *)(dbp - WHSIZE);
+       rhp = (struct pg_read_hdr *)(dbp - RHSIZE);
+
+       whp->magic   = PG_MAGIC;
+       whp->func    = PG_COMMAND;
+       whp->dlen    = sp->size;
+       whp->timeout = sp->timeout;
+
+       for (i = 0; i < 12; i++) {
+               if (i < sp->cdb_len)
+                       whp->packet[i] = sp->cdb.cmd_cdb[i];
+               else
+                       whp->packet[i] = 0;
+       }
+
+       i = WHSIZE;
+       if (!inward)
+               i += sp->size;
+
+       r = write(usalp->fd, (char *)whp, i);
+
+       if (r < 0) {                            /* command was not sent */
+               sp->ux_errno = geterrno();
+               if (sp->ux_errno == ETIME) {
+                       /*
+                        * If the previous command timed out, we cannot send
+                        * any further command until the command in the drive
+                        * is ready. So we behave as if the drive did not
+                        * respond to the command.
+                        */
+                       sp->error = SCG_FATAL;
+                       return (0);
+               }
+               return (-1);
+       }
+
+       if (r != i)
+               errmsg("usalo_send(%s) wrote %d bytes (expected %d).\n",
+                       usalp->cmdname, r, i);
+
+       sp->ux_errno = 0;
+       sp->sense_count = 0;
+
+       r = read(usalp->fd, (char *)rhp, RHSIZE+sp->size);
+
+       if (r < 0) {
+               sp->ux_errno = geterrno();
+               if (sp->ux_errno == ETIME) {
+                       sp->error = SCG_TIMEOUT;
+                       return (0);
+               }
+               sp->error = SCG_FATAL;
+               return (-1);
+       }
+
+       i = rhp->dlen;
+       if (i > sp->size) {
+               /*
+                * "DMA overrun" should be handled in the kernel.
+                * However this may happen with flaky PP adapters.
+                */
+               errmsgno(EX_BAD,
+                       "DMA (read) overrun by %d bytes (requested %d bytes).\n",
+                       i - sp->size, sp->size);
+               sp->resid = sp->size - i;
+               sp->error = SCG_RETRYABLE;
+               i = sp->size;
+       } else {
+               sp->resid = sp->size - i;
+       }
+
+       if (use_local && inward)
+               movebytes(dbp, sp->addr, i);
+
+       fillbytes(&sp->scb, sizeof (sp->scb), '\0');
+       fillbytes(&sp->u_sense.cmd_sense, sizeof (sp->u_sense.cmd_sense), '\0');
+
+       sp->error = SCG_NO_ERROR;
+       i = rhp->scsi?2:0;
+/*     i = rhp->scsi;*/
+       sp->u_scb.cmd_scb[0] = i;
+       if (i & 2) {
+               if (sp->ux_errno == 0)
+                       sp->ux_errno = EIO;
+               /*
+                * If there is no DMA overrun and there is a
+                * SCSI Status byte != 0 then the SCSI cdb transport was OK
+                * and sp->error must be SCG_NO_ERROR.
+                */
+/*             sp->error = SCG_RETRYABLE;*/
+       }
+
+       return (0);
+
+}
+
+static int
+do_usal_sense(SCSI *usalp, struct usal_cmd *sp)
+{
+       int             ret;
+       struct usal_cmd         s_cmd;
+
+       fillbytes((caddr_t)&s_cmd, sizeof (s_cmd), '\0');
+       s_cmd.addr = (caddr_t)sp->u_sense.cmd_sense;
+       s_cmd.size = sp->sense_len;
+       s_cmd.flags = SCG_RECV_DATA|SCG_DISRE_ENA;
+       s_cmd.cdb_len = SC_G0_CDBLEN;
+       s_cmd.sense_len = CCS_SENSE_LEN;
+       s_cmd.cdb.g0_cdb.cmd = SC_REQUEST_SENSE;
+       s_cmd.cdb.g0_cdb.lun = sp->cdb.g0_cdb.lun;
+       s_cmd.cdb.g0_cdb.count = sp->sense_len;
+       ret = do_usal_cmd(usalp, &s_cmd);
+
+       if (ret < 0)
+               return (ret);
+
+       sp->sense_count = sp->sense_len - s_cmd.resid;
+       return (ret);
+}
+
+static int
+usalo_send(SCSI *usalp)
+{
+       struct usal_cmd *sp = usalp->scmd;
+       int     ret;
+
+       if (usalp->fd < 0) {
+               sp->error = SCG_FATAL;
+               return (0);
+       }
+       ret = do_usal_cmd(usalp, sp);
+       if (ret < 0)
+               return (ret);
+       if (sp->u_scb.cmd_scb[0] & 2)
+               ret = do_usal_sense(usalp, sp);
+       return (ret);
+}
+
+/* end of scsi-linux-pg.c */
+
+#ifndef        USE_PG_ONLY
+
+#undef usalo_version
+#undef usalo_help
+#undef usalo_open
+#undef usalo_close
+#undef usalo_send
+#undef usalo_maxdma
+#undef usalo_initiator_id
+#undef usalo_isatapi
+#undef usalo_reset
+
+#endif
diff --git a/libusal/scsi-linux-sg.c b/libusal/scsi-linux-sg.c
new file mode 100644 (file)
index 0000000..81d33d4
--- /dev/null
@@ -0,0 +1,1754 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)scsi-linux-sg.c 1.86 05/11/22 Copyright 1997 J. Schilling */
+/*
+ *     Interface for Linux generic SCSI implementation (sg).
+ *
+ *     This is the interface for the broken Linux SCSI generic driver.
+ *     This is a hack, that tries to emulate the functionality
+ *     of the usal driver.
+ *
+ *     Design flaws of the sg driver:
+ *     -       cannot see if SCSI command could not be send
+ *     -       cannot get SCSI status byte
+ *     -       cannot get real dma count of tranfer
+ *     -       cannot get number of bytes valid in auto sense data
+ *     -       to few data in auto sense (CCS/SCSI-2/SCSI-3 needs >= 18)
+ *
+ *     This code contains support for the sg driver version 2 by
+ *             H. Eißfeld & J. Schilling
+ *     Although this enhanced version has been announced to Linus and Alan,
+ *     there was no reaction at all.
+ *
+ *     About half a year later there occured a version in the official
+ *     Linux that was also called version 2. The interface of this version
+ *     looks like a playground - the enhancements from this version are
+ *     more or less useless for a portable real-world program.
+ *
+ *     With Linux 2.4 the official version of the sg driver is called 3.x
+ *     and seems to be usable again. The main problem now is the curious
+ *     interface that is provided to raise the DMA limit from 32 kB to a
+ *     more reasonable value. To do this in a reliable way, a lot of actions
+ *     are required.
+ *
+ *     Warning: you may change this source, but if you do that
+ *     you need to change the _usal_version and _usal_auth* string below.
+ *     You may not return "schily" for an SCG_AUTHOR request anymore.
+ *     Choose your name instead of "schily" and make clear that the version
+ *     string is related to a modified source.
+ *
+ *     Copyright (c) 1997 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <linux/version.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <sys/utsname.h>
+
+#ifndef LINUX_VERSION_CODE     /* Very old kernel? */
+#      define LINUX_VERSION_CODE 0
+#endif
+
+#if LINUX_VERSION_CODE >= 0x01031a /* <linux/scsi.h> introduced in 1.3.26 */
+#if LINUX_VERSION_CODE >= 0x020000 /* <scsi/scsi.h> introduced somewhere. */
+/* Need to fine tune the ifdef so we get the transition point right. */
+#include <scsi/scsi.h>
+#else
+#include <linux/scsi.h>
+#endif
+#else                          /* LINUX_VERSION_CODE == 0 Very old kernel? */
+#define        __KERNEL__              /* Some Linux Include files are inconsistent */
+#include <linux/fs.h>          /* From ancient versions, really needed? */
+#undef __KERNEL__
+#include "block/blk.h"         /* From ancient versions, really needed? */
+#include "scsi/scsi.h"
+#endif
+
+#if    defined(HAVE_BROKEN_SCSI_SG_H) || \
+       defined(HAVE_BROKEN_SRC_SCSI_SG_H)
+/*
+ * Be very careful in case that the Linux Kernel maintainers
+ * unexpectedly fix the bugs in the Linux Lernel include files.
+ * Only introduce the attempt for a workaround in case the include
+ * files are broken anyway.
+ */
+#define        __user
+#endif
+#include "scsi/sg.h"
+#if    defined(HAVE_BROKEN_SCSI_SG_H) || \
+       defined(HAVE_BROKEN_SRC_SCSI_SG_H)
+#undef __user
+#endif
+
+#undef sense                   /* conflict in struct cdrom_generic_command */
+#include <linux/cdrom.h>
+
+#if    defined(CDROM_PACKET_SIZE) && defined(CDROM_SEND_PACKET)
+#define        USE_OLD_ATAPI
+#endif
+
+#include <glob.h>
+
+/*
+ *     Warning: you may change this source, but if you do that
+ *     you need to change the _usal_version and _usal_auth* string below.
+ *     You may not return "schily" for an SCG_AUTHOR request anymore.
+ *     Choose your name instead of "schily" and make clear that the version
+ *     string is related to a modified source.
+ */
+static char    _usal_trans_version[] = "scsi-linux-sg.c-1.86"; /* The version for this transport*/
+
+#ifndef        SCSI_IOCTL_GET_BUS_NUMBER
+#define        SCSI_IOCTL_GET_BUS_NUMBER 0x5386
+#endif
+
+/*
+ * XXX There must be a better way than duplicating things from system include
+ * XXX files. This is stolen from /usr/src/linux/drivers/scsi/scsi.h
+ */
+#ifndef        DID_OK
+#define        DID_OK          0x00 /* NO error                                */
+#define        DID_NO_CONNECT  0x01 /* Couldn't connect before timeout period  */
+#define        DID_BUS_BUSY    0x02 /* BUS stayed busy through time out period */
+#define        DID_TIME_OUT    0x03 /* TIMED OUT for other reason              */
+#define        DID_BAD_TARGET  0x04 /* BAD target.                             */
+#define        DID_ABORT       0x05 /* Told to abort for some other reason     */
+#define        DID_PARITY      0x06 /* Parity error                            */
+#define        DID_ERROR       0x07 /* Internal error                          */
+#define        DID_RESET       0x08 /* Reset by somebody.                      */
+#define        DID_BAD_INTR    0x09 /* Got an interrupt we weren't expecting.  */
+#endif
+
+/*
+ *  These indicate the error that occurred, and what is available.
+ */
+#ifndef        DRIVER_BUSY
+#define        DRIVER_BUSY     0x01
+#define        DRIVER_SOFT     0x02
+#define        DRIVER_MEDIA    0x03
+#define        DRIVER_ERROR    0x04
+
+#define        DRIVER_INVALID  0x05
+#define        DRIVER_TIMEOUT  0x06
+#define        DRIVER_HARD     0x07
+#define        DRIVER_SENSE    0x08
+#endif
+
+/*
+ * XXX Should add extra space in buscookies and usalfiles for a "PP bus"
+ * XXX and for two or more "ATAPI busses".
+ */
+#define        MAX_SCG         1256    /* Max # of SCSI controllers */
+#define        MAX_TGT         16
+#define        MAX_LUN         8
+
+#ifdef USE_OLD_ATAPI
+/*
+ * # of virtual buses (schilly_host number)
+ */
+#define        MAX_SCHILLY_HOSTS       MAX_SCG
+typedef struct {
+       Uchar   typ:4;
+       Uchar   bus:4;
+       Uchar   host:8;
+} ata_buscookies;
+#endif
+
+struct usal_local {
+       int     usalfile;               /* Used for SG_GET_BUFSIZE ioctl()*/
+       short   usalfiles[MAX_SCG][MAX_TGT][MAX_LUN];
+       char    *filenames[MAX_SCG][MAX_TGT][MAX_LUN];
+       short   buscookies[MAX_SCG];
+       int     pgbus;
+       int     pack_id;                /* Should be a random number    */
+       int     drvers;
+       short   isold;
+       short   flags;
+       long    xbufsize;
+       char    *xbuf;
+       char    *SCSIbuf;
+#ifdef USE_OLD_ATAPI
+       ata_buscookies  bc[MAX_SCHILLY_HOSTS];
+#endif
+};
+#define        usallocal(p)    ((struct usal_local *)((p)->local))
+
+/*
+ * Flag definitions
+ */
+
+#ifdef SG_BIG_BUFF
+#define        MAX_DMA_LINUX   SG_BIG_BUFF     /* Defined in include/scsi/sg.h */
+#else
+#define        MAX_DMA_LINUX   (4*1024)        /* Old Linux versions           */
+#endif
+
+#ifndef        SG_MAX_SENSE
+#      define  SG_MAX_SENSE    16      /* Too small for CCS / SCSI-2   */
+#endif                                 /* But cannot be changed        */
+
+#if    !defined(__i386) && !defined(i386) && !defined(mc68000)
+#define        MISALIGN
+#endif
+/*#define      MISALIGN*/
+/*#undef       SG_GET_BUFSIZE*/
+
+
+#ifdef MISALIGN
+static int     sg_getint(int *ip);
+#endif
+static int     usalo_send(SCSI *usalp);
+#ifdef SG_IO
+static int     sg_rwsend(SCSI *usalp);
+#endif
+static void    sg_clearnblock(int f);
+static BOOL    sg_setup(SCSI *usalp, int f, int busno, int tgt, int tlun, 
+                                                               int ataidx, char *origname);
+static void    sg_initdev(SCSI *usalp, int f);
+static int     sg_mapbus(SCSI *usalp, int busno, int ino);
+static BOOL    sg_mapdev(SCSI *usalp, int f, int *busp, int *tgtp, int *lunp,
+                                                                int *chanp, int *inop, int ataidx);
+#if defined(SG_SET_RESERVED_SIZE) && defined(SG_GET_RESERVED_SIZE)
+static long    sg_raisedma(SCSI *usalp, long newmax);
+#endif
+static void    sg_settimeout(int f, int timeout);
+
+int    sg_open_excl(char *device, int mode, BOOL beQuiet);
+
+static BOOL get_max_secs(char *dirpath, int *outval);
+
+#if    defined(USE_PG) && !defined(USE_PG_ONLY)
+#include "scsi-linux-pg.c"
+#endif
+#ifdef USE_OLD_ATAPI
+#include "scsi-linux-ata.c"
+#endif
+
+BOOL check_linux_26() {
+       int gen, tmp;
+       struct utsname buf;
+       return ( 0==uname( &buf ) && sscanf(buf.release, "%d.%d", &gen, &tmp)>1 && tmp>=6);
+}
+
+int sg_open_excl(char *device, int mode, BOOL beQuiet)
+{
+       int f;
+       int i=0;
+       long interval = beQuiet ? 400000 : 1000000;
+
+       f = open(device, mode|O_EXCL);
+       /* try to reopen locked/busy devices up to five times */
+       for (i = 0; (i < 5) && (f == -1 && errno == EBUSY); i++) {
+              if(!beQuiet)
+                      fprintf(stderr, "Error trying to open %s exclusively (%s)... %s\n",
+                                      device, strerror(errno), 
+                                      (i<4)?"retrying in 1 second.":"giving up.");
+              usleep(interval + interval * rand()/(RAND_MAX+1.0));
+              f = open(device, mode|O_EXCL);
+       }
+       if(i==5 && !beQuiet) {
+              FILE *g = fopen("/proc/mounts", "r");
+              if(g) {
+                      char buf[80];
+                      unsigned int len=strlen(device);
+                      while(!feof(g) && !ferror(g)) {
+                              if(fgets(buf, 79, g) && 0==strncmp(device, buf, len)) {
+                                      fprintf(stderr, "WARNING: %s seems to be mounted!\n", device);
+                              }
+                      }
+                      fclose(g);
+              }
+       }
+       return f;
+}
+
+#if 0
+// Dead code, that sysfs parts may become deprecated soon
+void map_sg_to_block(char *device, int len) {
+       char globpat[100];
+       glob_t globbuf;
+       snprintf(globpat, 100, "/sys/class/scsi_generic/%s/device/block:*", device+5);
+       memset(&globbuf, 0, sizeof(glob_t));
+       if(0==glob(globpat, GLOB_DOOFFS | GLOB_NOSORT, NULL, &globbuf)) {
+               char *p = strrchr(globbuf.gl_pathv[0], ':');
+               if(p) snprintf(device, len, "/dev/%s", p+1);
+       }
+       globfree(&globbuf);
+}
+#endif
+
+/*
+ * Return version information for the low level SCSI transport code.
+ * This has been introduced to make it easier to trace down problems
+ * in applications.
+ */
+static char *
+usalo_version(SCSI *usalp, int what)
+{
+       if (usalp != (SCSI *)0) {
+#ifdef USE_PG
+#error pg-junk
+               /*
+                * If we only have a Parallel port or only opened a handle
+                * for PP, just return PP version.
+                */
+               if (usallocal(usalp)->pgbus == 0 ||
+                   (usal_scsibus(usalp) >= 0 &&
+                   usal_scsibus(usalp) == usallocal(usalp)->pgbus))
+                       return (pg_version(usalp, what));
+#endif
+               switch (what) {
+
+               case SCG_VERSION:
+                       return (_usal_trans_version);
+               /*
+                * If you changed this source, you are not allowed to
+                * return "schily" for the SCG_AUTHOR request.
+                */
+               case SCG_AUTHOR:
+                       return (_usal_auth_cdrkit);
+               case SCG_SCCS_ID:
+                       return (__sccsid);
+               case SCG_KVERSION:
+                       {
+                               static  char kv[16];
+                               int     n;
+
+                               if (usallocal(usalp)->drvers >= 0) {
+                                       n = usallocal(usalp)->drvers;
+                                       snprintf(kv, sizeof (kv),
+                                       "%d.%d.%d",
+                                       n/10000, (n%10000)/100, n%100);
+
+                                       return (kv);
+                               }
+                       }
+               }
+       }
+       return ((char *)0);
+}
+
+static int
+usalo_help(SCSI *usalp, FILE *f)
+{
+       __usal_help(f, "sg", "Generic transport independent SCSI",
+               "", "bus,target,lun", "1,2,0", TRUE, FALSE);
+#ifdef USE_PG
+       pg_help(usalp, f);
+#endif
+#ifdef USE_OLD_ATAPI
+       usalo_ahelp(usalp, f);
+#endif
+       __usal_help(f, "ATA", "ATA Packet specific SCSI transport using sg interface",
+               "ATA:", "bus,target,lun", "1,2,0", TRUE, FALSE);
+       return (0);
+}
+
+#define in_scanmode (busno < 0 && tgt < 0 && tlun < 0)
+
+/*
+ * b/t/l is chopped of the device string.
+ */
+static int
+usalo_open(SCSI *usalp, char *device)
+{
+       int     busno   = usal_scsibus(usalp);
+       int     tgt     = usal_target(usalp);
+       int     tlun    = usal_lun(usalp);
+       register int    f;
+       register int    i;
+       register int    b;
+       register int    t;
+       register int    l;
+       register int    nopen = 0;
+       char            devname[64];
+       int fake_atabus=0;
+
+       if (busno >= MAX_SCG || tgt >= MAX_TGT || tlun >= MAX_LUN) {
+               errno = EINVAL;
+               if (usalp->errstr)
+                       snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                               "Illegal value for busno, target or lun '%d,%d,%d'",
+                               busno, tgt, tlun);
+               return (-1);
+       }
+
+       struct stat statbuf;
+       if(check_linux_26() && 0!=stat("/sys/kernel", &statbuf)) {
+               static int warn_sysfs=1;
+               if(warn_sysfs) {
+                       warn_sysfs=0;
+                       fprintf(stderr, "\nWarning, sysfs is not mounted on /sys!\n"
+                                       "It is recommended to mount sysfs to allow better device configuration\n");
+                       sleep(5);
+               }
+       }
+
+       if (device != NULL && *device != '\0') {
+               fake_atabus=0;
+               if(0==strncmp(device, "OLDATAPI", 8)) {
+                       device+=3;
+                       usalp->ops = &ata_ops;
+                       return (SCGO_OPEN(usalp, device));
+               }
+               else if(0==strncmp(device, "ATAPI", 5)) {
+                       if(check_linux_26()) {
+                               device+=5;
+                               fake_atabus=1;
+                               fprintf(stderr, "WARNING: the ATAPI: method is considered deprecated on modern kernels!\n"
+                                               "Mapping device specification to ATA: method now.\n"
+                                               "To force the old ATAPI: method, replace ATAPI: with OLDATAPI:\n");
+                       }
+                       else {
+                               usalp->ops = &ata_ops;
+                               return (SCGO_OPEN(usalp, device));
+                       }
+               }
+               else if(0==strncmp(device, "ATA", 3)) {
+                       fprintf(stderr, "WARNING: the ATA: method is considered deprecated on modern kernels!\n"
+                                       "Use --devices to display the native names.\n");
+                       fake_atabus=1;
+                       device+=3;
+               }
+               if(device[0]==':')
+                       device++;
+
+       }
+       else if( ! in_scanmode ) {
+                       fprintf(stderr, "WARNING: the deprecated pseudo SCSI syntax found as device specification.\n"
+                                       "Support for that may cease in the future versions of wodim. For now,\n"
+                                       "the device will be mapped to a block device file where possible.\n"
+                                       "Run \"wodim --devices\" for details.\n" );
+                       sleep(5);
+       }
+
+       if (usalp->local == NULL) {
+               usalp->local = malloc(sizeof (struct usal_local));
+               if (usalp->local == NULL)
+                       return (0);
+
+               usallocal(usalp)->usalfile = -1;
+               usallocal(usalp)->pgbus = -2;
+               usallocal(usalp)->SCSIbuf = (char *)-1;
+               usallocal(usalp)->pack_id = 5;
+               usallocal(usalp)->drvers = -1;
+               usallocal(usalp)->isold = -1;
+               usallocal(usalp)->flags = 0;
+               usallocal(usalp)->xbufsize = 0L;
+               usallocal(usalp)->xbuf = NULL;
+
+               for (b = 0; b < MAX_SCG; b++) {
+                       usallocal(usalp)->buscookies[b] = (short)-1;
+                       for (t = 0; t < MAX_TGT; t++) {
+                               for (l = 0; l < MAX_LUN; l++) {
+                                       usallocal(usalp)->usalfiles[b][t][l] = (short)-1;
+                                       usallocal(usalp)->filenames[b][t][l] = NULL;
+                               }
+                       }
+               }
+       }
+
+       if (device != NULL && *device != '\0')
+       {
+               /* open ONE directly */
+               b = -1;
+               if (device && strncmp(device, "/dev/hd", 7) == 0 && device[8]=='\0') {
+                       b = device[7] - 'a';
+                       if (b < 0 || b > 25)
+                               b = -1;
+               }
+               if(b>=0 && fake_atabus)
+                       b+=1000;
+
+               f = sg_open_excl(device, O_RDWR | O_NONBLOCK, FALSE);
+
+               if (f < 0) {
+                       /*
+                        * The pg driver has the same rules to decide whether
+                        * to use openbydev. If we cannot open the device, it
+                        * makes no sense to try the /dev/pg* driver.
+                        */
+                       if (usalp->errstr)
+                               snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                                               "Cannot open '%s'",
+                                               device);
+                       return (0);
+               }
+               sg_clearnblock(f);
+               /* get some fake SCSI data */
+               sg_mapdev(usalp, f, &busno, &tgt, &tlun, 0, 0, b);
+               usal_settarget(usalp, busno, tgt, tlun);
+               if (sg_setup(usalp, f, busno, tgt, tlun, b, device))
+                       return (++nopen);
+       }
+       else {
+               /* scan and maybe keep one open, sg_setup decides */
+#define HDX 0
+#define SCD 1
+#define SG 2
+               int h;
+/*
+retry_scan_open:
+*/
+               for(h=HDX; h <= (fake_atabus ? HDX : SG) ; h++) {
+                       char *pattern = NULL;
+                       unsigned int first = 0, last = 0;
+                       switch(h) {
+                               case(HDX): 
+                                       {
+                                               pattern="/dev/hd%c";
+                                               first='a';
+                                               last='z';
+                                               break;
+                                       }
+                               case(SCD):
+                                       {
+                                               if(!check_linux_26())
+                                                       continue;
+                                               pattern="/dev/scd%d";
+                                               first=0;
+                                               last=255;
+                                               break;
+                                       }
+                               case(SG):
+                                       {
+                                               if(check_linux_26())
+                                                       continue; 
+#if 0
+                                               /*
+                                                * Don't touch it on 2.6 until we have a proper locking scheme
+                                                */
+                                                       if(nopen<=0)
+                                                               fprintf(stderr, "Warning, using /dev/sg* for SG_IO operation. This method is considered harmful.\n");
+                                                       else if(found_scd)
+                                                               continue;
+#endif
+                                               pattern="/dev/sg%d";
+                                               first=0;
+                                               last=255;
+                                               break;
+                                       }
+                       }
+                       for(i=first; i<=last; i++) {
+                               snprintf(devname, sizeof (devname), pattern, i);
+                               f = sg_open_excl(devname, O_RDWR | O_NONBLOCK, in_scanmode);
+                               if (f < 0) {
+                                       if (usalp->errstr)
+                                               snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                                                               "Cannot open '%s'", devname);
+                               } else {
+                                       if(h == HDX) { // double-check the capabilities on ATAPI devices
+                                               int     iparm;
+
+                                               if (ioctl(f, SG_GET_TIMEOUT, &iparm) < 0) {
+                                                       if (usalp->errstr)
+                                                               snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                                                                               "SCSI unsupported with '%s'", devname);
+                                                       close(f);
+                                                       continue;
+                                               }
+                                       }
+                                       sg_clearnblock(f);      /* Be very proper about this */
+                                       
+                                       /* construct the fake bus number hint, keep it readable */
+                                       b=-1;
+                                       if(h==HDX) {
+                                               b=i-'a';
+                                               if(!fake_atabus)
+                                                       b+=1000;
+                                       }
+
+                                       /* sg_setup returns false in scan mode, true if one single target was specified and opened */
+                                       if (sg_setup(usalp, f, busno, tgt, tlun, b, devname))
+                                               return (++nopen);
+
+                                       if (in_scanmode)
+                                               nopen++;
+                               }
+                       }
+
+                       if (nopen > 0 && usalp->errstr)
+                               usalp->errstr[0] = '\0';
+
+                       /* that's crap, should not be reached in non-scan mode.
+                        * Let's see whether it can be mapped to an atapi
+                        * device to emulate some old cludge's behaviour. 
+                       if(!in_scanmode && busno < 1000 && busno >=0) {
+                               fake_atabus=1;
+                               fprintf(stderr, "Unable to open this SCSI ID. Trying to map to old ATA syntax."
+                                               "This workaround will disappear in the near future. Fix your configuration.");
+                               goto retry_scan_open;
+                       }
+                       */
+               }
+       }
+
+       if (usalp->debug > 0) for (b = 0; b < MAX_SCG; b++) {
+               fprintf((FILE *)usalp->errfile,
+                       "Bus: %d cookie: %X\n",
+                       b, usallocal(usalp)->buscookies[b]);
+               for (t = 0; t < MAX_TGT; t++) {
+                       for (l = 0; l < MAX_LUN; l++) {
+                               if (usallocal(usalp)->usalfiles[b][t][l] != (short)-1) {
+                                       fprintf((FILE *)usalp->errfile,
+                                               "file (%d,%d,%d): %d\n",
+                                               b, t, l, usallocal(usalp)->usalfiles[b][t][l]);
+                               }
+                       }
+               }
+       }
+
+       return (nopen);
+}
+
+static int
+usalo_close(SCSI *usalp)
+{
+       register int    f;
+       register int    b;
+       register int    t;
+       register int    l;
+
+       if (usalp->local == NULL)
+               return (-1);
+
+       for (b = 0; b < MAX_SCG; b++) {
+               if (b == usallocal(usalp)->pgbus)
+                       continue;
+               usallocal(usalp)->buscookies[b] = (short)-1;
+               for (t = 0; t < MAX_TGT; t++) {
+                       for (l = 0; l < MAX_LUN; l++) {
+                               f = usallocal(usalp)->usalfiles[b][t][l];
+                               if (f >= 0)
+                                       close(f);
+                               usallocal(usalp)->usalfiles[b][t][l] = (short)-1;
+                               if(usallocal(usalp)->filenames[b][t][l]) {
+                                       free(usallocal(usalp)->filenames[b][t][l]);
+                                       usallocal(usalp)->filenames[b][t][l]=NULL;
+                               }
+                       }
+               }
+       }
+       if (usallocal(usalp)->xbuf != NULL) {
+               free(usallocal(usalp)->xbuf);
+               usallocal(usalp)->xbufsize = 0L;
+               usallocal(usalp)->xbuf = NULL;
+       }
+#ifdef USE_PG
+       pg_close(usalp);
+#endif
+       return (0);
+}
+
+/*
+ * The Linux kernel becomes more and more unmaintainable.
+ * Every year, a new incompatible SCSI transport interface is added.
+ * Each of them has it's own contradictory constraints.
+ * While you cannot have O_NONBLOCK set during operation, at least one
+ * of the drivers requires O_NONBLOCK to be set during open().
+ * This is used to clear O_NONBLOCK immediately after open() succeeded.
+ */
+static void
+sg_clearnblock(int f)
+{
+       int     n;
+
+       n = fcntl(f, F_GETFL);
+       n &= ~O_NONBLOCK;
+       fcntl(f, F_SETFL, n);
+}
+
+/*!
+ *
+ * Return: TRUE when single target is chosen and was opened successfully, FALSE otherwise (on scans, etc).
+ */
+
+static BOOL
+sg_setup(SCSI *usalp, int f, int busno, int tgt, int tlun, int ataidx, char *origname)
+{
+       int     n;
+       int     Chan;
+       int     Ino;
+       int     Bus;
+       int     Target;
+       int     Lun;
+       BOOL    onetarget = FALSE;
+
+#ifdef SG_GET_VERSION_NUM
+       if (usallocal(usalp)->drvers < 0) {
+               usallocal(usalp)->drvers = 0;
+               if (ioctl(f, SG_GET_VERSION_NUM, &n) >= 0) {
+                       usallocal(usalp)->drvers = n;
+                       if (usalp->overbose) {
+                               fprintf((FILE *)usalp->errfile,
+                                       "Linux sg driver version: %d.%d.%d\n",
+                                       n/10000, (n%10000)/100, n%100);
+                       }
+               }
+       }
+#endif
+       if (usal_scsibus(usalp) >= 0 && usal_target(usalp) >= 0 && usal_lun(usalp) >= 0)
+               onetarget = TRUE;
+
+       sg_mapdev(usalp, f, &Bus, &Target, &Lun, &Chan, &Ino, ataidx);
+       /*
+        * For old kernels try to make the best guess.
+        */
+       Ino |= Chan << 8;
+       n = sg_mapbus(usalp, Bus, Ino);
+       if (Bus == -1) {
+               Bus = n;
+               if (usalp->debug > 0) {
+                       fprintf((FILE *)usalp->errfile,
+                               "SCSI Bus: %d (mapped from %d)\n", Bus, Ino);
+               }
+       }
+
+       if (Bus < 0 || Bus >= MAX_SCG || Target < 0 || Target >= MAX_TGT ||
+                                               Lun < 0 || Lun >= MAX_LUN) {
+               return (FALSE);
+       }
+
+       if (usallocal(usalp)->usalfiles[Bus][Target][Lun] == (short)-1)
+               usallocal(usalp)->usalfiles[Bus][Target][Lun] = (short)f;
+
+       if (usallocal(usalp)->filenames[Bus][Target][Lun] == NULL)
+               usallocal(usalp)->filenames[Bus][Target][Lun] = strdup(origname);
+
+       if (onetarget) {
+               if (Bus == busno && Target == tgt && Lun == tlun) {
+                       sg_initdev(usalp, f);
+                       usallocal(usalp)->usalfile = f; /* remember file for ioctl's */
+                       return (TRUE);
+               } else {
+                       usallocal(usalp)->usalfiles[Bus][Target][Lun] = (short)-1;
+                       close(f);
+               }
+       } else {
+               /*
+                * SCSI bus scanning may cause other generic SCSI activities to
+                * fail because we set the default timeout and clear command
+                * queues (in case of the old sg driver interface).
+                */
+               sg_initdev(usalp, f);
+               if (usallocal(usalp)->usalfile < 0)
+                       usallocal(usalp)->usalfile = f; /* remember file for ioctl's */
+       }
+       return (FALSE);
+}
+
+static void
+sg_initdev(SCSI *usalp, int f)
+{
+       struct sg_rep {
+               struct sg_header        hd;
+               unsigned char           rbuf[100];
+       } sg_rep;
+       int     n;
+       int     i;
+       struct stat sb;
+
+       sg_settimeout(f, usalp->deftimeout);
+
+       /*
+        * If it's a block device, don't read.... pre Linux-2.4 /dev/sg*
+        * definitely is a character device and we only need to clear the
+        * queue for old /dev/sg* versions. If somebody ever implements
+        * raw disk access for Linux, this test may fail.
+        */
+       if (fstat(f, &sb) >= 0 && S_ISBLK(sb.st_mode))
+               return;
+
+       /* Eat any unwanted garbage from prior use of this device */
+
+       n = fcntl(f, F_GETFL);  /* Be very proper about this */
+       fcntl(f, F_SETFL, n|O_NONBLOCK);
+
+       fillbytes((caddr_t)&sg_rep, sizeof (struct sg_header), '\0');
+       sg_rep.hd.reply_len = sizeof (struct sg_header);
+
+       /*
+        * This is really ugly.
+        * We come here if 'f' is related to a raw device. If Linux
+        * will ever have raw devices for /dev/hd* we may get problems.
+        * As long as there is no clean way to find out whether the
+        * filedescriptor 'f' is related to an old /dev/sg* or to
+        * /dev/hd*, we must assume that we found an old /dev/sg* and
+        * clean it up. Unfortunately, reading from /dev/hd* will
+        * Access the medium.
+        */
+       for (i = 0; i < 1000; i++) {    /* Read at least 32k from /dev/sg* */
+               int     ret;
+
+               ret = read(f, &sg_rep, sizeof (struct sg_rep));
+               if (ret > 0)
+                       continue;
+               if (ret == 0 || errno == EAGAIN || errno == EIO)
+                       break;
+               if (ret < 0 && i > 10)  /* Stop on repeated unknown error */
+                       break;
+       }
+       fcntl(f, F_SETFL, n);
+}
+
+static int
+sg_mapbus(SCSI *usalp, int busno, int ino)
+{
+       register int    i;
+
+       if (busno >= 0 && busno < MAX_SCG) {
+               /*
+                * SCSI_IOCTL_GET_BUS_NUMBER worked.
+                * Now we have the problem that Linux does not properly number
+                * SCSI busses. The Bus number that Linux creates really is
+                * the controller (card) number. I case of multi SCSI bus
+                * cards we are lost.
+                */
+               if (usallocal(usalp)->buscookies[busno] == (short)-1) {
+                       usallocal(usalp)->buscookies[busno] = ino;
+                       return (busno);
+               }
+               /*
+                * if (usallocal(usalp)->buscookies[busno] != (short)ino)
+                       errmsgno(EX_BAD, "Warning Linux Bus mapping botch.\n");
+                       */
+               return (busno);
+
+       } else for (i = 0; i < MAX_SCG; i++) {
+               if (usallocal(usalp)->buscookies[i] == (short)-1) {
+                       usallocal(usalp)->buscookies[i] = ino;
+                       return (i);
+               }
+
+               if (usallocal(usalp)->buscookies[i] == ino)
+                       return (i);
+       }
+       return (0);
+}
+
+static BOOL
+sg_mapdev(SCSI *usalp, int f, int *busp, int *tgtp, int *lunp, int *chanp, 
+                        int *inop, int ataidx)
+{
+       struct  sg_id {
+               long    l1; /* target | lun << 8 | channel << 16 | low_ino << 24 */
+               long    l2; /* Unique id */
+       } sg_id;
+       int     Chan;
+       int     Ino;
+       int     Bus;
+       int     Target;
+       int     Lun;
+
+       if (ataidx >= 0) {
+               /*
+                * The badly designed /dev/hd* interface maps everything
+                * to 0,0,0 so we need to do the mapping ourselves.
+                */
+               *busp = (ataidx/1000) * 1000;
+               *tgtp = ataidx%1000;
+               *lunp = 0;
+               if (chanp)
+                       *chanp = 0;
+               if (inop)
+                       *inop = 0;
+               return (TRUE);
+       }
+       if (ioctl(f, SCSI_IOCTL_GET_IDLUN, &sg_id))
+               return (FALSE);
+       if (usalp->debug > 0) {
+               fprintf((FILE *)usalp->errfile,
+                       "l1: 0x%lX l2: 0x%lX\n", sg_id.l1, sg_id.l2);
+       }
+       if (ioctl(f, SCSI_IOCTL_GET_BUS_NUMBER, &Bus) < 0) {
+               Bus = -1;
+       }
+
+       Target  = sg_id.l1 & 0xFF;
+       Lun     = (sg_id.l1 >> 8) & 0xFF;
+       Chan    = (sg_id.l1 >> 16) & 0xFF;
+       Ino     = (sg_id.l1 >> 24) & 0xFF;
+       if (usalp->debug > 0) {
+               fprintf((FILE *)usalp->errfile,
+                       "Bus: %d Target: %d Lun: %d Chan: %d Ino: %d\n",
+                       Bus, Target, Lun, Chan, Ino);
+       }
+       *busp = Bus;
+       *tgtp = Target;
+       *lunp = Lun;
+       if (chanp)
+               *chanp = Chan;
+       if (inop)
+               *inop = Ino;
+       return (TRUE);
+}
+
+#if defined(SG_SET_RESERVED_SIZE) && defined(SG_GET_RESERVED_SIZE)
+/*
+ * The way Linux does DMA resouce management is a bit curious.
+ * It totally deviates from all other OS and forces long ugly code.
+ * If we are opening all drivers for a SCSI bus scan operation, we need
+ * to set the limit for all open devices.
+ * This may use up all kernel memory ... so do the job carefully.
+ *
+ * A big problem is that SG_SET_RESERVED_SIZE does not return any hint
+ * on whether the request did fail. The only way to find if it worked
+ * is to use SG_GET_RESERVED_SIZE to read back the current values.
+ */
+static long
+sg_raisedma(SCSI *usalp, long newmax)
+{
+       register int    b;
+       register int    t;
+       register int    l;
+       register int    f;
+               int     val;
+               int     old;
+
+       /*
+        * First try to raise the DMA limit to a moderate value that
+        * most likely does not use up all kernel memory.
+        */
+       val = 126*1024;
+
+       if (val > MAX_DMA_LINUX) {
+               for (b = 0; b < MAX_SCG; b++) {
+                       for (t = 0; t < MAX_TGT; t++) {
+                               for (l = 0; l < MAX_LUN; l++) {
+                                       if ((f = SCGO_FILENO(usalp, b, t, l)) < 0)
+                                               continue;
+                                       old = 0;
+                                       if (ioctl(f, SG_GET_RESERVED_SIZE, &old) < 0)
+                                               continue;
+                                       if (val > old)
+                                               ioctl(f, SG_SET_RESERVED_SIZE, &val);
+                               }
+                       }
+               }
+       }
+
+       /*
+        * Now to raise the DMA limit to what we really need.
+        */
+       if (newmax > val) {
+               val = newmax;
+               for (b = 0; b < MAX_SCG; b++) {
+                       for (t = 0; t < MAX_TGT; t++) {
+                               for (l = 0; l < MAX_LUN; l++) {
+                                       if ((f = SCGO_FILENO(usalp, b, t, l)) < 0)
+                                               continue;
+                                       old = 0;
+                                       if (ioctl(f, SG_GET_RESERVED_SIZE, &old) < 0)
+                                               continue;
+                                       if (val > old)
+                                               ioctl(f, SG_SET_RESERVED_SIZE, &val);
+                               }
+                       }
+               }
+       }
+
+       /*
+        * To make sure we did not fail (the ioctl does not report errors)
+        * we need to check the DMA limits. We return the smallest value.
+        */
+       for (b = 0; b < MAX_SCG; b++) {
+               for (t = 0; t < MAX_TGT; t++) {
+                       for (l = 0; l < MAX_LUN; l++) {
+                               if ((f = SCGO_FILENO(usalp, b, t, l)) < 0)
+                                       continue;
+                               if (ioctl(f, SG_GET_RESERVED_SIZE, &val) < 0)
+                                       continue;
+                               if (usalp->debug > 0) {
+                                       fprintf((FILE *)usalp->errfile,
+                                               "Target (%d,%d,%d): DMA max %d old max: %ld\n",
+                                               b, t, l, val, newmax);
+                               }
+                               if (val < newmax)
+                                       newmax = val;
+                       }
+               }
+       }
+       return ((long)newmax);
+}
+#endif
+
+static char *freadstring(char *fn, char *out, int len) {
+        char *ret;
+       FILE *fd=fopen(fn, "r");
+       out[0]='\0';
+       if(!fd) return NULL;
+       ret = fgets(out, len, fd);
+       fclose(fd);
+        return ret;
+}
+
+static long
+usalo_maxdma(SCSI *usalp, long amt)
+{
+       struct stat stbuf;
+       long maxdma = MAX_DMA_LINUX;
+
+#if defined(SG_SET_RESERVED_SIZE) && defined(SG_GET_RESERVED_SIZE)
+       /*
+        * Use the curious new kernel interface found on Linux >= 2.2.10
+        * This interface first appeared in 2.2.6 but it was not working.
+        */
+       if (usallocal(usalp)->drvers >= 20134)
+               maxdma = sg_raisedma(usalp, amt);
+#endif
+       /*
+        * First try the modern kernel 2.6.1x way to detect the real maximum
+        * DMA for this specific device, then try the other methods.
+        */
+       if(0==fstat(usallocal(usalp)->usalfile, &stbuf)) {
+               /* that's ugly, there are so many symlinks in sysfs but none from
+                * major:minor to the relevant directory */
+               long int major, minor, i;
+               major=stbuf.st_rdev>>8;
+               minor=stbuf.st_rdev&0xFF;
+               if (usalp->debug > 0)
+                 fprintf(stderr, "Looking for data for major:minor: %ld:%ld\n", major, minor);
+               glob_t globbuf;
+               memset(&globbuf, 0, sizeof(glob_t));
+               /* *dev files contain the major:minor strings to compare */
+               glob("/sys/class/scsi_generic/*/device/block*/queue/max_sectors_kb", GLOB_DOOFFS | GLOB_NOSORT, NULL, &globbuf);
+               glob("/sys/block/*/device/block*/queue/max_sectors_kb", GLOB_DOOFFS | GLOB_NOSORT | GLOB_APPEND, NULL, &globbuf);
+               for(i=0;i<globbuf.gl_pathc; i++) {
+                       char *cut, *ende;
+                       char buf[64];
+                       cut=strstr(globbuf.gl_pathv[i], "/device/")+4;
+                       *cut='\0';
+                       freadstring(globbuf.gl_pathv[i], buf, sizeof(buf));
+                       if(strtol(buf, &ende, 10) == major && ende && atoi(ende) == minor) {
+                               *cut='i';
+                               freadstring(globbuf.gl_pathv[i], buf, sizeof(buf));
+                               return(1024*atoi(buf));
+                       }
+
+               }
+               globfree(&globbuf);
+       }
+#ifdef SG_GET_BUFSIZE
+       /*
+        * We assume that all /dev/sg instances use the same
+        * maximum buffer size.
+        */
+       maxdma = ioctl(usallocal(usalp)->usalfile, SG_GET_BUFSIZE, 0);
+#endif
+       if (maxdma < 0) {
+#ifdef USE_PG
+               /*
+                * If we only have a Parallel port, just return PP maxdma.
+                */
+               if (usallocal(usalp)->pgbus == 0)
+                       return (pg_maxdma(usalp, amt));
+#endif
+               if (usallocal(usalp)->usalfile >= 0)
+                       maxdma = MAX_DMA_LINUX;
+       }
+#ifdef USE_PG
+       if (usal_scsibus(usalp) == usallocal(usalp)->pgbus)
+               return (pg_maxdma(usalp, amt));
+       if ((usal_scsibus(usalp) < 0) && (pg_maxdma(usalp, amt) < maxdma))
+               return (pg_maxdma(usalp, amt));
+#endif
+       return (maxdma);
+}
+
+static void *
+usalo_getbuf(SCSI *usalp, long amt)
+{
+       char    *ret;
+
+       if (usalp->debug > 0) {
+               fprintf((FILE *)usalp->errfile,
+                               "usalo_getbuf: %ld bytes\n", amt);
+       }
+       /*
+        * For performance reason, we allocate pagesize()
+        * bytes before the SCSI buffer to avoid
+        * copying the whole buffer contents when
+        * setting up the /dev/sg data structures.
+        */
+       ret = valloc((size_t)(amt+getpagesize()));
+       if (ret == NULL)
+               return (ret);
+       usalp->bufbase = ret;
+       ret += getpagesize();
+       usallocal(usalp)->SCSIbuf = ret;
+       return ((void *)ret);
+}
+
+static void
+usalo_freebuf(SCSI *usalp)
+{
+       if (usalp->bufbase)
+               free(usalp->bufbase);
+       usalp->bufbase = NULL;
+}
+
+static BOOL
+usalo_havebus(SCSI *usalp, int busno)
+{
+       register int    t;
+       register int    l;
+
+       if (busno < 0 || busno >= MAX_SCG)
+               return (FALSE);
+
+       if (usalp->local == NULL)
+               return (FALSE);
+
+       for (t = 0; t < MAX_TGT; t++) {
+               for (l = 0; l < MAX_LUN; l++)
+                       if (usallocal(usalp)->usalfiles[busno][t][l] >= 0)
+                               return (TRUE);
+       }
+       return (FALSE);
+}
+
+static int
+usalo_fileno(SCSI *usalp, int busno, int tgt, int tlun)
+{
+       if (busno < 0 || busno >= MAX_SCG ||
+           tgt < 0 || tgt >= MAX_TGT ||
+           tlun < 0 || tlun >= MAX_LUN)
+               return (-1);
+
+       if (usalp->local == NULL)
+               return (-1);
+
+       return ((int)usallocal(usalp)->usalfiles[busno][tgt][tlun]);
+}
+
+static int
+usalo_initiator_id(SCSI *usalp)
+{
+#ifdef USE_PG
+       if (usal_scsibus(usalp) == usallocal(usalp)->pgbus)
+               return (pg_initiator_id(usalp));
+#endif
+       return (-1);
+}
+
+static int
+usalo_isatapi(SCSI *usalp)
+{
+       return -1;
+#if 0
+       /*
+        * Who exactly needs this information? Just for some bitching in wodim?
+        * Is this an _abstraction_ layer or spam layer?
+        */
+#ifdef USE_PG
+       if (usal_scsibus(usalp) == usallocal(usalp)->pgbus)
+               return (pg_isatapi(usalp));
+#endif
+
+       /*
+        * The /dev/hd* interface always returns TRUE for SG_EMULATED_HOST.
+        * So this is completely useless.
+        */
+       if (usallocal(usalp)->flags & LF_ATA)
+               return (-1);
+
+#ifdef SG_EMULATED_HOST
+       {
+       int     emulated = FALSE;
+
+       /*
+        * XXX Should we use this at all?
+        * XXX The badly designed /dev/hd* interface always
+        * XXX returns TRUE, even when used with e.g. /dev/sr0.
+        */
+       if (ioctl(usalp->fd, SG_EMULATED_HOST, &emulated) >= 0)
+               return (emulated != 0);
+       }
+#endif
+       return (-1);
+#endif
+}
+
+static int
+usalo_reset(SCSI *usalp, int what)
+{
+#ifdef SG_SCSI_RESET
+       int     f = usalp->fd;
+       int     func = -1;
+#endif
+#ifdef USE_PG
+       if (usal_scsibus(usalp) == usallocal(usalp)->pgbus)
+               return (pg_reset(usalp, what));
+#endif
+       /*
+        * Do we have a SCSI reset in the Linux sg driver?
+        */
+#ifdef SG_SCSI_RESET
+       /*
+        * Newer Linux sg driver seem to finally implement it...
+        */
+#ifdef SG_SCSI_RESET_NOTHING
+       func = SG_SCSI_RESET_NOTHING;
+       if (ioctl(f, SG_SCSI_RESET, &func) >= 0) {
+               if (what == SCG_RESET_NOP)
+                       return (0);
+#ifdef SG_SCSI_RESET_DEVICE
+               if (what == SCG_RESET_TGT) {
+                       func = SG_SCSI_RESET_DEVICE;
+                       if (ioctl(f, SG_SCSI_RESET, &func) >= 0)
+                               return (0);
+               }
+#endif
+#ifdef SG_SCSI_RESET_BUS
+               if (what == SCG_RESET_BUS) {
+                       func = SG_SCSI_RESET_BUS;
+                       if (ioctl(f, SG_SCSI_RESET, &func) >= 0)
+                               return (0);
+               }
+#endif
+       }
+#endif
+#endif
+       return (-1);
+}
+
+static void
+sg_settimeout(int f, int tmo)
+{
+#ifndef HZ
+       static int HZ=0;
+       if (!HZ)
+               HZ = sysconf(_SC_CLK_TCK);
+#endif
+       tmo *= HZ;
+       if (tmo)
+               tmo += HZ/2;
+
+       if (ioctl(f, SG_SET_TIMEOUT, &tmo) < 0)
+               comerr("Cannot set SG_SET_TIMEOUT.\n");
+}
+
+/*
+ * Get misaligned int.
+ * Needed for all recent processors (sparc/ppc/alpha)
+ * because the /dev/sg design forces us to do misaligned
+ * reads of integers.
+ */
+#ifdef MISALIGN
+static int
+sg_getint(int *ip)
+{
+               int     ret;
+       register char   *cp = (char *)ip;
+       register char   *tp = (char *)&ret;
+       register int    i;
+
+       for (i = sizeof (int); --i >= 0; )
+               *tp++ = *cp++;
+
+       return (ret);
+}
+#define        GETINT(a)       sg_getint(&(a))
+#else
+#define        GETINT(a)       (a)
+#endif
+
+#ifdef SG_IO
+static int
+usalo_send(SCSI *usalp)
+{
+       struct usal_cmd *sp = usalp->scmd;
+       int             ret;
+       sg_io_hdr_t     sg_io;
+       struct timeval  to;
+
+       if (usalp->fd < 0) {
+               sp->error = SCG_FATAL;
+               sp->ux_errno = EIO;
+               return (0);
+       }
+       if (usallocal(usalp)->isold > 0) {
+               return (sg_rwsend(usalp));
+       }
+       fillbytes((caddr_t)&sg_io, sizeof (sg_io), '\0');
+
+       sg_io.interface_id = 'S';
+
+       if (sp->flags & SCG_RECV_DATA) {
+               sg_io.dxfer_direction = SG_DXFER_FROM_DEV;
+       } else if (sp->size > 0) {
+               sg_io.dxfer_direction = SG_DXFER_TO_DEV;
+       } else {
+               sg_io.dxfer_direction = SG_DXFER_NONE;
+       }
+       sg_io.cmd_len = sp->cdb_len;
+       if (sp->sense_len > SG_MAX_SENSE)
+               sg_io.mx_sb_len = SG_MAX_SENSE;
+       else
+               sg_io.mx_sb_len = sp->sense_len;
+       sg_io.dxfer_len = sp->size;
+       sg_io.dxferp = sp->addr;
+       sg_io.cmdp = sp->cdb.cmd_cdb;
+       sg_io.sbp = sp->u_sense.cmd_sense;
+       sg_io.timeout = sp->timeout*1000;
+       sg_io.flags |= SG_FLAG_DIRECT_IO;
+
+       ret = ioctl(usalp->fd, SG_IO, &sg_io);
+       if (usalp->debug > 0) {
+               fprintf((FILE *)usalp->errfile,
+                               "ioctl ret: %d\n", ret);
+       }
+
+       if (ret < 0) {
+               sp->ux_errno = geterrno();
+               /*
+                * Check if SCSI command cound not be send at all.
+                * Linux usually returns EINVAL for an unknoen ioctl.
+                * In case somebody from the Linux kernel team learns that the
+                * corect errno would be ENOTTY, we check for this errno too.
+                */
+               if ((sp->ux_errno == ENOTTY || sp->ux_errno == EINVAL) &&
+                   usallocal(usalp)->isold < 0) {
+                       usallocal(usalp)->isold = 1;
+                       return (sg_rwsend(usalp));
+               }
+               if (sp->ux_errno == ENXIO ||
+                   sp->ux_errno == EINVAL || sp->ux_errno == EACCES) {
+                       return (-1);
+               }
+       }
+
+       sp->u_scb.cmd_scb[0] = sg_io.status;
+       sp->sense_count = sg_io.sb_len_wr;
+
+       if (usalp->debug > 0) {
+               fprintf((FILE *)usalp->errfile,
+                               "host_status: %02X driver_status: %02X\n",
+                               sg_io.host_status, sg_io.driver_status);
+       }
+
+       switch (sg_io.host_status) {
+
+       case DID_OK:
+                       /*
+                        * If there is no DMA overrun and there is a
+                        * SCSI Status byte != 0 then the SCSI cdb transport
+                        * was OK and sp->error must be SCG_NO_ERROR.
+                        */
+                       if ((sg_io.driver_status & DRIVER_SENSE) != 0) {
+                               if (sp->ux_errno == 0)
+                                       sp->ux_errno = EIO;
+
+                               if (sp->u_sense.cmd_sense[0] != 0 &&
+                                   sp->u_scb.cmd_scb[0] == 0) {
+                                       /*
+                                        * The Linux SCSI system up to 2.4.xx
+                                        * trashes the status byte in the
+                                        * kernel. This is true at least for
+                                        * ide-scsi emulation. Until this gets
+                                        * fixed, we need this hack.
+                                        */
+                                       sp->u_scb.cmd_scb[0] = ST_CHK_COND;
+                                       if (sp->sense_count == 0)
+                                               sp->sense_count = SG_MAX_SENSE;
+
+                                       if ((sp->u_sense.cmd_sense[2] == 0) &&
+                                           (sp->u_sense.cmd_sense[12] == 0) &&
+                                           (sp->u_sense.cmd_sense[13] == 0)) {
+                                               /*
+                                                * The Linux SCSI system will
+                                                * send a request sense for
+                                                * even a dma underrun error.
+                                                * Clear CHECK CONDITION state
+                                                * in case of No Sense.
+                                                */
+                                               sp->u_scb.cmd_scb[0] = 0;
+                                               sp->u_sense.cmd_sense[0] = 0;
+                                               sp->sense_count = 0;
+                                       }
+                               }
+                       }
+                       break;
+
+       case DID_NO_CONNECT:    /* Arbitration won, retry NO_CONNECT? */
+                       sp->error = SCG_RETRYABLE;
+                       break;
+       case DID_BAD_TARGET:
+                       sp->error = SCG_FATAL;
+                       break;
+
+       case DID_TIME_OUT:
+               __usal_times(usalp);
+
+               if (sp->timeout > 1 && usalp->cmdstop->tv_sec == 0) {
+                       sp->u_scb.cmd_scb[0] = 0;
+                       sp->error = SCG_FATAL;  /* a selection timeout */
+               } else {
+                       sp->error = SCG_TIMEOUT;
+               }
+               break;
+
+       default:
+               to.tv_sec = sp->timeout;
+               to.tv_usec = 500000;
+               __usal_times(usalp);
+
+               if (usalp->cmdstop->tv_sec < to.tv_sec ||
+                   (usalp->cmdstop->tv_sec == to.tv_sec &&
+                       usalp->cmdstop->tv_usec < to.tv_usec)) {
+
+                       sp->ux_errno = 0;
+                       sp->error = SCG_TIMEOUT;        /* a timeout */
+               } else {
+                       sp->error = SCG_RETRYABLE;
+               }
+               break;
+       }
+       if (sp->error && sp->ux_errno == 0)
+               sp->ux_errno = EIO;
+
+       sp->resid = sg_io.resid;
+       return (0);
+}
+#else
+#      define  sg_rwsend       usalo_send
+#endif
+
+static int
+sg_rwsend(SCSI *usalp)
+{
+       int             f = usalp->fd;
+       struct usal_cmd *sp = usalp->scmd;
+       struct sg_rq    *sgp;
+       struct sg_rq    *sgp2;
+       int     i;
+       int     pack_len;
+       int     reply_len;
+       int     amt = sp->cdb_len;
+       struct sg_rq {
+               struct sg_header        hd;
+               unsigned char           buf[MAX_DMA_LINUX+SCG_MAX_CMD];
+       } sg_rq;
+#ifdef SG_GET_BUFSIZE          /* We may use a 'sg' version 2 driver   */
+       char    driver_byte;
+       char    host_byte;
+       char    msg_byte;
+       char    status_byte;
+#endif
+
+       if (f < 0) {
+               sp->error = SCG_FATAL;
+               sp->ux_errno = EIO;
+               return (0);
+       }
+#ifdef USE_PG
+       if (usal_scsibus(usalp) == usallocal(usalp)->pgbus)
+               return (pg_send(usalp));
+#endif
+       if (sp->timeout != usalp->deftimeout)
+               sg_settimeout(f, sp->timeout);
+
+
+       sgp2 = sgp = &sg_rq;
+       if (sp->addr == usallocal(usalp)->SCSIbuf) {
+               sgp = (struct sg_rq *)
+                       (usallocal(usalp)->SCSIbuf - (sizeof (struct sg_header) + amt));
+               sgp2 = (struct sg_rq *)
+                       (usallocal(usalp)->SCSIbuf - (sizeof (struct sg_header)));
+       } else {
+               if (usalp->debug > 0) {
+                       fprintf((FILE *)usalp->errfile,
+                               "DMA addr: 0x%8.8lX size: %d - using copy buffer\n",
+                               (long)sp->addr, sp->size);
+               }
+               if (sp->size > (int)(sizeof (sg_rq.buf) - SCG_MAX_CMD)) {
+
+                       if (usallocal(usalp)->xbuf == NULL) {
+                               usallocal(usalp)->xbufsize = usalp->maxbuf;
+                               usallocal(usalp)->xbuf =
+                                       malloc(usallocal(usalp)->xbufsize +
+                                               SCG_MAX_CMD +
+                                               sizeof (struct sg_header));
+                               if (usalp->debug > 0) {
+                                       fprintf((FILE *)usalp->errfile,
+                                               "Allocated DMA copy buffer, addr: 0x%8.8lX size: %ld\n",
+                                               (long)usallocal(usalp)->xbuf,
+                                               usalp->maxbuf);
+                               }
+                       }
+                       if (usallocal(usalp)->xbuf == NULL ||
+                               sp->size > usallocal(usalp)->xbufsize) {
+                               errno = ENOMEM;
+                               return (-1);
+                       }
+                       sgp2 = sgp = (struct sg_rq *)usallocal(usalp)->xbuf;
+               }
+       }
+
+       /*
+        * This is done to avoid misaligned access of sgp->some_int
+        */
+       pack_len = sizeof (struct sg_header) + amt;
+       reply_len = sizeof (struct sg_header);
+       if (sp->flags & SCG_RECV_DATA) {
+               reply_len += sp->size;
+       } else {
+               pack_len += sp->size;
+       }
+
+#ifdef MISALIGN
+       /*
+        * sgp->some_int may be misaligned if (sp->addr == SCSIbuf)
+        * This is no problem on Intel porocessors, however
+        * all other processors don't like it.
+        * sizeof (struct sg_header) + amt is usually not a multiple of
+        * sizeof (int). For this reason, we fill in the values into sg_rq
+        * which is always corectly aligned and then copy it to the real
+        * location if this location differs from sg_rq.
+        * Never read/write directly to sgp->some_int !!!!!
+        */
+       fillbytes((caddr_t)&sg_rq, sizeof (struct sg_header), '\0');
+
+       sg_rq.hd.pack_len = pack_len;
+       sg_rq.hd.reply_len = reply_len;
+       sg_rq.hd.pack_id = usallocal(usalp)->pack_id++;
+/*     sg_rq.hd.result = 0;    not needed because of fillbytes() */
+
+       if ((caddr_t)&sg_rq != (caddr_t)sgp)
+               movebytes((caddr_t)&sg_rq, (caddr_t)sgp, sizeof (struct sg_header));
+#else
+       fillbytes((caddr_t)sgp, sizeof (struct sg_header), '\0');
+
+       sgp->hd.pack_len = pack_len;
+       sgp->hd.reply_len = reply_len;
+       sgp->hd.pack_id = usallocal(usalp)->pack_id++;
+/*     sgp->hd.result = 0;     not needed because of fillbytes() */
+#endif
+       if (amt == 12)
+               sgp->hd.twelve_byte = 1;
+
+
+       for (i = 0; i < amt; i++) {
+               sgp->buf[i] = sp->cdb.cmd_cdb[i];
+       }
+       if (!(sp->flags & SCG_RECV_DATA)) {
+               if ((void *)sp->addr != (void *)&sgp->buf[amt])
+                       movebytes(sp->addr, &sgp->buf[amt], sp->size);
+               amt += sp->size;
+       }
+#ifdef SG_GET_BUFSIZE
+       sgp->hd.want_new  = 1;                  /* Order new behaviour  */
+       sgp->hd.cdb_len   = sp->cdb_len;        /* Set CDB length       */
+       if (sp->sense_len > SG_MAX_SENSE)
+               sgp->hd.sense_len = SG_MAX_SENSE;
+       else
+               sgp->hd.sense_len = sp->sense_len;
+#endif
+       i = sizeof (struct sg_header) + amt;
+       if ((amt = write(f, sgp, i)) < 0) {                     /* write */
+               sg_settimeout(f, usalp->deftimeout);
+               return (-1);
+       } else if (amt != i) {
+               errmsg("usalo_send(%s) wrote %d bytes (expected %d).\n",
+                                               usalp->cmdname, amt, i);
+       }
+
+       if (sp->addr == usallocal(usalp)->SCSIbuf) {
+               movebytes(sgp, sgp2, sizeof (struct sg_header));
+               sgp = sgp2;
+       }
+       sgp->hd.sense_buffer[0] = 0;
+       if ((amt = read(f, sgp, reply_len)) < 0) {              /* read */
+               sg_settimeout(f, usalp->deftimeout);
+               return (-1);
+       }
+
+       if (sp->flags & SCG_RECV_DATA && ((void *)sgp->buf != (void *)sp->addr)) {
+               movebytes(sgp->buf, sp->addr, sp->size);
+       }
+       sp->ux_errno = GETINT(sgp->hd.result);          /* Unaligned read */
+       sp->error = SCG_NO_ERROR;
+
+#ifdef SG_GET_BUFSIZE
+       if (sgp->hd.grant_new) {
+               sp->sense_count = sgp->hd.sense_len;
+               pack_len    = GETINT(sgp->hd.sg_cmd_status);    /* Unaligned read */
+               driver_byte = (pack_len  >> 24) & 0xFF;
+               host_byte   = (pack_len  >> 16) & 0xFF;
+               msg_byte    = (pack_len  >> 8) & 0xFF;
+               status_byte =  pack_len  & 0xFF;
+
+               switch (host_byte) {
+
+               case DID_OK:
+                               if ((driver_byte & DRIVER_SENSE ||
+                                   sgp->hd.sense_buffer[0] != 0) &&
+                                   status_byte == 0) {
+                                       /*
+                                        * The Linux SCSI system up to 2.4.xx
+                                        * trashes the status byte in the
+                                        * kernel. This is true at least for
+                                        * ide-scsi emulation. Until this gets
+                                        * fixed, we need this hack.
+                                        */
+                                       status_byte = ST_CHK_COND;
+                                       if (sgp->hd.sense_len == 0)
+                                               sgp->hd.sense_len = SG_MAX_SENSE;
+
+                                       if ((sp->u_sense.cmd_sense[2] == 0) &&
+                                           (sp->u_sense.cmd_sense[12] == 0) &&
+                                           (sp->u_sense.cmd_sense[13] == 0)) {
+                                               /*
+                                                * The Linux SCSI system will
+                                                * send a request sense for
+                                                * even a dma underrun error.
+                                                * Clear CHECK CONDITION state
+                                                * in case of No Sense.
+                                                */
+                                               sp->u_scb.cmd_scb[0] = 0;
+                                               sp->u_sense.cmd_sense[0] = 0;
+                                               sp->sense_count = 0;
+                                       }
+                               }
+                               break;
+
+               case DID_NO_CONNECT:    /* Arbitration won, retry NO_CONNECT? */
+                               sp->error = SCG_RETRYABLE;
+                               break;
+
+               case DID_BAD_TARGET:
+                               sp->error = SCG_FATAL;
+                               break;
+
+               case DID_TIME_OUT:
+                               sp->error = SCG_TIMEOUT;
+                               break;
+
+               default:
+                               sp->error = SCG_RETRYABLE;
+
+                               if ((driver_byte & DRIVER_SENSE ||
+                                   sgp->hd.sense_buffer[0] != 0) &&
+                                   status_byte == 0) {
+                                       status_byte = ST_CHK_COND;
+                                       sp->error = SCG_NO_ERROR;
+                               }
+                               if (status_byte != 0 && sgp->hd.sense_len == 0) {
+                                       sgp->hd.sense_len = SG_MAX_SENSE;
+                                       sp->error = SCG_NO_ERROR;
+                               }
+                               break;
+
+               }
+               if ((host_byte != DID_OK || status_byte != 0) && sp->ux_errno == 0)
+                       sp->ux_errno = EIO;
+               sp->u_scb.cmd_scb[0] = status_byte;
+               if (status_byte & ST_CHK_COND) {
+                       sp->sense_count = sgp->hd.sense_len;
+                       movebytes(sgp->hd.sense_buffer, sp->u_sense.cmd_sense, sp->sense_count);
+               }
+       } else
+#endif
+       {
+               if (GETINT(sgp->hd.result) == EBUSY) {  /* Unaligned read */
+                       struct timeval to;
+
+                       to.tv_sec = sp->timeout;
+                       to.tv_usec = 500000;
+                       __usal_times(usalp);
+
+                       if (sp->timeout > 1 && usalp->cmdstop->tv_sec == 0) {
+                               sp->u_scb.cmd_scb[0] = 0;
+                               sp->ux_errno = EIO;
+                               sp->error = SCG_FATAL;  /* a selection timeout */
+                       } else if (usalp->cmdstop->tv_sec < to.tv_sec ||
+                           (usalp->cmdstop->tv_sec == to.tv_sec &&
+                               usalp->cmdstop->tv_usec < to.tv_usec)) {
+
+                               sp->ux_errno = EIO;
+                               sp->error = SCG_TIMEOUT;        /* a timeout */
+                       } else {
+                               sp->error = SCG_RETRYABLE;      /* may be BUS_BUSY */
+                       }
+               }
+
+               if (sp->flags & SCG_RECV_DATA)
+                       sp->resid = (sp->size + sizeof (struct sg_header)) - amt;
+               else
+                       sp->resid = 0;  /* sg version1 cannot return DMA resid count */
+
+               if (sgp->hd.sense_buffer[0] != 0) {
+                       sp->scb.chk = 1;
+                       sp->sense_count = SG_MAX_SENSE;
+                       movebytes(sgp->hd.sense_buffer, sp->u_sense.cmd_sense, sp->sense_count);
+                       if (sp->ux_errno == 0)
+                               sp->ux_errno = EIO;
+               }
+       }
+
+       if (usalp->verbose > 0 && usalp->debug > 0) {
+#ifdef SG_GET_BUFSIZE
+               fprintf((FILE *)usalp->errfile,
+                               "status: 0x%08X pack_len: %d, reply_len: %d pack_id: %d result: %d wn: %d gn: %d cdb_len: %d sense_len: %d sense[0]: %02X\n",
+                               GETINT(sgp->hd.sg_cmd_status),
+                               GETINT(sgp->hd.pack_len),
+                               GETINT(sgp->hd.reply_len),
+                               GETINT(sgp->hd.pack_id),
+                               GETINT(sgp->hd.result),
+                               sgp->hd.want_new,
+                               sgp->hd.grant_new,
+                               sgp->hd.cdb_len,
+                               sgp->hd.sense_len,
+                               sgp->hd.sense_buffer[0]);
+#else
+               fprintf((FILE *)usalp->errfile,
+                               "pack_len: %d, reply_len: %d pack_id: %d result: %d sense[0]: %02X\n",
+                               GETINT(sgp->hd.pack_len),
+                               GETINT(sgp->hd.reply_len),
+                               GETINT(sgp->hd.pack_id),
+                               GETINT(sgp->hd.result),
+                               sgp->hd.sense_buffer[0]);
+#endif
+#ifdef DEBUG
+               fprintf((FILE *)usalp->errfile, "sense: ");
+               for (i = 0; i < 16; i++)
+                       fprintf((FILE *)usalp->errfile, "%02X ", sgp->hd.sense_buffer[i]);
+               fprintf((FILE *)usalp->errfile, "\n");
+#endif
+       }
+
+       if (sp->timeout != usalp->deftimeout)
+               sg_settimeout(f, usalp->deftimeout);
+       return (0);
+};
+
+#define HAVE_NAT_NAMES
+static char * usalo_natname(SCSI *usalp, int busno, int tgt, int tlun) {
+       if (busno >= MAX_SCG || tgt >= MAX_TGT || tlun >= MAX_LUN)
+               return "BADID";
+       return usallocal(usalp)->filenames[busno][tgt][tlun];
+}
diff --git a/libusal/scsi-mac-iokit.c b/libusal/scsi-mac-iokit.c
new file mode 100644 (file)
index 0000000..7e5ee4f
--- /dev/null
@@ -0,0 +1,539 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)scsi-mac-iokit.c        1.10 05/05/15 Copyright 1997,2001-2004 J. Schilling */
+/*
+ *     Interface to the Darwin IOKit SCSI drivers
+ *
+ *     Notes: Uses the IOKit/scsi-commands/SCSITaskLib interface
+ *
+ *     As of October 2001, this interface does not support SCSI parallel bus
+ *     (old-fashioned SCSI). It does support ATAPI, Firewire, and USB.
+ *
+ *     First version done by Constantine Sapuntzakis <csapuntz@Stanford.EDU>
+ *
+ *     Warning: you may change this source, but if you do that
+ *     you need to change the _usal_version and _usal_auth* string below.
+ *     You may not return "schily" for an SCG_AUTHOR request anymore.
+ *     Choose your name instead of "schily" and make clear that the version
+ *     string is related to a modified source.
+ *
+ *     Copyright (c) 1997,2001-2004 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*
+ *     Warning: you may change this source, but if you do that
+ *     you need to change the _usal_version and _usal_auth* string below.
+ *     You may not return "schily" for an SCG_AUTHOR request anymore.
+ *     Choose your name instead of "schily" and make clear that the version
+ *     string is related to a modified source.
+ */
+static char    _usal_trans_version[] = "scsi-mac-iokit.c-1.10";        /* The version for this transport */
+
+#define        MAX_SCG         16      /* Max # of SCSI controllers */
+#define        MAX_TGT         16
+#define        MAX_LUN         8
+
+#include <statdefs.h>
+#include <mach/mach.h>
+#include <Carbon/Carbon.h>
+#include <IOKit/IOKitLib.h>
+#include <IOKit/IOCFPlugIn.h>
+#include <IOKit/scsi-commands/SCSITaskLib.h>
+#include <mach/mach_error.h>
+
+struct usal_local {
+       MMCDeviceInterface      **mmcDeviceInterface;
+       SCSITaskDeviceInterface **scsiTaskDeviceInterface;
+       mach_port_t             masterPort;
+};
+#define        usallocal(p)    ((struct usal_local *)((p)->local))
+
+#define        MAX_DMA_NEXT    (32*1024)
+#if 0
+#define        MAX_DMA_NEXT    (64*1024)       /* Check if this is not too big */
+#endif
+
+/*
+ * Return version information for the low level SCSI transport code.
+ * This has been introduced to make it easier to trace down problems
+ * in applications.
+ */
+static char *
+usalo_version(SCSI *usalp, int what)
+{
+       if (usalp != (SCSI *)0) {
+               switch (what) {
+
+               case SCG_VERSION:
+                       return (_usal_trans_version);
+               /*
+                * If you changed this source, you are not allowed to
+                * return "schily" for the SCG_AUTHOR request.
+                */
+               case SCG_AUTHOR:
+                       return (_usal_auth_cdrkit);
+               case SCG_SCCS_ID:
+                       return (__sccsid);
+               }
+       }
+       return ((char *)0);
+}
+
+static int
+usalo_help(SCSI *usalp, FILE *f)
+{
+       __usal_help(f, "SCSITaskDeviceInterface", "Apple SCSI",
+               "", "Mac Prom device name", "IOCompactDiscServices/0",
+                                                               FALSE, FALSE);
+       return (0);
+}
+
+
+/*
+ * Valid Device names:
+ *    IOCompactDiscServices
+ *    IODVDServices
+ *    IOSCSIPeripheralDeviceNub
+ *
+ * Also a / and a number can be appended to refer to something
+ * more than the first device (e.g. IOCompactDiscServices/5 for the 5th
+ * compact disc attached)
+ */
+static int
+usalo_open(SCSI *usalp, char *device)
+{
+       mach_port_t masterPort = NULL;
+       io_iterator_t scsiObjectIterator = NULL;
+       IOReturn ioReturnValue = kIOReturnSuccess;
+       CFMutableDictionaryRef dict = NULL;
+       io_object_t scsiDevice = NULL;
+       HRESULT plugInResult;
+       IOCFPlugInInterface **plugInInterface = NULL;
+       MMCDeviceInterface **mmcDeviceInterface = NULL;
+       SCSITaskDeviceInterface **scsiTaskDeviceInterface = NULL;
+       SInt32 score = 0;
+       int err = -1;
+       char *realdevice = NULL, *tmp;
+       int driveidx = 1, idx = 1;
+
+       if (device == NULL) {
+               snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+               "Please specify a device name (e.g. IOCompactDiscServices/0)");
+               goto out;
+       }
+
+       realdevice = tmp = strdup(device);
+       tmp = strchr(tmp, '/');
+       if (tmp != NULL) {
+               *tmp++ = '\0';
+               driveidx = atoi(tmp);
+       }
+
+       if (usalp->local == NULL) {
+               usalp->local = malloc(sizeof (struct usal_local));
+               if (usalp->local == NULL)
+                       goto out;
+       }
+
+       ioReturnValue = IOMasterPort(bootstrap_port, &masterPort);
+
+       if (ioReturnValue != kIOReturnSuccess) {
+               snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                           "Couldn't get a master IOKit port. Error %d",
+                           ioReturnValue);
+               goto out;
+       }
+
+       dict = IOServiceMatching(realdevice);
+       if (dict == NULL) {
+               snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                           "Couldn't create dictionary for searching");
+               goto out;
+       }
+
+       ioReturnValue = IOServiceGetMatchingServices(masterPort, dict,
+                                                   &scsiObjectIterator);
+       dict = NULL;
+
+       if (scsiObjectIterator == NULL ||
+           (ioReturnValue != kIOReturnSuccess)) {
+               snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                           "No matching device %s found.", device);
+               goto out;
+       }
+
+       if (driveidx <= 0)
+               driveidx = 1;
+
+       idx = 1;
+       while ((scsiDevice = IOIteratorNext(scsiObjectIterator)) != NULL) {
+               if (idx == driveidx)
+                       break;
+               IOObjectRelease(scsiDevice);
+               scsiDevice = NULL;
+               idx++;
+       }
+
+       if (scsiDevice == NULL) {
+               snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                           "No matching device found. Iterator failed.");
+               goto out;
+       }
+
+       ioReturnValue = IOCreatePlugInInterfaceForService(scsiDevice,
+                       kIOMMCDeviceUserClientTypeID,
+                       kIOCFPlugInInterfaceID,
+                       &plugInInterface, &score);
+       if (ioReturnValue != kIOReturnSuccess) {
+               goto try_generic;
+       }
+
+       plugInResult = (*plugInInterface)->QueryInterface(plugInInterface,
+                               CFUUIDGetUUIDBytes(kIOMMCDeviceInterfaceID),
+                               (LPVOID)&mmcDeviceInterface);
+
+       if (plugInResult != KERN_SUCCESS) {
+               snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                           "Unable to get MMC Interface: 0x%lX",
+                           (long)plugInResult);
+
+               goto out;
+       }
+
+       scsiTaskDeviceInterface =
+               (*mmcDeviceInterface)->GetSCSITaskDeviceInterface(mmcDeviceInterface);
+
+       if (scsiTaskDeviceInterface == NULL) {
+               snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                           "Failed to get taskDeviceInterface");
+               goto out;
+       }
+
+       goto init;
+
+try_generic:
+       ioReturnValue = IOCreatePlugInInterfaceForService(scsiDevice,
+                                       kIOSCSITaskDeviceUserClientTypeID,
+                                       kIOCFPlugInInterfaceID,
+                                       &plugInInterface, &score);
+       if (ioReturnValue != kIOReturnSuccess) {
+               snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                           "Unable to get plugin Interface: %x",
+                           ioReturnValue);
+               goto out;
+       }
+
+       plugInResult = (*plugInInterface)->QueryInterface(plugInInterface,
+                           CFUUIDGetUUIDBytes(kIOSCSITaskDeviceInterfaceID),
+                                       (LPVOID)&scsiTaskDeviceInterface);
+
+       if (plugInResult != KERN_SUCCESS) {
+               snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                           "Unable to get generic Interface: 0x%lX",
+                           (long)plugInResult);
+
+               goto out;
+       }
+
+init:
+       ioReturnValue =
+               (*scsiTaskDeviceInterface)->ObtainExclusiveAccess(scsiTaskDeviceInterface);
+
+       if (ioReturnValue != kIOReturnSuccess) {
+               snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                           "Unable to get exclusive access to device");
+               goto out;
+       }
+
+       if (mmcDeviceInterface) {
+               (*mmcDeviceInterface)->AddRef(mmcDeviceInterface);
+       }
+       (*scsiTaskDeviceInterface)->AddRef(scsiTaskDeviceInterface);
+       usallocal(usalp)->mmcDeviceInterface = mmcDeviceInterface;
+       usallocal(usalp)->scsiTaskDeviceInterface = scsiTaskDeviceInterface;
+       usallocal(usalp)->masterPort = masterPort;
+       usal_settarget(usalp, 0, 0, 0);
+       err = 1;
+
+out:
+       if (scsiTaskDeviceInterface != NULL) {
+               (*scsiTaskDeviceInterface)->Release(scsiTaskDeviceInterface);
+       }
+
+       if (plugInInterface != NULL) {
+               (*plugInInterface)->Release(plugInInterface);
+       }
+
+       if (scsiDevice != NULL) {
+               IOObjectRelease(scsiDevice);
+       }
+
+       if (scsiObjectIterator != NULL) {
+               IOObjectRelease(scsiObjectIterator);
+       }
+
+       if (err < 0) {
+               if (usalp->local) {
+                       free(usalp->local);
+                       usalp->local = NULL;
+               }
+
+               if (masterPort) {
+                       mach_port_deallocate(mach_task_self(), masterPort);
+               }
+       }
+
+       if (dict != NULL) {
+               CFRelease(dict);
+       }
+
+       if (realdevice != NULL) {
+               free(realdevice);
+       }
+       return (err);
+}
+
+static int
+usalo_close(SCSI *usalp)
+{
+       SCSITaskDeviceInterface **sc;
+       MMCDeviceInterface      **mmc;
+
+       if (usalp->local == NULL)
+               return (-1);
+
+       sc = usallocal(usalp)->scsiTaskDeviceInterface;
+       (*sc)->ReleaseExclusiveAccess(sc);
+       (*sc)->Release(sc);
+       usallocal(usalp)->scsiTaskDeviceInterface = NULL;
+
+       mmc = usallocal(usalp)->mmcDeviceInterface;
+       if (mmc != NULL)
+               (*mmc)->Release(mmc);
+
+       mach_port_deallocate(mach_task_self(), usallocal(usalp)->masterPort);
+
+       free(usalp->local);
+       usalp->local = NULL;
+
+       return (0);
+}
+
+static long
+usalo_maxdma(SCSI *usalp, long amt)
+{
+       long maxdma = MAX_DMA_NEXT;
+#ifdef SGIOCMAXDMA
+       int  m;
+
+       if (ioctl(usallocal(usalp)->usalfile, SGIOCMAXDMA, &m) >= 0) {
+               maxdma = m;
+               if (usalp->debug > 0) {
+                       fprintf((FILE *)usalp->errfile,
+                               "maxdma: %d\n", maxdma);
+               }
+       }
+#endif
+       return (maxdma);
+}
+
+static void *
+usalo_getbuf(SCSI *usalp, long amt)
+{
+       if (usalp->debug > 0) {
+               fprintf((FILE *)usalp->errfile,
+                       "usalo_getbuf: %ld bytes\n", amt);
+       }
+       usalp->bufbase = malloc((size_t)(amt));
+       return (usalp->bufbase);
+}
+
+static void
+usalo_freebuf(SCSI *usalp)
+{
+       if (usalp->bufbase)
+               free(usalp->bufbase);
+       usalp->bufbase = NULL;
+}
+
+static BOOL
+usalo_havebus(SCSI *usalp, int busno)
+{
+       if (busno == 0)
+               return (TRUE);
+       return (FALSE);
+}
+
+static int
+usalo_fileno(SCSI *usalp, int busno, int tgt, int tlun)
+{
+       return (-1);
+}
+
+static int
+usalo_initiator_id(SCSI *usalp)
+{
+       return (-1);
+}
+
+static int
+usalo_isatapi(SCSI *usalp)
+{
+       return (FALSE);
+}
+
+static int
+usalo_reset(SCSI *usalp, int what)
+{
+       if (what == SCG_RESET_NOP)
+               return (0);
+       if (what != SCG_RESET_BUS) {
+               errno = EINVAL;
+               return (-1);
+       }
+
+       errno = 0;
+       return (-1);
+}
+
+static int
+usalo_send(SCSI *usalp)
+{
+       struct usal_cmd         *sp = usalp->scmd;
+       SCSITaskDeviceInterface **sc = NULL;
+       SCSITaskInterface       **cmd = NULL;
+       IOVirtualRange          iov;
+       SCSI_Sense_Data         senseData;
+       SCSITaskStatus          status;
+       UInt64                  bytesTransferred;
+       IOReturn                ioReturnValue;
+       int                     ret = 0;
+
+       if (usalp->local == NULL) {
+               return (-1);
+       }
+
+       sc = usallocal(usalp)->scsiTaskDeviceInterface;
+
+       cmd = (*sc)->CreateSCSITask(sc);
+       if (cmd == NULL) {
+               snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                           "Failed to create SCSI task");
+               ret = -1;
+
+               sp->error = SCG_FATAL;
+               sp->ux_errno = EIO;
+               goto out;
+       }
+
+
+       iov.address = (IOVirtualAddress) sp->addr;
+       iov.length = sp->size;
+
+       ioReturnValue = (*cmd)->SetCommandDescriptorBlock(cmd,
+                                               sp->cdb.cmd_cdb, sp->cdb_len);
+
+       if (ioReturnValue != kIOReturnSuccess) {
+               snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                           "SetCommandDescriptorBlock failed with status %x",
+                           ioReturnValue);
+               ret = -1;
+               goto out;
+       }
+
+       ioReturnValue = (*cmd)->SetScatterGatherEntries(cmd, &iov, 1, sp->size,
+                               (sp->flags & SCG_RECV_DATA) ?
+                               kSCSIDataTransfer_FromTargetToInitiator :
+                               kSCSIDataTransfer_FromInitiatorToTarget);
+       if (ioReturnValue != kIOReturnSuccess) {
+               snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                           "SetScatterGatherEntries failed with status %x",
+                           ioReturnValue);
+               ret = -1;
+               goto out;
+       }
+
+       ioReturnValue = (*cmd)->SetTimeoutDuration(cmd, sp->timeout * 1000);
+       if (ioReturnValue != kIOReturnSuccess) {
+               snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                           "SetTimeoutDuration failed with status %x",
+                           ioReturnValue);
+               ret = -1;
+               goto out;
+       }
+
+       memset(&senseData, 0, sizeof (senseData));
+
+       seterrno(0);
+       ioReturnValue = (*cmd)->ExecuteTaskSync(cmd,
+                               &senseData, &status, &bytesTransferred);
+
+       sp->resid = sp->size - bytesTransferred;
+       sp->error = SCG_NO_ERROR;
+       sp->ux_errno = geterrno();
+
+       if (ioReturnValue != kIOReturnSuccess) {
+               snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                           "Command execution failed with status %x",
+                           ioReturnValue);
+               sp->error = SCG_RETRYABLE;
+               ret = -1;
+               goto out;
+       }
+
+       memset(&sp->scb, 0, sizeof (sp->scb));
+       memset(&sp->u_sense.cmd_sense, 0, sizeof (sp->u_sense.cmd_sense));
+       if (senseData.VALID_RESPONSE_CODE != 0 || status == 0x02) {
+               /*
+                * There is no sense length - we need to asume that
+                * we always get 18 bytes.
+                */
+               sp->sense_count = kSenseDefaultSize;
+               memmove(&sp->u_sense.cmd_sense, &senseData, kSenseDefaultSize);
+               if (sp->ux_errno == 0)
+                       sp->ux_errno = EIO;
+       }
+
+       sp->u_scb.cmd_scb[0] = status;
+
+       /* ??? */
+       if (status == kSCSITaskStatus_No_Status) {
+               sp->error = SCG_RETRYABLE;
+               ret = -1;
+               goto out;
+       }
+       /*
+        * XXX Is it possible to have other senseful SCSI transport error codes?
+        */
+
+out:
+       if (cmd != NULL) {
+               (*cmd)->Release(cmd);
+       }
+
+       return (ret);
+}
diff --git a/libusal/scsi-next.c b/libusal/scsi-next.c
new file mode 100644 (file)
index 0000000..bfbe2b3
--- /dev/null
@@ -0,0 +1,419 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)scsi-next.c     1.32 04/01/15 Copyright 1997 J. Schilling */
+/*
+ *     Interface for the NeXT Step generic SCSI implementation.
+ *
+ *     This is a hack, that tries to emulate the functionality
+ *     of the usal driver.
+ *
+ *     Warning: you may change this source, but if you do that
+ *     you need to change the _usal_version and _usal_auth* string below.
+ *     You may not return "schily" for an SCG_AUTHOR request anymore.
+ *     Choose your name instead of "schily" and make clear that the version
+ *     string is related to a modified source.
+ *
+ *     Copyright (c) 1997 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <bsd/dev/scsireg.h>
+
+/*
+ *     Warning: you may change this source, but if you do that
+ *     you need to change the _usal_version and _usal_auth* string below.
+ *     You may not return "schily" for an SCG_AUTHOR request anymore.
+ *     Choose your name instead of "schily" and make clear that the version
+ *     string is related to a modified source.
+ */
+static char    _usal_trans_version[] = "scsi-next.c-1.32";     /* The version for this transport*/
+
+#define        MAX_SCG         16      /* Max # of SCSI controllers */
+#define        MAX_TGT         16
+#define        MAX_LUN         8
+
+struct usal_local {
+       short   usalfiles[MAX_SCG][MAX_TGT][MAX_LUN];
+       int     usalfile;
+       int     max_scsibus;
+       int     cur_scsibus;
+       int     cur_target;
+       int     cur_lun;
+};
+#define        usallocal(p)    ((struct usal_local *)((p)->local))
+
+/*#define      MAX_DMA_NEXT    (32*1024)*/
+#define        MAX_DMA_NEXT    (64*1024)       /* Check if this is not too big */
+
+
+static BOOL    usal_setup(SCSI *usalp, int busno, int tgt, int tlun, BOOL ex);
+
+/*
+ * Return version information for the low level SCSI transport code.
+ * This has been introduced to make it easier to trace down problems
+ * in applications.
+ */
+static char *
+usalo_version(SCSI *usalp, int what)
+{
+       if (usalp != (SCSI *)0) {
+               switch (what) {
+
+               case SCG_VERSION:
+                       return (_usal_trans_version);
+               /*
+                * If you changed this source, you are not allowed to
+                * return "schily" for the SCG_AUTHOR request.
+                */
+               case SCG_AUTHOR:
+                       return (_usal_auth_cdrkit);
+               case SCG_SCCS_ID:
+                       return (__sccsid);
+               }
+       }
+       return ((char *)0);
+}
+
+static int
+usalo_help(SCSI *usalp, FILE *f)
+{
+       __usal_help(f, "SGIOCREQ", "Generic SCSI",
+               "", "bus,target,lun", "1,2,0", TRUE, FALSE);
+       return (0);
+}
+
+static int
+usalo_open(SCSI *usalp, char *device)
+{
+               int     busno   = usal_scsibus(usalp);
+               int     tgt     = usal_target(usalp);
+               int     tlun    = usal_lun(usalp);
+       register int    f;
+       register int    i;
+       char            devname[64];
+
+       if (busno >= MAX_SCG || tgt >= MAX_TGT || tlun >= MAX_LUN) {
+               errno = EINVAL;
+               if (usalp->errstr)
+                       snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                               "Illegal value for busno, target or lun '%d,%d,%d'",
+                               busno, tgt, tlun);
+               return (-1);
+       }
+
+       if ((device != NULL && *device != '\0') || (busno == -2 && tgt == -2)) {
+               errno = EINVAL;
+               if (usalp->errstr)
+                       snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                               "Open by 'devname' not supported on this OS");
+               return (-1);
+       }
+
+       if (usalp->local == NULL) {
+               usalp->local = malloc(sizeof (struct usal_local));
+               if (usalp->local == NULL)
+                       return (0);
+
+               usallocal(usalp)->usalfile              = -1;
+               usallocal(usalp)->max_scsibus   = -1;
+               usallocal(usalp)->cur_scsibus   = -1;
+               usallocal(usalp)->cur_target    = -1;
+               usallocal(usalp)->cur_lun               = -1;
+       }
+
+       for (i = 0; i < 4; i++) {
+               snprintf(devname, sizeof (devname), "/dev/sg%d", i);
+               f = open(devname, O_RDWR);
+               if (usalp->debug > 0)
+                       errmsg("open(devname: '%s') : %d\n", devname, f);
+               if (f < 0)
+                       continue;
+               usallocal(usalp)->usalfile = f;
+               break;
+
+       }
+       if (f >= 0) {
+               if (usallocal(usalp)->max_scsibus < 0) {
+                       for (i = 0; i < MAX_SCG; i++) {
+                               if (!SCGO_HAVEBUS(usalp, i))
+                                       break;
+                       }
+                       usallocal(usalp)->max_scsibus = i;
+               }
+               if (usalp->debug > 0) {
+                       fprintf((FILE *)usalp->errfile,
+                               "maxbus: %d\n", usallocal(usalp)->max_scsibus);
+               }
+               if (usallocal(usalp)->max_scsibus <= 0) {
+                       usallocal(usalp)->max_scsibus = 1;
+                       usallocal(usalp)->cur_scsibus = 0;
+               }
+
+               ioctl(f, SGIOCENAS);
+               if (busno > 0 && tgt > 0 && tlun > 0)
+                       usal_setup(usalp, busno, tgt, tlun, TRUE);
+               return (1);
+       }
+       if (usalp->errstr)
+               snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                       "Cannot open '/dev/sg*'");
+       return (0);
+}
+
+static int
+usalo_close(SCSI *usalp)
+{
+       if (usalp->local == NULL)
+               return (-1);
+
+       if (usallocal(usalp)->usalfile >= 0)
+               close(usallocal(usalp)->usalfile);
+       usallocal(usalp)->usalfile = -1;
+       return (0);
+}
+
+static BOOL
+usal_setup(SCSI *usalp, int busno, int tgt, int tlun, BOOL ex)
+{
+       scsi_adr_t sadr;
+
+       sadr.sa_target = tgt;
+       sadr.sa_lun = tlun;
+
+       if (usalp->debug > 0) {
+               fprintf((FILE *)usalp->errfile,
+                       "usal_setup curbus %d -> %d\n", usallocal(usalp)->cur_scsibus, busno);
+       }
+
+       if (usalp->debug > 0 && ((usallocal(usalp)->cur_scsibus < 0 || usallocal(usalp)->cur_scsibus != busno)))
+               fprintf((FILE *)usalp->errfile, "setting SCSI bus to: %d\n", busno);
+       if ((usallocal(usalp)->cur_scsibus < 0 || usallocal(usalp)->cur_scsibus != busno) &&
+                               ioctl(usallocal(usalp)->usalfile, SGIOCCNTR, &busno) < 0) {
+
+               usallocal(usalp)->cur_scsibus = -1;     /* Driver is in undefined state */
+               if (ex)
+/*                     comerr("Cannot set SCSI bus\n");*/
+                       errmsg("Cannot set SCSI bus\n");
+               return (FALSE);
+       }
+       usallocal(usalp)->cur_scsibus   = busno;
+
+       if (usalp->debug > 0) {
+               fprintf((FILE *)usalp->errfile,
+                       "setting target/lun to: %d/%d\n", tgt, tlun);
+       }
+       if (ioctl(usallocal(usalp)->usalfile, SGIOCSTL, &sadr) < 0) {
+               if (ex)
+                       comerr("Cannot set SCSI address\n");
+               return (FALSE);
+       }
+       usallocal(usalp)->cur_scsibus   = busno;
+       usallocal(usalp)->cur_target    = tgt;
+       usallocal(usalp)->cur_lun               = tlun;
+       return (TRUE);
+}
+
+static long
+usalo_maxdma(SCSI *usalp, long amt)
+{
+       long maxdma = MAX_DMA_NEXT;
+#ifdef SGIOCMAXDMA
+       int  m;
+
+       if (ioctl(usallocal(usalp)->usalfile, SGIOCMAXDMA, &m) >= 0) {
+               maxdma = m;
+               if (usalp->debug > 0) {
+                       fprintf((FILE *)usalp->errfile,
+                               "maxdma: %d\n", maxdma);
+               }
+       }
+#endif
+       return (maxdma);
+}
+#ifdef XXX
+#define        SGIOCENAS       _IO('s', 2)                     /* enable autosense */
+#define        SGIOCDAS        _IO('s', 3)                     /* disable autosense */
+#define        SGIOCRST        _IO('s', 4)                     /* reset SCSI bus */
+#define        SGIOCCNTR       _IOW('s', 6, int)               /* select controller */
+#define        SGIOCGAS        _IOR('s', 7, int)               /* get autosense */
+#define        SGIOCMAXDMA     _IOR('s', 8, int)               /* max DMA size */
+#define        SGIOCNUMTARGS   _IOR('s', 9, int)               /* # of targets/bus */
+#endif
+
+static void *
+usalo_getbuf(SCSI *usalp, long amt)
+{
+       if (usalp->debug > 0) {
+               fprintf((FILE *)usalp->errfile,
+                       "usalo_getbuf: %ld bytes\n", amt);
+       }
+       usalp->bufbase = valloc((size_t)(amt));
+       return (usalp->bufbase);
+}
+
+static void
+usalo_freebuf(SCSI *usalp)
+{
+       if (usalp->bufbase)
+               free(usalp->bufbase);
+       usalp->bufbase = NULL;
+}
+
+static BOOL
+usalo_havebus(SCSI *usalp, int busno)
+{
+       if (busno < 0 || busno >= MAX_SCG)
+               return (FALSE);
+
+       if (usalp->local == NULL)
+               return (FALSE);
+
+       if (usallocal(usalp)->max_scsibus > 0 && busno >= usallocal(usalp)->max_scsibus)
+               return (FALSE);
+
+       return (usal_setup(usalp, busno, 0, 0, FALSE));
+}
+
+static int
+usalo_fileno(SCSI *usalp, int busno, int tgt, int tlun)
+{
+       if (busno < 0 || busno >= MAX_SCG ||
+           tgt < 0 || tgt >= MAX_TGT ||
+           tlun < 0 || tlun >= MAX_LUN)
+               return (-1);
+       if (usallocal(usalp)->max_scsibus > 0 && busno >= usallocal(usalp)->max_scsibus)
+               return (-1);
+
+       if (usalp->local == NULL)
+               return (-1);
+
+       if ((busno != usallocal(usalp)->cur_scsibus) || (tgt != usallocal(usalp)->cur_target) || (tlun != usallocal(usalp)->cur_lun)) {
+               if (!usal_setup(usalp, busno, tgt, tlun, FALSE))
+                       return (-1);
+       }
+       return (usallocal(usalp)->usalfile);
+}
+
+static int
+usalo_initiator_id(SCSI *usalp)
+{
+       return (-1);
+}
+
+static int
+usalo_isatapi(SCSI *usalp)
+{
+       return (FALSE);
+}
+
+static int
+usalo_reset(SCSI *usalp, int what)
+{
+       if (what == SCG_RESET_NOP)
+               return (0);
+       if (what != SCG_RESET_BUS) {
+               errno = EINVAL;
+               return (-1);
+       }
+       return (ioctl(usalp->fd, SGIOCRST, 0));
+}
+
+static int
+usalo_send(SCSI *usalp)
+{
+       struct usal_cmd *sp = usalp->scmd;
+       struct scsi_req req;
+       register long   *lp1;
+       register long   *lp2;
+       int             ret = 0;
+
+       if (usalp->fd < 0 || (sp->cdb_len > sizeof (req.sr_cdb))) {
+               sp->error = SCG_FATAL;
+               sp->ux_errno = EIO;
+               return (0);
+       }
+       fillbytes(&req, sizeof (req), '\0');
+       movebytes(sp->cdb.cmd_cdb, &req.sr_cdb, sp->cdb_len);
+       if (sp->size) {
+               req.sr_dma_dir = SR_DMA_WR;
+               if (sp->flags & SCG_RECV_DATA)
+                       req.sr_dma_dir = SR_DMA_RD;
+       }
+       req.sr_addr = sp->addr;
+       req.sr_dma_max = sp->size;
+       req.sr_ioto = sp->timeout;
+       if (ioctl(usalp->fd, SGIOCREQ, (void *)&req) < 0) {
+               ret  = -1;
+               sp->ux_errno = geterrno();
+               if (sp->ux_errno != ENOTTY)
+                       ret = 0;
+       } else {
+               sp->ux_errno = 0;
+       }
+       if (usalp->debug > 0) {
+               fprintf((FILE *)usalp->errfile, "dma_dir:     %X\n", req.sr_dma_dir);
+               fprintf((FILE *)usalp->errfile, "dma_addr:    %X\n", req.sr_addr);
+               fprintf((FILE *)usalp->errfile, "io_time:     %d\n", req.sr_ioto);
+               fprintf((FILE *)usalp->errfile, "io_status:   %d\n", req.sr_io_status);
+               fprintf((FILE *)usalp->errfile, "scsi_status: %X\n", req.sr_scsi_status);
+               fprintf((FILE *)usalp->errfile, "dma_xfer:    %d\n", req.sr_dma_xfr);
+       }
+       sp->u_scb.cmd_scb[0] = req.sr_scsi_status;
+       sp->sense_count = sizeof (esense_reply_t);
+       if (sp->sense_count > sp->sense_len)
+               sp->sense_count = sp->sense_len;
+       if (sp->sense_count > SCG_MAX_SENSE)
+               sp->sense_count = SCG_MAX_SENSE;
+       if (sp->sense_count < 0)
+               sp->sense_count = 0;
+       movebytes(&req.sr_esense, sp->u_sense.cmd_sense, sp->sense_count);
+       sp->resid = sp->size - req.sr_dma_xfr;
+
+       switch (req.sr_io_status) {
+
+       case SR_IOST_GOOD:      sp->error = SCG_NO_ERROR;       break;
+
+       case SR_IOST_CHKSNV:    sp->sense_count = 0;
+       case SR_IOST_CHKSV:     sp->error = SCG_RETRYABLE;
+                               break;
+
+       case SR_IOST_SELTO:
+       case SR_IOST_DMAOR:
+                               sp->error = SCG_FATAL;          break;
+
+       case SR_IOST_IOTO:      sp->error = SCG_TIMEOUT;        break;
+
+       case SR_IOST_PERM:
+       case SR_IOST_NOPEN:
+                               sp->error = SCG_FATAL;
+                               ret = (-1);
+                               break;
+
+       default:                sp->error = SCG_RETRYABLE;      break;
+
+       }
+       return (ret);
+}
diff --git a/libusal/scsi-openserver.c b/libusal/scsi-openserver.c
new file mode 100644 (file)
index 0000000..d192302
--- /dev/null
@@ -0,0 +1,1015 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)scsi-openserver.c       1.31 04/01/15 Copyright 1998 J. Schilling, Santa Cruz Operation */
+/*
+ *     Interface for the SCO SCSI implementation.
+ *
+ *     Warning: you may change this source, but if you do that
+ *     you need to change the _usal_version and _usal_auth* string below.
+ *     You may not return "schily" for an SCG_AUTHOR request anymore.
+ *     Choose your name instead of "schily" and make clear that the version
+ *     string is related to a modified source.
+ *
+ *     Copyright (c) 1998 J. Schilling, Santa Cruz Operation
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#undef sense
+
+#include <sys/scsicmd.h>
+
+/*
+ *     Warning: you may change this source, but if you do that
+ *     you need to change the _usal_version and _usal_auth* string below.
+ *     You may not return "schily" for an SCG_AUTHOR request anymore.
+ *     Choose your name instead of "schily" and make clear that the version
+ *     string is related to a modified source.
+ */
+static char    _usal_trans_version[] = "scsi-openserver.c-1.31";       /* The version for this transport*/
+
+#define        MAX_SCG         16              /* Max # of cdrom devices */
+#define        MAX_TGT         16              /* Not really needed      */
+#define        MAX_LUN         8               /* Not really needed      */
+
+#define        MAX_DMA         (64*1024)
+
+#define        MAXPATH         256             /* max length of devicepath  */
+#define        MAXLINE         80              /* max length of input line  */
+#define        MAXSCSI         99              /* max number of mscsi lines */
+#define        MAXDRVN         10              /* max length of drivername  */
+
+#define        DEV_DIR         "/tmp"
+#define        DEV_NAME        "usal.s%1dt%1dl%1d"
+
+/*
+ * ---------------------------------------------------------------------
+ * We will only deal with cdroms by default! Only if you set a specific
+ * environment variable, we will scan "all" devices !
+ * Set LIBSCG_SCAN_ALL to any value to enable access to all your SCSI
+ * devices.
+ *
+ * The upcoming support for USB will be for USB 1.1, so as this is not
+ * tested yet, we will currently ignore drives connect to the USB stack
+ * (usbha controller) regardless of having set LIBSCG_SCAN_ALL or not!
+ */
+
+#define        DEV_ROOT        "/dev/dsk/0s0"
+
+#define        DEV_SDSK        "/dev/rdsk/%ds0"
+#define        DEV_SROM        "/dev/rcd%d"
+#define        DEV_STP         "/dev/xStp%d"
+#define        DEV_SFLP        "/dev/rdsk/fp%dh"
+
+#define        SCAN_DEV        "%s%s%d%d%d%d"
+
+#define        SCSI_CFG        "/etc/sconf -r"         /* no. of configured devices  */
+#define        SCSI_DEV        "/etc/sconf -g %d"      /* read line 'n' of mscsi tbl */
+
+#define        DRV_ATAPI       "wd"            /* SCO OpenServer IDE driver    */
+#define        DRV_USB         "usbha"         /* SCO OpenServer USB driver    */
+#define        DRV_NOHA        "noha"          /* IDE/ATAPI device configured, */
+                                       /* but missing !                */
+
+
+#define        T_DISK          "Sdsk"          /* SCO OpenServer SCSI disk     */
+#define        T_CDROM         "Srom"          /* SCO OpenServer SCSI cdrom    */
+#define        T_TAPE          "Stp"           /* SCO OpenServer SCSI tape     */
+#define        T_FLOPPY        "Sflp"          /* SCO OpenServer SCSI floppy   */
+
+
+/*
+ * ---------------------------------------------------------------------
+ * Environment variables to control certain functionality
+ */
+
+#define        SCAN_ALL        "LIBSCG_SCAN_ALL"       /* enable access for all devices */
+#define        SCSI_USER_CMD   "LIBSCG_SCSIUSERCMD"    /* use old SCSIUSERCMD ioctl() */
+#define        DMA_OVERRIDE    "LIBSCG_MAX_DMA"        /* override MAX_DMA value */
+#define        ENABLE_USB      "LIBSCG_ENABLE_USB"     /* enable access of USB devices */
+
+static int     scan_all        = 0;    /* don't scan all devices by default */
+static int     scsiusercmd     = 0;    /* use SCSIUSERCMD2 ioctl by default */
+static int     enable_usb      = 0;    /* don't scan USB devices by default */
+static long    max_dma         = MAX_DMA; /* use MAX_DMA DMA buffer by default */
+
+
+/*
+ * ---------------------------------------------------------------------
+ * There are two scsi passthrough ioctl() on SCO OpenServer 5.0.[45],
+ * while there is only one available on SCO OpenServer 5.0.[02].
+ *
+ * The SCSIUSERCMD ioctl is available on all OpenServer 5
+ *
+ * The SCSIUSERCMD2 ioctl which executes the usercmd and reads the sense
+ * in one go, is only available from 5.0.4 onwards.
+ *
+ * By default we will use the SCSIUSERCMD2 ioctl(), in order to execute
+ * the SCSIUSERCMD ioctl() instead set the environment variable
+ * LIBSCG_SCSIUSERCMD to any value. Using the olderSCSIUSERCMD ioctl() will
+ * if the SCSI commands returns a CHECK CONDITION status, run a seperate
+ * REQUEST_SENSE command immediately. But we need to remember that in a
+ * multi-tasking environment, there might be other code which has accessed
+ * the device in between these two steps and therefore the sense code
+ * is no longer valid !!!
+ *
+ * NOTE: There are problems with the usage of AHA 154X controllers
+ * and SCSIUSERCMD2 such as nonsense (weird) output on cdrecord -scanbus
+ *
+ */
+
+
+typedef struct usal2sdi {
+
+       int     valid;
+       int     open;
+       int     atapi;
+       int     fd;
+       int     lmscsi;
+
+} usal2sdi_t;
+
+static usal2sdi_t      sdidevs [MAX_SCG][MAX_TGT][MAX_LUN];
+
+typedef struct amscsi {
+       char    typ[MAXDRVN];
+       char    drv[MAXDRVN];
+       int     hba;
+       int     bus;
+       int     usal;
+       int     tgt;
+       int     lun;
+       char    dev[MAXPATH];
+
+} amscsi_t;
+
+struct usal_local {
+       short   usalfiles[MAX_SCG][MAX_TGT][MAX_LUN];
+};
+#define        usallocal(p)    ((struct usal_local *)((p)->local))
+
+static int     sort_mscsi(const void *l1, const void *l2);
+static int     openserver_init(SCSI *usalp);
+static void    cp_usal2sco(struct scsicmd2 *sco, struct usal_cmd *usal);
+static void    cp_sco2usal(struct scsicmd2 *sco, struct usal_cmd *usal);
+
+/*
+ * -------------------------------------------------------------------------
+ * SCO OpenServer does not have a generic scsi device driver, which can
+ * be used to access any configured scsi device. But we can use the "Sxxx"
+ * scsi peripherial drivers passthrough ioctl() (SCSIUSERCMD / SCSIUSERCMD2)
+ * to send scsi user comands to any target device controlled by the
+ * corresponding target driver.
+ *
+ * This passthrough implementation for libusal currently allows to
+ * handle the following devices classes:
+ *
+ *     1. DISK         handled by Sdsk
+ *     2. CD-ROM       handled by Srom
+ *     3. TAPES        handled by Stp
+ *     4. FLOPPY       handled by Sflp
+ *
+ * NOTE: The libusal OpenServer passthrough routines have changed with
+ *       cdrecord-1.8 to enable the -scanbus option. Therefore the
+ *      addressing scheme is now the same as used on many other platforms
+ *      like Solaris, Linux etc.
+ *
+ *   ===============================================================
+ *   RUN 'cdrecord -scanbus' TO SEE THE DEVICE ADDRESSES YOU CAN USE
+ *   ===============================================================
+ *
+ */
+
+/*
+ * Return version information for the low level SCSI transport code.
+ * This has been introduced to make it easier to trace down problems
+ * in applications.
+ */
+static char *
+usalo_version(SCSI *usalp, int what)
+{
+       if (usalp != (SCSI *)0) {
+               switch (what) {
+
+               case SCG_VERSION:
+                       return (_usal_trans_version);
+               /*
+                * If you changed this source, you are not allowed to
+                * return "schily" for the SCG_AUTHOR request.
+                */
+               case SCG_AUTHOR:
+                       return (_usal_auth_cdrkit);
+               case SCG_SCCS_ID:
+                       return (__sccsid);
+               }
+       }
+       return ((char *)0);
+}
+
+static int
+usalo_help(SCSI *usalp, FILE *f)
+{
+       __usal_help(f, "SCSIUSERCMD/SCSIUSERCMD2", "Generic SCSI",
+               "", "bus,target,lun", "1,2,0", TRUE, FALSE);
+       return (0);
+}
+
+/*
+ * ---------------------------------------------------------------
+ * This routine sorts the amscsi_t lines on the following columns
+ * in ascending order:
+ *
+ *     1. drv  - driver name
+ *     2. bus  - scsibus per controller
+ *     3. tgt  - target id of device
+ *     4. lun  - lun of the device
+ *
+ */
+
+
+static int
+sort_mscsi(const void *l1, const void *l2)
+{
+       amscsi_t        *t1 = (amscsi_t *) l1;
+       amscsi_t        *t2 = (amscsi_t *) l2;
+
+       if (strcmp(t1->drv, t2->drv) == 0) {
+               if (t1->bus < t2->bus) {
+                       return (-1);
+
+               } else if (t1->bus > t2->bus) {
+                       return (1);
+
+               } else if (t1->tgt < t2->tgt) {
+                       return (-1);
+
+               } else if (t1->tgt > t2->tgt) {
+                       return (1);
+
+               } else if (t1->lun < t2->lun) {
+                       return (-1);
+
+               } else if (t1->lun > t2->lun) {
+                       return (1);
+               } else {
+                       return (0);
+               }
+       } else {
+               return (strcmp(t1->drv, t2->drv));
+       }
+}
+
+/*
+ * ---------------------------------------------------------------
+ * This routine is introduced to find all scsi devices which are
+ * currently configured into the kernel. This is done by reading
+ * the dynamic kernel mscsi tables and parse the resulting lines.
+ * As the output of 'sconf' is not directly usable the information
+ * found is to be sorted and re-arranged to be used with the libusal
+ * routines.
+ *
+ * NOTE: One problem is currently still not solved ! If you don't
+ *       have a media in your CD-ROM/CD-Writer we are not able to
+ *       do an open() and therefore will set the drive to be not
+ *       available (valid=0).
+ *
+ *       This will for example cause cdrecord to not list the drive
+ *      in the -scanbus output.
+ *
+ */
+
+static int
+openserver_init(SCSI *usalp)
+{
+       FILE            *cmd;
+       int             nusal  = -1, lhba  = -1, lbus = -1;
+       int             nSrom = -1, nSdsk = -1, nStp = -1, nSflp = -1;
+       int             atapi, fd, nopen = 0;
+       int             pos = 0, len = 0, nlm = 0;
+       int             s = 0, t = 0, l = 0;
+       int             ide_rootdisk = 0;
+       long            dma_override = 0;
+       int             mscsi;
+       char            sconf[MAXLINE];
+       char            lines[MAXLINE];
+       char            drvid[MAXDRVN];
+       amscsi_t        cmtbl[MAXSCSI];
+       char            dname[MAXPATH];
+       char            **evsave;
+extern char            **environ;
+
+
+       for (s = 0; s < MAX_SCG; s++) {
+               for (t = 0; t < MAX_TGT; t++) {
+                       for (l = 0; l < MAX_LUN; l++) {
+                               sdidevs[s][t][l].valid  =  0;
+                               sdidevs[s][t][l].open   = -1;
+                               sdidevs[s][t][l].atapi  = -1;
+                               sdidevs[s][t][l].fd     = -1;
+                               sdidevs[s][t][l].lmscsi = -1;
+                       }
+               }
+       }
+
+       /* Check whether we want to use the older SCSIUSERCMD ioctl() */
+
+       if (getenv(SCSI_USER_CMD) != NULL) {
+               scsiusercmd = 1;
+       }
+
+       /*
+        * Check whether we want to scan all devices
+        */
+       if (getenv(SCAN_ALL) != NULL) {
+               scan_all = 1;
+       }
+
+       /*
+        * Check whether we want to use USB devices
+        */
+       if (getenv(ENABLE_USB) != NULL) {
+               enable_usb = 1;
+       }
+
+       /*
+        * Check whether we want to override the MAX_DMA value
+        */
+       if (getenv(DMA_OVERRIDE) != NULL) {
+               dma_override = atol(getenv(DMA_OVERRIDE));
+               if ((dma_override >= 1) && (dma_override <= (256)))
+                       max_dma = dma_override * 1024;
+       }
+
+
+       /* read sconf -r and get number of kernel mscsi lines ! */
+
+       evsave = environ;
+       environ = 0;
+       if ((cmd = popen(SCSI_CFG, "r")) == NULL) {
+               if (usalp->errstr)
+                       snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                               "Error popen() for \"%s\"",
+                               SCSI_CFG);
+               environ = evsave;
+               return (-1);
+       }
+       environ = evsave;
+
+       if (fgets(lines, MAXLINE, cmd) == NULL) {
+               errno = EIO;
+               if (usalp->errstr)
+                       snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                               "Error reading popen() for \"%s\"",
+                               SCSI_CFG);
+               return (-1);
+       } else
+               nlm = atoi(lines);
+
+       if (usalp->debug > 0) {
+               fprintf((FILE *)usalp->errfile, "-------------------- \n");
+               fprintf((FILE *)usalp->errfile, "mscsi lines = %d\n", nlm);
+               fprintf((FILE *)usalp->errfile, "-------------------- \n");
+       }
+
+       if (pclose(cmd) == -1) {
+               if (usalp->errstr)
+                       snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                               "Error pclose() for \"%s\"",
+                               SCSI_CFG);
+               return (-1);
+       }
+
+       for (l = 0; l < nlm; l++) {
+
+               /* initialize cmtbl entry */
+
+               cmtbl[l].hba = -1;
+               cmtbl[l].bus = -1;
+               cmtbl[l].tgt = -1;
+               cmtbl[l].lun = -1;
+               cmtbl[l].usal = -1;
+
+               memset(cmtbl[l].typ, '\0', MAXDRVN);
+               memset(cmtbl[l].drv, '\0', MAXDRVN);
+               memset(cmtbl[l].dev, '\0', MAXDRVN);
+
+               /* read sconf -g 'n' and get line of kernel mscsi table!  */
+               /* the order the lines will be received in will determine */
+               /* the device name we can use to open the device          */
+
+               snprintf(sconf, sizeof (sconf),
+                       SCSI_DEV, l + 1); /* enumeration starts with 1 */
+
+               evsave = environ;
+               environ = 0;
+               if ((cmd = popen(sconf, "r")) == NULL) {
+                       if (usalp->errstr)
+                               snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                                       "Error popen() for \"%s\"",
+                                       sconf);
+                       environ = evsave;
+                       return (-1);
+               }
+               environ = evsave;
+
+               if (fgets(lines, MAXLINE, cmd) == NULL)
+                       break;
+
+               if (pclose(cmd) == -1) {
+                       if (usalp->errstr)
+                               snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                                       "Error pclose() for \"%s\"",
+                                       sconf);
+                       return (-1);
+               }
+
+               sscanf(lines, SCAN_DEV, cmtbl[l].typ,
+                                       cmtbl[l].drv,
+                                       &cmtbl[l].hba,
+                                       &cmtbl[l].bus,
+                                       &cmtbl[l].tgt,
+                                       &cmtbl[l].lun);
+
+               if (strstr(cmtbl[l].typ, T_DISK) != NULL) {
+                       snprintf(cmtbl[l].dev,  sizeof (cmtbl[l].dev),
+                                       DEV_SDSK, ++nSdsk);
+               }
+
+               if (strstr(cmtbl[l].typ, T_CDROM) != NULL) {
+                       snprintf(cmtbl[l].dev,  sizeof (cmtbl[l].dev),
+                                       DEV_SROM, ++nSrom);
+               }
+
+               if (strstr(cmtbl[l].typ, T_TAPE) != NULL) {
+                       snprintf(cmtbl[l].dev, sizeof (cmtbl[l].dev),
+                                       DEV_STP, ++nStp);
+               }
+
+               if (strstr(cmtbl[l].typ, T_FLOPPY) != NULL) {
+                       snprintf(cmtbl[l].dev, sizeof (cmtbl[l].dev),
+                                       DEV_SFLP, ++nSflp);
+               }
+
+               if (usalp->debug > 0) {
+                       fprintf((FILE *)usalp->errfile,
+                               "%-4s = %5s(%d,%d,%d,%d) -> %s\n",
+                               cmtbl[l].typ,
+                               cmtbl[l].drv,
+                               cmtbl[l].hba,
+                               cmtbl[l].bus,
+                               cmtbl[l].tgt,
+                               cmtbl[l].lun,
+                               cmtbl[l].dev);
+               }
+
+       }
+
+       if (usalp->debug > 0) {
+               fprintf((FILE *)usalp->errfile, "-------------------- \n");
+               fprintf((FILE *)usalp->errfile, "%2d DISK  \n", nSdsk + 1);
+               fprintf((FILE *)usalp->errfile, "%2d CD-ROM\n", nSrom + 1);
+               fprintf((FILE *)usalp->errfile, "%2d TAPE  \n", nStp  + 1);
+               fprintf((FILE *)usalp->errfile, "%2d FLOPPY\n", nSflp + 1);
+               fprintf((FILE *)usalp->errfile, "-------------------- \n");
+       }
+
+       /* ok, now let's sort this array of scsi devices        */
+
+       qsort((void *) cmtbl, nlm, sizeof (amscsi_t), sort_mscsi);
+
+       if (usalp->debug > 0) {
+               for (l = 0; l < nlm; l++)
+               fprintf((FILE *)usalp->errfile,
+                       "%-4s = %5s(%d,%d,%d,%d) -> %s\n",
+                       cmtbl[l].typ,
+                       cmtbl[l].drv,
+                       cmtbl[l].hba,
+                       cmtbl[l].bus,
+                       cmtbl[l].tgt,
+                       cmtbl[l].lun,
+                       cmtbl[l].dev);
+               fprintf((FILE *)usalp->errfile, "-------------------- \n");
+       }
+
+       /* find root disk controller to make it usal 0          */
+
+       /*
+        * if we have disk(s) found in the mscsi table, we still
+        * don't know if the rootdisk is among these, there can
+        * be a IDE rootdisk as well, but it's not listed in
+        * the mscsi table.
+        */
+
+       t = 0;
+       if (nSdsk > 0) {
+               for (l = 0; l < nlm; l++)
+                       if (strcmp(cmtbl[l].dev, DEV_ROOT) == 0)
+                               t = l;
+       } else {
+
+               /*
+                * we haven't found a disk in mscsi, so we definitely
+                * have an IDE disk on a wd adapter as IDE disks are
+                * not listed as SCSI disks in the kernel mscsi table
+                */
+               ide_rootdisk = 1;
+
+       }
+
+       if (!(ide_rootdisk) && (usalp->debug > 0)) {
+               fprintf((FILE *)usalp->errfile,
+                       "root = %5s(%d,%d,%d,%d) -> %s\n",
+                       cmtbl[t].drv,
+                       cmtbl[t].hba,
+                       cmtbl[t].bus,
+                       cmtbl[t].tgt,
+                       cmtbl[t].lun,
+                       cmtbl[t].dev);
+               fprintf((FILE *)usalp->errfile, "-------------------- \n");
+       }
+
+       /* calculate usal from drv, hba and bus                         */
+
+       strcpy(drvid, "");
+
+       for (l = 0, s = t; l < nlm; l++, s = (t + l) % nlm) {
+
+               if (strcmp(drvid, cmtbl[s].drv) != 0) {
+                       strcpy(drvid, cmtbl[s].drv);
+                       lhba = cmtbl[s].hba;
+                       lbus = cmtbl[s].bus;
+                       cmtbl[s].usal = ++nusal;
+
+               } else if (cmtbl[s].hba != lhba) {
+                       lhba = cmtbl[s].hba;
+                       lbus = cmtbl[s].bus;
+                       cmtbl[s].usal = ++nusal;
+
+               } else if (cmtbl[s].bus != lbus) {
+                       lbus = cmtbl[s].bus;
+                       cmtbl[s].usal = ++nusal;
+               } else {
+                       cmtbl[s].usal = nusal;
+               }
+               sdidevs[cmtbl[s].usal][cmtbl[s].tgt][cmtbl[s].lun].open   = 0;
+
+               /* check whether we want to open all devices or it's a CDROM */
+
+               if ((scan_all) || (strcmp(cmtbl[s].typ, T_CDROM) == 0))
+                       sdidevs[cmtbl[s].usal][cmtbl[s].tgt][cmtbl[s].lun].valid = 1;
+
+               /* check whether we have an IDE/ATAPI device */
+
+               if (strcmp(cmtbl[s].drv, DRV_ATAPI) == 0)
+                       sdidevs[cmtbl[s].usal][cmtbl[s].tgt][cmtbl[s].lun].atapi = 1;
+
+               /* don't open a USB device if enable_usb is not set */
+
+               if (strcmp(cmtbl[s].drv, DRV_USB) == 0)
+                       sdidevs[cmtbl[s].usal][cmtbl[s].tgt][cmtbl[s].lun].valid = enable_usb;
+
+               /* don't open a IDE/ATAPI device which is missing but configured */
+
+               if (strcmp(cmtbl[s].drv, DRV_NOHA) == 0)
+                       sdidevs[cmtbl[s].usal][cmtbl[s].tgt][cmtbl[s].lun].valid = 0;
+
+
+               sdidevs[cmtbl[s].usal][cmtbl[s].tgt][cmtbl[s].lun].lmscsi = s;
+
+       }
+
+
+       /* open all yet valid device nodes */
+
+       for (s = 0; s < MAX_SCG; s++) {
+               for (t = 0; t < MAX_TGT; t++) {
+                       for (l = 0; l < MAX_LUN; l++) {
+
+                               if (sdidevs[s][t][l].valid == 0)
+                                       continue;
+
+                               /* Open pass-through device node */
+
+                               mscsi = sdidevs[s][t][l].lmscsi;
+
+                               strcpy(dname, cmtbl[mscsi].dev);
+
+       /*
+        * ------------------------------------------------------------------
+        * NOTE: If we can't open the device, we will set the device invalid!
+        * ------------------------------------------------------------------
+        */
+                               errno = 0;
+                               if ((fd = open(dname, (O_RDONLY | O_NONBLOCK))) < 0) {
+                                       sdidevs[s][t][l].valid = 0;
+                                       if (usalp->debug > 0) {
+                                               fprintf((FILE *)usalp->errfile,
+                                                       "%5s(%d,%d,%d,%d) -> %s open() failed: errno = %d (%s)\n",
+                                                       cmtbl[mscsi].drv,
+                                                       cmtbl[mscsi].hba,
+                                                       cmtbl[mscsi].bus,
+                                                       cmtbl[mscsi].tgt,
+                                                       cmtbl[mscsi].lun,
+                                                       cmtbl[mscsi].dev,
+                                                       errno,
+                                                       strerror(errno));
+                                       }
+                                       continue;
+                               }
+
+                               if (usalp->debug > 0) {
+                                       fprintf((FILE *)usalp->errfile,
+                                               "%d,%d,%d => %5s(%d,%d,%d,%d) -> %d : %s \n",
+                                               s, t, l,
+                                               cmtbl[mscsi].drv,
+                                               cmtbl[mscsi].hba,
+                                               cmtbl[mscsi].bus,
+                                               cmtbl[mscsi].tgt,
+                                               cmtbl[mscsi].lun,
+                                               cmtbl[mscsi].usal,
+                                               cmtbl[mscsi].dev);
+                               }
+
+                               sdidevs[s][t][l].fd   = fd;
+                               sdidevs[s][t][l].open = 1;
+                               nopen++;
+                               usallocal(usalp)->usalfiles[s][t][l] = (short) fd;
+                       }
+               }
+       }
+
+       if (usalp->debug > 0) {
+               fprintf((FILE *)usalp->errfile, "-------------------- \n");
+               fprintf((FILE *)usalp->errfile, "nopen = %d devices   \n", nopen);
+               fprintf((FILE *)usalp->errfile, "-------------------- \n");
+       }
+
+       return (nopen);
+}
+
+
+static int
+usalo_open(SCSI *usalp, char *device)
+{
+       int     busno   = usal_scsibus(usalp);
+       int     tgt     = usal_target(usalp);
+       int     tlun    = usal_lun(usalp);
+       int     f, b, t, l;
+       int     nopen = 0;
+       char    devname[64];
+
+       if (busno >= MAX_SCG || tgt >= MAX_TGT || tlun >= MAX_LUN) {
+               errno = EINVAL;
+               if (usalp->errstr)
+                       snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                               "Illegal value for busno, target or lun '%d,%d,%d'",
+                               busno, tgt, tlun);
+               return (-1);
+       }
+
+       if (usalp->local == NULL) {
+               usalp->local = malloc(sizeof (struct usal_local));
+               if (usalp->local == NULL)
+                       return (0);
+
+               for (b = 0; b < MAX_SCG; b++) {
+                       for (t = 0; t < MAX_TGT; t++) {
+                               for (l = 0; l < MAX_LUN; l++)
+                                       usallocal(usalp)->usalfiles[b][t][l] = (short)-1;
+                       }
+               }
+       }
+
+       if (*device != '\0') {          /* we don't allow old dev usage */
+               errno = EINVAL;
+               if (usalp->errstr)
+                       snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                       "Open by 'devname' no longer supported on this OS");
+               return (-1);
+       }
+
+       return (openserver_init(usalp));
+
+}
+
+static int
+usalo_close(SCSI *usalp)
+{
+       register int    f;
+       register int    b;
+       register int    t;
+       register int    l;
+
+       if (usalp->local == NULL)
+               return (-1);
+
+       for (b = 0; b < MAX_SCG; b++) {
+               for (t = 0; t < MAX_TGT; t++) {
+                       for (l = 0; l < MAX_LUN; l++) {
+
+                               f = usallocal(usalp)->usalfiles[b][t][l];
+                               if (f >= 0)
+                                       close(f);
+
+                               sdidevs[b][t][l].fd    = -1;
+                               sdidevs[b][t][l].open  =  0;
+                               sdidevs[b][t][l].valid =  0;
+
+                               usallocal(usalp)->usalfiles[b][t][l] = (short)-1;
+                       }
+               }
+       }
+       return (0);
+}
+
+static long
+usalo_maxdma(SCSI *usalp, long amt)
+{
+       return (max_dma);
+}
+
+
+static void *
+usalo_getbuf(SCSI *usalp, long amt)
+{
+       if (usalp->debug > 0) {
+               fprintf((FILE *)usalp->errfile,
+                       "usalo_getbuf: %ld bytes\n", amt);
+       }
+       usalp->bufbase = valloc((size_t)(amt));
+
+       return (usalp->bufbase);
+}
+
+static void
+usalo_freebuf(SCSI *usalp)
+{
+       if (usalp->bufbase)
+               free(usalp->bufbase);
+       usalp->bufbase = NULL;
+}
+
+static BOOL
+usalo_havebus(SCSI *usalp, int busno)
+{
+       register int    t;
+       register int    l;
+
+       if (busno < 0 || busno >= MAX_SCG)
+               return (FALSE);
+
+       if (usalp->local == NULL)
+               return (FALSE);
+
+       for (t = 0; t < MAX_TGT; t++) {
+               for (l = 0; l < MAX_LUN; l++)
+                       if (usallocal(usalp)->usalfiles[busno][t][l] >= 0)
+                               return (TRUE);
+       }
+       return (FALSE);
+}
+
+static int
+usalo_fileno(SCSI *usalp, int busno, int tgt, int tlun)
+{
+       if (busno < 0 || busno >= MAX_SCG ||
+           tgt   < 0 || tgt   >= MAX_TGT ||
+           tlun  < 0 || tlun  >= MAX_LUN)
+               return (-1);
+
+       if (usalp->local == NULL)
+               return (-1);
+
+       return ((int)usallocal(usalp)->usalfiles[busno][tgt][tlun]);
+}
+
+static int
+usalo_initiator_id(SCSI *usalp)
+{
+       return (-1);
+
+       /*
+        * We don't know the initiator ID yet, but we can if we parse the
+        * output of the command 'cat /dev/string/cfg | grep "%adapter"'
+        *
+        * Sample line:
+        *
+        *      %adapter 0xE800-0xE8FF 11 - type=alad ha=0 bus=0 id=7 fts=sto
+        *
+        * This tells us that the alad controller 0 has an id of 7 !
+        * The parsing should be done in openserver_init().
+        *
+        */
+}
+
+static int
+usalo_isatapi(SCSI *usalp)
+{
+       return (sdidevs[usal_scsibus(usalp)][usal_target(usalp)][usal_lun(usalp)].atapi);
+}
+
+static int
+usalo_reset(SCSI *usalp, int what)
+{
+       errno = EINVAL;
+       return (-1);            /* no scsi reset available */
+}
+
+static void
+cp_usal2sco(struct scsicmd2 *sco, struct usal_cmd *usal)
+{
+       sco->cmd.data_ptr = (char *) usal->addr;
+       sco->cmd.data_len = usal->size;
+       sco->cmd.cdb_len  = usal->cdb_len;
+
+       sco->sense_len    = usal->sense_len;
+       sco->sense_ptr    = usal->u_sense.cmd_sense;
+
+       if (!(usal->flags & SCG_RECV_DATA) && (usal->size > 0))
+               sco->cmd.is_write = 1;
+
+       if (usal->cdb_len == SC_G0_CDBLEN)
+               memcpy(sco->cmd.cdb, &usal->cdb.g0_cdb, usal->cdb_len);
+
+       if (usal->cdb_len == SC_G1_CDBLEN)
+               memcpy(sco->cmd.cdb, &usal->cdb.g1_cdb, usal->cdb_len);
+
+       if (usal->cdb_len == SC_G5_CDBLEN)
+               memcpy(sco->cmd.cdb, &usal->cdb.g5_cdb, usal->cdb_len);
+}
+
+
+static void
+cp_sco2usal(struct scsicmd2 *sco, struct usal_cmd *usal)
+{
+       usal->size      = sco->cmd.data_len;
+
+       memset(&usal->scb, 0, sizeof (usal->scb));
+
+       if (sco->sense_len > SCG_MAX_SENSE)
+               usal->sense_count = SCG_MAX_SENSE;
+       else
+               usal->sense_count = sco->sense_len;
+
+       usal->resid = 0;
+
+       usal->u_scb.cmd_scb[0] = sco->cmd.target_sts;
+
+}
+
+
+static int
+usalo_send(SCSI *usalp)
+{
+       struct usal_cmd *sp = usalp->scmd;
+       struct scsicmd2 scsi_cmd;
+       int             i;
+       Uchar           sense_buf[SCG_MAX_SENSE];
+
+       if (usalp->fd < 0) {
+               sp->error = SCG_FATAL;
+               return (0);
+       }
+
+       memset(&scsi_cmd, 0, sizeof (scsi_cmd));
+       memset(sense_buf, 0, sizeof (sense_buf));
+       scsi_cmd.sense_ptr = sense_buf;
+       scsi_cmd.sense_len = sizeof (sense_buf);
+       cp_usal2sco(&scsi_cmd, sp);
+
+       errno = 0;
+       sp->ux_errno = 0;
+       sp->error = SCG_NO_ERROR;
+       for (;;) {
+               int             ioctlStatus;
+               struct scsicmd  s_cmd;
+
+               if (scsiusercmd) {      /* Use SCSIUSERCMD ioctl() */
+                       if (usalp->debug > 1) {
+                               fprintf((FILE *)usalp->errfile, "calling SCSIUSERCMD ioctl()\n");
+                       }
+
+                       if ((ioctlStatus = ioctl(usalp->fd, SCSIUSERCMD, &(scsi_cmd.cmd))) < 0) {
+                               if (usalp->debug > 1) {
+                                       fprintf((FILE *)usalp->errfile, "returning from SCSIUSERCMD ioctl()\n");
+                               }
+                               if (errno == EINTR)
+                                       continue;
+
+                               cp_sco2usal(&scsi_cmd, sp);
+                               sp->ux_errno = errno;
+                               if (errno == 0)
+                                       sp->ux_errno = EIO;
+                               sp->error    = SCG_RETRYABLE;
+
+                               return (0);
+                       }
+
+                       if (usalp->debug > 1) {
+                               fprintf((FILE *)usalp->errfile, "returning from SCSIUSERCMD ioctl()\n");
+                       }
+                       cp_sco2usal(&scsi_cmd, sp);
+                       sp->ux_errno = errno;
+
+                       if (scsi_cmd.cmd.target_sts & 0x02) { /* Check Condition & get Sense */
+
+                               if (sp->sense_len > SCG_MAX_SENSE)
+                                       sp->sense_len = SCG_MAX_SENSE;
+
+                               memset((caddr_t)&s_cmd, 0, sizeof (s_cmd));
+
+                               s_cmd.data_ptr  = (caddr_t) sp->u_sense.cmd_sense;
+                               s_cmd.data_len  = sp->sense_len;
+                               s_cmd.is_write  = 0;
+                               s_cmd.cdb[0]    = SC_REQUEST_SENSE;
+
+                               while (((ioctlStatus = ioctl(usalp->fd, SCSIUSERCMD, &s_cmd)) < 0) &&
+                                       (errno == EINTR))
+                                               ;
+
+                               sp->sense_count = sp->sense_len;
+                               sp->ux_errno    = errno;
+
+                               if (errno == 0)
+                                       sp->ux_errno = EIO;
+                               sp->error = SCG_NO_ERROR;
+                       }
+
+                       if (usalp->debug > 0) {
+                               if (errno != 0)
+                                       fprintf((FILE *)usalp->errfile, "ux_errno: %d (%s) \n", sp->ux_errno, strerror(sp->ux_errno));
+                               if (sp->u_scb.cmd_scb[0] != 0)
+                                       fprintf((FILE *)usalp->errfile, "tgt_stat: %d \n", sp->u_scb.cmd_scb[0]);
+                       }
+                       break;
+
+               } else {                /* Use SCSIUSERCMD2 ioctl() */
+                       if (usalp->debug > 1) {
+                               fprintf((FILE *)usalp->errfile, "calling SCSIUSERCMD2 ioctl()\n");
+                       }
+
+                       if ((ioctlStatus = ioctl(usalp->fd, SCSIUSERCMD2, &scsi_cmd)) < 0) {
+                               if (usalp->debug > 1) {
+                                       fprintf((FILE *)usalp->errfile, "returning from SCSIUSERCMD2 ioctl()\n");
+                               }
+                               if (errno == EINTR)
+                                       continue;
+
+                               cp_sco2usal(&scsi_cmd, sp);
+                               sp->ux_errno = errno;
+                               if (errno == 0)
+                                       sp->ux_errno = EIO;
+                               sp->error    = SCG_RETRYABLE;
+
+                               return (0);
+                       }
+                       if (usalp->debug > 1) {
+                               fprintf((FILE *)usalp->errfile, "returning from SCSIUSERCMD2 ioctl()\n");
+                       }
+
+                       cp_sco2usal(&scsi_cmd, sp);
+                       sp->ux_errno = errno;
+
+                       if (scsi_cmd.cmd.target_sts & 0x02) { /* Check Condition */
+                               if (errno == 0)
+                                       sp->ux_errno = EIO;
+                               sp->error    = SCG_NO_ERROR;
+                       }
+
+                       if (usalp->debug > 0) {
+                               if (errno != 0)
+                                       fprintf((FILE *)usalp->errfile, "ux_errno: %d (%s) \n", sp->ux_errno, strerror(sp->ux_errno));
+                               if (sp->u_scb.cmd_scb[0] != 0)
+                                       fprintf((FILE *)usalp->errfile, "tgt_stat: %d \n", sp->u_scb.cmd_scb[0]);
+                       }
+                       break;
+
+               }
+       }
+
+       return (0);
+}
+
+#define        sense   u_sense.Sense
diff --git a/libusal/scsi-os2.c b/libusal/scsi-os2.c
new file mode 100644 (file)
index 0000000..5758b8d
--- /dev/null
@@ -0,0 +1,630 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)scsi-os2.c      1.25 04/01/15 Copyright 1998 J. Schilling, C. Wohlgemuth */
+/*
+ *     Interface for the OS/2 ASPI-Router ASPIROUT.SYS ((c) D. Dorau).
+ *             This additional driver is a prerequisite for using cdrecord.
+ *             Get it from HOBBES or LEO.
+ *
+ *     Warning: you may change this source, but if you do that
+ *     you need to change the _usal_version and _usal_auth* string below.
+ *     You may not return "schily" for an SCG_AUTHOR request anymore.
+ *     Choose your name instead of "schily" and make clear that the version
+ *     string is related to a modified source.
+ *
+ *     XXX it currently uses static SRB and for this reason is not reentrant
+ *
+ *     Copyright (c) 1998 J. Schilling
+ *     Copyright (c) 1998 C. Wohlgemuth for this interface.
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#undef sense
+
+/*#define      DEBUG*/
+
+/* For AspiRouter */
+#include "usal/srb_os2.h"
+
+/*
+ *     Warning: you may change this source, but if you do that
+ *     you need to change the _usal_version and _usal_auth* string below.
+ *     You may not return "schily" for an SCG_AUTHOR request anymore.
+ *     Choose your name instead of "schily" and make clear that the version
+ *     string is related to a modified source.
+ */
+static char    _usal_trans_version[] = "scsi-os2.c-1.25";      /* The version for this transport*/
+
+#define        FILE_OPEN                       0x0001
+#define        OPEN_SHARE_DENYREADWRITE        0x0010
+#define        OPEN_ACCESS_READWRITE           0x0002
+#define        DC_SEM_SHARED                   0x01
+#define        OBJ_TILE                        0x0040
+#define        PAG_READ                        0x0001
+#define        PAG_WRITE                       0x0002
+#define        PAG_COMMIT                      0x0010
+
+typedef unsigned long LHANDLE;
+typedef unsigned long ULONG;
+typedef unsigned char *PSZ;
+typedef unsigned short USHORT;
+typedef unsigned char UCHAR;
+
+typedef LHANDLE        HFILE;
+typedef ULONG  HEV;
+
+#define        MAX_SCG         16      /* Max # of SCSI controllers */
+#define        MAX_TGT         16
+#define        MAX_LUN         8
+
+struct usal_local {
+       int     dummy;
+};
+#define        usallocal(p)    ((struct usal_local *)((p)->local))
+
+#define        MAX_DMA_OS2     (63*1024) /* ASPI-Router allows up to 64k */
+
+static void    *buffer         = NULL;
+static HFILE   driver_handle   = 0;
+static HEV     postSema        = 0;
+
+static BOOL    open_driver(SCSI *usalp);
+static BOOL    close_driver(void);
+static ULONG   wait_post(ULONG ulTimeOut);
+static BOOL    init_buffer(void* mem);
+static void    exit_func(void);
+static void    set_error(SRB *srb, struct usal_cmd *sp);
+
+
+static void
+exit_func()
+{
+       if (!close_driver())
+               fprintf(stderr, "Cannot close OS/2-ASPI-Router!\n");
+}
+
+/*
+ * Return version information for the low level SCSI transport code.
+ * This has been introduced to make it easier to trace down problems
+ * in applications.
+ */
+static char *
+usalo_version(SCSI *usalp, int what)
+{
+       if (usalp != (SCSI *)0) {
+               switch (what) {
+
+               case SCG_VERSION:
+                       return (_usal_trans_version);
+               /*
+                * If you changed this source, you are not allowed to
+                * return "schily" for the SCG_AUTHOR request.
+                */
+               case SCG_AUTHOR:
+                       return (_usal_auth_cdrkit);
+               case SCG_SCCS_ID:
+                       return (__sccsid);
+               }
+       }
+       return ((char *)0);
+}
+
+static int
+usalo_help(SCSI *usalp, FILE *f)
+{
+       __usal_help(f, "ASPI", "Generic transport independent SCSI",
+               "", "bus,target,lun", "1,2,0", TRUE, FALSE);
+       return (0);
+}
+
+static int
+usalo_open(SCSI *usalp, char *device)
+{
+       int     busno   = usal_scsibus(usalp);
+       int     tgt     = usal_target(usalp);
+       int     tlun    = usal_lun(usalp);
+
+       if (busno >= MAX_SCG || tgt >= MAX_TGT || tlun >= MAX_LUN) {
+               errno = EINVAL;
+               if (usalp->errstr)
+                       snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                               "Illegal value for busno, target or lun '%d,%d,%d'",
+                               busno, tgt, tlun);
+               return (-1);
+       }
+
+       if ((device != NULL && *device != '\0') || (busno == -2 && tgt == -2)) {
+               errno = EINVAL;
+               if (usalp->errstr)
+                       snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                               "Open by 'devname' not supported on this OS");
+               return (-1);
+       }
+
+       if (usalp->local == NULL) {
+               usalp->local = malloc(sizeof (struct usal_local));
+               if (usalp->local == NULL)
+                       return (0);
+       }
+
+       if (!open_driver(usalp))        /* Try to open ASPI-Router */
+               return (-1);
+       atexit(exit_func);      /* Install Exit Function which closes the ASPI-Router */
+
+       /*
+        * Success after all
+        */
+       return (1);
+}
+
+static int
+usalo_close(SCSI *usalp)
+{
+       exit_func();
+       return (0);
+}
+
+static long
+usalo_maxdma(SCSI *cgp, long amt)
+{
+       long maxdma = MAX_DMA_OS2;
+       return (maxdma);
+}
+
+static void *
+usalo_getbuf(SCSI *usalp, long amt)
+{
+       ULONG rc;
+
+#ifdef DEBUG
+       fprintf((FILE *)usalp->errfile, "usalo_getbuf: %ld bytes\n", amt);
+#endif
+       rc = DosAllocMem(&buffer, amt, OBJ_TILE | PAG_READ | PAG_WRITE | PAG_COMMIT);
+
+       if (rc) {
+               fprintf((FILE *)usalp->errfile, "Cannot allocate buffer.\n");
+               return ((void *)0);
+       }
+       usalp->bufbase = buffer;
+
+#ifdef DEBUG
+       fprintf((FILE *)usalp->errfile, "Buffer allocated at: 0x%x\n", usalp->bufbase);
+#endif
+
+       /* Lock memory */
+       if (init_buffer(usalp->bufbase))
+               return (usalp->bufbase);
+
+       fprintf((FILE *)usalp->errfile, "Cannot lock memory buffer.\n");
+       return ((void *)0); /* Error */
+}
+
+static void
+usalo_freebuf(SCSI *usalp)
+{
+       if (usalp->bufbase && DosFreeMem(usalp->bufbase)) {
+               fprintf((FILE *)usalp->errfile,
+               "Cannot free buffer memory for ASPI-Router!\n"); /* Free our memory buffer if not already done */
+       }
+       if (buffer == usalp->bufbase)
+               buffer = NULL;
+       usalp->bufbase = NULL;
+}
+
+static BOOL
+usalo_havebus(SCSI *usalp, int busno)
+{
+       register int    t;
+       register int    l;
+
+       if (busno < 0 || busno >= MAX_SCG)
+               return (FALSE);
+
+       return (TRUE);
+}
+
+static int
+usalo_fileno(SCSI *usalp, int busno, int tgt, int tlun)
+{
+       if (busno < 0 || busno >= MAX_SCG ||
+           tgt < 0 || tgt >= MAX_TGT ||
+           tlun < 0 || tlun >= MAX_LUN)
+               return (-1);
+
+       /*
+        * Return fake
+        */
+       return (1);
+}
+
+
+static int
+usalo_initiator_id(SCSI *usalp)
+{
+       return (-1);
+}
+
+static int
+usalo_isatapi(SCSI *usalp)
+{
+       return (FALSE);
+}
+
+
+static int
+usalo_reset(SCSI *usalp, int what)
+{
+       ULONG   rc;                             /* return value */
+       ULONG   cbreturn;
+       ULONG   cbParam;
+       BOOL    success;
+static SRB     SRBlock;                        /* XXX makes it non reentrant */
+
+       if (what == SCG_RESET_NOP)
+               return (0);
+       if (what != SCG_RESET_BUS) {
+               errno = EINVAL;
+               return (-1);
+       }
+       /*
+        * XXX Does this reset TGT or BUS ???
+        */
+       SRBlock.cmd             = SRB_Reset;            /* reset device         */
+       SRBlock.ha_num          = usal_scsibus(usalp);  /* host adapter number  */
+       SRBlock.flags           = SRB_Post;             /* posting enabled      */
+       SRBlock.u.res.target    = usal_target(usalp);   /* target id            */
+       SRBlock.u.res.lun       = usal_lun(usalp);      /* target LUN           */
+
+       rc = DosDevIOCtl(driver_handle, 0x92, 0x02, (void*) &SRBlock, sizeof (SRB), &cbParam,
+                       (void*) &SRBlock, sizeof (SRB), &cbreturn);
+       if (rc) {
+               fprintf((FILE *)usalp->errfile,
+                               "DosDevIOCtl() failed in resetDevice.\n");
+               return (1);                     /* DosDevIOCtl failed */
+       } else {
+               success = wait_post(40000);     /** wait for SRB being processed */
+               if (success)
+                       return (2);
+       }
+       if (SRBlock.status != SRB_Done)
+               return (3);
+#ifdef DEBUG
+       fprintf((FILE *)usalp->errfile,
+               "resetDevice of host: %d target: %d lun: %d successful.\n", usal_scsibus(usalp), usal_target(usalp), usal_lun(usalp));
+       fprintf((FILE *)usalp->errfile,
+               "SRBlock.ha_status: 0x%x, SRBlock.target_status: 0x%x, SRBlock.satus: 0x%x\n",
+                               SRBlock.u.cmd.ha_status, SRBlock.u.cmd.target_status, SRBlock.status);
+#endif
+       return (0);
+}
+
+/*
+ * Set error flags
+ */
+static void
+set_error(SRB *srb, struct usal_cmd *sp)
+{
+       switch (srb->status) {
+
+       case SRB_InvalidCmd:            /* 0x80 Invalid SCSI request        */
+       case SRB_InvalidHA:             /* 0x81 Invalid host adapter number */
+       case SRB_BadDevice:             /* 0x82 SCSI device not installed   */
+               sp->error = SCG_FATAL;
+               sp->ux_errno = EINVAL;  /* Should we ever return != EIO     */
+               sp->ux_errno = EIO;
+               break;
+
+
+       case SRB_Busy:                  /* 0x00 SCSI request in progress    */
+       case SRB_Aborted:               /* 0x02 SCSI aborted by host        */
+       case SRB_BadAbort:              /* 0x03 Unable to abort SCSI request */
+       case SRB_Error:                 /* 0x04 SCSI request completed with error */
+       default:
+               sp->error = SCG_RETRYABLE;
+               sp->ux_errno = EIO;
+               break;
+       }
+}
+
+static int
+usalo_send(SCSI *usalp)
+{
+       struct usal_cmd *sp = usalp->scmd;
+       ULONG   rc;                             /* return value */
+static SRB     SRBlock;                        /* XXX makes it non reentrant */
+       Ulong   cbreturn;
+       Ulong   cbParam;
+       UCHAR*  ptr;
+
+       if (usalp->fd < 0) {                    /* Set in usalo_open() */
+               sp->error = SCG_FATAL;
+               return (0);
+       }
+
+       if (sp->cdb_len > sizeof (SRBlock.u.cmd.cdb_st)) { /* commandsize too big */
+               sp->error = SCG_FATAL;
+               sp->ux_errno = EINVAL;
+               fprintf((FILE *)usalp->errfile,
+                       "sp->cdb_len > SRBlock.u.cmd.cdb_st. Fatal error in usalo_send, exiting...\n");
+               return (-1);
+       }
+
+       /* clear command block */
+       fillbytes((caddr_t)&SRBlock.u.cmd.cdb_st, sizeof (SRBlock.u.cmd.cdb_st), '\0');
+       /* copy cdrecord command into SRB */
+       movebytes(&sp->cdb, &SRBlock.u.cmd.cdb_st, sp->cdb_len);
+
+       /* Build SRB command block */
+       SRBlock.cmd = SRB_Command;
+       SRBlock.ha_num = usal_scsibus(usalp);   /* host adapter number */
+
+       SRBlock.flags = SRB_Post;               /* flags */
+
+       SRBlock.u.cmd.target    = usal_target(usalp); /* Target SCSI ID */
+       SRBlock.u.cmd.lun       = usal_lun(usalp); /* Target SCSI LUN */
+       SRBlock.u.cmd.data_len  = sp->size;     /* # of bytes transferred */
+       SRBlock.u.cmd.data_ptr  = 0;            /* pointer to data buffer */
+       SRBlock.u.cmd.sense_len = sp->sense_len; /* length of sense buffer */
+
+       SRBlock.u.cmd.link_ptr  = 0;            /* pointer to next SRB */
+       SRBlock.u.cmd.cdb_len   = sp->cdb_len;  /* SCSI command length */
+
+       /* Specify direction */
+       if (sp->flags & SCG_RECV_DATA) {
+               SRBlock.flags |= SRB_Read;
+       } else {
+               if (sp->size > 0) {
+                       SRBlock.flags |= SRB_Write;
+                       if (usalp->bufbase != sp->addr) { /* Copy only if data not in ASPI-Mem */
+                               movebytes(sp->addr, usalp->bufbase, sp->size);
+                       }
+               } else {
+                       SRBlock.flags |= SRB_NoTransfer;
+               }
+       }
+       sp->error       = SCG_NO_ERROR;
+       sp->sense_count = 0;
+       sp->u_scb.cmd_scb[0] = 0;
+       sp->resid       = 0;
+
+       /* execute SCSI command */
+       rc = DosDevIOCtl(driver_handle, 0x92, 0x02,
+                       (void*) &SRBlock, sizeof (SRB), &cbParam,
+                       (void*) &SRBlock, sizeof (SRB), &cbreturn);
+
+       if (rc) {               /* An error occured */
+               fprintf((FILE *)usalp->errfile,
+                               "DosDevIOCtl() in sendCommand failed.\n");
+               sp->error = SCG_FATAL;
+               sp->ux_errno = EIO;     /* Später vielleicht errno einsetzen */
+               return (rc);
+       } else {
+               /* Wait until the command is processed */
+               rc = wait_post(sp->timeout*1000);
+               if (rc) {       /* An error occured */
+                       if (rc == 640) {
+                               /* Timeout */
+                               sp->error = SCG_TIMEOUT;
+                               sp->ux_errno = EIO;
+                               fprintf((FILE *)usalp->errfile,
+                                               "Timeout during SCSI-Command.\n");
+                               return (1);
+                       }
+                       sp->error = SCG_FATAL;
+                       sp->ux_errno = EIO;
+                       fprintf((FILE *)usalp->errfile,
+                                       "Fatal Error during DosWaitEventSem().\n");
+                       return (1);
+               }
+
+               /* The command is processed */
+               if (SRBlock.status == SRB_Done) {       /* succesful completion */
+#ifdef DEBUG
+                       fprintf((FILE *)usalp->errfile,
+                               "Command successful finished. SRBlock.status=0x%x\n\n", SRBlock.status);
+#endif
+                       sp->sense_count = 0;
+                       sp->resid = 0;
+                       if (sp->flags & SCG_RECV_DATA) {        /* We read data */
+                               if (sp->addr && sp->size) {
+                                       if (usalp->bufbase != sp->addr) /* Copy only if data not in ASPI-Mem */
+                                               movebytes(usalp->bufbase, sp->addr, SRBlock.u.cmd.data_len);
+                                       ptr = (UCHAR*)sp->addr;
+                                       sp->resid = sp->size - SRBlock.u.cmd.data_len; /*nicht Ã¼bertragene bytes. Korrekt berechnet???*/
+                               }
+                       }       /* end of if (sp->flags & SCG_RECV_DATA) */
+                       if (SRBlock.u.cmd.target_status == SRB_CheckStatus) { /* Sense data valid */
+                               sp->sense_count = (int)SRBlock.u.cmd.sense_len;
+                               if (sp->sense_count > sp->sense_len)
+                                       sp->sense_count = sp->sense_len;
+
+                               ptr = (UCHAR*)&SRBlock.u.cmd.cdb_st;
+                               ptr += SRBlock.u.cmd.cdb_len;
+
+                               fillbytes(&sp->u_sense.Sense, sizeof (sp->u_sense.Sense), '\0');
+                               movebytes(ptr, &sp->u_sense.Sense, sp->sense_len);
+
+                               sp->u_scb.cmd_scb[0] = SRBlock.u.cmd.target_status;
+                               sp->ux_errno = EIO;     /* Später differenzieren? */
+                       }
+                       return (0);
+               }
+               /* SCSI-Error occured */
+               set_error(&SRBlock, sp);
+
+               if (SRBlock.u.cmd.target_status == SRB_CheckStatus) {   /* Sense data valid */
+                       sp->sense_count = (int)SRBlock.u.cmd.sense_len;
+                       if (sp->sense_count > sp->sense_len)
+                               sp->sense_count = sp->sense_len;
+
+                       ptr = (UCHAR*)&SRBlock.u.cmd.cdb_st;
+                       ptr += SRBlock.u.cmd.cdb_len;
+
+                       fillbytes(&sp->u_sense.Sense, sizeof (sp->u_sense.Sense), '\0');
+                       movebytes(ptr, &sp->u_sense.Sense, sp->sense_len);
+
+                       sp->u_scb.cmd_scb[0] = SRBlock.u.cmd.target_status;
+               }
+               if (sp->flags & SCG_RECV_DATA) {
+                       if (sp->addr && sp->size) {
+                               if (usalp->bufbase != sp->addr) /* Copy only if data not in ASPI-Mem */
+                                       movebytes(usalp->bufbase, sp->addr, SRBlock.u.cmd.data_len);
+                       }
+               }
+#ifdef really
+               sp->resid       = SRBlock.u.cmd.data_len; /* XXXXX Got no Data ????? */
+#else
+               sp->resid       = sp->size - SRBlock.u.cmd.data_len;
+#endif
+               return (1);
+       }
+}
+
+/***************************************************************************
+ *                                                                        *
+ *  BOOL open_driver()                                                    *
+ *                                                                        *
+ *  Opens the ASPI Router device driver and sets device_handle.                   *
+ *  Returns:                                                              *
+ *    TRUE - Success                                                      *
+ *    FALSE - Unsuccessful opening of device driver                       *
+ *                                                                        *
+ *  Preconditions: ASPI Router driver has be loaded                       *
+ *                                                                        *
+ ***************************************************************************/
+static BOOL
+open_driver(SCSI *usalp)
+{
+       ULONG   rc;                     /* return value */
+       ULONG   ActionTaken;            /* return value */
+       USHORT  openSemaReturn;         /* return value */
+       ULONG   cbreturn;
+       ULONG   cbParam;
+
+       if (driver_handle)              /* ASPI-Router already opened   */
+               return (TRUE);
+
+       rc = DosOpen((PSZ) "aspirou$",  /* open driver*/
+                       &driver_handle,
+                       &ActionTaken,
+                       0,
+                       0,
+                       FILE_OPEN,
+                       OPEN_SHARE_DENYREADWRITE | OPEN_ACCESS_READWRITE,
+                       NULL);
+       if (rc) {
+               fprintf((FILE *)usalp->errfile,
+                               "Cannot open ASPI-Router!\n");
+
+               return (FALSE);         /* opening failed -> return false*/
+       }
+
+       /* Init semaphore */
+       if (DosCreateEventSem(NULL, &postSema,  /* create event semaphore */
+                               DC_SEM_SHARED, 0)) {
+               DosClose(driver_handle);
+               fprintf((FILE *)usalp->errfile,
+                               "Cannot create event semaphore!\n");
+
+               return (FALSE);
+       }
+       rc = DosDevIOCtl(driver_handle, 0x92, 0x03,     /* pass semaphore handle */
+                       (void*) &postSema, sizeof (HEV), /* to driver            */
+                       &cbParam, (void*) &openSemaReturn,
+                       sizeof (USHORT), &cbreturn);
+
+       if (rc||openSemaReturn) {                       /* Error */
+               DosCloseEventSem(postSema);
+               DosClose(driver_handle);
+               return (FALSE);
+       }
+       return (TRUE);
+}
+
+/***************************************************************************
+ *                                                                        *
+ *  BOOL close_driver()                                                           *
+ *                                                                        *
+ *  Closes the device driver                                              *
+ *  Returns:                                                              *
+ *    TRUE - Success                                                      *
+ *    FALSE - Unsuccessful closing of device driver                       *
+ *                                                                        *
+ *  Preconditions: ASPI Router driver has be opened with open_driver      *
+ *                                                                        *
+ ***************************************************************************/
+static BOOL
+close_driver()
+{
+       ULONG rc;                               /* return value */
+
+       if (driver_handle) {
+               rc = DosClose(driver_handle);
+               if (rc)
+                       return (FALSE);         /* closing failed -> return false */
+               driver_handle = 0;
+               if (DosCloseEventSem(postSema))
+                       fprintf(stderr, "Cannot close event semaphore!\n");
+               if (buffer && DosFreeMem(buffer)) {
+                       fprintf(stderr,
+                       "Cannot free buffer memory for ASPI-Router!\n"); /* Free our memory buffer if not already done */
+               }
+               buffer = NULL;
+       }
+       return (TRUE);
+}
+
+static ULONG
+wait_post(ULONG ulTimeOut)
+{
+       ULONG count = 0;
+       ULONG rc;                                       /* return value */
+
+/*     rc = DosWaitEventSem(postSema, -1);*/           /* wait forever*/
+       rc = DosWaitEventSem(postSema, ulTimeOut);
+       DosResetEventSem(postSema, &count);
+       return (rc);
+}
+
+static BOOL
+init_buffer(void *mem)
+{
+       ULONG   rc;                                     /* return value */
+       USHORT lockSegmentReturn;                       /* return value */
+       Ulong   cbreturn;
+       Ulong   cbParam;
+
+       rc = DosDevIOCtl(driver_handle, 0x92, 0x04,     /* pass buffers pointer */
+                       (void*) mem, sizeof (void*),    /* to driver */
+                       &cbParam, (void*) &lockSegmentReturn,
+                       sizeof (USHORT), &cbreturn);
+       if (rc)
+               return (FALSE);                         /* DosDevIOCtl failed */
+       if (lockSegmentReturn)
+               return (FALSE);                         /* Driver could not lock segment */
+       return (TRUE);
+}
+#define        sense   u_sense.Sense
diff --git a/libusal/scsi-osf.c b/libusal/scsi-osf.c
new file mode 100644 (file)
index 0000000..79d0708
--- /dev/null
@@ -0,0 +1,445 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)scsi-osf.c      1.26 04/01/15 Copyright 1998 J. Schilling */
+/*
+ *     Interface for Digital UNIX (OSF/1 generic SCSI implementation (/dev/cam).
+ *
+ *     Created out of the hacks from:
+ *             Stefan Traby <stefan@sime.com> and
+ *             Bruno Achauer <bruno@tk.uni-linz.ac.at>
+ *
+ *     Warning: you may change this source, but if you do that
+ *     you need to change the _usal_version and _usal_auth* string below.
+ *     You may not return "schily" for an SCG_AUTHOR request anymore.
+ *     Choose your name instead of "schily" and make clear that the version
+ *     string is related to a modified source.
+ *
+ *     Copyright (c) 1998 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <sys/types.h>
+#include <io/common/iotypes.h>
+#include <io/cam/cam.h>
+#include <io/cam/uagt.h>
+
+/*
+ *     Warning: you may change this source, but if you do that
+ *     you need to change the _usal_version and _usal_auth* string below.
+ *     You may not return "schily" for an SCG_AUTHOR request anymore.
+ *     Choose your name instead of "schily" and make clear that the version
+ *     string is related to a modified source.
+ */
+static char    _usal_trans_version[] = "scsi-osf.c-1.26";      /* The version for this transport*/
+
+#define        MAX_SCG         16      /* Max # of SCSI controllers */
+#define        MAX_TGT         16
+#define        MAX_LUN         8
+
+struct usal_local {
+       int     usalfile;       /* Used for ioctl()     */
+       short   usalfiles[MAX_SCG][MAX_TGT][MAX_LUN];
+};
+#define        usallocal(p)    ((struct usal_local *)((p)->local))
+
+static BOOL    scsi_checktgt(SCSI *usalp, int f, int busno, int tgt, int tlun);
+
+/*
+ * I don't have any documentation about CAM
+ */
+#define        MAX_DMA_OSF_CAM (64*1024)
+
+#ifndef        AUTO_SENSE_LEN
+#      define  AUTO_SENSE_LEN  32      /* SCG_MAX_SENSE */
+#endif
+
+/*
+ * Return version information for the low level SCSI transport code.
+ * This has been introduced to make it easier to trace down problems
+ * in applications.
+ */
+static char *
+usalo_version(SCSI *usalp, int what)
+{
+       if (usalp != (SCSI *)0) {
+               switch (what) {
+
+               case SCG_VERSION:
+                       return (_usal_trans_version);
+               /*
+                * If you changed this source, you are not allowed to
+                * return "schily" for the SCG_AUTHOR request.
+                */
+               case SCG_AUTHOR:
+                       return (_usal_auth_cdrkit);
+               case SCG_SCCS_ID:
+                       return (__sccsid);
+               }
+       }
+       return ((char *)0);
+}
+
+static int
+usalo_help(SCSI *usalp, FILE *f)
+{
+       __usal_help(f, "CAM", "Generic transport independent SCSI (Common Access Method)",
+               "", "bus,target,lun", "1,2,0", TRUE, FALSE);
+       return (0);
+}
+
+static int
+usalo_open(SCSI *usalp, char *device)
+{
+               int     busno   = usal_scsibus(usalp);
+               int     tgt     = usal_target(usalp);
+               int     tlun    = usal_lun(usalp);
+       register int    b;
+       register int    t;
+       register int    l;
+
+       if (busno >= MAX_SCG || tgt >= MAX_TGT || tlun >= MAX_LUN) {
+               errno = EINVAL;
+               if (usalp->errstr)
+                       snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                               "Illegal value for busno, target or lun '%d,%d,%d'",
+                               busno, tgt, tlun);
+               return (-1);
+       }
+
+       if ((device != NULL && *device != '\0') || (busno == -2 && tgt == -2)) {
+               errno = EINVAL;
+               if (usalp->errstr)
+                       snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                               "Open by 'devname' not supported on this OS");
+               return (-1);
+       }
+
+       if (usalp->local == NULL) {
+               usalp->local = malloc(sizeof (struct usal_local));
+               if (usalp->local == NULL)
+                       return (0);
+               usallocal(usalp)->usalfile = -1;
+
+               for (b = 0; b < MAX_SCG; b++) {
+                       for (t = 0; t < MAX_TGT; t++) {
+                               for (l = 0; l < MAX_LUN; l++)
+                                       usallocal(usalp)->usalfiles[b][t][l] = 0;
+                       }
+               }
+       }
+
+       if (usallocal(usalp)->usalfile != -1)   /* multiple opens ??? */
+               return (1);                     /* not yet ready .... */
+
+       if ((usallocal(usalp)->usalfile = open("/dev/cam", O_RDWR, 0)) < 0) {
+               if (usalp->errstr)
+                       snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                               "Cannot open '/dev/cam'");
+               return (-1);
+       }
+
+       if (busno >= 0 && tgt >= 0 && tlun >= 0) {
+               /* scsi_checktgt() ??? */
+               for (l = 0; l < MAX_LUN; l++)
+                       usallocal(usalp)->usalfiles[b][t][l] = 1;
+               return (1);
+       }
+       /*
+        * There seems to be no clean way to check whether
+        * a SCSI bus is present in the current system.
+        * scsi_checktgt() is used as a workaround for this problem.
+        */
+       for (b = 0; b < MAX_SCG; b++) {
+               for (t = 0; t < MAX_TGT; t++) {
+                       if (scsi_checktgt(usalp, usallocal(usalp)->usalfile, b, t, 0)) {
+                               for (l = 0; l < MAX_LUN; l++)
+                                       usallocal(usalp)->usalfiles[b][t][l] = 1;
+                               /*
+                                * Found a target on this bus.
+                                * Comment the 'break' for a complete scan.
+                                */
+                               break;
+                       }
+               }
+       }
+       return (1);
+}
+
+static int
+usalo_close(SCSI *usalp)
+{
+       if (usalp->local == NULL)
+               return (-1);
+
+       if (usallocal(usalp)->usalfile >= 0)
+               close(usallocal(usalp)->usalfile);
+       usallocal(usalp)->usalfile = -1;
+       return (0);
+}
+
+/*
+ * We send a test unit ready command to the target to check whether the
+ * OS is considering this target to be valid.
+ * XXX Is this really needed? We should rather let the cmd fail later.
+ */
+static BOOL
+scsi_checktgt(SCSI *usalp, int f, int busno, int tgt, int tlun)
+{
+       struct usal_cmd *sp = usalp->scmd;
+       struct usal_cmd sc;
+       int     ret;
+       int     ofd  = usalp->fd;
+       int     obus = usal_scsibus(usalp);
+       int     otgt = usal_target(usalp);
+       int     olun = usal_lun(usalp);
+
+       usal_settarget(usalp, busno, tgt, tlun);
+       usalp->fd = f;
+
+       sc = *sp;
+       fillbytes((caddr_t)sp, sizeof (*sp), '\0');
+       sp->addr = (caddr_t)0;
+       sp->size = 0;
+       sp->flags = SCG_DISRE_ENA | SCG_SILENT;
+       sp->cdb_len = SC_G0_CDBLEN;
+       sp->sense_len = CCS_SENSE_LEN;
+       sp->cdb.g0_cdb.cmd = SC_TEST_UNIT_READY;
+       sp->cdb.g0_cdb.lun = usal_lun(usalp);
+
+       usalo_send(usalp);
+       usal_settarget(usalp, obus, otgt, olun);
+       usalp->fd = ofd;
+
+       if (sp->error != SCG_FATAL)
+               return (TRUE);
+       ret = sp->ux_errno != EINVAL;
+       *sp = sc;
+       return (ret);
+}
+
+
+static long
+usalo_maxdma(SCSI *usalp, long amt)
+{
+       long maxdma = MAX_DMA_OSF_CAM;
+
+       return (maxdma);
+}
+
+static void *
+usalo_getbuf(SCSI *usalp, long amt)
+{
+       if (usalp->debug > 0) {
+               fprintf((FILE *)usalp->errfile,
+                       "usalo_getbuf: %ld bytes\n", amt);
+       }
+       usalp->bufbase = valloc((size_t)(amt));
+       return (usalp->bufbase);
+}
+
+static void
+usalo_freebuf(SCSI *usalp)
+{
+       if (usalp->bufbase)
+               free(usalp->bufbase);
+       usalp->bufbase = NULL;
+}
+
+static BOOL
+usalo_havebus(SCSI *usalp, int busno)
+{
+       register int    t;
+
+       if (busno < 0 || busno >= MAX_SCG)
+               return (FALSE);
+
+       if (usalp->local == NULL)
+               return (FALSE);
+
+       for (t = 0; t < MAX_TGT; t++) {
+               if (usallocal(usalp)->usalfiles[busno][t][0] != 0)
+                       return (TRUE);
+       }
+       return (FALSE);
+}
+
+
+static int
+usalo_fileno(SCSI *usalp, int busno, int tgt, int tlun)
+{
+       if (usalp->local == NULL)
+               return (-1);
+
+       return ((busno < 0 || busno >= MAX_SCG) ? -1 : usallocal(usalp)->usalfile);
+}
+
+static int
+usalo_initiator_id(SCSI *usalp)
+{
+       return (-1);
+}
+
+static int
+usalo_isatapi(SCSI *usalp)
+{
+       return (FALSE);
+}
+
+static int
+usalo_reset(SCSI *usalp, int what)
+{
+       errno = EINVAL;
+       return (-1);
+}
+
+static int
+usalo_send(SCSI *usalp)
+{
+       struct usal_cmd *sp = usalp->scmd;
+       CCB_SCSIIO      ccb;
+       UAGT_CAM_CCB    ua;
+       unsigned char   *cdb;
+       CCB_RELSIM      relsim;
+       UAGT_CAM_CCB    relua;
+       int             i;
+
+       if (usalp->fd < 0) {
+               sp->error = SCG_FATAL;
+               return (0);
+       }
+
+       fillbytes(&ua, sizeof (UAGT_CAM_CCB), 0);
+       fillbytes(&ccb, sizeof (CCB_SCSIIO), 0);
+
+       ua.uagt_ccb = (CCB_HEADER *) &ccb;
+       ua.uagt_ccblen = sizeof (CCB_SCSIIO);
+       ccb.cam_ch.my_addr = (CCB_HEADER *) &ccb;
+       ccb.cam_ch.cam_ccb_len = sizeof (CCB_SCSIIO);
+
+       ua.uagt_snsbuf = ccb.cam_sense_ptr = sp->u_sense.cmd_sense;
+       ua.uagt_snslen = ccb.cam_sense_len = AUTO_SENSE_LEN;
+
+       cdb = (unsigned char *) ccb.cam_cdb_io.cam_cdb_bytes;
+
+       ccb.cam_timeout = sp->timeout;
+
+       ccb.cam_data_ptr = ua.uagt_buffer = (Uchar *) sp->addr;
+       ccb.cam_dxfer_len = ua.uagt_buflen = sp->size;
+       ccb.cam_ch.cam_func_code = XPT_SCSI_IO;
+       ccb.cam_ch.cam_flags = 0;       /* CAM_DIS_CALLBACK; */
+
+       if (sp->size == 0) {
+               ccb.cam_data_ptr = ua.uagt_buffer = (Uchar *) NULL;
+               ccb.cam_ch.cam_flags |= CAM_DIR_NONE;
+       } else {
+               if (sp->flags & SCG_RECV_DATA) {
+                       ccb.cam_ch.cam_flags |= CAM_DIR_IN;
+               } else {
+                       ccb.cam_ch.cam_flags |= CAM_DIR_OUT;
+               }
+       }
+
+       ccb.cam_cdb_len = sp->cdb_len;
+       for (i = 0; i < sp->cdb_len; i++)
+               cdb[i] = sp->cdb.cmd_cdb[i];
+
+       ccb.cam_ch.cam_path_id    = usal_scsibus(usalp);
+       ccb.cam_ch.cam_target_id  = usal_target(usalp);
+       ccb.cam_ch.cam_target_lun = usal_lun(usalp);
+
+       sp->sense_count = 0;
+       sp->ux_errno = 0;
+       sp->error = SCG_NO_ERROR;
+
+
+       if (ioctl(usalp->fd, UAGT_CAM_IO, (caddr_t) &ua) < 0) {
+               sp->ux_errno = geterrno();
+               sp->error = SCG_FATAL;
+               if (usalp->debug > 0) {
+                       errmsg("ioctl(fd, UAGT_CAM_IO, dev=%d,%d,%d) failed.\n",
+                                       usal_scsibus(usalp), usal_target(usalp), usal_lun(usalp));
+               }
+               return (0);
+       }
+       if (usalp->debug > 0) {
+               errmsgno(EX_BAD, "cam_status = 0x%.2X scsi_status = 0x%.2X dev=%d,%d,%d\n",
+                                       ccb.cam_ch.cam_status,
+                                       ccb.cam_scsi_status,
+                                       usal_scsibus(usalp), usal_target(usalp), usal_lun(usalp));
+               fflush(stderr);
+       }
+       switch (ccb.cam_ch.cam_status & CAM_STATUS_MASK) {
+
+       case CAM_REQ_CMP:       break;
+
+       case CAM_SEL_TIMEOUT:   sp->error = SCG_FATAL;
+                               sp->ux_errno = EIO;
+                               break;
+
+       case CAM_CMD_TIMEOUT:   sp->error = SCG_TIMEOUT;
+                               sp->ux_errno = EIO;
+                               break;
+
+       default:                sp->error = SCG_RETRYABLE;
+                               sp->ux_errno = EIO;
+                               break;
+       }
+
+       sp->u_scb.cmd_scb[0] = ccb.cam_scsi_status;
+
+       if (ccb.cam_ch.cam_status & CAM_AUTOSNS_VALID) {
+               sp->sense_count = MIN(ccb.cam_sense_len - ccb.cam_sense_resid,
+                       SCG_MAX_SENSE);
+               sp->sense_count = MIN(sp->sense_count, sp->sense_len);
+               if (sp->sense_len < 0)
+                       sp->sense_count = 0;
+       }
+       sp->resid = ccb.cam_resid;
+
+
+       /*
+        * this is perfectly wrong.
+        * But without this, we hang...
+        */
+       if (ccb.cam_ch.cam_status & CAM_SIM_QFRZN) {
+               fillbytes(&relsim, sizeof (CCB_RELSIM), 0);
+               relsim.cam_ch.cam_ccb_len = sizeof (CCB_SCSIIO);
+               relsim.cam_ch.cam_func_code = XPT_REL_SIMQ;
+               relsim.cam_ch.cam_flags = CAM_DIR_IN | CAM_DIS_CALLBACK;
+               relsim.cam_ch.cam_path_id       = usal_scsibus(usalp);
+               relsim.cam_ch.cam_target_id     = usal_target(usalp);
+               relsim.cam_ch.cam_target_lun    = usal_lun(usalp);
+
+               relua.uagt_ccb = (struct ccb_header *) & relsim;        /* wrong cast */
+               relua.uagt_ccblen = sizeof (relsim);
+               relua.uagt_buffer = NULL;
+               relua.uagt_buflen = 0;
+
+               if (ioctl(usalp->fd, UAGT_CAM_IO, (caddr_t) & relua) < 0)
+                       errmsg("DEC CAM -> LMA\n");
+       }
+       return (0);
+}
diff --git a/libusal/scsi-qnx.c b/libusal/scsi-qnx.c
new file mode 100644 (file)
index 0000000..7342025
--- /dev/null
@@ -0,0 +1,316 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)scsi-qnx.c      1.3 04/01/15 Copyright 1998-2003 J. Schilling */
+/*
+ *     Interface for QNX (Neutrino generic SCSI implementation).
+ *     First version adopted from the OSF-1 version by
+ *     Kevin Chiles <kchiles@qnx.com>
+ *
+ *     Warning: you may change this source, but if you do that
+ *     you need to change the _usal_version and _usal_auth* string below.
+ *     You may not return "schily" for an SCG_AUTHOR request anymore.
+ *     Choose your name instead of "schily" and make clear that the version
+ *     string is related to a modified source.
+ *
+ *     Copyright (c) 1998-2003 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/dcmd_cam.h>
+#include <sys/cam_device.h>
+
+/*
+ *     Warning: you may change this source, but if you do that
+ *     you need to change the _usal_version and _usal_auth* string below.
+ *     You may not return "schily" for an SCG_AUTHOR request anymore.
+ *     Choose your name instead of "schily" and make clear that the version
+ *     string is related to a modified source.
+ */
+static char    _usal_trans_version[] = "scsi-qnx.c-1.3";       /* The version for this transport*/
+
+#define        MAX_SCG         16      /* Max # of SCSI controllers */
+#define        MAX_TGT         16
+#define        MAX_LUN         8
+
+struct usal_local {
+       int             fd;
+};
+
+#define        usallocal(p)    ((struct usal_local *)((p)->local))
+#define        QNX_CAM_MAX_DMA (32*1024)
+
+#ifndef        AUTO_SENSE_LEN
+#      define  AUTO_SENSE_LEN  32      /* SCG_MAX_SENSE */
+#endif
+
+/*
+ * Return version information for the low level SCSI transport code.
+ * This has been introduced to make it easier to trace down problems
+ * in applications.
+ */
+static char *
+usalo_version(SCSI *usalp, int what)
+{
+       if (usalp != (SCSI *)0) {
+               switch (what) {
+
+               case SCG_VERSION:
+                       return (_usal_trans_version);
+               /*
+                * If you changed this source, you are not allowed to
+                * return "schily" for the SCG_AUTHOR request.
+                */
+               case SCG_AUTHOR:
+                       return ("Initial Version adopted from OSF-1 by QNX-people");
+                       return (_usal_auth_cdrkit);
+               case SCG_SCCS_ID:
+                       return (__sccsid);
+               }
+       }
+       return ((char *)0);
+}
+
+static int
+usalo_help(SCSI *usalp, FILE *f)
+{
+       __usal_help(f, "CAM", "Generic transport independent SCSI (Common Access Method)",
+               "", "bus,target,lun", "1,2,0", TRUE, FALSE);
+       return (0);
+}
+
+static int
+usalo_open(SCSI *usalp, char *device)
+{
+       int fd;
+
+       if (device == NULL || *device == '\0') {
+               errno = EINVAL;
+               if (usalp->errstr)
+                       snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                               "'devname' must be specified on this OS");
+               return (-1);
+       }
+
+       if (usalp->local == NULL) {
+               usalp->local = malloc(sizeof (struct usal_local));
+               if (usalp->local == NULL)
+                       return (0);
+               usallocal(usalp)->fd = -1;
+       }
+
+       if (usallocal(usalp)->fd != -1) /* multiple open? */
+               return (1);
+
+       if ((usallocal(usalp)->fd = open(device, O_RDONLY, 0)) < 0) {
+               if (usalp->errstr)
+                       snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                               "Cannot open '%s'", device);
+               return (-1);
+       }
+
+       usal_settarget(usalp, 0, 0, 0);
+
+       return (1);
+}
+
+static int
+usalo_close(SCSI *usalp)
+{
+       if (usalp->local == NULL)
+               return (-1);
+
+       if (usallocal(usalp)->fd >= 0)
+               close(usallocal(usalp)->fd);
+       usallocal(usalp)->fd = -1;
+       return (0);
+}
+
+static long
+usalo_maxdma(SCSI *usalp, long amt)
+{
+       long maxdma = QNX_CAM_MAX_DMA;
+
+       return (maxdma);
+}
+
+static void *
+usalo_getbuf(SCSI *usalp, long amt)
+{
+       void    *addr;
+
+       if (usalp->debug > 0) {
+               fprintf((FILE *)usalp->errfile, "usalo_getbuf: %ld bytes\n", amt);
+       }
+
+       if ((addr = mmap(NULL, amt, PROT_READ | PROT_WRITE | PROT_NOCACHE,
+                                               MAP_ANON | MAP_PHYS | MAP_NOX64K, NOFD, 0)) == MAP_FAILED) {
+               return (NULL);
+       }
+
+       usalp->bufbase = addr;
+       return (addr);
+}
+
+static void
+usalo_freebuf(SCSI *usalp)
+{
+       if (usalp->bufbase)
+               munmap(usalp->bufbase, QNX_CAM_MAX_DMA);
+       usalp->bufbase = NULL;
+}
+
+static BOOL
+usalo_havebus(SCSI *usalp, int busno)
+{
+       return (FALSE);
+}
+
+
+static int
+usalo_fileno(SCSI *usalp, int busno, int tgt, int tlun)
+{
+       if (usalp->local == NULL)
+               return (-1);
+
+       return ((busno < 0 || busno >= MAX_SCG) ? -1 : usallocal(usalp)->fd);
+}
+
+static int
+usalo_initiator_id(SCSI *usalp)
+{
+       return (-1);
+}
+
+static int
+usalo_isatapi(SCSI *usalp)
+{
+       cam_devinfo_t   cinfo;
+
+       if (devctl(usalp->fd, DCMD_CAM_DEVINFO, &cinfo, sizeof (cinfo), NULL) != EOK) {
+               return (TRUE);          /* default to ATAPI */
+       }
+       return ((cinfo.flags & DEV_ATAPI) ? TRUE : FALSE);
+}
+
+static int
+usalo_reset(SCSI *usalp, int what)
+{
+       errno = EINVAL;
+       return (-1);
+}
+
+static int
+usalo_send(SCSI *usalp)
+{
+       int             i;
+       struct usal_cmd *sp;
+       int             icnt;
+       iov_t           iov[3];
+       CAM_PASS_THRU   cpt;
+
+       icnt    = 1;
+       sp      = usalp->scmd;
+       if (usalp->fd < 0) {
+               sp->error = SCG_FATAL;
+               return (0);
+       }
+
+       memset(&cpt, 0, sizeof (cpt));
+
+       sp->sense_count = 0;
+       sp->ux_errno    = 0;
+       sp->error       = SCG_NO_ERROR;
+       cpt.cam_timeout = sp->timeout;
+       cpt.cam_cdb_len = sp->cdb_len;
+       memcpy(cpt.cam_cdb, sp->cdb.cmd_cdb, sp->cdb_len);
+
+       if (sp->sense_len != -1) {
+               cpt.cam_sense_len       = sp->sense_len;
+               cpt.cam_sense_ptr       = sizeof (cpt); /* XXX Offset from start of struct to data ??? */
+               icnt++;
+       } else {
+               cpt.cam_flags |= CAM_DIS_AUTOSENSE;
+       }
+
+       if (cpt.cam_dxfer_len = sp->size) {
+               icnt++;
+               cpt.cam_data_ptr        = (paddr_t)sizeof (cpt) + cpt.cam_sense_len;
+               if (sp->flags & SCG_RECV_DATA) {
+                       cpt.cam_flags |= CAM_DIR_IN;
+               } else {
+                       cpt.cam_flags |= CAM_DIR_OUT;
+               }
+       } else {
+               cpt.cam_flags |= CAM_DIR_NONE;
+       }
+
+       SETIOV(&iov[0], &cpt, sizeof (cpt));
+       SETIOV(&iov[1], sp->u_sense.cmd_sense, cpt.cam_sense_len);
+       SETIOV(&iov[2], sp->addr, sp->size);
+       if (devctlv(usallocal(usalp)->fd, DCMD_CAM_PASS_THRU, icnt, icnt, iov, iov, NULL)) {
+               sp->ux_errno = geterrno();
+               sp->error = SCG_FATAL;
+               if (usalp->debug > 0) {
+                       errmsg("cam_io failed\n");
+               }
+               return (0);
+       }
+
+       sp->resid               = cpt.cam_resid;
+       sp->u_scb.cmd_scb[0]    = cpt.cam_scsi_status;
+
+       switch (cpt.cam_status & CAM_STATUS_MASK) {
+               case CAM_REQ_CMP:
+                       break;
+
+               case CAM_SEL_TIMEOUT:
+                       sp->error       = SCG_FATAL;
+                       sp->ux_errno    = EIO;
+                       break;
+
+               case CAM_CMD_TIMEOUT:
+                       sp->error       = SCG_TIMEOUT;
+                       sp->ux_errno    = EIO;
+                       break;
+
+               default:
+                       sp->error       = SCG_RETRYABLE;
+                       sp->ux_errno    = EIO;
+                       break;
+       }
+
+       if (cpt.cam_status & CAM_AUTOSNS_VALID) {
+               sp->sense_count = min(cpt.cam_sense_len - cpt.cam_sense_resid,
+                                                       SCG_MAX_SENSE);
+               sp->sense_count = min(sp->sense_count, sp->sense_len);
+               if (sp->sense_len < 0)
+                       sp->sense_count = 0;
+       }
+
+       return (0);
+}
diff --git a/libusal/scsi-remote.c b/libusal/scsi-remote.c
new file mode 100644 (file)
index 0000000..f9b40d6
--- /dev/null
@@ -0,0 +1,1213 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+#define        USE_REMOTE
+/* @(#)scsi-remote.c   1.18 06/01/12 Copyright 1990,2000-2003 J. Schilling */
+/*
+ *     Remote SCSI user level command transport routines
+ *
+ *     Warning: you may change this source, but if you do that
+ *     you need to change the _usal_version and _usal_auth* string below.
+ *     You may not return "schily" for an SCG_AUTHOR request anymore.
+ *     Choose your name instead of "schily" and make clear that the version
+ *     string is related to a modified source.
+ *
+ *     Copyright (c) 1990,2000-2003 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <mconfig.h>
+
+#if !defined(HAVE_FORK) || !defined(HAVE_SOCKETPAIR) || !defined(HAVE_DUP2)
+#undef USE_RCMD_RSH
+#endif
+/*
+ * We may work without getservbyname() if we restructure the code not to
+ * use the port number if we only use _rcmdrsh().
+ */
+#if !defined(HAVE_GETSERVBYNAME)
+#undef USE_REMOTE                              /* Cannot get rcmd() port # */
+#endif
+#if (!defined(HAVE_NETDB_H) || !defined(HAVE_RCMD)) && !defined(USE_RCMD_RSH)
+#undef USE_REMOTE                              /* There is no rcmd() */
+#endif
+
+#ifdef USE_REMOTE
+#include <stdio.h>
+#include <sys/types.h>
+#include <fctldefs.h>
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#include <errno.h>
+#include <signal.h>
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef HAVE_PWD_H
+#include <pwd.h>
+#endif
+#include <standard.h>
+#include <stdxlib.h>
+#include <unixstd.h>
+#include <strdefs.h>
+#include <schily.h>
+
+#include <usal/usalcmd.h>
+#include <usal/scsitransp.h>
+
+#if    defined(SIGDEFER) || defined(SVR4)
+#define        signal  sigset
+#endif
+
+/*
+ * On Cygwin, there are no privilleged ports.
+ * On UNIX, rcmd() uses privilleged port that only work for root.
+ */
+#ifdef IS_CYGWIN
+#define        privport_ok()   (1)
+#else
+#ifdef HAVE_GETPPRIV
+#define        privport_ok()   ppriv_ok()
+#else
+#define        privport_ok()   (geteuid() == 0)
+#endif
+#endif
+
+#define        CMD_SIZE        80
+
+#define        MAX_SCG         16      /* Max # of SCSI controllers */
+#define        MAX_TGT         16
+#define        MAX_LUN         8
+
+/*extern       BOOL    debug;*/
+LOCAL  BOOL    debug = 1;
+
+LOCAL  char    _usal_trans_version[] = "remote-1.18";  /* The version for remote SCSI  */
+LOCAL  char    _usal_auth_cdrkit[]     = "cdrkit-team";        /* The author for this module   */
+
+LOCAL  int     usalo_rsend             __PR((SCSI *usalp));
+LOCAL  char *  usalo_rversion          __PR((SCSI *usalp, int what));
+LOCAL  int     usalo_rhelp             __PR((SCSI *usalp, FILE *f));
+LOCAL  int     usalo_ropen             __PR((SCSI *usalp, char *device));
+LOCAL  int     usalo_rclose            __PR((SCSI *usalp));
+LOCAL  long    usalo_rmaxdma           __PR((SCSI *usalp, long amt));
+LOCAL  void *  usalo_rgetbuf           __PR((SCSI *usalp, long amt));
+LOCAL  void    usalo_rfreebuf          __PR((SCSI *usalp));
+LOCAL  BOOL    usalo_rhavebus          __PR((SCSI *usalp, int busno));
+LOCAL  int     usalo_rfileno           __PR((SCSI *usalp, int busno, int tgt, int tlun));
+LOCAL  int     usalo_rinitiator_id     __PR((SCSI *usalp));
+LOCAL  int     usalo_risatapi          __PR((SCSI *usalp));
+LOCAL  int     usalo_rreset            __PR((SCSI *usalp, int what));
+
+/*
+ * XXX We should rethink the fd parameter now that we introduced
+ * XXX the rscsirchar() function and most access of remfd is done
+ * XXX via usallocal(usalp)->remfd.
+ */
+LOCAL  void    rscsiabrt               __PR((int sig));
+LOCAL  int     rscsigetconn            __PR((SCSI *usalp, char *host));
+LOCAL  char    *rscsiversion           __PR((SCSI *usalp, int fd, int what));
+LOCAL  int     rscsiopen               __PR((SCSI *usalp, int fd, char *fname));
+LOCAL  int     rscsiclose              __PR((SCSI *usalp, int fd));
+LOCAL  int     rscsimaxdma             __PR((SCSI *usalp, int fd, long amt));
+LOCAL  int     rscsigetbuf             __PR((SCSI *usalp, int fd, long amt));
+LOCAL  int     rscsifreebuf            __PR((SCSI *usalp, int fd));
+LOCAL  int     rscsihavebus            __PR((SCSI *usalp, int fd, int bus));
+LOCAL  int     rscsifileno             __PR((SCSI *usalp, int fd, int busno, int tgt, int tlun));
+LOCAL  int     rscsiinitiator_id       __PR((SCSI *usalp, int fd));
+LOCAL  int     rscsiisatapi            __PR((SCSI *usalp, int fd));
+LOCAL  int     rscsireset              __PR((SCSI *usalp, int fd, int what));
+LOCAL  int     rscsiscmd               __PR((SCSI *usalp, int fd, struct usal_cmd *sp));
+LOCAL  int     rscsifillrbuf           __PR((SCSI *usalp));
+LOCAL  int     rscsirchar              __PR((SCSI *usalp, char *cp));
+LOCAL  int     rscsireadbuf            __PR((SCSI *usalp, int fd, char *buf, int count));
+LOCAL  void    rscsivoidarg            __PR((SCSI *usalp, int fd, int count));
+LOCAL  int     rscsicmd                __PR((SCSI *usalp, int fd, char *name, char *cbuf));
+LOCAL  void    rscsisendcmd            __PR((SCSI *usalp, int fd, char *name, char *cbuf));
+LOCAL  int     rscsigetline            __PR((SCSI *usalp, int fd, char *line, int count));
+LOCAL  int     rscsireadnum            __PR((SCSI *usalp, int fd));
+LOCAL  int     rscsigetstatus          __PR((SCSI *usalp, int fd, char *name));
+LOCAL  int     rscsiaborted            __PR((SCSI *usalp, int fd));
+#ifdef USE_RCMD_RSH
+LOCAL  int     _rcmdrsh                __PR((char **ahost, int inport,
+                                               const char *locuser,
+                                               const char *remuser,
+                                               const char *cmd,
+                                               const char *rsh));
+#ifdef HAVE_GETPPRIV
+LOCAL  BOOL    ppriv_ok                __PR((void));
+#endif
+#endif
+
+/*--------------------------------------------------------------------------*/
+
+#define        READBUF_SIZE    128
+
+struct usal_local {
+       int     remfd;
+       char    readbuf[READBUF_SIZE];
+       char    *readbptr;
+       int     readbcnt;
+       BOOL    isopen;
+       int     rsize;
+       int     wsize;
+       char    *v_version;
+       char    *v_author;
+       char    *v_sccs_id;
+};
+
+
+#define        usallocal(p)    ((struct usal_local *)((p)->local))
+
+usal_ops_t remote_ops = {
+       usalo_rsend,            /* "S" end      */
+       usalo_rversion,         /* "V" ersion   */
+       usalo_rhelp,            /*     help     */
+       usalo_ropen,            /* "O" pen      */
+       usalo_rclose,           /* "C" lose     */
+       usalo_rmaxdma,          /* "D" MA       */
+       usalo_rgetbuf,          /* "M" alloc    */
+       usalo_rfreebuf,         /* "F" free     */
+       usalo_rhavebus,         /* "B" us       */
+       usalo_rfileno,          /* "T" arget    */
+       usalo_rinitiator_id,    /* "I" nitiator */
+       usalo_risatapi,         /* "A" tapi     */
+       usalo_rreset,           /* "R" eset     */
+};
+
+/*
+ * Return our ops ptr.
+ */
+usal_ops_t *
+usal_remote()
+{
+       return (&remote_ops);
+}
+
+/*
+ * Return version information for the low level SCSI transport code.
+ * This has been introduced to make it easier to trace down problems
+ * in applications.
+ */
+LOCAL char *
+usalo_rversion(usalp, what)
+       SCSI    *usalp;
+       int     what;
+{
+       int     f;
+
+       if (usalp->local == NULL)
+               return ((char *)0);
+
+       f = usallocal(usalp)->remfd;
+       if (usalp != (SCSI *)0) {
+               switch (what) {
+
+               case SCG_VERSION:
+                       return (_usal_trans_version);
+               /*
+                * If you changed this source, you are not allowed to
+                * return "schily" for the SCG_AUTHOR request.
+                */
+               case SCG_AUTHOR:
+                       return (_usal_auth_cdrkit);
+               case SCG_SCCS_ID:
+                       return (__sccsid);
+
+               case SCG_RVERSION:
+                       if (usallocal(usalp)->v_version == NULL)
+                               usallocal(usalp)->v_version = rscsiversion(usalp, f, SCG_VERSION);
+                       return (usallocal(usalp)->v_version);
+               /*
+                * If you changed this source, you are not allowed to
+                * return "schily" for the SCG_AUTHOR request.
+                */
+               case SCG_RAUTHOR:
+                       if (usallocal(usalp)->v_author == NULL)
+                               usallocal(usalp)->v_author = rscsiversion(usalp, f, SCG_AUTHOR);
+                       return (usallocal(usalp)->v_author);
+               case SCG_RSCCS_ID:
+                       if (usallocal(usalp)->v_sccs_id == NULL)
+                               usallocal(usalp)->v_sccs_id = rscsiversion(usalp, f, SCG_SCCS_ID);
+                       return (usallocal(usalp)->v_sccs_id);
+               }
+       }
+       return ((char *)0);
+}
+
+LOCAL int
+usalo_rhelp(usalp, f)
+       SCSI    *usalp;
+       FILE    *f;
+{
+       __usal_help(f, "RSCSI", "Remote SCSI",
+               "REMOTE:", "rscsi@host:bus,target,lun", "REMOTE:rscsi@host:1,2,0", TRUE, FALSE);
+       return (0);
+}
+
+LOCAL int
+usalo_ropen(usalp, device)
+       SCSI    *usalp;
+       char    *device;
+{
+               int     busno   = usal_scsibus(usalp);
+               int     tgt     = usal_target(usalp);
+               int     tlun    = usal_lun(usalp);
+       register int    f;
+       register int    nopen = 0;
+       char            devname[128];
+       char            *p;
+
+       if (usalp->overbose)
+               fprintf(stderr, "Warning: Using remote SCSI interface.\n");
+
+       if (busno >= MAX_SCG || tgt >= MAX_TGT || tlun >= MAX_LUN) {
+               errno = EINVAL;
+               if (usalp->errstr)
+                       snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                       "Illegal value for busno, target or lun '%d,%d,%d'",
+                       busno, tgt, tlun);
+
+               return (-1);
+       }
+       if (usalp->local == NULL) {
+               usalp->local = malloc(sizeof (struct usal_local));
+               if (usalp->local == NULL)
+                       return (0);
+               usallocal(usalp)->remfd = -1;
+               usallocal(usalp)->readbptr = usallocal(usalp)->readbuf;
+               usallocal(usalp)->readbcnt = 0;
+               usallocal(usalp)->isopen = FALSE;
+               usallocal(usalp)->rsize = 0;
+               usallocal(usalp)->wsize = 0;
+               usallocal(usalp)->v_version = NULL;
+               usallocal(usalp)->v_author  = NULL;
+               usallocal(usalp)->v_sccs_id = NULL;
+       }
+
+       if (device == NULL || (strncmp(device, "REMOTE", 6) != 0) ||
+                               (device = strchr(device, ':')) == NULL) {
+               if (usalp->errstr)
+                       snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                               "Illegal remote device syntax");
+               return (-1);
+       }
+       device++;
+       /*
+        * Save non user@host:device
+        */
+       snprintf(devname, sizeof (devname), "%s", device);
+
+       if ((p = strchr(devname, ':')) != NULL)
+               *p++ = '\0';
+
+       f = rscsigetconn(usalp, devname);
+       if (f < 0) {
+               if (usalp->errstr)
+                       snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                               "Cannot get connection to remote host");
+               return (-1);
+       }
+       usallocal(usalp)->remfd = f;
+       debug = usalp->debug;
+       if (rscsiopen(usalp, f, p) >= 0) {
+               nopen++;
+               usallocal(usalp)->isopen = TRUE;
+       }
+       return (nopen);
+}
+
+LOCAL int
+usalo_rclose(usalp)
+       SCSI    *usalp;
+{
+       register int    f;
+               int     ret;
+
+       if (usalp->local == NULL)
+               return (-1);
+
+       if (usallocal(usalp)->v_version != NULL) {
+               free(usallocal(usalp)->v_version);
+               usallocal(usalp)->v_version = NULL;
+       }
+       if (usallocal(usalp)->v_author != NULL) {
+               free(usallocal(usalp)->v_author);
+               usallocal(usalp)->v_author  = NULL;
+       }
+       if (usallocal(usalp)->v_sccs_id != NULL) {
+               free(usallocal(usalp)->v_sccs_id);
+               usallocal(usalp)->v_sccs_id = NULL;
+       }
+
+       f = usallocal(usalp)->remfd;
+       if (f < 0 || !usallocal(usalp)->isopen)
+               return (0);
+       ret = rscsiclose(usalp, f);
+       usallocal(usalp)->isopen = FALSE;
+       close(f);
+       usallocal(usalp)->remfd = -1;
+       return (ret);
+}
+
+LOCAL long
+usalo_rmaxdma(usalp, amt)
+       SCSI    *usalp;
+       long    amt;
+{
+       if (usalp->local == NULL)
+               return (-1L);
+
+       return (rscsimaxdma(usalp, usallocal(usalp)->remfd, amt));
+}
+
+LOCAL void *
+usalo_rgetbuf(usalp, amt)
+       SCSI    *usalp;
+       long    amt;
+{
+       int     ret;
+
+       if (usalp->local == NULL)
+               return ((void *)0);
+
+       ret = rscsigetbuf(usalp, usallocal(usalp)->remfd, amt);
+       if (ret < 0)
+               return ((void *)0);
+
+#ifdef HAVE_VALLOC
+       usalp->bufbase = (void *)valloc((size_t)amt);
+#else
+       usalp->bufbase = (void *)malloc((size_t)amt);
+#endif
+       if (usalp->bufbase == NULL) {
+               usalo_rfreebuf(usalp);
+               return ((void *)0);
+       }
+       return (usalp->bufbase);
+}
+
+LOCAL void
+usalo_rfreebuf(usalp)
+       SCSI    *usalp;
+{
+       int     f;
+
+       if (usalp->bufbase)
+               free(usalp->bufbase);
+       usalp->bufbase = NULL;
+
+       if (usalp->local == NULL)
+               return;
+
+       f = usallocal(usalp)->remfd;
+       if (f < 0 || !usallocal(usalp)->isopen)
+               return;
+       rscsifreebuf(usalp, f);
+}
+
+LOCAL BOOL
+usalo_rhavebus(usalp, busno)
+       SCSI    *usalp;
+       int     busno;
+{
+       if (usalp->local == NULL || busno < 0 || busno >= MAX_SCG)
+               return (FALSE);
+
+       return (rscsihavebus(usalp, usallocal(usalp)->remfd, busno));
+}
+
+LOCAL int
+usalo_rfileno(usalp, busno, tgt, tlun)
+       SCSI    *usalp;
+       int     busno;
+       int     tgt;
+       int     tlun;
+{
+       int     f;
+
+       if (usalp->local == NULL ||
+           busno < 0 || busno >= MAX_SCG ||
+           tgt < 0 || tgt >= MAX_TGT ||
+           tlun < 0 || tlun >= MAX_LUN)
+               return (-1);
+
+       f = usallocal(usalp)->remfd;
+       if (f < 0 || !usallocal(usalp)->isopen)
+               return (-1);
+       return (rscsifileno(usalp, f, busno, tgt, tlun));
+}
+
+LOCAL int
+usalo_rinitiator_id(usalp)
+       SCSI    *usalp;
+{
+       if (usalp->local == NULL)
+               return (-1);
+
+       return (rscsiinitiator_id(usalp, usallocal(usalp)->remfd));
+}
+
+LOCAL int
+usalo_risatapi(usalp)
+       SCSI    *usalp;
+{
+       if (usalp->local == NULL)
+               return (-1);
+
+       return (rscsiisatapi(usalp, usallocal(usalp)->remfd));
+}
+
+LOCAL int
+usalo_rreset(usalp, what)
+       SCSI    *usalp;
+       int     what;
+{
+       if (usalp->local == NULL)
+               return (-1);
+
+       return (rscsireset(usalp, usallocal(usalp)->remfd, what));
+}
+
+LOCAL int
+usalo_rsend(usalp)
+       SCSI            *usalp;
+{
+       struct usal_cmd *sp = usalp->scmd;
+       int             ret;
+
+       if (usalp->local == NULL)
+               return (-1);
+
+       if (usalp->fd < 0) {
+               sp->error = SCG_FATAL;
+               return (0);
+       }
+       ret = rscsiscmd(usalp, usallocal(usalp)->remfd, usalp->scmd);
+
+       return (ret);
+}
+
+/*--------------------------------------------------------------------------*/
+LOCAL void
+rscsiabrt(sig)
+       int     sig;
+{
+       rscsiaborted((SCSI *)0, -1);
+}
+
+LOCAL int
+rscsigetconn(usalp, host)
+       SCSI    *usalp;
+       char    *host;
+{
+       static  struct servent  *sp = 0;
+       static  struct passwd   *pw = 0;
+               char            *name = "root";
+               char            *p;
+               char            *rscsi;
+               char            *rsh;
+               int             rscsisock;
+               char            *rscsipeer;
+               char            rscsiuser[128];
+
+
+       signal(SIGPIPE, rscsiabrt);
+       if (sp == 0) {
+               sp = getservbyname("shell", "tcp");
+               if (sp == 0) {
+                       comerrno(EX_BAD, "shell/tcp: unknown service\n");
+                       /* NOTREACHED */
+               }
+               pw = getpwuid(getuid());
+               if (pw == 0) {
+                       comerrno(EX_BAD, "who are you? No passwd entry found.\n");
+                       /* NOTREACHED */
+               }
+       }
+       if ((p = strchr(host, '@')) != NULL) {
+               size_t d = p - host;
+
+               if (d > sizeof (rscsiuser))
+                       d = sizeof (rscsiuser);
+               snprintf(rscsiuser, sizeof (rscsiuser), "%.*s", (int)d, host);
+               name = rscsiuser;
+               host = &p[1];
+       } else {
+               name = pw->pw_name;
+       }
+       if (usalp->debug > 0)
+               errmsgno(EX_BAD, "locuser: '%s' rscsiuser: '%s' host: '%s'\n",
+                                               pw->pw_name, name, host);
+       rscsipeer = host;
+
+       if ((rscsi = getenv("RSCSI")) == NULL)
+               rscsi = "/usr/sbin/netscsid";
+       rsh = getenv("RSH");
+
+#ifdef USE_RCMD_RSH
+       if (!privport_ok() || rsh != NULL)
+               rscsisock = _rcmdrsh(&rscsipeer, (unsigned short)sp->s_port,
+                                       pw->pw_name, name, rscsi, rsh);
+       else
+#endif
+#ifdef HAVE_RCMD
+               rscsisock = rcmd(&rscsipeer, (unsigned short)sp->s_port,
+                                       pw->pw_name, name, rscsi, 0);
+#else
+               rscsisock = _rcmdrsh(&rscsipeer, (unsigned short)sp->s_port,
+                                       pw->pw_name, name, rscsi, rsh);
+#endif
+
+       return (rscsisock);
+}
+
+LOCAL char *
+rscsiversion(usalp, fd, what)
+       SCSI    *usalp;
+       int     fd;
+       int     what;
+{
+       char    cbuf[CMD_SIZE];
+       char    *p;
+       int     ret;
+
+       snprintf(cbuf, sizeof (cbuf), "V%d\n", what);
+       ret = rscsicmd(usalp, fd, "version", cbuf);
+       p = malloc(ret);
+       if (p == NULL)
+               return (p);
+       rscsireadbuf(usalp, fd, p, ret);
+       return (p);
+}
+
+LOCAL int
+rscsiopen(usalp, fd, fname)
+       SCSI    *usalp;
+       int     fd;
+       char    *fname;
+{
+       char    cbuf[CMD_SIZE];
+       int     ret;
+       int     bus;
+       int     chan;
+       int     tgt;
+       int     lun;
+
+       snprintf(cbuf, sizeof (cbuf), "O%s\n", fname?fname:"");
+       ret = rscsicmd(usalp, fd, "open", cbuf);
+       if (ret < 0)
+               return (ret);
+
+       bus = rscsireadnum(usalp, fd);
+       chan = rscsireadnum(usalp, fd);
+       tgt = rscsireadnum(usalp, fd);
+       lun = rscsireadnum(usalp, fd);
+
+       usal_settarget(usalp, bus, tgt, lun);
+       return (ret);
+}
+
+LOCAL int
+rscsiclose(usalp, fd)
+       SCSI    *usalp;
+       int     fd;
+{
+       return (rscsicmd(usalp, fd, "close", "C\n"));
+}
+
+LOCAL int
+rscsimaxdma(usalp, fd, amt)
+       SCSI    *usalp;
+       int     fd;
+       long    amt;
+{
+       char    cbuf[CMD_SIZE];
+
+       snprintf(cbuf, sizeof (cbuf), "D%ld\n", amt);
+       return (rscsicmd(usalp, fd, "maxdma", cbuf));
+}
+
+LOCAL int
+rscsigetbuf(usalp, fd, amt)
+       SCSI    *usalp;
+       int     fd;
+       long    amt;
+{
+       char    cbuf[CMD_SIZE];
+       int     size;
+       int     ret;
+
+       snprintf(cbuf, sizeof (cbuf), "M%ld\n", amt);
+       ret = rscsicmd(usalp, fd, "getbuf", cbuf);
+       if (ret < 0)
+               return (ret);
+
+       size = ret + 1024;      /* Add protocol overhead */
+
+#ifdef SO_SNDBUF
+       if (size > usallocal(usalp)->wsize) while (size > 512 &&
+               setsockopt(fd, SOL_SOCKET, SO_SNDBUF,
+                                       (char *)&size, sizeof (size)) < 0) {
+               size -= 512;
+       }
+       if (size > usallocal(usalp)->wsize) {
+               usallocal(usalp)->wsize = size;
+               if (usalp->debug > 0)
+                       errmsgno(EX_BAD, "sndsize: %d\n", size);
+       }
+#endif
+#ifdef SO_RCVBUF
+       if (size > usallocal(usalp)->rsize) while (size > 512 &&
+               setsockopt(fd, SOL_SOCKET, SO_RCVBUF,
+                                       (char *)&size, sizeof (size)) < 0) {
+               size -= 512;
+       }
+       if (size > usallocal(usalp)->rsize) {
+               usallocal(usalp)->rsize = size;
+               if (usalp->debug > 0)
+                       errmsgno(EX_BAD, "rcvsize: %d\n", size);
+       }
+#endif
+       return (ret);
+}
+
+LOCAL int
+rscsifreebuf(usalp, fd)
+       SCSI    *usalp;
+       int     fd;
+{
+       return (rscsicmd(usalp, fd, "freebuf", "F\n"));
+}
+
+LOCAL int
+rscsihavebus(usalp, fd, busno)
+       SCSI    *usalp;
+       int     fd;
+       int     busno;
+{
+       char    cbuf[2*CMD_SIZE];
+
+       snprintf(cbuf, sizeof (cbuf), "B%d\n%d\n",
+               busno,
+               0);
+       return (rscsicmd(usalp, fd, "havebus", cbuf));
+}
+
+LOCAL int
+rscsifileno(usalp, fd, busno, tgt, tlun)
+       SCSI    *usalp;
+       int     fd;
+       int     busno;
+       int     tgt;
+       int     tlun;
+{
+       char    cbuf[3*CMD_SIZE];
+
+       snprintf(cbuf, sizeof (cbuf), "T%d\n%d\n%d\n%d\n",
+               busno,
+               0,
+               tgt,
+               tlun);
+       return (rscsicmd(usalp, fd, "fileno", cbuf));
+}
+
+LOCAL int
+rscsiinitiator_id(usalp, fd)
+       SCSI    *usalp;
+       int     fd;
+{
+       return (rscsicmd(usalp, fd, "initiator id", "I\n"));
+}
+
+LOCAL int
+rscsiisatapi(usalp, fd)
+       SCSI    *usalp;
+       int     fd;
+{
+       return (rscsicmd(usalp, fd, "isatapi", "A\n"));
+}
+
+LOCAL int
+rscsireset(usalp, fd, what)
+       SCSI    *usalp;
+       int     fd;
+       int     what;
+{
+       char    cbuf[CMD_SIZE];
+
+       snprintf(cbuf, sizeof (cbuf), "R%d\n", what);
+       return (rscsicmd(usalp, fd, "reset", cbuf));
+}
+
+LOCAL int
+rscsiscmd(usalp, fd, sp)
+       SCSI    *usalp;
+       int     fd;
+       struct usal_cmd  *sp;
+{
+       char    cbuf[1600];
+       int     ret;
+       int     amt = 0;
+       int     voidsize = 0;
+
+       ret = snprintf(cbuf, sizeof (cbuf), "S%d\n%d\n%d\n%d\n%d\n",
+               sp->size, sp->flags,
+               sp->cdb_len, sp->sense_len,
+               sp->timeout);
+       movebytes(sp->cdb.cmd_cdb, &cbuf[ret], sp->cdb_len);
+       ret += sp->cdb_len;
+
+       if ((sp->flags & SCG_RECV_DATA) == 0 && sp->size > 0) {
+               amt = sp->size;
+               if ((ret + amt) <= sizeof (cbuf)) {
+                       movebytes(sp->addr, &cbuf[ret], amt);
+                       ret += amt;
+                       amt = 0;
+               }
+       }
+       errno = 0;
+       if (_nixwrite(fd, cbuf, ret) != ret)
+               rscsiaborted(usalp, fd);
+
+       if (amt > 0) {
+               if (_nixwrite(fd, sp->addr, amt) != amt)
+                       rscsiaborted(usalp, fd);
+       }
+
+       ret = rscsigetstatus(usalp, fd, "sendcmd");
+       if (ret < 0)
+               return (ret);
+
+       sp->resid = sp->size - ret;
+       sp->error = rscsireadnum(usalp, fd);
+       sp->ux_errno = rscsireadnum(usalp, fd);
+       *(Uchar *)&sp->scb = rscsireadnum(usalp, fd);
+       sp->sense_count = rscsireadnum(usalp, fd);
+
+       if (sp->sense_count > SCG_MAX_SENSE) {
+               voidsize = sp->sense_count - SCG_MAX_SENSE;
+               sp->sense_count = SCG_MAX_SENSE;
+       }
+       if (sp->sense_count > 0) {
+               rscsireadbuf(usalp, fd, (char *)sp->u_sense.cmd_sense, sp->sense_count);
+               rscsivoidarg(usalp, fd, voidsize);
+       }
+
+       if ((sp->flags & SCG_RECV_DATA) != 0 && ret > 0)
+               rscsireadbuf(usalp, fd, sp->addr, ret);
+
+       return (0);
+}
+
+LOCAL int
+rscsifillrbuf(usalp)
+       SCSI    *usalp;
+{
+       usallocal(usalp)->readbptr = usallocal(usalp)->readbuf;
+
+       return (usallocal(usalp)->readbcnt =
+                       _niread(usallocal(usalp)->remfd,
+                           usallocal(usalp)->readbuf, READBUF_SIZE));
+}
+
+LOCAL int
+rscsirchar(usalp, cp)
+       SCSI    *usalp;
+       char    *cp;
+{
+       if (--(usallocal(usalp)->readbcnt) < 0) {
+               if (rscsifillrbuf(usalp) <= 0)
+                       return (usallocal(usalp)->readbcnt);
+               --(usallocal(usalp)->readbcnt);
+       }
+       *cp = *(usallocal(usalp)->readbptr)++;
+       return (1);
+}
+
+LOCAL int
+rscsireadbuf(usalp, fd, buf, count)
+       SCSI    *usalp;
+       int     fd;
+       char    *buf;
+       int     count;
+{
+       register int    n = count;
+       register int    amt = 0;
+       register int    cnt;
+
+       if (usallocal(usalp)->readbcnt > 0) {
+               cnt = usallocal(usalp)->readbcnt;
+               if (cnt > n)
+                       cnt = n;
+               movebytes(usallocal(usalp)->readbptr, buf, cnt);
+               usallocal(usalp)->readbptr += cnt;
+               usallocal(usalp)->readbcnt -= cnt;
+               amt += cnt;
+       }
+       while (amt < n) {
+               if ((cnt = _niread(fd, &buf[amt], n - amt)) <= 0) {
+                       return (rscsiaborted(usalp, fd));
+               }
+               amt += cnt;
+       }
+       return (amt);
+}
+
+LOCAL void
+rscsivoidarg(usalp, fd, n)
+       SCSI    *usalp;
+       int     fd;
+       register int    n;
+{
+       register int    i;
+       register int    amt;
+               char    buf[512];
+
+       for (i = 0; i < n; i += amt) {
+               amt = sizeof (buf);
+               if ((n - i) < amt)
+                       amt = n - i;
+               rscsireadbuf(usalp, fd, buf, amt);
+       }
+}
+
+LOCAL int
+rscsicmd(usalp, fd, name, cbuf)
+       SCSI    *usalp;
+       int     fd;
+       char    *name;
+       char    *cbuf;
+{
+       rscsisendcmd(usalp, fd, name, cbuf);
+       return (rscsigetstatus(usalp, fd, name));
+}
+
+LOCAL void
+rscsisendcmd(usalp, fd, name, cbuf)
+       SCSI    *usalp;
+       int     fd;
+       char    *name;
+       char    *cbuf;
+{
+       int     buflen = strlen(cbuf);
+
+       errno = 0;
+       if (_nixwrite(fd, cbuf, buflen) != buflen)
+               rscsiaborted(usalp, fd);
+}
+
+LOCAL int
+rscsigetline(usalp, fd, line, count)
+       SCSI    *usalp;
+       int     fd;
+       char    *line;
+       int     count;
+{
+       register char   *cp;
+
+       for (cp = line; cp < &line[count]; cp++) {
+               if (rscsirchar(usalp, cp) != 1)
+                       return (rscsiaborted(usalp, fd));
+
+               if (*cp == '\n') {
+                       *cp = '\0';
+                       return (cp - line);
+               }
+       }
+       return (rscsiaborted(usalp, fd));
+}
+
+LOCAL int
+rscsireadnum(usalp, fd)
+       SCSI    *usalp;
+       int     fd;
+{
+       char    cbuf[CMD_SIZE];
+
+       rscsigetline(usalp, fd, cbuf, sizeof (cbuf));
+       return (atoi(cbuf));
+}
+
+LOCAL int
+rscsigetstatus(usalp, fd, name)
+       SCSI    *usalp;
+       int     fd;
+       char    *name;
+{
+       char    cbuf[CMD_SIZE];
+       char    code;
+       int     number;
+       int     count;
+       int     voidsize = 0;
+
+       rscsigetline(usalp, fd, cbuf, sizeof (cbuf));
+       code = cbuf[0];
+       number = atoi(&cbuf[1]);
+
+       if (code == 'E' || code == 'F') {
+               rscsigetline(usalp, fd, cbuf, sizeof (cbuf));
+               if (code == 'F')        /* should close file ??? */
+                       rscsiaborted(usalp, fd);
+
+               rscsigetline(usalp, fd, cbuf, sizeof (cbuf));
+               count = atoi(cbuf);
+               if (count > 0) {
+                       if (usalp->errstr == NULL) {
+                               voidsize = count;
+                               count = 0;
+                       } else if (count > SCSI_ERRSTR_SIZE) {
+                               voidsize = count - SCSI_ERRSTR_SIZE;
+                               count = SCSI_ERRSTR_SIZE;
+                       }
+                       rscsireadbuf(usalp, fd, usalp->errstr, count);
+                       rscsivoidarg(usalp, fd, voidsize);
+               }
+               if (usalp->debug > 0)
+                       errmsgno(number, "Remote status(%s): %d '%s'.\n",
+                                                       name, number, cbuf);
+               errno = number;
+               return (-1);
+       }
+       if (code != 'A') {
+               /* XXX Hier kommt evt Command not found ... */
+               if (usalp->debug > 0)
+                       errmsgno(EX_BAD, "Protocol error (got %s).\n", cbuf);
+               return (rscsiaborted(usalp, fd));
+       }
+       return (number);
+}
+
+LOCAL int
+rscsiaborted(usalp, fd)
+       SCSI    *usalp;
+       int     fd;
+{
+       if ((usalp && usalp->debug > 0) || debug)
+               errmsgno(EX_BAD, "Lost connection to remote host ??\n");
+       /* if fd >= 0 */
+       /* close file */
+       if (errno == 0)
+               errno = EIO;
+       return (-1);
+}
+
+/*--------------------------------------------------------------------------*/
+#ifdef USE_RCMD_RSH
+/*
+ * If we make a separate file for libschily, we would need these include files:
+ *
+ * socketpair():       sys/types.h + sys/socket.h
+ * dup2():             unixstd.h (hat auch sys/types.h)
+ * strrchr():          strdefs.h
+ *
+ * and make sure that we use sigset() instead of signal() if possible.
+ */
+#include <waitdefs.h>
+LOCAL int
+_rcmdrsh(ahost, inport, locuser, remuser, cmd, rsh)
+       char            **ahost;
+       int             inport;         /* port is ignored */
+       const char      *locuser;
+       const char      *remuser;
+       const char      *cmd;
+       const char      *rsh;
+{
+       struct passwd   *pw;
+       int     pp[2];
+       int     pid;
+
+       if (rsh == 0)
+               rsh = "rsh";
+
+       /*
+        * Verify that 'locuser' is present on local host.
+        */
+       if ((pw = getpwnam(locuser)) == NULL) {
+               errmsgno(EX_BAD, "Unknown user: %s\n", locuser);
+               return (-1);
+       }
+       /* XXX Check the existence for 'ahost' here? */
+
+       /*
+        * rcmd(3) creates a single socket to be used for communication.
+        * We need a bi-directional pipe to implement the same interface.
+        * On newer OS that implement bi-directional we could use pipe(2)
+        * but it makes no sense unless we find an OS that implements a
+        * bi-directional pipe(2) but no socketpair().
+        */
+       if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pp) == -1) {
+               errmsg("Cannot create socketpair.\n");
+               return (-1);
+       }
+
+       pid = fork();
+       if (pid < 0) {
+               return (-1);
+       } else if (pid == 0) {
+               const char      *p;
+               const char      *av0;
+               int             xpid;
+
+               (void) close(pp[0]);
+               if (dup2(pp[1], 0) == -1 ||     /* Pipe becomes 'stdin'  */
+                   dup2(0, 1) == -1) {         /* Pipe becomes 'stdout' */
+
+                       errmsg("dup2 failed.\n");
+                       _exit(EX_BAD);
+                       /* NOTREACHED */
+               }
+               (void) close(pp[1]);            /* We don't need this anymore*/
+
+               /*
+                * Become 'locuser' to tell the rsh program the local user id.
+                */
+               if (getuid() != pw->pw_uid &&
+                   setuid(pw->pw_uid) == -1) {
+                       errmsg("setuid(%lld) failed.\n",
+                                                       (Llong)pw->pw_uid);
+                       _exit(EX_BAD);
+                       /* NOTREACHED */
+               }
+               if (getuid() != geteuid() &&
+#ifdef HAVE_SETREUID
+                   setreuid(-1, pw->pw_uid) == -1) {
+#else
+#ifdef HAVE_SETEUID
+                   seteuid(pw->pw_uid) == -1) {
+#else
+                   setuid(pw->pw_uid) == -1) {
+#endif
+#endif
+                       errmsg("seteuid(%lld) failed.\n",
+                                                       (Llong)pw->pw_uid);
+                       _exit(EX_BAD);
+                       /* NOTREACHED */
+               }
+               if (getuid() != geteuid() &&
+                   seteuid(pw->pw_uid) == -1) {
+                       errmsg("seteuid(%lld) failed.\n",
+                                                       (Llong)pw->pw_uid);
+                       _exit(EX_BAD);
+                       /* NOTREACHED */
+               }
+
+               /*
+                * Fork again to completely detach from parent
+                * and avoid the need to wait(2).
+                */
+               if ((xpid = fork()) == -1) {
+                       errmsg("rcmdsh: fork to lose parent failed.\n");
+                       _exit(EX_BAD);
+                       /* NOTREACHED */
+               }
+               if (xpid > 0) {
+                       _exit(0);
+                       /* NOTREACHED */
+               }
+
+               /*
+                * Always use remote shell programm (even for localhost).
+                * The client command may call getpeername() for security
+                * reasons and this would fail on a simple pipe.
+                */
+
+
+               /*
+                * By default, 'rsh' handles terminal created signals
+                * but this is not what we like.
+                * For this reason, we tell 'rsh' to ignore these signals.
+                * Ignoring these signals is important to allow 'star' / 'sdd'
+                * to e.g. implement SIGQUIT as signal to trigger intermediate
+                * status printing.
+                *
+                * For now (late 2002), we know that the following programs
+                * are broken and do not implement signal handling correctly:
+                *
+                *      rsh     on SunOS-5.0...SunOS-5.9
+                *      ssh     from ssh.com
+                *      ssh     from openssh.org
+                *
+                * Sun already did accept a bug report for 'rsh'. For the ssh
+                * commands we need to send out bug reports. Meanwhile it could
+                * help to call setsid() if we are running under X so the ssh
+                * X pop up for passwd reading will work.
+                */
+               signal(SIGINT, SIG_IGN);
+               signal(SIGQUIT, SIG_IGN);
+#ifdef SIGTSTP
+               signal(SIGTSTP, SIG_IGN); /* We would not be able to continue*/
+#endif
+
+               av0 = rsh;
+               if ((p = strrchr(rsh, '/')) != NULL)
+                       av0 = ++p;
+               execlp(rsh, av0, *ahost, "-l", remuser, cmd, (char *)NULL);
+
+               errmsg("execlp '%s' failed.\n", rsh);
+               _exit(EX_BAD);
+               /* NOTREACHED */
+       } else {
+               (void) close(pp[1]);
+               /*
+                * Wait for the intermediate child.
+                * The real 'rsh' program is completely detached from us.
+                */
+               wait(0);
+               return (pp[0]);
+       }
+       return (-1);    /* keep gcc happy */
+}
+
+#ifdef HAVE_GETPPRIV
+#include <priv.h>
+
+LOCAL BOOL
+ppriv_ok()
+{
+       priv_set_t      *privset;
+       BOOL            net_privaddr = FALSE;
+
+
+       if ((privset = priv_allocset()) == NULL) {
+               return (FALSE);
+       }
+       if (getppriv(PRIV_EFFECTIVE, privset) == -1) {
+               priv_freeset(privset);
+               return (FALSE);
+       }
+       if (priv_ismember(privset, PRIV_NET_PRIVADDR)) {
+               net_privaddr = TRUE;
+       }
+       priv_freeset(privset);
+
+       return (net_privaddr);
+}
+#endif /* HAVE_GETPPRIV */
+
+#endif /* USE_RCMD_RSH */
+
+#endif /* USE_REMOTE */
diff --git a/libusal/scsi-sgi.c b/libusal/scsi-sgi.c
new file mode 100644 (file)
index 0000000..b19a3ae
--- /dev/null
@@ -0,0 +1,479 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)scsi-sgi.c      1.36 04/01/15 Copyright 1997 J. Schilling */
+/*
+ *     Interface for the SGI generic SCSI implementation.
+ *
+ *     First Hacky implementation
+ *     (needed libds, did not support bus scanning and had no error checking)
+ *     from "Frank van Beek" <frank@neogeo.nl>
+ *
+ *     Actual implementation supports all usal features.
+ *
+ *     Warning: you may change this source, but if you do that
+ *     you need to change the _usal_version and _usal_auth* string below.
+ *     You may not return "schily" for an SCG_AUTHOR request anymore.
+ *     Choose your name instead of "schily" and make clear that the version
+ *     string is related to a modified source.
+ *
+ *     Copyright (c) 1997 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <dslib.h>
+
+/*
+ *     Warning: you may change this source, but if you do that
+ *     you need to change the _usal_version and _usal_auth* string below.
+ *     You may not return "schily" for an SCG_AUTHOR request anymore.
+ *     Choose your name instead of "schily" and make clear that the version
+ *     string is related to a modified source.
+ */
+static char    _usal_trans_version[] = "scsi-sgi.c-1.36";      /* The version for this transport*/
+
+#ifdef USE_DSLIB
+
+struct dsreq * dsp = 0;
+#define        MAX_SCG         1       /* Max # of SCSI controllers */
+
+#else
+
+#define        MAX_SCG         16      /* Max # of SCSI controllers */
+#define        MAX_TGT         16
+#define        MAX_LUN         8
+
+struct usal_local {
+       short   usalfiles[MAX_SCG][MAX_TGT][MAX_LUN];
+};
+#define        usallocal(p)    ((struct usal_local *)((p)->local))
+
+#endif
+
+#define        MAX_DMA_SGI     (256*1024)      /* Check if this is not too big */
+
+
+#ifndef        USE_DSLIB
+static int     usal_sendreq(SCSI *usalp, struct usal_cmd *sp, struct dsreq *dsp);
+#endif
+
+
+/*
+ * Return version information for the low level SCSI transport code.
+ * This has been introduced to make it easier to trace down problems
+ * in applications.
+ */
+static char *
+usalo_version(SCSI *usalp, int what)
+{
+       if (usalp != (SCSI *)0) {
+               switch (what) {
+
+               case SCG_VERSION:
+                       return (_usal_trans_version);
+               /*
+                * If you changed this source, you are not allowed to
+                * return "schily" for the SCG_AUTHOR request.
+                */
+               case SCG_AUTHOR:
+                       return (_usal_auth_cdrkit);
+               case SCG_SCCS_ID:
+                       return (__sccsid);
+               }
+       }
+       return ((char *)0);
+}
+
+static int
+usalo_help(SCSI *usalp, FILE *f)
+{
+       __usal_help(f, "DS", "Generic SCSI",
+               "", "bus,target,lun", "1,2,0", TRUE, FALSE);
+       return (0);
+}
+
+static int
+usalo_open(SCSI *usalp, char *device)
+{
+               int     busno   = usal_scsibus(usalp);
+               int     tgt     = usal_target(usalp);
+               int     tlun    = usal_lun(usalp);
+       register int    f;
+       register int    b;
+       register int    t;
+       register int    l;
+       register int    nopen = 0;
+       char            devname[64];
+
+       if (busno >= MAX_SCG || tgt >= MAX_TGT || tlun >= MAX_LUN) {
+               errno = EINVAL;
+               if (usalp->errstr)
+                       snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                               "Illegal value for busno, target or lun '%d,%d,%d'",
+                               busno, tgt, tlun);
+               return (-1);
+       }
+
+       if ((device != NULL && *device != '\0') || (busno == -2 && tgt == -2)) {
+               errno = EINVAL;
+               if (usalp->errstr)
+                       snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                               "Open by 'devname' not supported on this OS");
+               return (-1);
+       }
+
+       if (usalp->local == NULL) {
+               usalp->local = malloc(sizeof (struct usal_local));
+               if (usalp->local == NULL)
+                       return (0);
+
+               for (b = 0; b < MAX_SCG; b++) {
+                       for (t = 0; t < MAX_TGT; t++) {
+                               for (l = 0; l < MAX_LUN; l++)
+                                       usallocal(usalp)->usalfiles[b][t][l] = (short)-1;
+                       }
+               }
+       }
+
+       if (busno >= 0 && tgt >= 0 && tlun >= 0) {
+
+               snprintf(devname, sizeof (devname),
+                               "/dev/scsi/sc%dd%dl%d", busno, tgt, tlun);
+#ifdef USE_DSLIB
+               dsp = dsopen(devname, O_RDWR);
+               if (dsp == 0)
+                       return (-1);
+#else
+               f = open(devname, O_RDWR);
+               if (f < 0) {
+                       if (usalp->errstr)
+                               snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                                       "Cannot open '%s'",
+                                       devname);
+                       return (-1);
+               }
+               usallocal(usalp)->usalfiles[busno][tgt][tlun] = f;
+#endif
+               return (1);
+       } else {
+#ifdef USE_DSLIB
+               return (-1);
+#else
+               for (b = 0; b < MAX_SCG; b++) {
+                       for (t = 0; t < MAX_TGT; t++) {
+/*                             for (l = 0; l < MAX_LUN; l++) {*/
+                               for (l = 0; l < 1; l++) {
+                                       snprintf(devname, sizeof (devname),
+                                                       "/dev/scsi/sc%dd%dl%d", b, t, l);
+                                       f = open(devname, O_RDWR);
+                                       if (f >= 0) {
+                                               usallocal(usalp)->usalfiles[b][t][l] = (short)f;
+                                               nopen++;
+                                       }
+                               }
+                       }
+               }
+#endif
+       }
+       return (nopen);
+}
+
+static int
+usalo_close(SCSI *usalp)
+{
+#ifndef        USE_DSLIB
+       register int    f;
+       register int    b;
+       register int    t;
+       register int    l;
+
+       if (usalp->local == NULL)
+               return (-1);
+
+       for (b = 0; b < MAX_SCG; b++) {
+               for (t = 0; t < MAX_TGT; t++) {
+                       for (l = 0; l < MAX_LUN; l++) {
+                               f = usallocal(usalp)->usalfiles[b][t][l];
+                               if (f >= 0)
+                                       close(f);
+                               usallocal(usalp)->usalfiles[b][t][l] = (short)-1;
+                       }
+               }
+       }
+#else
+       dsclose(dsp);
+#endif
+       return (0);
+}
+
+static long
+usalo_maxdma(SCSI *usalp, long amt)
+{
+       return (MAX_DMA_SGI);
+}
+
+static void *
+usalo_getbuf(SCSI *usalp, long amt)
+{
+       if (usalp->debug > 0) {
+               fprintf((FILE *)usalp->errfile,
+                               "usalo_getbuf: %ld bytes\n", amt);
+       }
+       usalp->bufbase = valloc((size_t)(amt));
+       return (usalp->bufbase);
+}
+
+static void
+usalo_freebuf(SCSI *usalp)
+{
+       if (usalp->bufbase)
+               free(usalp->bufbase);
+       usalp->bufbase = NULL;
+}
+
+static BOOL
+usalo_havebus(SCSI *usalp, int busno)
+{
+       register int    t;
+       register int    l;
+
+       if (busno < 0 || busno >= MAX_SCG)
+               return (FALSE);
+
+       if (usalp->local == NULL)
+               return (FALSE);
+
+       for (t = 0; t < MAX_TGT; t++) {
+               for (l = 0; l < MAX_LUN; l++)
+                       if (usallocal(usalp)->usalfiles[busno][t][l] >= 0)
+                               return (TRUE);
+       }
+       return (FALSE);
+}
+
+static int
+usalo_fileno(SCSI *usalp, int busno, int tgt, int tlun)
+{
+#ifdef USE_DSLIB
+       if (dsp == NULL)
+               return (-1);
+       return (getfd(dsp));
+#else
+       if (busno < 0 || busno >= MAX_SCG ||
+           tgt < 0 || tgt >= MAX_TGT ||
+           tlun < 0 || tlun >= MAX_LUN)
+               return (-1);
+
+       if (usalp->local == NULL)
+               return (-1);
+
+       return ((int)usallocal(usalp)->usalfiles[busno][tgt][tlun]);
+#endif
+}
+
+static int
+usalo_initiator_id(SCSI *usalp)
+{
+       return (-1);
+}
+
+static int
+usalo_isatapi(SCSI *usalp)
+{
+       return (FALSE);
+}
+
+static int
+usalo_reset(SCSI *usalp, int what)
+{
+       /*
+        * Do we have a SCSI reset on SGI?
+        */
+#ifdef DS_RESET
+       if (what == SCG_RESET_NOP)
+               return (0);
+       if (what != SCG_RESET_BUS) {
+               errno = EINVAL;
+               return (-1);
+       }
+       /*
+        * XXX Does this reset TGT or BUS ???
+        */
+       return (ioctl(usalp->fd, DS_RESET, 0));
+#else
+       return (-1);
+#endif
+}
+
+#ifndef        USE_DSLIB
+static int
+usal_sendreq(SCSI *usalp, struct usal_cmd *sp, struct dsreq *dsp)
+{
+       int     ret;
+       int     retries = 4;
+       Uchar   status;
+
+/*     if ((sp->flags & SCG_CMD_RETRY) == 0)*/
+/*             retries = 0;*/
+
+       while (--retries > 0) {
+               ret = ioctl(usalp->fd, DS_ENTER, dsp);
+               if (ret < 0)  {
+                       RET(dsp) = DSRT_DEVSCSI;
+                       return (-1);
+               }
+               /*
+                * SGI implementattion botch!!!
+                * If a target does not select the bus,
+                * the return code is DSRT_TIMEOUT
+                */
+               if (RET(dsp) == DSRT_TIMEOUT) {
+                       struct timeval to;
+
+                       to.tv_sec = TIME(dsp)/1000;
+                       to.tv_usec = TIME(dsp)%1000;
+                       __usal_times(usalp);
+
+                       if (sp->cdb.g0_cdb.cmd == SC_TEST_UNIT_READY &&
+                           usalp->cmdstop->tv_sec < to.tv_sec ||
+                           (usalp->cmdstop->tv_sec == to.tv_sec &&
+                               usalp->cmdstop->tv_usec < to.tv_usec)) {
+
+                               RET(dsp) = DSRT_NOSEL;
+                               return (-1);
+                       }
+               }
+               if (RET(dsp) == DSRT_NOSEL)
+                       continue;               /* retry noselect 3X */
+
+               status = STATUS(dsp);
+               switch (status) {
+
+               case 0x08:              /*  BUSY */
+               case 0x18:              /*  RESERV CONFLICT */
+                       if (retries > 0)
+                               sleep(2);
+                       continue;
+               case 0x00:              /*  GOOD */
+               case 0x02:              /*  CHECK CONDITION */
+               case 0x10:              /*  INTERM/GOOD */
+               default:
+                       return (status);
+               }
+       }
+       return (-1);    /* failed retry limit */
+}
+#endif
+
+static int
+usalo_send(SCSI *usalp)
+{
+       struct usal_cmd *sp = usalp->scmd;
+       int     ret;
+       int     i;
+       int     amt = sp->cdb_len;
+       int flags;
+#ifndef        USE_DSLIB
+       struct dsreq    ds;
+       struct dsreq    *dsp = &ds;
+
+       dsp->ds_iovbuf = 0;
+       dsp->ds_iovlen = 0;
+#endif
+
+       if (usalp->fd < 0) {
+               sp->error = SCG_FATAL;
+               return (0);
+       }
+
+       flags = DSRQ_SENSE;
+       if (sp->flags & SCG_RECV_DATA)
+               flags |= DSRQ_READ;
+       else if (sp->size > 0)
+               flags |= DSRQ_WRITE;
+
+       dsp->ds_flags   = flags;
+       dsp->ds_link    = 0;
+       dsp->ds_synch   = 0;
+       dsp->ds_ret     = 0;
+
+       DATABUF(dsp)    = sp->addr;
+       DATALEN(dsp)    = sp->size;
+       CMDBUF(dsp)     = (void *) &sp->cdb;
+       CMDLEN(dsp)     = sp->cdb_len;
+       SENSEBUF(dsp)   = (caddr_t)sp->u_sense.cmd_sense;
+       SENSELEN(dsp)   = sizeof (sp->u_sense.cmd_sense);
+       TIME(dsp)       = (sp->timeout * 1000) + 100;
+
+       errno           = 0;
+       sp->ux_errno    = 0;
+       sp->sense_count = 0;
+
+#ifdef USE_DSLIB
+       ret = doscsireq(usalp->fd, dsp);
+#else
+       ret = usal_sendreq(usalp, sp, dsp);
+#endif
+
+       if (RET(dsp) != DSRT_DEVSCSI)
+               ret = 0;
+
+       if (RET(dsp)) {
+               if (RET(dsp) == DSRT_SHORT) {
+                       sp->resid = DATALEN(dsp)- DATASENT(dsp);
+               } else if (errno) {
+                       sp->ux_errno = errno;
+               } else {
+                       sp->ux_errno = EIO;
+               }
+
+               sp->u_scb.cmd_scb[0] = STATUS(dsp);
+
+               sp->sense_count = SENSESENT(dsp);
+               if (sp->sense_count > SCG_MAX_SENSE)
+                       sp->sense_count = SCG_MAX_SENSE;
+
+       }
+       switch (RET(dsp)) {
+
+       default:
+               sp->error = SCG_RETRYABLE;      break;
+
+       case 0:                 /* OK                                   */
+       case DSRT_SHORT:        /* not implemented                       */
+               sp->error = SCG_NO_ERROR;       break;
+
+       case DSRT_UNIMPL:       /* not implemented                      */
+       case DSRT_REVCODE:      /* software obsolete must recompile     */
+       case DSRT_NOSEL:
+               sp->u_scb.cmd_scb[0] = 0;
+               sp->error = SCG_FATAL;          break;
+
+       case DSRT_TIMEOUT:
+               sp->u_scb.cmd_scb[0] = 0;
+               sp->error = SCG_TIMEOUT;        break;
+       }
+       return (ret);
+}
diff --git a/libusal/scsi-sun.c b/libusal/scsi-sun.c
new file mode 100644 (file)
index 0000000..9ea8da8
--- /dev/null
@@ -0,0 +1,1133 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)scsi-sun.c      1.83 05/11/20 Copyright 1988,1995,2000-2004 J. Schilling */
+/*
+ *     SCSI user level command transport routines for
+ *     the SCSI general driver 'usal'.
+ *
+ *     Warning: you may change this source, but if you do that
+ *     you need to change the _usal_version and _usal_auth* string below.
+ *     You may not return "schily" for an SCG_AUTHOR request anymore.
+ *     Choose your name instead of "schily" and make clear that the version
+ *     string is related to a modified source.
+ *
+ *     Copyright (c) 1988,1995,2000-2004 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <usal/usalio.h>
+
+#include <libport.h>           /* Needed for gethostid() */
+#ifdef HAVE_SUN_DKIO_H
+#      include <sun/dkio.h>
+
+#      define  dk_cinfo        dk_conf
+#      define  dki_slave       dkc_slave
+#      define  DKIO_GETCINFO   DKIOCGCONF
+#endif
+#ifdef HAVE_SYS_DKIO_H
+#      include <sys/dkio.h>
+
+#      define  DKIO_GETCINFO   DKIOCINFO
+#endif
+
+#define        TARGET(slave)   ((slave) >> 3)
+#define        LUN(slave)      ((slave) & 07)
+
+/*
+ * Tht USCSI ioctl() is not usable on SunOS 4.x
+ */
+#ifdef __SVR4
+/*#define      VOLMGT_DEBUG*/
+#include <volmgt.h>
+#include <statdefs.h>
+#      define  USE_USCSI
+#endif
+
+static char    _usal_trans_version[] = "usal-1.83";    /* The version for /dev/usal    */
+static char    _usal_utrans_version[] = "uscsi-1.83";  /* The version for USCSI        */
+
+#ifdef USE_USCSI
+static int     usalo_uhelp(SCSI *usalp, FILE *f);
+static int     usalo_uopen(SCSI *usalp, char *device);
+static int     usalo_volopen(SCSI *usalp, char *devname);
+static int     usalo_openmedia(SCSI *usalp, char *mname);
+static int     usalo_uclose(SCSI *usalp);
+static int     usalo_ucinfo(int f, struct dk_cinfo *cp, int debug);
+static int     usalo_ugettlun(int f, int *tgtp, int *lunp);
+static long    usalo_umaxdma(SCSI *usalp, long amt);
+static int     usalo_openide(void);
+static BOOL    usalo_uhavebus(SCSI *usalp, int);
+static int     usalo_ufileno(SCSI *usalp, int, int, int);
+static int     usalo_uinitiator_id(SCSI *usalp);
+static int     usalo_uisatapi(SCSI *usalp);
+static int     usalo_ureset(SCSI *usalp, int what);
+static int     usalo_usend(SCSI *usalp);
+
+static int     have_volmgt = -1;
+
+static usal_ops_t sun_uscsi_ops = {
+       usalo_usend,
+       usalo_version,          /* Shared with SCG driver */
+       usalo_uhelp,
+       usalo_uopen,
+       usalo_uclose,
+       usalo_umaxdma,
+       usalo_getbuf,           /* Shared with SCG driver */
+       usalo_freebuf,          /* Shared with SCG driver */
+       usalo_uhavebus,
+       usalo_ufileno,
+       usalo_uinitiator_id,
+       usalo_uisatapi,
+       usalo_ureset,
+};
+#endif
+
+/*
+ * Need to move this into an usal driver ioctl.
+ */
+/*#define      MAX_DMA_SUN4M   (1024*1024)*/
+#define        MAX_DMA_SUN4M   (124*1024)      /* Currently max working size */
+/*#define      MAX_DMA_SUN4C   (126*1024)*/
+#define        MAX_DMA_SUN4C   (124*1024)      /* Currently max working size */
+#define        MAX_DMA_SUN3    (63*1024)
+#define        MAX_DMA_SUN386  (56*1024)
+#define        MAX_DMA_OTHER   (32*1024)
+
+#define        ARCH_MASK       0xF0
+#define        ARCH_SUN2       0x00
+#define        ARCH_SUN3       0x10
+#define        ARCH_SUN4       0x20
+#define        ARCH_SUN386     0x30
+#define        ARCH_SUN3X      0x40
+#define        ARCH_SUN4C      0x50
+#define        ARCH_SUN4E      0x60
+#define        ARCH_SUN4M      0x70
+#define        ARCH_SUNX       0x80
+
+/*
+ * We are using a "real" /dev/usal?
+ */
+#define        scsi_xsend(usalp)       ioctl((usalp)->fd, SCGIO_CMD, (usalp)->scmd)
+#define        MAX_SCG         16      /* Max # of SCSI controllers */
+#define        MAX_TGT         16
+#define        MAX_LUN         8
+
+struct usal_local {
+       union {
+               int     SCG_files[MAX_SCG];
+#ifdef USE_USCSI
+               short   usal_files[MAX_SCG][MAX_TGT][MAX_LUN];
+#endif
+       } u;
+};
+#define        usallocal(p)    ((struct usal_local *)((p)->local))
+#define        usalfiles(p)    (usallocal(p)->u.SCG_files)
+
+/*
+ * Return version information for the low level SCSI transport code.
+ * This has been introduced to make it easier to trace down problems
+ * in applications.
+ */
+static char *
+usalo_version(SCSI *usalp, int what)
+{
+       if (usalp != (SCSI *)0) {
+               switch (what) {
+
+               case SCG_VERSION:
+#ifdef USE_USCSI
+                       if (usalp->ops == &sun_uscsi_ops)
+                               return (_usal_utrans_version);
+#endif
+                       return (_usal_trans_version);
+               /*
+                * If you changed this source, you are not allowed to
+                * return "schily" for the SCG_AUTHOR request.
+                */
+               case SCG_AUTHOR:
+                       return (_usal_auth_cdrkit);
+               case SCG_SCCS_ID:
+                       return (__sccsid);
+               }
+       }
+       return ((char *)0);
+}
+
+static int
+usalo_help(SCSI *usalp, FILE *f)
+{
+       __usal_help(f, "usal", "Generic transport independent SCSI",
+               "", "bus,target,lun", "1,2,0", TRUE, FALSE);
+#ifdef USE_USCSI
+       usalo_uhelp(usalp, f);
+#endif
+       return (0);
+}
+
+static int
+usalo_open(SCSI *usalp, char *device)
+{
+               int     busno   = usal_scsibus(usalp);
+               int     tgt     = usal_target(usalp);
+/*             int     tlun    = usal_lun(usalp);*/
+       register int    f;
+       register int    i;
+       register int    nopen = 0;
+       char            devname[32];
+
+       if (busno >= MAX_SCG) {
+               errno = EINVAL;
+               if (usalp->errstr)
+                       snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                               "Illegal value for busno '%d'", busno);
+               return (-1);
+       }
+
+       if ((device != NULL && *device != '\0') || (busno == -2 && tgt == -2)) {
+#ifdef USE_USCSI
+               usalp->ops = &sun_uscsi_ops;
+               return (SCGO_OPEN(usalp, device));
+#else
+               errno = EINVAL;
+               if (usalp->errstr)
+                       snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                               "Open by 'devname' not supported on this OS");
+               return (-1);
+#endif
+       }
+
+       if (usalp->local == NULL) {
+               usalp->local = malloc(sizeof (struct usal_local));
+               if (usalp->local == NULL) {
+                       if (usalp->errstr)
+                               snprintf(usalp->errstr, SCSI_ERRSTR_SIZE, "No memory for usal_local");
+                       return (0);
+               }
+
+               for (i = 0; i < MAX_SCG; i++) {
+                       usalfiles(usalp)[i] = -1;
+               }
+       }
+
+
+       for (i = 0; i < MAX_SCG; i++) {
+               /*
+                * Skip unneeded devices if not in SCSI Bus scan open mode
+                */
+               if (busno >= 0 && busno != i)
+                       continue;
+               snprintf(devname, sizeof (devname), "/dev/usal%d", i);
+               f = open(devname, O_RDWR);
+               if (f < 0) {
+                       if (errno != ENOENT && errno != ENXIO) {
+                               if (usalp->errstr)
+                                       snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                                               "Cannot open '%s'", devname);
+                               return (-1);
+                       }
+               } else {
+                       nopen++;
+               }
+               usalfiles(usalp)[i] = f;
+       }
+#ifdef USE_USCSI
+       if (nopen <= 0) {
+               if (usalp->local != NULL) {
+                       free(usalp->local);
+                       usalp->local = NULL;
+               }
+               usalp->ops = &sun_uscsi_ops;
+               return (SCGO_OPEN(usalp, device));
+       }
+#endif
+       return (nopen);
+}
+
+static int
+usalo_close(SCSI *usalp)
+{
+       register int    i;
+
+       if (usalp->local == NULL)
+               return (-1);
+
+       for (i = 0; i < MAX_SCG; i++) {
+               if (usalfiles(usalp)[i] >= 0)
+                       close(usalfiles(usalp)[i]);
+               usalfiles(usalp)[i] = -1;
+       }
+       return (0);
+}
+
+static long
+usalo_maxdma(SCSI *usalp, long amt)
+{
+       long    maxdma = MAX_DMA_OTHER;
+#if    !defined(__i386_) && !defined(i386)
+       int     cpu_type;
+#endif
+
+#if    defined(__i386_) || defined(i386)
+       maxdma = MAX_DMA_SUN386;
+#else
+       cpu_type = gethostid() >> 24;
+
+       switch (cpu_type & ARCH_MASK) {
+
+       case ARCH_SUN4C:
+       case ARCH_SUN4E:
+               maxdma = MAX_DMA_SUN4C;
+               break;
+
+       case ARCH_SUN4M:
+       case ARCH_SUNX:
+               maxdma = MAX_DMA_SUN4M;
+               break;
+
+       default:
+               maxdma = MAX_DMA_SUN3;
+       }
+#endif
+
+#ifndef        __SVR4
+       /*
+        * SunOS 4.x allows esp hardware on VME boards and thus
+        * limits DMA on esp to 64k-1
+        */
+       if (maxdma > MAX_DMA_SUN3)
+               maxdma = MAX_DMA_SUN3;
+#endif
+       return (maxdma);
+}
+
+static BOOL
+usalo_havebus(SCSI *usalp, int busno)
+{
+       if (usalp->local == NULL)
+               return (FALSE);
+
+       return (busno < 0 || busno >= MAX_SCG) ? FALSE : (usalfiles(usalp)[busno] >= 0);
+}
+
+static int
+usalo_fileno(SCSI *usalp, int busno, int tgt, int tlun)
+{
+       if (usalp->local == NULL)
+               return (-1);
+
+       return ((busno < 0 || busno >= MAX_SCG) ? -1 : usalfiles(usalp)[busno]);
+}
+
+static int
+usalo_initiator_id(SCSI *usalp)
+{
+       int             id = -1;
+#ifdef DKIO_GETCINFO
+       struct dk_cinfo conf;
+#endif
+
+#ifdef DKIO_GETCINFO
+       if (usalp->fd < 0)
+               return (id);
+       if (ioctl(usalp->fd, DKIO_GETCINFO, &conf) < 0)
+               return (id);
+       if (TARGET(conf.dki_slave) != -1)
+               id = TARGET(conf.dki_slave);
+#endif
+       return (id);
+}
+
+static int
+usalo_isatapi(SCSI *usalp)
+{
+       return (FALSE);
+}
+
+static int
+usalo_reset(SCSI *usalp, int what)
+{
+       if (what == SCG_RESET_NOP)
+               return (0);
+       if (what != SCG_RESET_BUS) {
+               errno = EINVAL;
+               return (-1);
+       }
+       return (ioctl(usalp->fd, SCGIORESET, 0));
+}
+
+static void *
+usalo_getbuf(SCSI *usalp, long amt)
+{
+       usalp->bufbase = (void *)valloc((size_t)amt);
+       return (usalp->bufbase);
+}
+
+static void
+usalo_freebuf(SCSI *usalp)
+{
+       if (usalp->bufbase)
+               free(usalp->bufbase);
+       usalp->bufbase = NULL;
+}
+
+static int
+usalo_send(SCSI *usalp)
+{
+       usalp->scmd->target = usal_target(usalp);
+       return (ioctl(usalp->fd, SCGIO_CMD, usalp->scmd));
+}
+
+/*--------------------------------------------------------------------------*/
+/*
+ *     This is Sun USCSI interface code ...
+ */
+#ifdef USE_USCSI
+#include <sys/scsi/impl/uscsi.h>
+
+/*
+ * Bit Mask definitions, for use accessing the status as a byte.
+ */
+#define        STATUS_MASK                     0x3E
+#define        STATUS_GOOD                     0x00
+#define        STATUS_CHECK                    0x02
+
+#define        STATUS_RESERVATION_CONFLICT     0x18
+#define        STATUS_TERMINATED               0x22
+
+#ifdef nonono
+#define        STATUS_MASK                     0x3E
+#define        STATUS_GOOD                     0x00
+#define        STATUS_CHECK                    0x02
+
+#define        STATUS_MET                      0x04
+#define        STATUS_BUSY                     0x08
+#define        STATUS_INTERMEDIATE             0x10
+#define        STATUS_SCSI2                    0x20
+#define        STATUS_INTERMEDIATE_MET         0x14
+#define        STATUS_RESERVATION_CONFLICT     0x18
+#define        STATUS_TERMINATED               0x22
+#define        STATUS_QFULL                    0x28
+#define        STATUS_ACA_ACTIVE               0x30
+#endif
+
+static int
+usalo_uhelp(SCSI *usalp, FILE *f)
+{
+       __usal_help(f, "USCSI", "SCSI transport for targets known by Solaris drivers",
+               "USCSI:", "bus,target,lun", "USCSI:1,2,0", TRUE, TRUE);
+       return (0);
+}
+
+static int
+usalo_uopen(SCSI *usalp, char *device)
+{
+               int     busno   = usal_scsibus(usalp);
+               int     tgt     = usal_target(usalp);
+               int     tlun    = usal_lun(usalp);
+       register int    f;
+       register int    b;
+       register int    t;
+       register int    l;
+       register int    nopen = 0;
+       char            devname[32];
+
+       if (have_volmgt < 0)
+               have_volmgt = volmgt_running();
+
+       if (usalp->overbose) {
+               fprintf((FILE *)usalp->errfile,
+                               "Warning: Using USCSI interface.\n");
+       }
+#ifndef        SEEK_HOLE
+       /*
+        * SEEK_HOLE first appears in Solaris 11 Build 14, volmgt supports
+        * medialess drives since Build 21. Using SEEK_HOLD as indicator
+        * seems to be the best guess.
+        */
+       if (usalp->overbose > 0 && have_volmgt) {
+               fprintf((FILE *)usalp->errfile,
+               "Warning: Volume management is running, medialess managed drives are invisible.\n");
+       }
+#endif
+
+       if (busno >= MAX_SCG || tgt >= MAX_TGT || tlun >= MAX_LUN) {
+               errno = EINVAL;
+               if (usalp->errstr) {
+                       snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                               "Illegal value for busno, target or lun '%d,%d,%d'",
+                                       busno, tgt, tlun);
+               }
+               return (-1);
+       }
+       if (usalp->local == NULL) {
+               usalp->local = malloc(sizeof (struct usal_local));
+               if (usalp->local == NULL) {
+                       if (usalp->errstr)
+                               snprintf(usalp->errstr, SCSI_ERRSTR_SIZE, "No memory for usal_local");
+                       return (0);
+               }
+
+               for (b = 0; b < MAX_SCG; b++) {
+                       for (t = 0; t < MAX_TGT; t++) {
+                               for (l = 0; l < MAX_LUN; l++)
+                                       usallocal(usalp)->u.usal_files[b][t][l] = (short)-1;
+                       }
+               }
+       }
+
+       if (device != NULL && strcmp(device, "USCSI") == 0)
+               goto uscsiscan;
+
+       if ((device != NULL && *device != '\0') || (busno == -2 && tgt == -2))
+               goto openbydev;
+
+uscsiscan:
+       if (busno >= 0 && tgt >= 0 && tlun >= 0) {
+
+               if (busno >= MAX_SCG || tgt >= MAX_TGT || tlun >= MAX_LUN)
+                       return (-1);
+
+               snprintf(devname, sizeof (devname), "/dev/rdsk/c%dt%dd%ds2",
+                       busno, tgt, tlun);
+               f = open(devname, O_RDONLY | O_NDELAY);
+               if (f < 0 && geterrno() == EBUSY)
+                       f = usalo_volopen(usalp, devname);
+               if (f < 0) {
+                       snprintf(usalp->errstr,
+                                   SCSI_ERRSTR_SIZE,
+                               "Cannot open '%s'", devname);
+                       return (0);
+               }
+               usallocal(usalp)->u.usal_files[busno][tgt][tlun] = f;
+               return (1);
+       } else {
+
+               for (b = 0; b < MAX_SCG; b++) {
+                       for (t = 0; t < MAX_TGT; t++) {
+                               for (l = 0; l < MAX_LUN; l++) {
+                                       snprintf(devname, sizeof (devname),
+                                               "/dev/rdsk/c%dt%dd%ds2",
+                                               b, t, l);
+                                       f = open(devname, O_RDONLY | O_NDELAY);
+                                       if (f < 0 && geterrno() == EBUSY) {
+                                               f = usalo_volopen(usalp, devname);
+                                               /*
+                                                * Hack to mark inaccessible
+                                                * drives with fd == -2
+                                                */
+                                               if (f < 0 &&
+                                                   usallocal(usalp)->u.usal_files[b][t][l] < 0)
+                                                       usallocal(usalp)->u.usal_files[b][t][l] = f;
+                                       }
+                                       if (f < 0 && errno != ENOENT &&
+                                                   errno != ENXIO &&
+                                                   errno != ENODEV) {
+                                               if (usalp->errstr)
+                                                       snprintf(usalp->errstr,
+                                                           SCSI_ERRSTR_SIZE,
+                                                           "Cannot open '%s'", devname);
+                                       }
+                                       if (f < 0 && l == 0)
+                                               break;
+                                       if (f >= 0) {
+                                               nopen ++;
+                                               if (usallocal(usalp)->u.usal_files[b][t][l] == -1)
+                                                       usallocal(usalp)->u.usal_files[b][t][l] = f;
+                                               else
+                                                       close(f);
+                                       }
+                               }
+                       }
+               }
+       }
+openbydev:
+       if (nopen == 0) {
+               int     target;
+               int     lun;
+
+               if (device != NULL && strncmp(device, "USCSI:", 6) == 0)
+                       device += 6;
+               if (device == NULL || device[0] == '\0')
+                       return (0);
+
+               f = open(device, O_RDONLY | O_NDELAY);
+               if (f < 0)
+                       f = usalo_volopen(usalp, device);
+               if (f < 0) {
+                       snprintf(usalp->errstr,
+                                   SCSI_ERRSTR_SIZE,
+                               "Cannot open '%s'", device);
+                       return (0);
+               }
+
+               if (busno < 0)
+                       busno = 0;      /* Use Fake number if not specified */
+
+               if (usalo_ugettlun(f, &target, &lun) >= 0) {
+                       if (tgt >= 0 && tlun >= 0) {
+                               if (tgt != target || tlun != lun) {
+                                       close(f);
+                                       return (0);
+                               }
+                       }
+                       tgt = target;
+                       tlun = lun;
+               } else {
+                       if (tgt < 0 || tlun < 0) {
+                               close(f);
+                               return (0);
+                       }
+               }
+
+               if (usallocal(usalp)->u.usal_files[busno][tgt][tlun] == -1)
+                       usallocal(usalp)->u.usal_files[busno][tgt][tlun] = f;
+               usal_settarget(usalp, busno, tgt, tlun);
+
+               return (++nopen);
+       }
+       return (nopen);
+}
+
+static int
+usalo_volopen(SCSI *usalp, char *devname)
+{
+       int     oerr = geterrno();
+       int     f = -1;
+       char    *name   = NULL; /* Volume symbolic device name          */
+       char    *symdev = NULL; /* /dev/... name based on "name"        */
+       char    *mname  = NULL; /* Volume media name based on "name"    */
+
+       if (!have_volmgt)
+               return (-1);
+
+#ifdef VOLMGT_DEBUG
+       usalp->debug++;
+#endif
+       if (usalp->debug > 0) {
+               fprintf((FILE *)usalp->errfile,
+                       "usalo_volopen(%s)\n", devname);
+       }
+
+       /*
+        * We come here because trying to open "devname" did not work.
+        * First try to translate between a symbolic name and a /dev/...
+        * based device name. Then translate back to a symbolic name.
+        */
+       symdev = volmgt_symdev(devname);
+       if (symdev)
+               name = volmgt_symname(symdev);
+       if (usalp->debug > 0) {
+               fprintf((FILE *)usalp->errfile,
+                       "volmgt_symdev(%s)=%s -> %s\n", devname, symdev, name);
+       }
+
+       /*
+        * If "devname" is not a symbolic device name, then it must be
+        * a /dev/... based device name. Try to translate it into a
+        * symbolic name. Then translate back to a /dev/... name.
+        */
+       if (name == NULL) {
+               name = volmgt_symname(devname);
+               if (name)
+                       symdev = volmgt_symdev(name);
+       }
+       if (usalp->debug > 0) {
+               fprintf((FILE *)usalp->errfile,
+                       "volmgt_symdev(%s)=%s -> %s\n", devname, symdev, name);
+       }
+
+       /*
+        * If we have been able to translate to a symbolic device name,
+        * translate this name into a volume management media name that
+        * may be used for opening.
+        */
+       if (name)
+               mname = media_findname(name);
+       if (usalp->debug > 0) {
+               fprintf((FILE *)usalp->errfile,
+                       "symdev %s name %s mname %s\n", symdev, name, mname);
+       }
+
+       /*
+        * Das scheint nur mit dem normierten /dev/rdsk/ *s2 Namen zu gehen.
+        */
+       if (usalp->debug > 0) {
+               fprintf((FILE *)usalp->errfile,
+                       "volmgt_inuse(%s) %d\n", symdev, volmgt_inuse(symdev));
+       }
+       if (mname)
+               f = usalo_openmedia(usalp, mname);
+       else if (name)
+               f = -2; /* Mark inaccessible drives with fd == -2 */
+
+       /*
+        * Besonderen Fehlertext oder fprintf/errfile bei non-scanbus Open und
+        * wenn errrno == EBUSY && kein Mapping?
+        */
+       if (name)
+               free(name);
+       if (symdev)
+               free(symdev);
+       if (mname)
+               free(mname);
+       seterrno(oerr);
+#ifdef VOLMGT_DEBUG
+       usalp->debug--;
+#endif
+       return (f);
+}
+
+static int
+usalo_openmedia(SCSI *usalp, char *mname)
+{
+       int     f = -1;
+       char    *device = NULL;
+       struct  stat sb;
+
+       if (mname == NULL)
+               return (-1);
+
+       /*
+        * Check whether the media name refers to a directory.
+        * In this case, the medium is partitioned and we need to
+        * check all partitions.
+        */
+       if (stat(mname, &sb) >= 0) {
+               if (S_ISDIR(sb.st_mode)) {
+                       char    name[128];
+                       int     i;
+
+                       /*
+                        * First check partition '2', the whole disk.
+                        */
+                       snprintf(name, sizeof (name), "%s/s2", mname);
+                       f = open(name, O_RDONLY | O_NDELAY);
+                       if (f >= 0)
+                               return (f);
+                       /*
+                        * Now try all other partitions.
+                        */
+                       for (i = 0; i < 16; i++) {
+                               if (i == 2)
+                                       continue;
+                               snprintf(name, sizeof (name),
+                                                       "%s/s%d", mname, i);
+                               if (stat(name, &sb) >= 0)
+                                       break;
+                       }
+                       if (i < 16) {
+                               device = mname;
+                       }
+               } else {
+                       device = mname;
+               }
+       }
+       if (device)
+               f = open(device, O_RDONLY | O_NDELAY);
+       return (f);
+}
+
+static int
+usalo_uclose(SCSI *usalp)
+{
+       register int    f;
+       register int    b;
+       register int    t;
+       register int    l;
+
+       if (usalp->local == NULL)
+               return (-1);
+
+       for (b = 0; b < MAX_SCG; b++) {
+               for (t = 0; t < MAX_TGT; t++) {
+                       for (l = 0; l < MAX_LUN; l++) {
+                               f = usallocal(usalp)->u.usal_files[b][t][l];
+                               if (f >= 0)
+                                       close(f);
+                               usallocal(usalp)->u.usal_files[b][t][l] = (short)-1;
+                       }
+               }
+       }
+       return (0);
+}
+
+static int
+usalo_ucinfo(int f, struct dk_cinfo *cp, int debug)
+{
+       fillbytes(cp, sizeof (*cp), '\0');
+
+       if (ioctl(f, DKIOCINFO, cp) < 0)
+               return (-1);
+
+       if (debug <= 0)
+               return (0);
+
+       fprintf(stderr, "cname:         '%s'\n", cp->dki_cname);
+       fprintf(stderr, "ctype:         0x%04hX %hd\n", cp->dki_ctype, cp->dki_ctype);
+       fprintf(stderr, "cflags:                0x%04hX\n", cp->dki_flags);
+       fprintf(stderr, "cnum:          %hd\n", cp->dki_cnum);
+#ifdef __EVER__
+       fprintf(stderr, "addr:          %d\n", cp->dki_addr);
+       fprintf(stderr, "space:         %d\n", cp->dki_space);
+       fprintf(stderr, "prio:          %d\n", cp->dki_prio);
+       fprintf(stderr, "vec:           %d\n", cp->dki_vec);
+#endif
+       fprintf(stderr, "dname:         '%s'\n", cp->dki_dname);
+       fprintf(stderr, "unit:          %d\n", cp->dki_unit);
+       fprintf(stderr, "slave:         %d %04o Tgt: %d Lun: %d\n",
+                               cp->dki_slave, cp->dki_slave,
+                               TARGET(cp->dki_slave), LUN(cp->dki_slave));
+       fprintf(stderr, "partition:     %hd\n", cp->dki_partition);
+       fprintf(stderr, "maxtransfer:   %d (%d)\n",
+                               cp->dki_maxtransfer,
+                               cp->dki_maxtransfer * DEV_BSIZE);
+       return (0);
+}
+
+static int
+usalo_ugettlun(int f, int *tgtp, int *lunp)
+{
+       struct dk_cinfo ci;
+
+       if (usalo_ucinfo(f, &ci, 0) < 0)
+               return (-1);
+       if (tgtp)
+               *tgtp = TARGET(ci.dki_slave);
+       if (lunp)
+               *lunp = LUN(ci.dki_slave);
+       return (0);
+}
+
+static long
+usalo_umaxdma(SCSI *usalp, long amt)
+{
+       register int    b;
+       register int    t;
+       register int    l;
+       long            maxdma = -1L;
+       int             f;
+       struct dk_cinfo ci;
+       BOOL            found_ide = FALSE;
+
+       if (usalp->local == NULL)
+               return (-1L);
+
+       for (b = 0; b < MAX_SCG; b++) {
+               for (t = 0; t < MAX_TGT; t++) {
+                       for (l = 0; l < MAX_LUN; l++) {
+                               if ((f = usallocal(usalp)->u.usal_files[b][t][l]) < 0)
+                                       continue;
+                               if (usalo_ucinfo(f, &ci, usalp->debug) < 0)
+                                       continue;
+                               if (maxdma < 0)
+                                       maxdma = (long)(ci.dki_maxtransfer * DEV_BSIZE);
+                               if (maxdma > (long)(ci.dki_maxtransfer * DEV_BSIZE))
+                                       maxdma = (long)(ci.dki_maxtransfer * DEV_BSIZE);
+                               if (streql(ci.dki_cname, "ide"))
+                                       found_ide = TRUE;
+                       }
+               }
+       }
+
+#if    defined(__i386_) || defined(i386)
+       /*
+        * At least on Solaris 9 x86, DKIOCINFO returns a wrong value
+        * for dki_maxtransfer if the target is an ATAPI drive.
+        * Without DMA, it seems to work if we use 256 kB DMA size for ATAPI,
+        * but if we allow DMA, only 68 kB will work (for more we get a silent
+        * DMA residual count == DMA transfer count).
+        * For this reason, we try to figure out the correct value for 'ide'
+        * by retrieving the (correct) value from a ide hard disk.
+        */
+       if (found_ide) {
+               if ((f = usalo_openide()) >= 0) {
+#ifdef sould_we
+                       long omaxdma = maxdma;
+#endif
+
+                       if (usalo_ucinfo(f, &ci, usalp->debug) >= 0) {
+                               if (maxdma < 0)
+                                       maxdma = (long)(ci.dki_maxtransfer * DEV_BSIZE);
+                               if (maxdma > (long)(ci.dki_maxtransfer * DEV_BSIZE))
+                                       maxdma = (long)(ci.dki_maxtransfer * DEV_BSIZE);
+                       }
+                       close(f);
+#ifdef sould_we
+                       /*
+                        * The kernel returns 56 kB but we tested that 68 kB works.
+                        */
+                       if (omaxdma > maxdma && maxdma == (112 * DEV_BSIZE))
+                               maxdma = 136 * DEV_BSIZE;
+#endif
+               } else {
+                       /*
+                        * No IDE disk on this system?
+                        */
+                       if (maxdma == (512 * DEV_BSIZE))
+                               maxdma = MAX_DMA_SUN386;
+               }
+       }
+#endif
+       /*
+        * The Sun tape driver does not support to retrieve the max DMA count.
+        * Use the knwoledge about default DMA sizes in this case.
+        */
+       if (maxdma < 0)
+               maxdma = usalo_maxdma(usalp, amt);
+
+       return (maxdma);
+}
+
+#if    defined(__i386_) || defined(i386)
+static int
+usalo_openide()
+{
+       char    buf[20];
+       int     b;
+       int     t;
+       int     f = -1;
+
+       for (b = 0; b < 5; b++) {
+               for (t = 0; t < 2; t++) {
+                       snprintf(buf, sizeof (buf),
+                               "/dev/rdsk/c%dd%dp0", b, t);
+                       if ((f = open(buf, O_RDONLY | O_NDELAY)) >= 0)
+                               goto out;
+               }
+       }
+out:
+       return (f);
+}
+#endif
+
+static BOOL
+usalo_uhavebus(SCSI *usalp, int busno)
+{
+       register int    t;
+       register int    l;
+
+       if (usalp->local == NULL || busno < 0 || busno >= MAX_SCG)
+               return (FALSE);
+
+       for (t = 0; t < MAX_TGT; t++) {
+               for (l = 0; l < MAX_LUN; l++)
+                       if (usallocal(usalp)->u.usal_files[busno][t][l] >= 0)
+                               return (TRUE);
+       }
+       return (FALSE);
+}
+
+static int
+usalo_ufileno(SCSI *usalp, int busno, int tgt, int tlun)
+{
+       if (usalp->local == NULL ||
+           busno < 0 || busno >= MAX_SCG ||
+           tgt < 0 || tgt >= MAX_TGT ||
+           tlun < 0 || tlun >= MAX_LUN)
+               return (-1);
+
+       return ((int)usallocal(usalp)->u.usal_files[busno][tgt][tlun]);
+}
+
+static int
+usalo_uinitiator_id(SCSI *usalp)
+{
+       return (-1);
+}
+
+static int
+usalo_uisatapi(SCSI *usalp)
+{
+       char            devname[32];
+       char            symlinkname[MAXPATHLEN];
+       int             len;
+       struct dk_cinfo ci;
+
+       if (ioctl(usalp->fd, DKIOCINFO, &ci) < 0)
+               return (-1);
+
+       snprintf(devname, sizeof (devname), "/dev/rdsk/c%dt%dd%ds2",
+               usal_scsibus(usalp), usal_target(usalp), usal_lun(usalp));
+
+       symlinkname[0] = '\0';
+       len = readlink(devname, symlinkname, sizeof (symlinkname));
+       if (len > 0)
+               symlinkname[len] = '\0';
+
+       if (len >= 0 && strstr(symlinkname, "ide") != NULL)
+               return (TRUE);
+       else
+               return (FALSE);
+}
+
+static int
+usalo_ureset(SCSI *usalp, int what)
+{
+       struct uscsi_cmd req;
+
+       if (what == SCG_RESET_NOP)
+               return (0);
+
+       fillbytes(&req, sizeof (req), '\0');
+
+       if (what == SCG_RESET_TGT) {
+               req.uscsi_flags = USCSI_RESET | USCSI_SILENT;   /* reset target */
+       } else if (what != SCG_RESET_BUS) {
+               req.uscsi_flags = USCSI_RESET_ALL | USCSI_SILENT; /* reset bus */
+       } else {
+               errno = EINVAL;
+               return (-1);
+       }
+
+       return (ioctl(usalp->fd, USCSICMD, &req));
+}
+
+static int
+usalo_usend(SCSI *usalp)
+{
+       struct usal_cmd *sp = usalp->scmd;
+       struct uscsi_cmd req;
+       int             ret;
+static uid_t           cureuid = 0;    /* XXX Hack until we have uid management */
+
+       if (usalp->fd < 0) {
+               sp->error = SCG_FATAL;
+               return (0);
+       }
+
+       fillbytes(&req, sizeof (req), '\0');
+
+       req.uscsi_flags = USCSI_SILENT | USCSI_DIAGNOSE | USCSI_RQENABLE;
+
+       if (sp->flags & SCG_RECV_DATA) {
+               req.uscsi_flags |= USCSI_READ;
+       } else if (sp->size > 0) {
+               req.uscsi_flags |= USCSI_WRITE;
+       }
+       req.uscsi_buflen        = sp->size;
+       req.uscsi_bufaddr       = sp->addr;
+       req.uscsi_timeout       = sp->timeout;
+       req.uscsi_cdblen        = sp->cdb_len;
+       req.uscsi_rqbuf         = (caddr_t) sp->u_sense.cmd_sense;
+       req.uscsi_rqlen         = sp->sense_len;
+       req.uscsi_cdb           = (caddr_t) &sp->cdb;
+
+       if (cureuid != 0)
+               seteuid(0);
+again:
+       errno = 0;
+       ret = ioctl(usalp->fd, USCSICMD, &req);
+
+       if (ret < 0 && geterrno() == EPERM) {   /* XXX Hack until we have uid management */
+               cureuid = geteuid();
+               if (seteuid(0) >= 0)
+                       goto again;
+       }
+       if (cureuid != 0)
+               seteuid(cureuid);
+
+       if (usalp->debug > 0) {
+               fprintf((FILE *)usalp->errfile, "ret: %d errno: %d (%s)\n", ret, errno, errmsgstr(errno));
+               fprintf((FILE *)usalp->errfile, "uscsi_flags:     0x%x\n", req.uscsi_flags);
+               fprintf((FILE *)usalp->errfile, "uscsi_status:    0x%x\n", req.uscsi_status);
+               fprintf((FILE *)usalp->errfile, "uscsi_timeout:   %d\n", req.uscsi_timeout);
+               fprintf((FILE *)usalp->errfile, "uscsi_bufaddr:   0x%lx\n", (long)req.uscsi_bufaddr);
+                                                               /*
+                                                                * Cast auf int OK solange sp->size
+                                                                * auch ein int bleibt.
+                                                                */
+               fprintf((FILE *)usalp->errfile, "uscsi_buflen:    %d\n", (int)req.uscsi_buflen);
+               fprintf((FILE *)usalp->errfile, "uscsi_resid:     %d\n", (int)req.uscsi_resid);
+               fprintf((FILE *)usalp->errfile, "uscsi_rqlen:     %d\n", req.uscsi_rqlen);
+               fprintf((FILE *)usalp->errfile, "uscsi_rqstatus:  0x%x\n", req.uscsi_rqstatus);
+               fprintf((FILE *)usalp->errfile, "uscsi_rqresid:   %d\n", req.uscsi_rqresid);
+               fprintf((FILE *)usalp->errfile, "uscsi_rqbuf ptr: 0x%lx\n", (long)req.uscsi_rqbuf);
+               fprintf((FILE *)usalp->errfile, "uscsi_rqbuf:     ");
+               if (req.uscsi_rqbuf != NULL && req.uscsi_rqlen > req.uscsi_rqresid) {
+                       int     i;
+                       int     len = req.uscsi_rqlen - req.uscsi_rqresid;
+
+                       for (i = 0; i < len; i++) {
+                               fprintf((FILE *)usalp->errfile, "0x%02X ", ((char *)req.uscsi_rqbuf)[i]);
+                       }
+                       fprintf((FILE *)usalp->errfile, "\n");
+               } else {
+                       fprintf((FILE *)usalp->errfile, "<data not available>\n");
+               }
+       }
+       if (ret < 0) {
+               sp->ux_errno = geterrno();
+               /*
+                * Check if SCSI command cound not be send at all.
+                */
+               if (sp->ux_errno == ENOTTY && usalo_uisatapi(usalp) == TRUE) {
+                       if (usalp->debug > 0) {
+                               fprintf((FILE *)usalp->errfile,
+                                       "ENOTTY atapi: %d\n", usalo_uisatapi(usalp));
+                       }
+                       sp->error = SCG_FATAL;
+                       return (0);
+               }
+               if (errno == ENXIO) {
+                       sp->error = SCG_FATAL;
+                       return (0);
+               }
+               if (errno == ENOTTY || errno == EINVAL || errno == EACCES) {
+                       return (-1);
+               }
+       } else {
+               sp->ux_errno = 0;
+       }
+       ret                     = 0;
+       sp->sense_count         = req.uscsi_rqlen - req.uscsi_rqresid;
+       sp->resid               = req.uscsi_resid;
+       sp->u_scb.cmd_scb[0]    = req.uscsi_status;
+
+       if ((req.uscsi_status & STATUS_MASK) == STATUS_GOOD) {
+               sp->error = SCG_NO_ERROR;
+               return (0);
+       }
+       if (req.uscsi_rqstatus == 0 &&
+           ((req.uscsi_status & STATUS_MASK) == STATUS_CHECK)) {
+               sp->error = SCG_NO_ERROR;
+               return (0);
+       }
+       if (req.uscsi_status & (STATUS_TERMINATED |
+           STATUS_RESERVATION_CONFLICT)) {
+               sp->error = SCG_FATAL;
+       }
+       if (req.uscsi_status != 0) {
+               /*
+                * This is most likely wrong. There seems to be no way
+                * to produce SCG_RETRYABLE with USCSI.
+                */
+               sp->error = SCG_RETRYABLE;
+       }
+
+       return (ret);
+}
+#endif /* USE_USCSI */
diff --git a/libusal/scsi-unixware.c b/libusal/scsi-unixware.c
new file mode 100644 (file)
index 0000000..4a149f1
--- /dev/null
@@ -0,0 +1,922 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)scsi-unixware.c 1.36 04/01/15 Copyright 1998 J. Schilling, Santa Cruz Operation */
+/*
+ *     Interface for the SCO UnixWare SCSI implementation.
+ *
+ *     Warning: you may change this source, but if you do that
+ *     you need to change the _usal_version and _usal_auth* string below.
+ *     You may not return "schily" for an SCG_AUTHOR request anymore.
+ *     Choose your name instead of "schily" and make clear that the version
+ *     string is related to a modified source.
+ *
+ *     Copyright (c) 1998 J. Schilling, Santa Cruz Operation
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#undef sense
+#undef SC_PARITY
+#undef scb
+
+#include <sys/sysmacros.h>     /* XXX Falsch, richtig -> sys/mkdev.h */
+#include <sys/scsi.h>
+#include <sys/sdi_edt.h>
+#include <sys/sdi.h>
+
+/*
+ *     Warning: you may change this source, but if you do that
+ *     you need to change the _usal_version and _usal_auth* string below.
+ *     You may not return "schily" for an SCG_AUTHOR request anymore.
+ *     Choose your name instead of "schily" and make clear that the version
+ *     string is related to a modified source.
+ */
+static char    _usal_trans_version[] = "scsi-unixware.c-1.36"; /* The version for this transport*/
+
+/* Max. number of usal scsibusses.  The real limit would be            */
+/* MAX_HBA * MAX_BUS (which would be 32 * 8 on UnixWare 2.1/7.x),      */
+/* but given that we will hardly see such a beast, lets take 32                */
+
+#define        MAX_SCG         32
+
+       /* maximum defines for UnixWare 2.x/7.x from <sys/sdi_edt.h> */
+
+#define        MAX_TGT         MAX_EXTCS       /* Max # of target id's         */
+#define        MAX_LUN         MAX_EXLUS       /* Max # of lun's               */
+
+#define        MAX_DMA         (32*1024)
+#ifdef __WHAT_TODO__
+#define        MAX_DMA         (16*1024)       /* On UnixWare 2.1.x w/ AHA2940 HBA */
+                                       /* the max DMA size is 16KB.        */
+#endif
+
+#define        MAXLINE         80
+#define        MAXPATH         256
+
+#define        DEV_DIR         "/tmp"
+#define        DEV_NAME        "usal.s%1dt%1dl%1d"
+
+#define        SCAN_HBA        "%d:%d,%d,%d:%7s : %n"
+#define        SCAN_DEV        "%d,%d,%d:%7s : %n"
+
+#define        PRIM_HBA        "/dev/hba/hba1"
+#define        SCSI_CFG        "LC_ALL=C /etc/scsi/pdiconfig -l"
+
+#define        SCAN_ALL        "LIBSCG_SCAN_ALL"
+
+#define        SDI_VALID       0x01    /* Entry may be used (non disk)    */
+#define        SDI_ATAPI       0x02    /* Connected via IDE HBA           */
+#define        SDI_INITIATOR   0x04    /* This is the initiator target ID */
+
+typedef struct usal2sdi {
+       short   open;
+       short   flags;
+       short   fd;
+       char    hba;
+       char    bus;
+       char    tgt;
+       char    lun;
+
+       dev_t   node;
+       dev_t   major;
+       dev_t   minor;
+/*#define      SCG_DEBUG*/
+#ifdef SCG_DEBUG
+       char    type[20];
+       char    vend[40];
+       char    devn[32];
+#endif
+} usal2sdi_t;
+
+static usal2sdi_t      sdidevs [MAX_SCG][MAX_TGT][MAX_LUN];
+static BOOL            sdiinit = FALSE;
+
+struct usal_local {
+       short   usalfiles[MAX_SCG][MAX_TGT][MAX_LUN];
+};
+#define        usallocal(p)    ((struct usal_local *)((p)->local))
+
+static int     unixware_init(SCSI *usalp);
+static int     do_usal_cmd(SCSI *usalp, struct usal_cmd *sp);
+static int     do_usal_sense(SCSI *usalp, struct usal_cmd *sp);
+static FILE    *xpopen(char *cmd, char *type);
+static int     xpclose(FILE *f);
+
+/*
+ * -------------------------------------------------------------------------
+ * SCO UnixWare 2.1.x / UnixWare 7 provides a scsi pass-through mechanism,
+ * which can be used to access any configured scsi device.
+ *
+ * NOTE: The libusal UnixWare passthrough routines have changed with
+ *       cdrecord-1.8 to enable the -scanbus, -load, -eject option
+ *      regardless of the status of media and the addressing
+ *       scheme is now the same as used on many other platforms like
+ *       Solaris, Linux etc.
+ *
+ *      ===============================================================
+ *     RUN 'cdrecord -scanbus' TO SEE THE DEVICE ADDRESSES YOU CAN USE
+ *     ===============================================================
+ */
+
+/*
+ * Return version information for the low level SCSI transport code.
+ * This has been introduced to make it easier to trace down problems
+ * in applications.
+ *
+ */
+static char *
+usalo_version(SCSI *usalp, int what)
+{
+       if (usalp != (SCSI *)0) {
+               switch (what) {
+
+               case SCG_VERSION:
+                       return (_usal_trans_version);
+               /*
+                * If you changed this source, you are not allowed to
+                * return "schily" for the SCG_AUTHOR request.
+                */
+               case SCG_AUTHOR:
+                       return (_usal_auth_cdrkit);
+               case SCG_SCCS_ID:
+                       return (__sccsid);
+               }
+       }
+       return ((char *)0);
+}
+
+
+static int
+usalo_help(SCSI *usalp, FILE *f)
+{
+       __usal_help(f, "SDI_SEND", "Generic SCSI",
+               "", "bus,target,lun", "1,2,0", TRUE, FALSE);
+       return (0);
+}
+
+/*
+ * ---------------------------------------------------------------
+ * This routine is introduced to create all device nodes necessary
+ * to access any detected scsi device. It parses the output of
+ * /etc/scsi/pdiconfig -l and creates passthru device node for each
+ * found scsi device apart from the listed hba's.
+ *
+ */
+
+static int
+unixware_init(SCSI *usalp)
+{
+       FILE            *cmd;
+       int             hba = 0, bus = 0, usal = 0, tgt = 0, lun = 0;
+       int             nusal = -1, lhba = -1, lbus = 0;
+       int             atapi, fd, nopen = 0, pos = 0, len = 0;
+       int             s, t, l;
+       int             scan_disks;
+       char            lines[MAXLINE];
+       char            class[MAXLINE];
+       char            ident[MAXLINE];
+       char            devnm[MAXPATH];
+       char            dname[MAXPATH];
+       struct stat     stbuf;
+       dev_t           ptdev, major, minor, node;
+       char            **evsave;
+extern char            **environ;
+
+       /* Check for validity of primary hostbus adapter node */
+
+       if (stat(PRIM_HBA, &stbuf) < 0) {
+               if (usalp->errstr)
+                       snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                               "Can not stat() primary hba (%s)",
+                               PRIM_HBA);
+               return (-1);
+       }
+
+       if (!S_ISCHR(stbuf.st_mode)) {
+               if (usalp->errstr)
+                       snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                               "Primary hba (%s) not a character device",
+                               PRIM_HBA);
+               return (-1);
+       }
+
+       major = getmajor(stbuf.st_rdev);
+
+       /*
+        * Check whether we want to scan all devices
+        */
+       if (getenv(SCAN_ALL) != NULL) {
+               scan_disks = 1;
+       } else {
+               scan_disks = 0;
+       }
+
+       /* read pdiconfig output and get all attached scsi devices ! */
+
+       evsave = environ;
+       environ = 0;
+       if ((cmd = xpopen(SCSI_CFG, "r")) == NULL) {
+               if (usalp->errstr)
+                       snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                               "Error popen() for \"%s\"",
+                               SCSI_CFG);
+               environ = evsave;
+               return (-1);
+       }
+       environ = evsave;
+
+
+       for (;;) {
+               if (fgets(lines, MAXLINE, cmd) == NULL)
+                       break;
+
+               memset(class, '\0', sizeof (class));
+               memset(ident, '\0', sizeof (ident));
+
+               if (lines[0] == ' ') {
+                       sscanf(lines, SCAN_DEV, &bus, &tgt, &lun, class, &pos);
+                       hba = lhba;
+               } else {
+                       sscanf(lines, SCAN_HBA, &hba, &bus, &tgt, &lun, class, &pos);
+                       nusal++;
+                       lhba = hba;
+                       atapi = 0;
+               }
+
+               /* We can't sscanf() the ident string of the device     */
+               /* as it may contain characters sscanf() will           */
+               /* recognize as a delimiter. So do a strcpy() instead ! */
+
+               len = strlen(lines) - pos - 1; /* don't copy the '\n' */
+
+               strncpy(ident, &lines[pos], len);
+
+               if (usalp->debug > 0) {
+                       fprintf((FILE *)usalp->errfile,
+                               "SDI -> %d:%d,%d,%d: %-7s : %s\n",
+                               hba, bus, tgt, lun, class, ident);
+               }
+               if (bus != lbus) {
+                       nusal++;
+                       lbus = bus;
+               }
+
+               usal = nusal;
+
+               /* check whether we have a HBA or a SCSI device, don't  */
+               /* let HBA's be valid device for cdrecord, but mark     */
+               /* them as a controller (initiator = 1).                */
+
+               /* Don't detect disks, opening a mounted disk can hang  */
+               /* the disk subsystem !!! So unless we set an           */
+               /* environment variable LIBSCG_SCAN_ALL, we will ignore */
+               /* disks                                                */
+
+               if (strstr(class, "HBA") == NULL) {
+                       if (strstr(class, "DISK") != NULL) {
+                               if (scan_disks)
+                                       sdidevs[usal][tgt][lun].flags |= SDI_VALID;
+                               else
+                                       sdidevs[usal][tgt][lun].flags &= ~SDI_VALID;
+                       } else {
+                               sdidevs[usal][tgt][lun].flags |= SDI_VALID;
+                       }
+               } else {
+                       sdidevs[usal][tgt][lun].flags |= SDI_INITIATOR;
+               }
+
+
+               /* There is no real flag that shows a HBA as an ATAPI   */
+               /* controller, so as we know the driver is called 'ide' */
+               /* we can check the ident string for the occurence of it*/
+
+               if (strstr(ident, "(ide,") != NULL) {
+                       atapi = 1;
+               }
+
+               /*
+                * Fill the sdidevs array with all we know now.
+                * Do not overwrite fields that may contain old state like
+                * sdidevs[usal][tgt][lun].open
+                */
+
+               if (atapi)
+                       sdidevs[usal][tgt][lun].flags |= SDI_ATAPI;
+               else
+                       sdidevs[usal][tgt][lun].flags &= ~SDI_ATAPI;
+
+               sdidevs[usal][tgt][lun].hba = hba;
+               sdidevs[usal][tgt][lun].bus = bus;
+               sdidevs[usal][tgt][lun].tgt = tgt;
+               sdidevs[usal][tgt][lun].lun = lun;
+
+#ifdef SCG_DEBUG
+               strcpy(sdidevs[usal][tgt][lun].type, class);
+               strcpy(sdidevs[usal][tgt][lun].vend, ident);
+
+               snprintf(sdidevs[usal][tgt][lun].devn,
+                               sizeof (sdidevs[usal][tgt][lun].devn),
+                               DEV_NAME, usal, tgt, lun);
+#endif
+               snprintf(devnm, sizeof (devnm),
+                               DEV_NAME, usal, tgt, lun);
+
+               minor = SDI_MINOR(hba, tgt, lun, bus);
+               node  = makedevice(major, minor);
+
+               sdidevs[usal][tgt][lun].major = major;
+               sdidevs[usal][tgt][lun].minor = minor;
+               sdidevs[usal][tgt][lun].node  = node;
+
+               if (usalp->debug > 0) {
+
+                       fprintf((FILE *)usalp->errfile,
+                       "h = %d; b = %d, s = %d, t = %d, l = %d, a = %d, ma = %d, mi = %2d, dev = '%s', id = '%s'\n",
+                       hba, bus, usal, tgt, lun,
+                       (sdidevs[usal][tgt][lun].flags & SDI_ATAPI) != 0,
+                       sdidevs[usal][tgt][lun].major,
+                       sdidevs[usal][tgt][lun].minor,
+                       devnm,
+                       ident);
+               }
+
+
+       }
+
+       if (xpclose(cmd) == -1) {
+               if (usalp->errstr)
+                       snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                               "Error pclose() for \"%s\"",
+                               SCSI_CFG);
+               return (-1);
+       }
+
+
+       /* create all temporary device nodes */
+
+       for (s = 0; s < MAX_SCG; s++) {
+               for (t = 0; t < MAX_TGT; t++) {
+                       for (l = 0; l < MAX_LUN; l++) {
+
+                               if ((sdidevs[s][t][l].flags & SDI_VALID) == 0) {
+                                       if (sdidevs[s][t][l].fd >= 0) {
+                                               close(sdidevs[s][t][l].fd);
+                                       }
+                                       sdidevs[s][t][l].fd = -1;
+                                       sdidevs[s][t][l].open = 0;
+                                       continue;
+                               }
+
+                               /* Make pass-through interface device node */
+
+                               snprintf(devnm,
+                                       sizeof (devnm),
+                                       DEV_NAME, s, t, l);
+
+                               snprintf(dname, sizeof (dname),
+                                       "%s/%s", DEV_DIR, devnm);
+
+                               ptdev = sdidevs[s][t][l].node;
+
+                               if (mknod(dname, S_IFCHR | 0700, ptdev) < 0) {
+                                       if (errno == EEXIST) {
+                                               unlink(dname);
+
+                                               if (mknod(dname, S_IFCHR | 0700, ptdev) < 0) {
+                                                       if (usalp->errstr)
+                                                               snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                                                                       "mknod() error for \"%s\"", dname);
+                                                       return (-1);
+                                               }
+                                       } else {
+                                               if (usalp->errstr)
+                                                       snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                                                               "mknod() error for \"%s\"", dname);
+                                               return (-1);
+                                       }
+                               }
+
+                               /* Open pass-through device node */
+
+                               if ((fd = open(dname, O_RDONLY)) < 0) {
+                                       if (errno == EBUSY && sdidevs[s][t][l].open > 0) {
+                                               /*
+                                                * Device has already been opened, just
+                                                * return the saved file desc.
+                                                */
+                                               fd = sdidevs[s][t][l].fd;
+                                       } else {
+                                               if (usalp->errstr)
+                                                       snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                                                               "can not open pass-through %s", dname);
+                                               return (-1);
+                                       }
+                               }
+
+                               /*
+                                * If for whatever reason we may open a pass through
+                                * device more than once, this will waste fs's as we
+                                * do not check for sdidevs[s][t][l].fd == -1.
+                                */
+                               sdidevs[s][t][l].fd   = fd;
+                               sdidevs[s][t][l].open++;
+                               nopen++;
+                               usallocal(usalp)->usalfiles[s][t][l] = (short) fd;
+
+                               if (usalp->debug > 0) {
+
+                                       fprintf((FILE *)usalp->errfile,
+                                               "s = %d, t = %d, l = %d, dev = %s, fd = %d\n",
+                                               s, t, l,
+                                               devnm,
+                                               sdidevs[s][t][l].fd);
+                               }
+
+                       }
+               }
+       }
+
+       return (nopen);
+}
+
+
+static int
+usalo_open(SCSI *usalp, char *device)
+{
+       int     busno   = usal_scsibus(usalp);
+       int     tgt     = usal_target(usalp);
+       int     tlun    = usal_lun(usalp);
+       int     b, t, l;
+
+       if (busno >= MAX_SCG || tgt >= MAX_TGT || tlun >= MAX_LUN) {
+               errno = EINVAL;
+               if (usalp->errstr)
+                       snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                               "Illegal value for busno, target or lun '%d,%d,%d'",
+                               busno, tgt, tlun);
+               return (-1);
+       }
+
+       if (usalp->local == NULL) {
+               usalp->local = malloc(sizeof (struct usal_local));
+               if (usalp->local == NULL)
+                       return (0);
+
+               for (b = 0; b < MAX_SCG; b++) {
+                       for (t = 0; t < MAX_TGT; t++) {
+                               for (l = 0; l < MAX_LUN; l++)
+                                       usallocal(usalp)->usalfiles[b][t][l] = (short)-1;
+                       }
+               }
+       }
+
+       if (!sdiinit) {
+               sdiinit = TRUE;
+               memset(sdidevs, 0, sizeof (sdidevs));   /* init tmp_structure */
+               for (b = 0; b < MAX_SCG; b++) {
+                       for (t = 0; t < MAX_TGT; t++) {
+                               for (l = 0; l < MAX_LUN; l++) {
+
+                                       sdidevs[b][t][l].flags = 0;
+                                       sdidevs[b][t][l].fd = -1;
+                                       sdidevs[b][t][l].open = 0;
+                               }
+                       }
+               }
+       }
+
+       if (*device != '\0') {          /* we don't allow old dev usage */
+               errno = EINVAL;
+               if (usalp->errstr)
+                       snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                       "Open by 'devname' no longer supported on this OS");
+               return (-1);
+       } else {                        /* this is the new stuff         */
+                                       /* it will do the initialisation */
+                                       /* and return the number of      */
+                                       /* detected devices to be used   */
+                                       /* with the new addressing       */
+                                       /* scheme.                       */
+
+               return (unixware_init(usalp));
+       }
+
+}
+
+
+static int
+usalo_close(SCSI *usalp)
+{
+       register int    f;
+       register int    b;
+       register int    t;
+       register int    l;
+
+       if (usalp->local == NULL)
+               return (-1);
+
+       for (b = 0; b < MAX_SCG; b++) {
+               for (t = 0; t < MAX_TGT; t++) {
+                       for (l = 0; l < MAX_LUN; l++) {
+
+                               f = usallocal(usalp)->usalfiles[b][t][l];
+                               if (f >= 0) {
+                                       if (sdidevs[b][t][l].open > 0)
+                                               sdidevs[b][t][l].open--;
+                                       if (sdidevs[b][t][l].open <= 0) {
+                                               if (sdidevs[b][t][l].fd >= 0)
+                                                       close(sdidevs[b][t][l].fd);
+                                               sdidevs[b][t][l].fd    = -1;
+                                               sdidevs[b][t][l].flags &= ~SDI_VALID;
+                                       }
+                               }
+                               usallocal(usalp)->usalfiles[b][t][l] = (short)-1;
+                       }
+               }
+       }
+       return (0);
+}
+
+static long
+usalo_maxdma(SCSI *usalp, long amt)
+{
+       return (MAX_DMA);
+}
+
+
+static void *
+usalo_getbuf(SCSI *usalp, long amt)
+{
+       if (usalp->debug > 0) {
+               fprintf((FILE *)usalp->errfile,
+                       "usalo_getbuf: %ld bytes\n", amt);
+       }
+       usalp->bufbase = (void *) valloc((size_t)(amt));
+
+       return (usalp->bufbase);
+}
+
+static void
+usalo_freebuf(SCSI *usalp)
+{
+       if (usalp->bufbase)
+               free(usalp->bufbase);
+       usalp->bufbase = NULL;
+}
+
+static BOOL
+usalo_havebus(SCSI *usalp, int busno)
+{
+       register int    t;
+       register int    l;
+
+       if (busno < 0 || busno >= MAX_SCG)
+               return (FALSE);
+
+       if (usalp->local == NULL)
+               return (FALSE);
+
+       for (t = 0; t < MAX_TGT; t++) {
+               for (l = 0; l < MAX_LUN; l++)
+                       if (usallocal(usalp)->usalfiles[busno][t][l] >= 0)
+                               return (TRUE);
+       }
+       return (FALSE);
+}
+
+static int
+usalo_fileno(SCSI *usalp, int busno, int tgt, int tlun)
+{
+       if (busno < 0 || busno >= MAX_SCG ||
+           tgt   < 0 || tgt   >= MAX_TGT ||
+           tlun  < 0 || tlun  >= MAX_LUN)
+               return (-1);
+
+       if (usalp->local == NULL)
+               return (-1);
+
+       return ((int)usallocal(usalp)->usalfiles[busno][tgt][tlun]);
+}
+
+static int
+usalo_initiator_id(SCSI *usalp)
+{
+       register int    t;
+       register int    l;
+       register int    busno;
+
+       busno = usal_scsibus(usalp);
+
+       if (busno < 0 || busno >= MAX_SCG)
+               return (FALSE);
+
+       for (t = 0; t < MAX_TGT; t++) {
+               for (l = 0; l < MAX_LUN; l++)
+                       if ((sdidevs[busno][t][l].flags & SDI_INITIATOR) != 0) {
+                               if (usalp->debug > 0) {
+                                       fprintf((FILE *)usalp->errfile,
+                                               "usalo_initiator_id: id = %d\n", t);
+                               }
+                               return (t);
+                       }
+       }
+
+       return (-1);
+}
+
+static int
+usalo_isatapi(SCSI *usalp)
+{
+       /* if the new address method is used we know if this is ATAPI */
+
+       return ((sdidevs[usal_scsibus(usalp)][usal_target(usalp)][usal_lun(usalp)].flags & SDI_ATAPI) != 0);
+}
+
+static int
+usalo_reset(SCSI *usalp, int what)
+{
+       int     f = usalp->fd;
+
+       errno = EINVAL;
+
+#if defined(SDI_TRESET) || defined(SDI_BRESET)
+       if (what == SCG_RESET_NOP) {
+               errno = 0;
+               return (0);
+       }
+
+#ifdef SDI_TRESET
+       if (what == SCG_RESET_TGT) {
+               errno = 0;
+               if (ioctl(f, SDI_TRESET, 0) >= 0)
+                       return (0);
+       }
+#endif
+
+#ifdef SDI_BRESET
+       if (what == SCG_RESET_BUS) {
+               errno = 0;
+               if (ioctl(f, SDI_BRESET, 0) >= 0)
+                       return (0);
+       }
+#endif
+
+#endif /* defined(SDI_TRESET) || defined(SDI_BRESET) */
+
+       return (-1);
+}
+
+static int
+do_usal_cmd(SCSI *usalp, struct usal_cmd *sp)
+{
+       int                     ret;
+       int                     i;
+       struct sb               scsi_cmd;
+       struct scb              *scbp;
+
+       memset(&scsi_cmd,  0, sizeof (scsi_cmd));
+
+       scsi_cmd.sb_type = ISCB_TYPE;
+       scbp = &scsi_cmd.SCB;
+
+       scbp->sc_cmdpt = (caddr_t) sp->cdb.cmd_cdb;
+       scbp->sc_cmdsz = sp->cdb_len;
+
+       scbp->sc_datapt = sp->addr;
+       scbp->sc_datasz = sp->size;
+
+       if (!(sp->flags & SCG_RECV_DATA) && (sp->size > 0))
+               scbp->sc_mode = SCB_WRITE;
+       else
+               scbp->sc_mode = SCB_READ;
+
+       scbp->sc_time = sp->timeout;
+
+       sp->error = SCG_NO_ERROR;
+       errno = 0;
+       for (;;) {
+               if ((ret = ioctl(usalp->fd, SDI_SEND, &scsi_cmd)) < 0) {
+                       if (errno == EAGAIN) {
+                               sleep(1);
+                               errno = 0;
+                               continue;
+                       }
+                       sp->ux_errno = errno;
+                       if (errno == 0)
+                               sp->ux_errno = EIO;
+                       sp->error = SCG_RETRYABLE;
+
+#ifdef __needed__
+                       if (errno == ENOTTY || errno == EINVAL ||
+                           errno == EACCES) {
+                               return (-1);
+                       }
+#endif
+                       return (ret);
+               }
+               break;
+       }
+       sp->ux_errno = errno;
+       sp->resid = scbp->sc_resid;
+       memset(&sp->u_scb.Scb, 0, sizeof (sp->u_scb.Scb));
+       sp->u_scb.cmd_scb[0] = scbp->sc_status;
+
+       if (sp->u_scb.cmd_scb[0] & 0x02) {
+               if (sp->ux_errno == 0)
+                       sp->ux_errno = EIO;
+       }
+
+       switch (scbp->sc_comp_code) {
+
+               case SDI_ASW     : /* Job completed normally            */
+               case SDI_LINKF0  : /* Linked command done without flag  */
+               case SDI_LINKF1  : /* Linked command done with flag     */
+
+                               sp->error = SCG_NO_ERROR;
+                               break;
+
+               case SDI_CKSTAT  : /* Check the status byte             */
+
+                               sp->error = SCG_NO_ERROR;
+                               break;
+
+               case SDI_NOALLOC : /* This block is not allocated       */
+               case SDI_NOTEQ   : /* Addressed device not present      */
+               case SDI_OOS     : /* Device is out of service          */
+               case SDI_NOSELE  : /* The SCSI bus select failed        */
+               case SDI_SBRESC  : /* SCSI bus reservation conflict     */
+
+                               sp->error = SCG_FATAL;
+                               if (sp->ux_errno == 0)
+                                       sp->ux_errno = EIO;
+                               break;
+
+               case SDI_QFLUSH  : /* Job was flushed                   */
+               case SDI_ABORT   : /* Command was aborted               */
+               case SDI_RESET   : /* Reset was detected on the bus     */
+               case SDI_CRESET  : /* Reset was caused by this unit     */
+               case SDI_V2PERR  : /* vtop failed                       */
+               case SDI_HAERR   : /* Host adapter error                */
+               case SDI_MEMERR  : /* Memory fault                      */
+               case SDI_SBUSER  : /* SCSI bus error                    */
+               case SDI_SCBERR  : /* SCB error                         */
+               case SDI_MISMAT  : /* parameter mismatch                */
+
+               case SDI_PROGRES : /* Job in progress                   */
+               case SDI_UNUSED  : /* Job not in use                    */
+
+               case SDI_ONEIC   : /* More than one immediate request   */
+               case SDI_SFBERR  : /* SFB error                         */
+               case SDI_TCERR   : /* Target protocol error detected    */
+               default:
+                               sp->error = SCG_RETRYABLE;
+                               if (sp->ux_errno == 0)
+                                       sp->ux_errno = EIO;
+                               break;
+
+               case SDI_TIME    : /* Job timed out                     */
+               case SDI_TIME_NOABORT : /* Job timed out, but could not be aborted */
+
+                               sp->error = SCG_TIMEOUT;
+                               if (sp->ux_errno == 0)
+                                       sp->ux_errno = EIO;
+                               break;
+       }
+       return (0);
+}
+
+
+static int
+do_usal_sense(SCSI *usalp, struct usal_cmd *sp)
+{
+       int             ret;
+       struct usal_cmd s_cmd;
+
+       memset((caddr_t)&s_cmd, 0, sizeof (s_cmd));
+
+       s_cmd.addr      = (caddr_t) sp->u_sense.cmd_sense;
+       s_cmd.size      = sp->sense_len;
+       s_cmd.flags     = SCG_RECV_DATA|SCG_DISRE_ENA;
+       s_cmd.cdb_len   = SC_G0_CDBLEN;
+       s_cmd.sense_len = CCS_SENSE_LEN;
+
+       s_cmd.cdb.g0_cdb.cmd   = SC_REQUEST_SENSE;
+       s_cmd.cdb.g0_cdb.lun   = sp->cdb.g0_cdb.lun;
+       s_cmd.cdb.g0_cdb.count = sp->sense_len;
+
+       ret = do_usal_cmd(usalp, &s_cmd);
+
+       if (ret < 0)
+               return (ret);
+
+       sp->sense_count = sp->sense_len - s_cmd.resid;
+       return (ret);
+}
+
+static int
+usalo_send(SCSI *usalp)
+{
+       struct usal_cmd *sp = usalp->scmd;
+       int     ret;
+
+       if (usalp->fd < 0) {
+               sp->error = SCG_FATAL;
+               return (0);
+       }
+
+       ret = do_usal_cmd(usalp, sp);
+       if (ret < 0)
+               return (ret);
+
+       if (sp->u_scb.cmd_scb[0] & S_CKCON)
+               ret = do_usal_sense(usalp, sp);
+
+       return (ret);
+}
+
+#define        sense   u_sense.Sense
+#undef SC_PARITY
+#define        SC_PARITY       0x09
+#define        scb             u_scb.Scb
+
+/*--------------------------------------------------------------------------*/
+#include <unixstd.h>
+#include <waitdefs.h>
+/*
+ * Simplified version of popen()
+ * This version of popen() is not usable more than once at a time.
+ * Needed because /etc/scsi/pdiconfig will not work if euid != uid
+ */
+static pid_t   po_pid;
+
+static FILE *
+xpopen(char *cmd, char *type)
+{
+       FILE    *ret;
+       FILE    *pp[2];
+
+       if (po_pid != 0)
+               return ((FILE *)NULL);
+
+       if (*type != 'r')
+               return ((FILE *)NULL);
+
+       if (fpipe(pp) == 0)
+               return ((FILE *)NULL);
+
+
+       if ((po_pid = fork()) == 0) {
+               setuid(0);
+
+               fclose(pp[0]);
+               (void) rols_fexecl("/bin/sh", stdin, pp[1], stderr,
+                                       "sh", "-c", cmd, (char *)0);
+               _exit(1);
+       }
+       fclose(pp[1]);
+
+       if (po_pid == (pid_t)-1) {
+               fclose(pp[0]);
+               return ((FILE *)NULL);
+       }
+       return (pp[0]);
+}
+
+static int
+xpclose(FILE *f)
+{
+       int     ret = 0;
+
+       if (po_pid == 0)
+               return (-1);
+
+       fclose(f);
+
+       if (waitpid(po_pid, &ret, 0) < 0)
+               ret = -1;
+
+       po_pid = 0;
+       return (ret);
+}
diff --git a/libusal/scsi-vms.c b/libusal/scsi-vms.c
new file mode 100644 (file)
index 0000000..ef29d76
--- /dev/null
@@ -0,0 +1,540 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)scsi-vms.c      1.33 04/01/15 Copyright 1997 J. Schilling */
+/*
+ *     Interface for the VMS generic SCSI implementation.
+ *
+ *     The idea for an elegant mapping to VMS device dontroller names
+ *     is from Chip Dancy Chip.Dancy@hp.com. This allows up to
+ *     26 IDE controllers (DQ[A-Z][0-1]).
+ *
+ *     This is a hack, that tries to emulate the functionality
+ *     of the usal driver.
+ *
+ *     Warning: you may change this source, but if you do that
+ *     you need to change the _usal_version and _usal_auth* string below.
+ *     You may not return "schily" for an SCG_AUTHOR request anymore.
+ *     Choose your name instead of "schily" and make clear that the version
+ *     string is related to a modified source.
+ *
+ *     Copyright (c) 1997 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <iodef.h>
+#include <ssdef.h>
+#include <descrip.h>
+#include <starlet.h>
+#include <string.h>
+#include <LIB$ROUTINES.H>
+
+/*
+ *     Warning: you may change this source, but if you do that
+ *     you need to change the _usal_version and _usal_auth* string below.
+ *     You may not return "schily" for an SCG_AUTHOR request anymore.
+ *     Choose your name instead of "schily" and make clear that the version
+ *     string is related to a modified source.
+ */
+static char    _usal_trans_version[] = "scsi-vms.c-1.33";      /* The version for this transport*/
+
+#define        VMS_MAX_DK      4               /* DK[A-D] VMS device controllers */
+#define        VMS_MAX_GK      4               /* GK[A-D] VMS device controllers */
+#define        VMS_MAX_DQ      26              /* DQ[A-Z] VMS device controllers */
+
+#define        VMS_DKRANGE_MAX VMS_MAX_DK
+#define        VMS_GKRANGE_MAX (VMS_DKRANGE_MAX + VMS_MAX_GK)
+#define        VMS_DQRANGE_MAX (VMS_GKRANGE_MAX + VMS_MAX_DQ)
+
+#define        MAX_SCG         VMS_DQRANGE_MAX /* Max # of SCSI controllers */
+#define        MAX_TGT         16
+#define        MAX_LUN         8
+
+#define        MAX_DMA_VMS     (63*1024)       /* Check if this is not too big */
+#define        MAX_PHSTMO_VMS  300
+#define        MAX_DSCTMO_VMS  ((64*1024)-1)   /* max value for OpenVMS/AXP 7.1 ehh*/
+
+/*
+ * Define a mapping from the scsi busno to the three character
+ * VMS device controller.
+ * The valid busno values are broken into three ranges, one for each of
+ * the three supported devices: dk, gk, and dq.
+ * The vmschar[] and vmschar1[] arrays are subscripted by an offset
+ * corresponding to each of the three ranges [0,1,2] to provide the
+ * two characters of the VMS device.
+ * The offset of the busno value within its range is used to define the
+ * third character, using the vmschar2[] array.
+ */
+static char    vmschar[]       = {'d', 'g', 'd'};
+static char    vmschar1[]      = {'k', 'k', 'q'};
+static char    vmschar2[]      = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
+                                   'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
+                                   'u', 'v', 'w', 'x', 'y', 'z'};
+
+
+static int     do_usal_cmd(SCSI *usalp, struct usal_cmd *sp);
+static int     do_usal_sense(SCSI *usalp, struct usal_cmd *sp);
+
+#define        DEVICE_NAMELEN 8
+
+struct SCSI$DESC {
+       Uint    SCSI$L_OPCODE;          /* SCSI Operation Code */
+       Uint    SCSI$L_FLAGS;           /* SCSI Flags Bit Map */
+       char    *SCSI$A_CMD_ADDR;       /* ->SCSI command buffer */
+       Uint    SCSI$L_CMD_LEN;         /* SCSI command length, bytes */
+       char    *SCSI$A_DATA_ADDR;      /* ->SCSI data buffer */
+       Uint    SCSI$L_DATA_LEN;        /* SCSI data length, bytes */
+       Uint    SCSI$L_PAD_LEN;         /* SCSI pad length, bytes */
+       Uint    SCSI$L_PH_CH_TMOUT;     /* SCSI phase change timeout */
+       Uint    SCSI$L_DISCON_TMOUT;    /* SCSI disconnect timeout */
+       Uint    SCSI$L_RES_1;           /* Reserved */
+       Uint    SCSI$L_RES_2;           /* Reserved */
+       Uint    SCSI$L_RES_3;           /* Reserved */
+       Uint    SCSI$L_RES_4;           /* Reserved */
+       Uint    SCSI$L_RES_5;           /* Reserved */
+       Uint    SCSI$L_RES_6;           /* Reserved */
+};
+
+#ifdef __ALPHA
+#pragma member_alignment save
+#pragma nomember_alignment
+#endif
+
+struct SCSI$IOSB {
+       Ushort  SCSI$W_VMS_STAT;        /* VMS status code */
+       Ulong   SCSI$L_IOSB_TFR_CNT;    /* Actual #bytes transferred */
+       char    SCSI$B_IOSB_FILL_1;
+       Uchar   SCSI$B_IOSB_STS;        /* SCSI device status */
+};
+
+#ifdef __ALPHA
+#pragma member_alignment restore
+#endif
+
+#define        SCSI$K_GOOD_STATUS              0
+#define        SCSI$K_CHECK_CONDITION          0x2
+#define        SCSI$K_CONDITION_MET            0x4
+#define        SCSI$K_BUSY                     0x8
+#define        SCSI$K_INTERMEDIATE             0x10
+#define        SCSI$K_INTERMEDIATE_C_MET       0x14
+#define        SCSI$K_RESERVATION_CONFLICT     0x18
+#define        SCSI$K_COMMAND_TERMINATED       0x22
+#define        SCSI$K_QUEUE_FULL               0x28
+
+
+#define        SCSI$K_WRITE            0X0     /* direction of transfer=write */
+#define        SCSI$K_READ             0X1     /* direction of transfer=read */
+#define        SCSI$K_FL_ENAB_DIS      0X2     /* enable disconnects */
+#define        SCSI$K_FL_ENAB_SYNC     0X4     /* enable sync */
+#define        GK_EFN                  0       /* Event flag number */
+
+static char    gk_device[8];           /* XXX JS hoffentlich gibt es keinen Ueberlauf */
+static Ushort  gk_chan;
+static Ushort  transfer_length;
+static int     i;
+static int     status;
+static $DESCRIPTOR(gk_device_desc, gk_device);
+static struct SCSI$IOSB gk_iosb;
+static struct SCSI$DESC gk_desc;
+static FILE *fp;
+
+
+struct usal_local {
+       Ushort  gk_chan;
+};
+#define        usallocal(p)    ((struct usal_local *)((p)->local))
+
+/*
+ * Return version information for the low level SCSI transport code.
+ * This has been introduced to make it easier to trace down problems
+ * in applications.
+ */
+static char *
+usalo_version(SCSI *usalp, int what)
+{
+       if (usalp != (SCSI *)0) {
+               switch (what) {
+
+               case SCG_VERSION:
+                       return (_usal_trans_version);
+               /*
+                * If you changed this source, you are not allowed to
+                * return "schily" for the SCG_AUTHOR request.
+                */
+               case SCG_AUTHOR:
+                       return (_usal_auth_cdrkit);
+               case SCG_SCCS_ID:
+                       return (__sccsid);
+               }
+       }
+       return ((char *)0);
+}
+
+static int
+usalo_help(SCSI *usalp, FILE *f)
+{
+       __usal_help(f, "IO$_DIAGNOSE", "Generic SCSI",
+               "", "bus,target,lun", "1,2,0", FALSE, FALSE);
+       return (0);
+}
+
+static int
+usalo_open(SCSI *usalp, char *device)
+{
+       int     busno   = usal_scsibus(usalp);
+       int     tgt     = usal_target(usalp);
+       int     tlun    = usal_lun(usalp);
+       char    devname[DEVICE_NAMELEN];
+       char    buschar;
+       char    buschar1;
+       char    buschar2;
+       int     range;
+       int     range_offset;
+
+       if (busno >= MAX_SCG || tgt >= MAX_TGT || tlun >= MAX_LUN) {
+               errno = EINVAL;
+               if (usalp->errstr)
+                       snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                               "Illegal value for busno, target or lun '%d,%d,%d'",
+                               busno, tgt, tlun);
+               return (-1);
+       }
+
+       if ((device != NULL && *device != '\0') || (busno == -2 && tgt == -2)) {
+               errno = EINVAL;
+               if (usalp->errstr)
+                       snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                               "Open by 'devname' not supported on this OS");
+               return (-1);
+       }
+       if (busno < 0 || tgt < 0 || tlun < 0) {
+               /*
+                * There is no real reason why we cannot scan on VMS,
+                * but for now it is not possible.
+                */
+               if (usalp->errstr)
+                       snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                               "Unable to scan on VMS");
+               return (0);
+       }
+
+       if (usalp->local == NULL) {
+               usalp->local = malloc(sizeof (struct usal_local));
+               if (usalp->local == NULL)
+                       return (0);
+       }
+
+       if (busno < VMS_DKRANGE_MAX) {                  /* in the dk range?   */
+               range = 0;
+               range_offset = busno;
+       } else if (busno < VMS_GKRANGE_MAX) {           /* in the gk range?   */
+               range = 1;
+               range_offset = busno - VMS_DKRANGE_MAX;
+       } else if (busno < VMS_DQRANGE_MAX) {           /* in the dq range?   */
+               range = 2;
+               range_offset = busno - VMS_GKRANGE_MAX;
+       }
+       buschar = vmschar[range];                       /* get first device char*/
+       buschar1 = vmschar1[range];                     /* get 2nd device char*/
+       buschar2 = vmschar2[range_offset];              /* get controller char*/
+
+       snprintf(devname, sizeof (devname), "%c%c%c%d0%d:",
+                                       buschar, buschar1, buschar2,
+                                       tgt, tlun);
+       strcpy(gk_device, devname);
+       status = sys$assign(&gk_device_desc, &gk_chan, 0, 0);
+       if (!(status & 1)) {
+               fprintf((FILE *)usalp->errfile,
+                       "Unable to access scsi-device \"%s\"\n", &gk_device[0]);
+               return (-1);
+       }
+       if (usalp->debug > 0) {
+               fp = fopen("cdrecord_io.log", "w", "rfm=stmlf", "rat=cr");
+               if (fp == NULL) {
+                       perror("Failing opening i/o-logfile");
+                       exit(SS$_NORMAL);
+               }
+       }
+       return (status);
+}
+
+static int
+usalo_close(SCSI *usalp)
+{
+       /*
+        * XXX close gk_chan ???
+        */
+       /*
+        * sys$dassgn()
+        */
+
+       status = sys$dassgn(gk_chan);
+
+       return (status);
+}
+
+static long
+usalo_maxdma(SCSI *usalp, long amt)
+{
+       return (MAX_DMA_VMS);
+}
+
+static BOOL
+usalo_havebus(SCSI *usalp, int busno)
+{
+       if (gk_chan == 0)
+               return (FALSE);
+       return (TRUE);
+}
+
+static int
+usalo_fileno(SCSI *usalp, int busno, int tgt, int tlun)
+{
+       if (gk_chan == 0)
+               return (-1);
+       return (gk_chan);
+}
+
+static int
+usalo_initiator_id(SCSI *usalp)
+{
+       return (-1);
+}
+
+static int
+usalo_isatapi(SCSI *usalp)
+{
+       int     busno = usal_scsibus(usalp);
+
+       if (busno >= 8)
+               return (TRUE);
+
+       return (FALSE);
+}
+
+static int
+usalo_reset(SCSI *usalp, int what)
+{
+       errno = EINVAL;
+       return (-1);
+}
+
+static void *
+usalo_getbuf(SCSI *usalp, long amt)
+{
+       if (usalp->debug > 0) {
+               fprintf((FILE *)usalp->errfile,
+                               "usalo_getbuf: %ld bytes\n", amt);
+       }
+       usalp->bufbase = malloc((size_t)(amt)); /* XXX JS XXX valloc() ??? */
+       return (usalp->bufbase);
+}
+
+static void
+usalo_freebuf(SCSI *usalp)
+{
+       if (usalp->bufbase)
+               free(usalp->bufbase);
+       usalp->bufbase = NULL;
+}
+
+static int
+do_usal_cmd(SCSI *usalp, struct usal_cmd *sp)
+{
+       char            *cmdadr;
+       int             notcmdretry;
+       int             len;
+       Uchar           scsi_sts;
+       int             severity;
+
+       /* XXX JS XXX This cannot be OK */
+       notcmdretry = (sp->flags & SCG_CMD_RETRY)^SCG_CMD_RETRY;
+       /* error corrected ehh  */
+/*
+ * XXX JS Wenn das notcmdretry Flag bei VMS auch 0x08 ist und Du darauf hoffst,
+ * XXX Dasz ich den Wert nie aendere, dann ist das richtig.
+ * XXX Siehe unten: Das gleiche gilt fuer SCG_RECV_DATA und SCG_DISRE_ENA !!!
+ */
+
+       cmdadr = (char *)sp->cdb.cmd_cdb;
+       /* XXX JS XXX This cannot be OK */
+       gk_desc.SCSI$L_FLAGS = ((sp->flags & SCG_RECV_DATA) |
+                               (sp->flags & SCG_DISRE_ENA)|
+                               notcmdretry);
+                               /* XXX siehe oben, das ist ein bitweises oder!!! */
+       gk_desc.SCSI$A_DATA_ADDR = sp->addr;
+       gk_desc.SCSI$L_DATA_LEN = sp->size;
+       gk_desc.SCSI$A_CMD_ADDR = cmdadr;
+       gk_desc.SCSI$L_CMD_LEN = sp->cdb_len;
+       gk_desc.SCSI$L_PH_CH_TMOUT = sp->timeout;
+       gk_desc.SCSI$L_DISCON_TMOUT = sp->timeout;
+       if (gk_desc.SCSI$L_PH_CH_TMOUT > MAX_PHSTMO_VMS)
+           gk_desc.SCSI$L_PH_CH_TMOUT = MAX_PHSTMO_VMS;
+       if (gk_desc.SCSI$L_DISCON_TMOUT > MAX_DSCTMO_VMS)
+           gk_desc.SCSI$L_DISCON_TMOUT = MAX_DSCTMO_VMS;
+       gk_desc.SCSI$L_OPCODE = 1;      /* SCSI Operation Code */
+       gk_desc.SCSI$L_PAD_LEN = 0;     /* SCSI pad length, bytes */
+       gk_desc.SCSI$L_RES_1 = 0;       /* Reserved */
+       gk_desc.SCSI$L_RES_2 = 0;       /* Reserved */
+       gk_desc.SCSI$L_RES_3 = 0;       /* Reserved */
+       gk_desc.SCSI$L_RES_4 = 0;       /* Reserved */
+       gk_desc.SCSI$L_RES_5 = 0;       /* Reserved */
+       gk_desc.SCSI$L_RES_6 = 0;       /* Reserved */
+       if (usalp->debug > 0) {
+               fprintf(fp, "***********************************************************\n");
+               fprintf(fp, "SCSI VMS-I/O parameters\n");
+               fprintf(fp, "OPCODE: %d", gk_desc.SCSI$L_OPCODE);
+               fprintf(fp, " FLAGS: %d\n", gk_desc.SCSI$L_FLAGS);
+               fprintf(fp, "CMD:");
+               for (i = 0; i < gk_desc.SCSI$L_CMD_LEN; i++) {
+                       fprintf(fp, "%x ", sp->cdb.cmd_cdb[i]);
+               }
+               fprintf(fp, "\n");
+               fprintf(fp, "DATA_LEN: %d\n", gk_desc.SCSI$L_DATA_LEN);
+               fprintf(fp, "PH_CH_TMOUT: %d", gk_desc.SCSI$L_PH_CH_TMOUT);
+               fprintf(fp, " DISCON_TMOUT: %d\n", gk_desc.SCSI$L_DISCON_TMOUT);
+       }
+       status = sys$qiow(GK_EFN, gk_chan, IO$_DIAGNOSE, &gk_iosb, 0, 0,
+                       &gk_desc, sizeof (gk_desc), 0, 0, 0, 0);
+
+
+       if (usalp->debug > 0) {
+               fprintf(fp, "qiow-status: %i\n", status);
+               fprintf(fp, "VMS status code %i\n", gk_iosb.SCSI$W_VMS_STAT);
+               fprintf(fp, "Actual #bytes transferred %i\n", gk_iosb.SCSI$L_IOSB_TFR_CNT);
+               fprintf(fp, "SCSI device status %i\n", gk_iosb.SCSI$B_IOSB_STS);
+               if (gk_iosb.SCSI$L_IOSB_TFR_CNT != gk_desc.SCSI$L_DATA_LEN) {
+                       fprintf(fp, "#bytes transferred != DATA_LEN\n");
+               }
+       }
+
+       if (!(status & 1)) {            /* Fehlerindikation fuer sys$qiow() */
+               sp->ux_errno = geterrno();
+               /* schwerwiegender nicht SCSI bedingter Fehler => return (-1) */
+               if (sp->ux_errno == ENOTTY || sp->ux_errno == ENXIO ||
+                   sp->ux_errno == EINVAL || sp->ux_errno == EACCES) {
+                       return (-1);
+               }
+               if (sp->ux_errno == 0)
+                       sp->ux_errno == EIO;
+       } else {
+               sp->ux_errno = 0;
+       }
+
+       sp->resid = gk_desc.SCSI$L_DATA_LEN - gk_iosb.SCSI$L_IOSB_TFR_CNT;
+
+       if (usalo_isatapi(usalp)) {
+               scsi_sts = ((gk_iosb.SCSI$B_IOSB_STS >> 4) & 0x7);
+       } else {
+               scsi_sts = gk_iosb.SCSI$B_IOSB_STS;
+       }
+
+       if (gk_iosb.SCSI$W_VMS_STAT == SS$_NORMAL && scsi_sts == 0) {
+               sp->error = SCG_NO_ERROR;
+               if (usalp->debug > 0) {
+                       fprintf(fp, "scsi_sts == 0\n");
+                       fprintf(fp, "gk_iosb.SCSI$B_IOSB_STS == 0\n");
+                       fprintf(fp, "sp->error %i\n", sp->error);
+                       fprintf(fp, "sp->resid %i\n", sp->resid);
+               }
+               return (0);
+       }
+
+       severity = gk_iosb.SCSI$W_VMS_STAT & 0x7;
+
+       if (severity == 4) {
+               sp->error = SCG_FATAL;
+               if (usalp->debug > 0) {
+                       fprintf(fp, "scsi_sts & 2\n");
+                       fprintf(fp, "gk_iosb.SCSI$B_IOSB_STS & 2\n");
+                       fprintf(fp, "gk_iosb.SCSI$W_VMS_STAT & 0x7 == SS$_FATAL\n");
+                       fprintf(fp, "sp->error %i\n", sp->error);
+               }
+               return (0);
+       }
+       if (gk_iosb.SCSI$W_VMS_STAT == SS$_TIMEOUT) {
+               sp->error = SCG_TIMEOUT;
+               if (usalp->debug > 0) {
+                       fprintf(fp, "scsi_sts & 2\n");
+                       fprintf(fp, "gk_iosb.SCSI$B_IOSB_STS & 2\n");
+                       fprintf(fp, "gk_iosb.SCSI$W_VMS_STAT == SS$_TIMEOUT\n");
+                       fprintf(fp, "sp->error %i\n", sp->error);
+               }
+               return (0);
+       }
+       sp->error = SCG_RETRYABLE;
+       sp->u_scb.cmd_scb[0] = scsi_sts;
+       if (usalp->debug > 0) {
+               fprintf(fp, "scsi_sts & 2\n");
+               fprintf(fp, "gk_iosb.SCSI$B_IOSB_STS & 2\n");
+               fprintf(fp, "gk_iosb.SCSI$W_VMS_STAT != 0\n");
+               fprintf(fp, "sp->error %i\n", sp->error);
+       }
+       return (0);
+}
+
+static int
+do_usal_sense(SCSI *usalp, struct usal_cmd *sp)
+{
+       int             ret;
+       struct usal_cmd s_cmd;
+
+       fillbytes((caddr_t)&s_cmd, sizeof (s_cmd), '\0');
+       s_cmd.addr = (char *)sp->u_sense.cmd_sense;
+       s_cmd.size = sp->sense_len;
+       s_cmd.flags = SCG_RECV_DATA|SCG_DISRE_ENA;
+       s_cmd.cdb_len = SC_G0_CDBLEN;
+       s_cmd.sense_len = CCS_SENSE_LEN;
+       s_cmd.cdb.g0_cdb.cmd = SC_REQUEST_SENSE;
+       s_cmd.cdb.g0_cdb.lun = sp->cdb.g0_cdb.lun;
+       s_cmd.cdb.g0_cdb.count = sp->sense_len;
+       ret = do_usal_cmd(usalp, &s_cmd);
+
+       if (ret < 0)
+               return (ret);
+       if (s_cmd.u_scb.cmd_scb[0] & 02) {
+               /* XXX ??? Check condition on request Sense ??? */
+       }
+       sp->sense_count = sp->sense_len - s_cmd.resid;
+       return (ret);
+}
+
+static int
+usalo_send(SCSI *usalp)
+{
+       struct usal_cmd *sp = usalp->scmd;
+       int     ret;
+
+       if (usalp->fd < 0) {
+               sp->error = SCG_FATAL;
+               return (0);
+       }
+       ret = do_usal_cmd(usalp, sp);
+       if (ret < 0)
+               return (ret);
+       if (sp->u_scb.cmd_scb[0] & 02)
+               ret = do_usal_sense(usalp, sp);
+       return (ret);
+}
diff --git a/libusal/scsi-wnt.c b/libusal/scsi-wnt.c
new file mode 100644 (file)
index 0000000..ddce64b
--- /dev/null
@@ -0,0 +1,1848 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)scsi-wnt.c      1.45 04/07/19 Copyright 1998-2004 J. Schilling, A.L. Faber, J.A. Key */
+/*
+ *     Interface for the Win32 ASPI library.
+ *             You need wnaspi32.dll and aspi32.sys
+ *             Both can be installed from ASPI_ME
+ *
+ *     Warning: you may change this source, but if you do that
+ *     you need to change the _usal_version and _usal_auth* string below.
+ *     You may not return "schily" for an SCG_AUTHOR request anymore.
+ *     Choose your name instead of "schily" and make clear that the version
+ *     string is related to a modified source.
+ *
+ *     Copyright (c) 1998-2004 J. Schilling
+ *     Copyright (c) 1999 A.L. Faber for the first implementation
+ *                        of this interface.
+ *     TODO:
+ *     -       DMA resid handling
+ *     -       better handling of maxDMA
+ *     -       SCSI reset support
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+/*
+ * Include for Win32 ASPI AspiRouter
+ *
+ * NOTE: aspi-win32.h includes Windows.h and Windows.h includes
+ *      Base.h which has a second typedef for BOOL.
+ *      We define BOOL to make all local code use BOOL
+ *      from Windows.h and use the hidden __SBOOL for
+ *      our global interfaces.
+ */
+#define        BOOL    WBOOL           /* This is the Win BOOL         */
+#define        format  __format
+#include <usal/aspi-win32.h>
+#include <usal/spti-wnt.h>
+#undef format
+
+#ifdef __CYGWIN32__            /* Use dlopen()                 */
+#include <dlfcn.h>
+#endif
+
+/*
+ *     Warning: you may change this source, but if you do that
+ *     you need to change the _usal_version and _usal_auth* string below.
+ *     You may not return "schily" for an SCG_AUTHOR request anymore.
+ *     Choose your name instead of "schily" and make clear that the version
+ *     string is related to a modified source.
+ */
+static char    _usal_trans_version[] = "scsi-wnt.c-1.45";      /* The version for this transport*/
+static char    _usal_itrans_version[] = "SPTI-scsi-wnt.c-1.45";        /* The version for SPTI */
+
+/*
+ * Local defines and constants
+ */
+/*#define DEBUG_WNTASPI*/
+
+#define        MAX_SCG         16      /* Max # of SCSI controllers    */
+#define        MAX_TGT         16      /* Max # of SCSI Targets        */
+#define        MAX_LUN         8       /* Max # of SCSI LUNs           */
+
+#ifdef DEBUG_WNTASPI
+#endif
+
+struct usal_local {
+       int     dummy;
+       char *filenames[MAX_SCG][MAX_TGT][MAX_LUN];
+       char drive_wanted;
+};
+#define        usallocal(p)    ((struct usal_local *)((p)->local))
+
+/*
+ * Local variables
+ */
+static int     busses;
+static DWORD   (*pfnGetASPI32SupportInfo)(void)                = NULL;
+static DWORD   (*pfnSendASPI32Command)(LPSRB)                  = NULL;
+static BOOL    (*pfnGetASPI32Buffer)(PASPI32BUFF)              = NULL;
+static BOOL    (*pfnFreeASPI32Buffer)(PASPI32BUFF)             = NULL;
+static BOOL    (*pfnTranslateASPI32Address)(PDWORD, PDWORD)    = NULL;
+
+static int     DriverLoaded                    = 0;    /* ASPI or SPTI */
+static HANDLE  hAspiLib                        = NULL; /* Used for Loadlib */
+
+#define        MAX_DMA_WNT     (63L*1024L) /* ASPI-Driver  allows up to 64k ??? */
+
+/*
+ * Local function prototypes
+ */
+static void    exit_func(void);
+#ifdef DEBUG_WNTASPI
+static void    DebugScsiSend(SCSI *usalp, SRB_ExecSCSICmd *s, int bDisplayBuffer);
+#endif
+static void    copy_sensedata(SRB_ExecSCSICmd *cp, struct usal_cmd *sp);
+static void    set_error(SRB_ExecSCSICmd *cp, struct usal_cmd *sp);
+static BOOL    open_driver(SCSI *usalp);
+static BOOL    load_aspi(SCSI *usalp);
+static BOOL    close_driver(void);
+static int     ha_inquiry(SCSI *usalp, int id, SRB_HAInquiry   *ip);
+#ifdef __USED__
+static int     resetSCSIBus(SCSI *usalp);
+#endif
+static int     scsiabort(SCSI *usalp, SRB_ExecSCSICmd *sp);
+
+
+/* SPTI Start ---------------------------------------------------------------*/
+/*
+ * From scsipt.c - Copyright (C) 1999 Jay A. Key
+ * Homepage: http://akrip.sourceforge.net/
+ * Native NT support functions via the SCSI Pass Through interface instead
+ * of ASPI.  Although based on information from the NT 4.0 DDK from
+ * Microsoft, the information has been sufficiently distilled to allow
+ * compilation w/o having the DDK installed.
+ * added to scsi-wnt.c by Richard Stemmer, rs@epost.de
+ * See http://www.ste-home.de/cdrtools-spti/
+ */
+
+#define        PREFER_SPTI     1               /* Prefer SPTI if available, else try ASPI, force ASPI with dev=ASPI: */
+/* #define     CREATE_NONSHARED 1 */   /* open CDROM-Device not SHARED if possible */
+/* #define     _DEBUG_SCSIPT 1   */
+#ifdef _DEBUG_SCSIPT
+FILE *usalp_errfile; /* File for SPTI-Debug-Messages */
+#endif
+
+#define        SENSE_LEN_SPTI          32      /* Sense length for ASPI is only 14 */
+#define        NUM_MAX_NTSCSI_DRIVES   26      /* a: ... z:                    */
+#define        NUM_FLOPPY_DRIVES       2
+#define        NUM_MAX_NTSCSI_HA       NUM_MAX_NTSCSI_DRIVES
+
+#define        NTSCSI_HA_INQUIRY_SIZE  36
+
+#define        SCSI_CMD_INQUIRY        0x12
+
+typedef struct {
+       BYTE    ha;                     /* SCSI Bus #                   */
+       BYTE    tgt;                    /* SCSI Target #                */
+       BYTE    lun;                    /* SCSI Lun #                   */
+       BYTE    PortNumber;             /* SCSI Card # (\\.\SCSI%d)     */
+       BYTE    PathId;                 /* SCSI Bus/Channel # on card n */
+       BYTE    driveLetter;            /* Win32 drive letter (e.g. c:) */
+       BOOL    bUsed;                  /* Win32 drive letter is used   */
+       HANDLE  hDevice;                /* Win32 handle for ioctl()     */
+       BYTE    inqData[NTSCSI_HA_INQUIRY_SIZE];
+} DRIVE;
+
+typedef struct {
+       BYTE    numAdapters;
+       DRIVE   drive[NUM_MAX_NTSCSI_DRIVES];
+} SPTIGLOBAL;
+
+static int     InitSCSIPT(SCSI *usalp);
+static int     DeinitSCSIPT(void);
+static void    GetDriveInformation(BYTE i, DRIVE *pDrive);
+static BYTE    SPTIGetNumAdapters(void);
+static BYTE    SPTIGetDeviceIndex(BYTE ha, BYTE tgt, BYTE lun);
+static DWORD   SPTIHandleHaInquiry(LPSRB_HAInquiry lpsrb);
+static DWORD   SPTIExecSCSICommand(LPSRB_ExecSCSICmd lpsrb, int sptTimeOutValue, BOOL bBeenHereBefore);
+static HANDLE  GetFileHandle(BYTE i, BOOL openshared);
+
+static BOOL    bSCSIPTInit = FALSE;
+static SPTIGLOBAL sptiglobal;
+static BOOL    UsingSPTI = FALSE;
+static BOOL    ForceAccess = FALSE;
+static int     sptihamax;
+static USHORT  sptihasortarr[NUM_MAX_NTSCSI_HA];
+
+/*
+ * Initialization of SCSI Pass Through Interface code.  Responsible for
+ * setting up the array of SCSI devices.  This code will be a little
+ * different from the normal code -- it will query each drive letter from
+ * C: through Z: to see if it is  a CD.  When we identify a CD, we then
+ * send CDB with the INQUIRY command to it -- NT will automagically fill in
+ * the PathId, TargetId, and Lun for us.
+ */
+static int InitSCSIPT(SCSI *usalp) {
+       BYTE    i;
+       BYTE    j;
+       char    buf[4];
+       UINT    uDriveType;
+       int     retVal = 0;
+       USHORT hasortval;
+       char adapter_name[20];
+       HANDLE  fh;
+       ULONG   returned;
+       BOOL    status;
+       char    InquiryBuffer[2048];
+       PSCSI_ADAPTER_BUS_INFO  ai;
+       BYTE    bus;
+       int     id_wanted=-1;
+
+       if (bSCSIPTInit)
+               return (0);
+
+       /*
+        * Detect all Busses on all SCSI-Adapters
+        * Fill up map array that allows us to later assign devices to
+        * bus numbers.
+        */
+       sptihamax = 0;
+       i = 0;
+       do {
+               snprintf(adapter_name, sizeof (adapter_name), "\\\\.\\SCSI%d:", i);
+               fh = CreateFile(adapter_name, GENERIC_READ | GENERIC_WRITE,
+                                               FILE_SHARE_READ | FILE_SHARE_WRITE,
+                                               NULL,
+                                               OPEN_EXISTING, 0, NULL);
+               if (fh != INVALID_HANDLE_VALUE) {
+                       status  = DeviceIoControl(fh,
+                                               IOCTL_SCSI_GET_INQUIRY_DATA,
+                                               NULL,
+                                               0,
+                                               InquiryBuffer,
+                                               2048,
+                                               &returned,
+                                               FALSE);
+                       if (status) {
+                               ai = (PSCSI_ADAPTER_BUS_INFO) InquiryBuffer;
+                               for (bus = 0; bus < ai->NumberOfBusses; bus++) {
+                                       sptihasortarr[sptihamax] = ((i<<8) | bus);
+                                       sptihamax++;
+                               }
+                       }
+                       CloseHandle(fh);
+               }
+               i++;
+       } while (fh != INVALID_HANDLE_VALUE);
+
+       errno = 0;
+       memset(&sptiglobal, 0, sizeof (SPTIGLOBAL));
+       for (i = 0; i < NUM_MAX_NTSCSI_DRIVES; i++)
+               sptiglobal.drive[i].hDevice = INVALID_HANDLE_VALUE;
+
+       for (i = NUM_FLOPPY_DRIVES; i < NUM_MAX_NTSCSI_DRIVES; i++) {
+               snprintf(buf, sizeof (buf), "%c:\\", (char)('A'+i));
+               uDriveType = GetDriveType(buf);
+#ifdef CDROM_ONLY
+               if (uDriveType == DRIVE_CDROM) {
+#else
+               if (TRUE) {
+#endif
+                       GetDriveInformation(i, &sptiglobal.drive[i]);
+
+                       if (sptiglobal.drive[i].bUsed) {
+                               retVal++;
+                               hasortval = (sptiglobal.drive[i].PortNumber<<8) | sptiglobal.drive[i].PathId;
+                               for (j = 0; j < sptihamax; j++) {
+                                       if (hasortval <= sptihasortarr[j])
+                                               break;
+                               }
+                               if (j == sptihamax) {
+                                       sptihasortarr[j] = hasortval;
+                                       sptihamax++;
+                               } else if (hasortval < sptihasortarr[j]) {
+                                       memmove(&sptihasortarr[j+1], &sptihasortarr[j], (sptihamax-j) * sizeof (USHORT));
+                                       sptihasortarr[j] = hasortval;
+                                       sptihamax++;
+                               }
+
+                               /* shortcut for device names, remember the hit */
+                               if(uDriveType==DRIVE_CDROM && usalp->local) {
+                                       /* printf("seen, %d at %d, %d, %d\n", sptiglobal.drive[i].driveLetter, sptiglobal.drive[i].ha, sptiglobal.drive[i].tgt, sptiglobal.drive[i].lun); */
+                                      if(usallocal(usalp)->drive_wanted && *buf==toupper(usallocal(usalp)->drive_wanted))
+                                              id_wanted=i;
+                                      /* don't keep the names, serial search in _natname is sufficient */
+                               }
+                       }
+               }
+       }
+               /* looks like a workaround for diverging ASPI and SPTI hostadapter numbers,
+                  most likely an attempt to keep the world of fake numbers
+                  consistent;
+                  EB */
+       if (sptihamax > 0) {
+               for (i = NUM_FLOPPY_DRIVES; i < NUM_MAX_NTSCSI_DRIVES; i++)
+                       if (sptiglobal.drive[i].bUsed)
+                               for (j = 0; j < sptihamax; j++) {
+                                       if (sptihasortarr[j] == ((sptiglobal.drive[i].PortNumber<<8) | sptiglobal.drive[i].PathId)) {
+                                               sptiglobal.drive[i].ha = j;
+                                               break;
+                                       }
+                               }
+       }
+       sptiglobal.numAdapters = SPTIGetNumAdapters();
+
+       bSCSIPTInit = TRUE;
+       if(id_wanted>0) {
+               usal_scsibus(usalp)=sptiglobal.drive[id_wanted].ha;
+               usal_target(usalp) =sptiglobal.drive[id_wanted].tgt;
+               usal_lun(usalp)    =sptiglobal.drive[id_wanted].lun;
+
+               //#if 1
+               #ifdef _DEBUG_SCSIPT
+               fprintf(stderr, "named SCSIPT drive type %d found as %c, choosing %d, %d, %d\n", 
+                               uDriveType,
+                               'A'+id_wanted, 
+                               usal_scsibus(usalp), 
+                               usal_target(usalp), 
+                               usal_lun(usalp));
+               #endif
+       }
+
+       if (retVal > 0)
+               UsingSPTI = TRUE;
+
+       return (retVal);
+}
+
+
+static int
+DeinitSCSIPT(void)
+{
+       BYTE    i;
+
+       if (!bSCSIPTInit)
+               return (0);
+
+       for (i = NUM_FLOPPY_DRIVES; i < NUM_MAX_NTSCSI_DRIVES; i++) {
+               if (sptiglobal.drive[i].bUsed) {
+                       CloseHandle(sptiglobal.drive[i].hDevice);
+               }
+       }
+
+       sptiglobal.numAdapters = SPTIGetNumAdapters();
+
+       memset(&sptiglobal, 0, sizeof (SPTIGLOBAL));
+       bSCSIPTInit = FALSE;
+       return (-1);
+}
+
+
+/*
+ * Returns the number of "adapters" present.
+ */
+static BYTE
+SPTIGetNumAdapters(void)
+{
+       BYTE    buf[256];
+       WORD    i;
+       BYTE    numAdapters = 0;
+
+       memset(buf, 0, 256);
+
+       /*
+        * PortNumber 0 should exist, so pre-mark it.  This avoids problems
+        * when the primary IDE drives are on PortNumber 0, but can't be opened
+        * because of insufficient privelege (ie. non-admin).
+        */
+       buf[0] = 1;
+       for (i = 0; i < NUM_MAX_NTSCSI_DRIVES; i++) {
+               if (sptiglobal.drive[i].bUsed)
+                       buf[sptiglobal.drive[i].ha] = 1;
+       }
+
+       for (i = 0; i <= 255; i++)
+               if (buf[i])
+                       numAdapters = (BYTE)(i + 1);
+
+/*     numAdapters++; */
+
+       return (numAdapters);
+}
+
+#include <ctype.h>
+static BOOL
+w2k_or_newer(void)
+{
+       OSVERSIONINFO osver;
+
+       memset(&osver, 0, sizeof (osver));
+       osver.dwOSVersionInfoSize = sizeof (osver);
+       GetVersionEx(&osver);
+       if (osver.dwPlatformId == VER_PLATFORM_WIN32_NT) {
+               /*
+                * Win2000 is NT-5.0, Win-XP is NT-5.1
+                */
+               if (osver.dwMajorVersion > 4)
+                       return (TRUE);
+       }
+       return (FALSE);
+}
+
+static BOOL
+w2kstyle_create(void)
+{
+       OSVERSIONINFO osver;
+
+/*     return FALSE; */
+       memset(&osver, 0, sizeof (osver));
+       osver.dwOSVersionInfoSize = sizeof (osver);
+       GetVersionEx(&osver);
+       if (osver.dwPlatformId == VER_PLATFORM_WIN32_NT) {
+               /*
+                * Win2000 is NT-5.0, Win-XP is NT-5.1
+                */
+               if (osver.dwMajorVersion > 4)
+                       return (TRUE);
+
+               if (osver.dwMajorVersion == 4) {                /* NT-4.x */
+                       char    *vers = osver.szCSDVersion;
+
+                       if (strlen(vers) == 0)
+                               return (FALSE);
+
+                       /*
+                        * Servicepack is installed, skip over non-digit part
+                        */
+                       while (*vers != '\0' && !isdigit(*vers))
+                               vers++;
+                       if (*vers == '\0')
+                               return (FALSE);
+
+                       if (isdigit(vers[0]) &&
+                           (atoi(vers) >= 4 || isdigit(vers[1])))      /* Fom Service Pack 4 */
+                               return (TRUE);                          /* same as for W2K */
+               }
+       }
+       return (FALSE);
+}
+
+
+/*
+ * Universal function to get a file handle to the CD device.  Since
+ * NT 4.0 wants just the GENERIC_READ flag, and Win2K wants both
+ * GENERIC_READ and GENERIC_WRITE (why a read-only CD device needs
+ * GENERIC_WRITE access is beyond me...), the easist workaround is to just
+ * try them both.
+ */
+static HANDLE
+GetFileHandle(BYTE i, BOOL openshared)
+{
+       char    buf[12];
+       HANDLE  fh;
+       DWORD   dwFlags = GENERIC_READ;
+       DWORD   dwAccessMode = 0;
+
+       dwAccessMode = FILE_SHARE_READ;
+       if (w2kstyle_create()) { /* if Win2K or greater, add GENERIC_WRITE */
+               dwFlags |= GENERIC_WRITE;
+               dwAccessMode |= FILE_SHARE_WRITE;
+#ifdef _DEBUG_SCSIPT
+               fprintf(usalp_errfile, "SPTI: GetFileHandle(): Setting for Win2K\n");
+#endif
+       }
+       snprintf(buf, sizeof (buf), "\\\\.\\%c:", (char)('A'+i));
+#ifdef CREATE_NONSHARED
+       if (openshared) {
+               fh = CreateFile(buf, dwFlags, dwAccessMode, NULL,
+                                               OPEN_EXISTING, 0, NULL);
+       } else {
+               fh = CreateFile(buf, dwFlags, 0, NULL,
+                                               OPEN_EXISTING, 0, NULL);
+       }
+       if (!openshared && fh == INVALID_HANDLE_VALUE && GetLastError() == ERROR_SHARING_VIOLATION)
+#endif
+               fh = CreateFile(buf, dwFlags, dwAccessMode, NULL,
+                                               OPEN_EXISTING, 0, NULL);
+       if (fh == INVALID_HANDLE_VALUE) {
+               /*
+                * it went foobar somewhere, so try it with the GENERIC_WRITE
+                * bit flipped
+                */
+               dwFlags ^= GENERIC_WRITE;
+               dwAccessMode ^= FILE_SHARE_WRITE;
+#ifdef CREATE_NONSHARED
+               if (openshared) {
+                       fh = CreateFile(buf, dwFlags, dwAccessMode, NULL,
+                                               OPEN_EXISTING, 0, NULL);
+               } else {
+                       fh = CreateFile(buf, dwFlags, 0, NULL,
+                                               OPEN_EXISTING, 0, NULL);
+               }
+               if (!openshared && fh == INVALID_HANDLE_VALUE && GetLastError() == ERROR_SHARING_VIOLATION)
+#endif
+                       fh = CreateFile(buf, dwFlags, dwAccessMode, NULL,
+                                               OPEN_EXISTING, 0, NULL);
+       }
+#ifdef _DEBUG_SCSIPT
+       if (fh == INVALID_HANDLE_VALUE)
+               fprintf(usalp_errfile, "SPTI: CreateFile() failed! -> %d\n", GetLastError());
+       else
+               fprintf(usalp_errfile, "SPTI: CreateFile() returned %d\n", GetLastError());
+#endif
+
+       return (fh);
+}
+
+
+/*
+ * fills in a pDrive structure with information from a SCSI_INQUIRY
+ * and obtains the ha:tgt:lun values via IOCTL_SCSI_GET_ADDRESS
+ */
+static void GetDriveInformation(BYTE i, DRIVE *pDrive)
+{
+       HANDLE          fh;
+       BOOL            status;
+       SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER swb;
+       SCSI_ADDRESS    scsiAddr;
+       ULONG           length;
+       ULONG           returned;
+       BYTE            inqData[NTSCSI_HA_INQUIRY_SIZE];
+
+#ifdef _DEBUG_SCSIPT
+       fprintf(usalp_errfile, "SPTI: Checking drive %c:", 'A'+i);
+#endif
+
+       fh = GetFileHandle(i, TRUE);    /* No NONSHARED Create for inquiry */
+
+       if (fh == INVALID_HANDLE_VALUE) {
+#ifdef _DEBUG_SCSIPT
+               fprintf(usalp_errfile, "       : fh == INVALID_HANDLE_VALUE\n");
+#endif
+               return;
+       }
+
+#ifdef _DEBUG_SCSIPT
+       fprintf(usalp_errfile, "       : Index %d: fh == %08X\n", i, fh);
+#endif
+
+
+       /*
+        * Get the drive inquiry data
+        */
+       memset(&swb, 0, sizeof (swb));
+       memset(inqData, 0, sizeof (inqData));
+       swb.spt.Length          = sizeof (SCSI_PASS_THROUGH_DIRECT);
+       swb.spt.CdbLength       = 6;
+       swb.spt.SenseInfoLength = 24;
+       swb.spt.DataIn          = SCSI_IOCTL_DATA_IN;
+       swb.spt.DataTransferLength = 100;
+       swb.spt.TimeOutValue    = 2;
+       swb.spt.DataBuffer      = inqData;
+       swb.spt.SenseInfoOffset = offsetof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER, ucSenseBuf);
+       swb.spt.Cdb[0]          = SCSI_CMD_INQUIRY;
+       swb.spt.Cdb[4]          = NTSCSI_HA_INQUIRY_SIZE;
+
+       length = sizeof (SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER);
+       status = DeviceIoControl(fh,
+                           IOCTL_SCSI_PASS_THROUGH_DIRECT,
+                           &swb,
+                           sizeof (swb),
+                           &swb,
+                           sizeof (swb),
+                           &returned,
+                           NULL);
+
+       if (!status) {
+               CloseHandle(fh);
+#ifdef _DEBUG_SCSIPT
+               fprintf(usalp_errfile, "SPTI: Error DeviceIoControl() -> %d\n", GetLastError());
+#endif
+               return;
+       }
+
+       memcpy(pDrive->inqData, inqData, NTSCSI_HA_INQUIRY_SIZE);
+
+       /*
+        * get the address (path/tgt/lun) of the drive via IOCTL_SCSI_GET_ADDRESS
+        */
+       memset(&scsiAddr, 0, sizeof (SCSI_ADDRESS));
+       scsiAddr.Length = sizeof (SCSI_ADDRESS);
+       if (DeviceIoControl(fh, IOCTL_SCSI_GET_ADDRESS, NULL, 0,
+                       &scsiAddr, sizeof (SCSI_ADDRESS), &returned,
+                       NULL)) {
+#ifdef _DEBUG_SCSIPT
+               fprintf(usalp_errfile, "Device %c: Port=%d, PathId=%d, TargetId=%d, Lun=%d\n",
+                       (char)i+'A', scsiAddr.PortNumber, scsiAddr.PathId,
+                       scsiAddr.TargetId, scsiAddr.Lun);
+#endif
+               pDrive->bUsed           = TRUE;
+               pDrive->ha              = scsiAddr.PortNumber; /* preliminary */
+               pDrive->PortNumber      = scsiAddr.PortNumber;
+               pDrive->PathId          = scsiAddr.PathId;
+               pDrive->tgt             = scsiAddr.TargetId;
+               pDrive->lun             = scsiAddr.Lun;
+               pDrive->driveLetter     = i;
+               pDrive->hDevice         = INVALID_HANDLE_VALUE;
+
+       } else if (GetLastError() == 50) { /* support USB/FIREWIRE devices where this call is not supported assign drive letter as device ID */
+               pDrive->bUsed = TRUE;
+               pDrive->ha = i;
+               pDrive->PortNumber = i+64; /* hopefully no conflict with other PortNumber */
+               pDrive->PathId  = 0;
+               pDrive->tgt = 0;
+               pDrive->lun = 0;
+               pDrive->driveLetter = i;
+               pDrive->hDevice = INVALID_HANDLE_VALUE;
+#ifdef _DEBUG_SCSIPT
+               fprintf(usalp_errfile, "USB/Firewire Device %c: Port=%d, TargetId=%d, Lun=%d\n", (char)i+'A', i, 0, 0);
+#endif
+       } else {
+               pDrive->bUsed   = FALSE;
+#ifdef _DEBUG_SCSIPT
+               fprintf(usalp_errfile, "SPTI: Device %s: Error DeviceIoControl(): %d\n", (char)i+'A', GetLastError());
+#endif
+               CloseHandle(fh);
+               return;
+       }
+#ifdef _DEBUG_SCSIPT
+       fprintf(usalp_errfile,  "SPTI: Adding drive %c: (%d:%d:%d)\n", 'A'+i,
+                                       pDrive->ha, pDrive->tgt, pDrive->lun);
+#endif
+       CloseHandle(fh);
+}
+
+
+
+static DWORD
+SPTIHandleHaInquiry(LPSRB_HAInquiry lpsrb)
+{
+       DWORD   *pMTL;
+
+       lpsrb->HA_Count    = sptiglobal.numAdapters;
+       if (lpsrb->SRB_HaId >= sptiglobal.numAdapters) {
+               lpsrb->SRB_Status = SS_INVALID_HA;
+               return (SS_INVALID_HA);
+       }
+       lpsrb->HA_SCSI_ID  = 7;                 /* who cares... we're not really an ASPI manager */
+       memcpy(lpsrb->HA_ManagerId,  "AKASPI v0.000001", 16);
+       memcpy(lpsrb->HA_Identifier, "SCSI Adapter    ", 16);
+       lpsrb->HA_Identifier[13] = (char)('0'+lpsrb->SRB_HaId);
+       memset(lpsrb->HA_Unique, 0, 16);
+       lpsrb->HA_Unique[3] = 8;
+       pMTL = (LPDWORD)&lpsrb->HA_Unique[4];
+       *pMTL = 64 * 1024;
+
+       lpsrb->SRB_Status = SS_COMP;
+       return (SS_COMP);
+}
+
+/*
+ * Looks up the index in the drive array for a given ha:tgt:lun triple
+ */
+static BYTE
+SPTIGetDeviceIndex(BYTE ha, BYTE tgt, BYTE lun)
+{
+       BYTE    i;
+
+#ifdef _DEBUG_SCSIPT
+       fprintf(usalp_errfile,  "SPTI: SPTIGetDeviceIndex, %d, %d, %d\n", ha,
+                       tgt, lun);
+#endif
+
+       for (i = NUM_FLOPPY_DRIVES; i < NUM_MAX_NTSCSI_DRIVES; i++) {
+               if (sptiglobal.drive[i].bUsed) {
+                       DRIVE   *lpd;
+
+                       lpd = &sptiglobal.drive[i];
+                       if ((lpd->ha == ha) && (lpd->tgt == tgt) && (lpd->lun == lun))
+                               return (i);
+               }
+       }
+
+       return (0);
+}
+
+/*
+ * Converts ASPI-style SRB to SCSI Pass Through IOCTL
+ */
+
+static DWORD
+SPTIExecSCSICommand(LPSRB_ExecSCSICmd lpsrb, int sptTimeOutValue, BOOL bBeenHereBefore)
+{
+       BOOL    status;
+       SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER swb;
+       ULONG   length;
+       ULONG   returned;
+       BYTE    idx;
+       BYTE    j;
+
+       idx = SPTIGetDeviceIndex(lpsrb->SRB_HaId, lpsrb->SRB_Target, lpsrb->SRB_Lun);
+
+       if (idx == 0) {
+               lpsrb->SRB_Status = SS_NO_DEVICE;
+               return (SS_NO_DEVICE);
+       }
+
+       if (lpsrb->CDBByte[0] == SCSI_CMD_INQUIRY) {
+               lpsrb->SRB_Status = SS_COMP;
+               memcpy(lpsrb->SRB_BufPointer, sptiglobal.drive[idx].inqData, NTSCSI_HA_INQUIRY_SIZE);
+               return (SS_COMP);
+       }
+
+       if (sptiglobal.drive[idx].hDevice == INVALID_HANDLE_VALUE)
+               sptiglobal.drive[idx].hDevice = GetFileHandle(sptiglobal.drive[idx].driveLetter, FALSE);
+
+       memset(&swb, 0, sizeof (swb));
+       swb.spt.Length          = sizeof (SCSI_PASS_THROUGH);
+       swb.spt.CdbLength       = lpsrb->SRB_CDBLen;
+       if (lpsrb->SRB_Flags & SRB_DIR_IN)
+               swb.spt.DataIn  = SCSI_IOCTL_DATA_IN;
+       else if (lpsrb->SRB_Flags & SRB_DIR_OUT)
+               swb.spt.DataIn  = SCSI_IOCTL_DATA_OUT;
+       else
+               swb.spt.DataIn  = SCSI_IOCTL_DATA_UNSPECIFIED;
+       swb.spt.DataTransferLength = lpsrb->SRB_BufLen;
+       swb.spt.TimeOutValue    = sptTimeOutValue;
+       swb.spt.SenseInfoLength = lpsrb->SRB_SenseLen;
+       swb.spt.DataBuffer      = lpsrb->SRB_BufPointer;
+       swb.spt.SenseInfoOffset =  offsetof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER, ucSenseBuf);
+       memcpy(swb.spt.Cdb, lpsrb->CDBByte, lpsrb->SRB_CDBLen);
+       length = sizeof (swb);
+
+#ifdef _DEBUG_SCSIPT
+       fprintf(usalp_errfile, "SPTI: SPTIExecSCSICmd: calling DeviceIoControl()");
+       fprintf(usalp_errfile, "       : cmd == 0x%02X", swb.spt.Cdb[0]);
+#endif
+       status = DeviceIoControl(sptiglobal.drive[idx].hDevice,
+                           IOCTL_SCSI_PASS_THROUGH_DIRECT,
+                           &swb,
+                           length,
+                           &swb,
+                           length,
+                           &returned,
+                           NULL);
+
+       lpsrb->SRB_SenseLen = swb.spt.SenseInfoLength;
+       memcpy(lpsrb->SenseArea, swb.ucSenseBuf, lpsrb->SRB_SenseLen);
+       if (status && swb.spt.ScsiStatus == 0) {
+               lpsrb->SRB_Status = SS_COMP;
+#ifdef _DEBUG_SCSIPT
+               fprintf(usalp_errfile, "       : SRB_Status == SS_COMP\n");
+#endif
+       } else {
+               DWORD   dwErrCode;
+
+               lpsrb->SRB_Status = SS_ERR;
+/*             lpsrb->SRB_TargStat =  0x0004;*/
+               lpsrb->SRB_TargStat =  swb.spt.ScsiStatus;
+
+               dwErrCode = GetLastError();
+#ifdef _DEBUG_SCSIPT
+               fprintf(usalp_errfile, "       : error == %d   handle == %08X\n", dwErrCode, sptiglobal.drive[idx].hDevice);
+#endif
+               /*
+                * KLUDGE ALERT! KLUDGE ALERT! KLUDGE ALERT!
+                * Whenever a disk changer switches disks, it may render the device
+                * handle invalid.  We try to catch these errors here and recover
+                * from them.
+                */
+               if (!bBeenHereBefore &&
+                       ((dwErrCode == ERROR_MEDIA_CHANGED) || (dwErrCode == ERROR_INVALID_HANDLE))) {
+                       if (dwErrCode != ERROR_INVALID_HANDLE)
+                               CloseHandle(sptiglobal.drive[idx].hDevice);
+                       GetDriveInformation(idx, &sptiglobal.drive[idx]);
+                       if (sptihamax > 0) {
+                               if (sptiglobal.drive[idx].bUsed)
+                                       for (j = 0; j < sptihamax; j++) {
+                                               if (sptihasortarr[j] ==
+                                                   ((sptiglobal.drive[idx].PortNumber << 8) | sptiglobal.drive[idx].PathId)) {
+                                                       sptiglobal.drive[idx].ha = j;
+                                                       break;
+                                               }
+                               }
+                       }
+#ifdef _DEBUG_SCSIPT
+                       fprintf(usalp_errfile, "SPTI: SPTIExecSCSICommand: Retrying after ERROR_MEDIA_CHANGED\n");
+#endif
+                       return (SPTIExecSCSICommand(lpsrb, sptTimeOutValue, TRUE));
+               }
+       }
+       return (lpsrb->SRB_Status);
+}
+/* SPTI End -----------------------------------------------------------------*/
+
+
+static void
+exit_func()
+{
+       if (!close_driver())
+               errmsgno(EX_BAD, "Cannot close Win32-ASPI-Driver.\n");
+}
+
+/*
+ * Return version information for the low level SCSI transport code.
+ * This has been introduced to make it easier to trace down problems
+ * in applications.
+ */
+static char *
+usalo_version(SCSI *usalp, int what)
+{
+       if (usalp != (SCSI *)0) {
+               switch (what) {
+
+               case SCG_VERSION:
+                       if (UsingSPTI)
+                               return (_usal_itrans_version);
+                       return (_usal_trans_version);
+               /*
+                * If you changed this source, you are not allowed to
+                * return "schily" for the SCG_AUTHOR request.
+                */
+               case SCG_AUTHOR:
+                       return (_usal_auth_cdrkit);
+               case SCG_SCCS_ID:
+                       return (__sccsid);
+               }
+       }
+       return ((char *)0);
+}
+
+static int
+usalo_help(SCSI *usalp, FILE *f)
+{
+       __usal_help(f, "ASPI", "Generic transport independent SCSI",
+               "ASPI:", "bus,target,lun", "ASPI:1,2,0", TRUE, FALSE);
+       __usal_help(f, "SPTI", "Generic SCSI for Windows NT/2000/XP",
+               "SPTI:", "bus,target,lun", "SPTI:1,2,0", TRUE, FALSE);
+       return (0);
+}
+
+static int
+usalo_open(SCSI *usalp, char *device)
+{
+       int     busno   = usal_scsibus(usalp);
+       int     tgt     = usal_target(usalp);
+       int     tlun    = usal_lun(usalp);
+
+       /*usal_local(usalp)->drive_wanted = NULL;
+       for(i=0;i<MAX_SCG*MAX_TGT*MAX_LUN;i++)
+               usallocal(usalp)->filenames[i]=NULL;
+               */
+       usalp->local = calloc(1, sizeof (struct usal_local));
+       if (usalp->local == NULL)
+               return (0);
+
+       if (busno >= MAX_SCG || tgt >= MAX_TGT || tlun >= MAX_LUN) {
+               errno = EINVAL;
+               if (usalp->errstr)
+                       snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                               "Illegal value for busno, target or lun '%d,%d,%d'",
+                               busno, tgt, tlun);
+               return (-1);
+       }
+
+       /* Explicite choice of Schilling syntax */
+       if (device != NULL && (strcmp(device, "SPTI") == 0 || strcmp(device, "ASPI") == 0))
+               goto devok;
+
+       /* use device as drive letter */
+       if ((device != NULL && *device != '\0') || (busno == -2 && tgt == -2)) {
+/*
+               errno = EINVAL;
+               if (usalp->errstr)
+                       snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
+                               "Open by 'devname' not supported on this OS");
+               return (-1);
+*/
+
+               UsingSPTI = TRUE;
+               usallocal(usalp)->drive_wanted = *device;
+
+               /* not the finest solution but prevents breaking on various
+                * places for no good reasons... */
+               usal_scsibus(usalp)=0;
+               usal_target(usalp)=0;
+               usal_lun(usalp)=0;
+               goto openbydev;
+       }
+devok:
+       if (DriverLoaded <= 0) {        /* do not change access method on open driver */
+               ForceAccess = FALSE;
+#ifdef PREFER_SPTI
+               UsingSPTI = TRUE;
+#else
+               UsingSPTI = FALSE;
+#endif
+               if (!w2k_or_newer())
+                       UsingSPTI = FALSE;
+
+               if (usalp->debug > 0) {
+                       fprintf((FILE *)usalp->errfile,
+                               "usalo_open: Prefered SCSI transport: %s\n",
+                                       UsingSPTI ? "SPTI":"ASPI");
+               }
+               if (device != NULL && strcmp(device, "SPTI") == 0) {
+                       UsingSPTI = TRUE;
+                       ForceAccess = TRUE;
+               } else if (device != NULL && strcmp(device, "ASPI") == 0) {
+                       UsingSPTI = FALSE;
+                       ForceAccess = TRUE;
+               }
+               if (device != NULL && usalp->debug > 0) {
+                       fprintf((FILE *)usalp->errfile,
+                               "usalo_open: Selected SCSI transport: %s\n",
+                                       UsingSPTI ? "SPTI":"ASPI");
+               }
+       }
+
+       /*
+        *  Check if variables are within the range
+        */
+       if (tgt >= 0 && tgt >= 0 && tlun >= 0) {
+               /*
+                * This is the non -scanbus case.
+                */
+               ;
+       } else if (tgt == -2 && tgt == -2 &&
+                   (tgt == -2 || tlun >= 0)) {
+               /*
+                * This is the dev=ASPI case.
+                */
+               ;
+       } else if (tgt != -1 || tgt != -1 || tlun != -1) {
+               errno = EINVAL;
+               return (-1);
+       }
+
+openbydev:
+       /*
+        * Try to open ASPI-Router
+        */
+       if (!open_driver(usalp))
+               return (-1);
+
+       /*
+        * More than we have ...
+        */
+       if (busno >= busses) {
+               close_driver();
+               return (-1);
+       }
+
+       /*
+        * Install Exit Function which closes the ASPI-Router
+        */
+       atexit(exit_func);
+
+       /*
+        * Success after all
+        */
+       return (1);
+}
+
+static int
+usalo_close(SCSI *usalp)
+{
+       int i;
+       /*
+       for(i=0;i<MAX_SCG*MAX_TGT*MAX_LUN;i++) {
+               if(usallocal(usalp)->filenames[i]) {
+                       free(usallocal(usalp)->filenames[i]);
+                       usallocal(usalp)->filenames[i]=NULL;
+               }
+       }
+       */
+       if(usalp->local) {
+              free(usalp->local);
+              usalp->local=NULL;
+       }
+       //printf("closing\n");
+
+       exit_func();
+       return (0);
+}
+
+static long
+usalo_maxdma(SCSI *usalp, long amt)
+{
+       return (MAX_DMA_WNT);
+}
+
+static void *
+usalo_getbuf(SCSI *usalp, long amt)
+{
+       if (usalp->debug > 0) {
+               fprintf((FILE *)usalp->errfile,
+                               "usalo_getbuf: %ld bytes\n", amt);
+       }
+       usalp->bufbase = malloc((size_t)(amt));
+       return (usalp->bufbase);
+}
+
+static void
+usalo_freebuf(SCSI *usalp)
+{
+       if (usalp->bufbase)
+               free(usalp->bufbase);
+       usalp->bufbase = NULL;
+}
+
+static __SBOOL
+usalo_havebus(SCSI *usalp, int busno)
+{
+       if (busno < 0 || busno >= busses)
+               return (FALSE);
+
+       return (TRUE);
+}
+
+static int
+usalo_fileno(SCSI *usalp, int busno, int tgt, int tlun)
+{
+       if (busno < 0 || busno >= busses ||
+           tgt < 0 || tgt >= MAX_TGT ||
+           tlun < 0 || tlun >= MAX_LUN)
+               return (-1);
+
+       /*
+        * Return fake
+        */
+       return (1);
+}
+
+
+static int
+usalo_initiator_id(SCSI *usalp)
+{
+       SRB_HAInquiry   s;
+
+       if (ha_inquiry(usalp, usal_scsibus(usalp), &s) < 0)
+               return (-1);
+       return (s.HA_SCSI_ID);
+}
+
+static int
+usalo_isatapi(SCSI *usalp)
+{
+       return (-1);    /* XXX Need to add real test */
+}
+
+
+/*
+ * XXX usalo_reset not yet tested
+ */
+static int
+usalo_reset(SCSI *usalp, int what)
+{
+
+       DWORD                   Status = 0;
+       DWORD                   EventStatus = WAIT_OBJECT_0;
+       HANDLE                  Event    = NULL;
+       SRB_BusDeviceReset      s;
+
+       if (what == SCG_RESET_NOP) {
+               if (UsingSPTI)
+                       return (-1);
+               else
+                       return (0);  /* Can ASPI really reset? */
+       }
+       if (what != SCG_RESET_BUS) {
+               errno = EINVAL;
+               return (-1);
+       }
+       if (UsingSPTI) {
+               fprintf((FILE *)usalp->errfile,
+                                       "Reset SCSI device not implemented with SPTI\n");
+               return (-1);
+       }
+
+       /*
+        * XXX Does this reset TGT or BUS ???
+        */
+       if (usalp->debug > 0) {
+               fprintf((FILE *)usalp->errfile,
+                               "Attempting to reset SCSI device\n");
+       }
+
+       /*
+        * Check if ASPI library is loaded
+        */
+       if (DriverLoaded <= 0) {
+               fprintf((FILE *)usalp->errfile,
+                               "error in usalo_reset: ASPI driver not loaded !\n");
+               return (-1);
+       }
+
+       memset(&s, 0, sizeof (s));      /* Clear SRB_BesDeviceReset structure */
+
+       Event = CreateEvent(NULL, TRUE, FALSE, NULL);
+
+       /*
+        * Set structure variables
+        */
+       s.SRB_Cmd       = SC_RESET_DEV;                 /* ASPI command code = SC_RESET_DEV     */
+       s.SRB_HaId      = usal_scsibus(usalp);          /* ASPI host adapter number             */
+       s.SRB_Flags     = SRB_EVENT_NOTIFY;             /* Flags                                */
+       s.SRB_Target    = usal_target(usalp);           /* Target's SCSI ID                     */
+       s.SRB_Lun       = usal_lun(usalp);              /* Target's LUN number                  */
+       s.SRB_PostProc  = (LPVOID)Event;                /* Post routine                         */
+
+       /*
+        * Initiate SCSI command
+        */
+       Status = pfnSendASPI32Command((LPSRB)&s);
+
+       /*
+        * Check status
+        */
+       if (Status == SS_PENDING) {
+               /*
+                * Wait till command completes
+                */
+               EventStatus = WaitForSingleObject(Event, INFINITE);
+       }
+
+
+       /**************************************************/
+       /* Reset event to non-signaled state.             */
+       /**************************************************/
+
+       if (EventStatus == WAIT_OBJECT_0) {
+               /*
+                * Clear event
+                */
+               ResetEvent(Event);
+       }
+
+       /*
+        * Close the event handle
+        */
+       CloseHandle(Event);
+
+       /*
+        * Check condition
+        */
+       if (s.SRB_Status != SS_COMP) {
+               fprintf((FILE *)usalp->errfile,
+                                       "ERROR! 0x%08X\n", s.SRB_Status);
+
+               /*
+                * Indicate that error has occured
+                */
+               return (-1);
+       }
+
+       if (usalp->debug > 0) {
+               fprintf((FILE *)usalp->errfile,
+                                       "Reset SCSI device completed\n");
+       }
+
+       /*
+        * Everything went OK
+        */
+       return (0);
+}
+
+
+#ifdef DEBUG_WNTASPI
+static void
+DebugScsiSend(SCSI *usalp, SRB_ExecSCSICmd *s, int bDisplayBuffer)
+{
+       int i;
+
+       fprintf((FILE *)usalp->errfile, "\n\nDebugScsiSend\n");
+       fprintf((FILE *)usalp->errfile, "s->SRB_Cmd          = 0x%02x\n", s->SRB_Cmd);
+       fprintf((FILE *)usalp->errfile, "s->SRB_HaId         = 0x%02x\n", s->SRB_HaId);
+       fprintf((FILE *)usalp->errfile, "s->SRB_Flags        = 0x%02x\n", s->SRB_Flags);
+       fprintf((FILE *)usalp->errfile, "s->SRB_Target       = 0x%02x\n", s->SRB_Target);
+       fprintf((FILE *)usalp->errfile, "s->SRB_Lun          = 0x%02x\n", s->SRB_Lun);
+       fprintf((FILE *)usalp->errfile, "s->SRB_BufLen       = 0x%02x\n", s->SRB_BufLen);
+       fprintf((FILE *)usalp->errfile, "s->SRB_BufPointer   = %x\n",      s->SRB_BufPointer);
+       fprintf((FILE *)usalp->errfile, "s->SRB_CDBLen       = 0x%02x\n", s->SRB_CDBLen);
+       fprintf((FILE *)usalp->errfile, "s->SRB_SenseLen     = 0x%02x\n", s->SRB_SenseLen);
+       fprintf((FILE *)usalp->errfile, "s->CDBByte          =");
+       for (i = 0; i < min(s->SRB_CDBLen, 16); i++) {
+               fprintf((FILE *)usalp->errfile, " %02X ", s->CDBByte[i]);
+       }
+       fprintf((FILE *)usalp->errfile, "\n");
+
+       /*
+       if (bDisplayBuffer != 0 && s->SRB_BufLen >= 8) {
+
+               fprintf((FILE *)usalp->errfile, "s->SRB_BufPointer   =");
+               for (i = 0; i < 8; i++) {
+                       fprintf((FILE *)usalp->errfile,
+                                       " %02X ", ((char *)s->SRB_BufPointer)[i]);
+               }
+               fprintf((FILE *)usalp->errfile, "\n");
+       }
+*/
+       fprintf((FILE *)usalp->errfile, "Debug done\n");
+}
+#endif
+
+static void
+copy_sensedata(SRB_ExecSCSICmd *cp, struct usal_cmd *sp)
+{
+       sp->sense_count = cp->SRB_SenseLen;
+       if (sp->sense_count > sp->sense_len)
+               sp->sense_count = sp->sense_len;
+
+       memset(&sp->u_sense.Sense, 0x00, sizeof (sp->u_sense.Sense));
+       memcpy(&sp->u_sense.Sense, cp->SenseArea, sp->sense_count);
+
+       sp->u_scb.cmd_scb[0] = cp->SRB_TargStat;
+}
+
+/*
+ * Set error flags
+ */
+static void
+set_error(SRB_ExecSCSICmd *cp, struct usal_cmd *sp)
+{
+       switch (cp->SRB_Status) {
+
+       case SS_COMP:                   /* 0x01 SRB completed without error  */
+               sp->error = SCG_NO_ERROR;
+               sp->ux_errno = 0;
+               break;
+
+       case SS_ERR:                    /* 0x04 SRB completed with error    */
+               /*
+                * If the SCSI Status byte is != 0, we definitely could send
+                * the command to the target. We signal NO transport error.
+                */
+               sp->error = SCG_NO_ERROR;
+               sp->ux_errno = EIO;
+               if (cp->SRB_TargStat)
+                       break;
+
+       case SS_PENDING:                /* 0x00 SRB being processed         */
+               /*
+                * XXX Could SS_PENDING happen ???
+                */
+       case SS_ABORTED:                /* 0x02 SRB aborted                 */
+       case SS_ABORT_FAIL:             /* 0x03 Unable to abort SRB         */
+       default:
+               sp->error = SCG_RETRYABLE;
+               sp->ux_errno = EIO;
+               break;
+
+       case SS_INVALID_CMD:            /* 0x80 Invalid ASPI command        */
+       case SS_INVALID_HA:             /* 0x81 Invalid host adapter number */
+       case SS_NO_DEVICE:              /* 0x82 SCSI device not installed   */
+
+       case SS_INVALID_SRB:            /* 0xE0 Invalid parameter set in SRB */
+       case SS_ILLEGAL_MODE:           /* 0xE2 Unsupported Windows mode    */
+       case SS_NO_ASPI:                /* 0xE3 No ASPI managers            */
+       case SS_FAILED_INIT:            /* 0xE4 ASPI for windows failed init */
+       case SS_MISMATCHED_COMPONENTS:  /* 0xE7 The DLLs/EXEs of ASPI don't */
+                                       /*      version check               */
+       case SS_NO_ADAPTERS:            /* 0xE8 No host adapters to manager */
+
+       case SS_ASPI_IS_SHUTDOWN:       /* 0xEA Call came to ASPI after     */
+                                       /*      PROCESS_DETACH              */
+       case SS_BAD_INSTALL:            /* 0xEB The DLL or other components */
+                                       /*      are installed wrong         */
+               sp->error = SCG_FATAL;
+               sp->ux_errno = EINVAL;
+               break;
+
+#ifdef XXX
+       case SS_OLD_MANAGER:            /* 0xE1 ASPI manager doesn't support */
+                                       /*      windows                     */
+#endif
+       case SS_BUFFER_ALIGN:           /* 0xE1 Buffer not aligned (replaces */
+                                       /*      SS_OLD_MANAGER in Win32)    */
+               sp->error = SCG_FATAL;
+               sp->ux_errno = EFAULT;
+               break;
+
+       case SS_ASPI_IS_BUSY:           /* 0xE5 No resources available to   */
+                                       /*      execute command             */
+               sp->error = SCG_RETRYABLE;
+               sp->ux_errno = EBUSY;
+               break;
+
+#ifdef XXX
+       case SS_BUFFER_TO_BIG:          /* 0xE6 Buffer size too big to handle*/
+#endif
+       case SS_BUFFER_TOO_BIG:         /* 0xE6 Correct spelling of 'too'   */
+       case SS_INSUFFICIENT_RESOURCES: /* 0xE9 Couldn't allocate resources */
+                                       /*      needed to init              */
+               sp->error = SCG_RETRYABLE;
+               sp->ux_errno = ENOMEM;
+               break;
+       }
+}
+
+
+struct aspi_cmd {
+       SRB_ExecSCSICmd         s;
+       char                    pad[32];
+};
+
+static int
+usalo_send(SCSI *usalp)
+{
+       struct usal_cmd         *sp = usalp->scmd;
+       DWORD                   Status = 0;
+       DWORD                   EventStatus = WAIT_OBJECT_0;
+       HANDLE                  Event    = NULL;
+       struct aspi_cmd         ac;
+       SRB_ExecSCSICmd         *s;
+
+       s = &ac.s;
+
+       /*
+        * Check if ASPI library is loaded
+        */
+       if (DriverLoaded <= 0) {
+               errmsgno(EX_BAD, "error in usalo_send: ASPI driver not loaded.\n");
+               sp->error = SCG_FATAL;
+               return (0);
+       }
+
+       if (usalp->fd < 0) {
+               sp->error = SCG_FATAL;
+               return (-1);
+       }
+
+       /*
+        * Initialize variables
+        */
+       sp->error               = SCG_NO_ERROR;
+       sp->sense_count         = 0;
+       sp->u_scb.cmd_scb[0]    = 0;
+       sp->resid               = 0;
+
+       memset(&ac, 0, sizeof (ac));    /* Clear SRB structure */
+
+       /*
+        * Check cbd_len > the maximum command pakket that can be handled by ASPI
+        */
+       if (sp->cdb_len > 16) {
+               sp->error = SCG_FATAL;
+               sp->ux_errno = EINVAL;
+               fprintf((FILE *)usalp->errfile,
+                       "sp->cdb_len > sizeof (SRB_ExecSCSICmd.CDBByte). Fatal error in usalo_send, exiting...\n");
+               return (-1);
+       }
+       /*
+        * copy cdrecord command into SRB
+        */
+       movebytes(&sp->cdb, &(s->CDBByte), sp->cdb_len);
+
+       Event = CreateEvent(NULL, TRUE, FALSE, NULL);
+
+       /*
+        * Fill ASPI structure
+        */
+       s->SRB_Cmd       = SC_EXEC_SCSI_CMD;            /* SCSI Command                 */
+       s->SRB_HaId      = usal_scsibus(usalp);         /* Host adapter number          */
+       s->SRB_Flags     = SRB_EVENT_NOTIFY;            /* Flags                        */
+       s->SRB_Target    = usal_target(usalp);          /* Target SCSI ID               */
+       s->SRB_Lun       = usal_lun(usalp);             /* Target SCSI LUN              */
+       s->SRB_BufLen    = sp->size;                    /* # of bytes transferred       */
+       s->SRB_BufPointer = sp->addr;                   /* pointer to data buffer       */
+       s->SRB_CDBLen    = sp->cdb_len;                 /* SCSI command length          */
+       s->SRB_PostProc  = Event;                       /* Post proc event              */
+       if (UsingSPTI)
+               s->SRB_SenseLen = SENSE_LEN_SPTI;       /* Length of sense buffer, SPTI returns SenseInfoLength */
+       else
+               s->SRB_SenseLen = SENSE_LEN;            /* fixed length 14 for ASPI */
+       /*
+        * Do we receive data from this ASPI command?
+        */
+       if (sp->flags & SCG_RECV_DATA) {
+
+               s->SRB_Flags |= SRB_DIR_IN;
+       } else {
+               /*
+                * Set direction to output
+                */
+               if (sp->size > 0) {
+                       s->SRB_Flags |= SRB_DIR_OUT;
+               }
+       }
+
+#ifdef DEBUG_WNTASPI
+       /*
+        * Dump some debug information when enabled
+        */
+       DebugScsiSend(usalp, s, TRUE);
+/*     DebugScsiSend(usalp, s, (s->SRB_Flags&SRB_DIR_OUT) == SRB_DIR_OUT);*/
+#endif
+
+       /*
+        * ------------ Send SCSI command --------------------------
+        */
+
+       ResetEvent(Event);                      /* Clear event handle       */
+       if (UsingSPTI) {
+#ifdef _DEBUG_SCSIPT
+               usalp_errfile = (FILE *)usalp->errfile;
+#endif
+               Status = SPTIExecSCSICommand(s, sp->timeout, FALSE);
+       }
+       else
+               Status = pfnSendASPI32Command((LPSRB)s); /* Initiate SCSI command */
+       if (Status == SS_PENDING) {             /* If in progress           */
+               /*
+                * Wait untill command completes, or times out.
+                */
+               EventStatus = WaitForSingleObject(Event, sp->timeout*1000L);
+/*             EventStatus = WaitForSingleObject(Event, 10L);*/
+
+               if (EventStatus == WAIT_OBJECT_0)
+                       ResetEvent(Event);      /* Clear event, time out    */
+
+               if (s->SRB_Status == SS_PENDING) { /* Check if we got a timeout */
+                       if (usalp->debug > 0) {
+                               fprintf((FILE *)usalp->errfile,
+                                               "Timeout....\n");
+                       }
+                       scsiabort(usalp, s);
+                       ResetEvent(Event);      /* Clear event, time out    */
+                       CloseHandle(Event);     /* Close the event handle   */
+
+                       sp->error = SCG_TIMEOUT;
+                       return (1);             /* Return error             */
+               }
+       }
+       CloseHandle(Event);                     /* Close the event handle   */
+
+       /*
+        * Check ASPI command status
+        */
+       if (s->SRB_Status != SS_COMP) {
+               if (usalp->debug > 0) {
+                       fprintf((FILE *)usalp->errfile,
+                               "Error in usalo_send: s->SRB_Status is 0x%x\n", s->SRB_Status);
+               }
+
+               set_error(s, sp);               /* Set error flags          */
+               copy_sensedata(s, sp);          /* Copy sense and status    */
+
+               if (usalp->debug > 0) {
+                       fprintf((FILE *)usalp->errfile,
+                               "Mapped to: error %d errno: %d\n", sp->error, sp->ux_errno);
+               }
+               return (1);
+       }
+
+       /*
+        * Return success
+        */
+       return (0);
+}
+
+/***************************************************************************
+ *                                                                        *
+ *  BOOL open_driver()                                                    *
+ *                                                                        *
+ *  Opens the ASPI Router device driver and sets device_handle.                   *
+ *  Returns:                                                              *
+ *    TRUE - Success                                                      *
+ *    FALSE - Unsuccessful opening of device driver                       *
+ *                                                                        *
+ *  Preconditions: ASPI Router driver has be loaded                       *
+ *                                                                        *
+ ***************************************************************************/
+static BOOL
+open_driver(SCSI *usalp)
+{
+       DWORD   astatus;
+       BYTE    HACount;
+       BYTE    ASPIStatus;
+       int     i;
+
+#ifdef DEBUG_WNTASPI
+       fprintf((FILE *)usalp->errfile, "enter open_driver\n");
+#endif
+
+       /*
+        * Check if ASPI library is already loaded yet
+        */
+       if (DriverLoaded > 0) {
+               DriverLoaded++;
+               return (TRUE);
+       }
+
+       /*
+        * Load the ASPI library or SPTI
+        */
+#ifdef _DEBUG_SCSIPT
+       usalp_errfile = (FILE *)usalp->errfile;
+#endif
+#ifdef PREFER_SPTI
+       if (UsingSPTI)
+               if (InitSCSIPT(usalp) > 0) DriverLoaded++;
+#endif
+#ifdef PREFER_SPTI
+       if ((!UsingSPTI || !ForceAccess) && DriverLoaded <= 0) {
+#else
+       if (!UsingSPTI || !ForceAccess) {
+#endif
+               if (load_aspi(usalp)) {
+                       DriverLoaded++;
+                       UsingSPTI = FALSE;
+               }
+       }
+
+#ifndef        PREFER_SPTI
+       if ((UsingSPTI || !ForceAccess) && DriverLoaded <= 0)
+               if (InitSCSIPT(usalp) > 0)
+                       DriverLoaded++;
+#endif /*PREFER_SPTI*/
+
+       if (DriverLoaded <= 0) {
+               if (UsingSPTI) {
+                       if (errno == 0)
+                               errno = ENOSYS;
+               }
+               fprintf((FILE *)usalp->errfile, "Can not load %s driver! ",
+                                               UsingSPTI ? "SPTI":"ASPI");
+               return (FALSE);
+       }
+
+       if (UsingSPTI) {
+               if (usalp->debug > 0)
+                       fprintf((FILE *)usalp->errfile, "using SPTI Transport\n");
+
+               if (!sptiglobal.numAdapters)
+                       astatus = (DWORD)(MAKEWORD(0, SS_NO_ADAPTERS));
+               else
+                       astatus = (DWORD)(MAKEWORD(sptiglobal.numAdapters, SS_COMP));
+       } else {
+               astatus = pfnGetASPI32SupportInfo();
+       }
+
+       ASPIStatus = HIBYTE(LOWORD(astatus));
+       HACount    = LOBYTE(LOWORD(astatus));
+
+       if (usalp->debug > 0) {
+               fprintf((FILE *)usalp->errfile,
+                       "open_driver %lX HostASPIStatus=0x%x HACount=0x%x\n", astatus, ASPIStatus, HACount);
+       }
+
+       if (ASPIStatus != SS_COMP && ASPIStatus != SS_NO_ADAPTERS) {
+               fprintf((FILE *)usalp->errfile, "Could not find any host adapters\n");
+               fprintf((FILE *)usalp->errfile, "ASPIStatus == 0x%02X", ASPIStatus);
+               return (FALSE);
+       }
+       busses = HACount;
+
+#ifdef DEBUG_WNTASPI
+       fprintf((FILE *)usalp->errfile, "open_driver HostASPIStatus=0x%x HACount=0x%x\n", ASPIStatus, HACount);
+       fprintf((FILE *)usalp->errfile, "leaving open_driver\n");
+#endif
+
+       for (i = 0; i < busses; i++) {
+               SRB_HAInquiry   s;
+
+               ha_inquiry(usalp, i, &s);
+       }
+
+       /*
+        * Indicate that library loaded/initialized properly
+        */
+       return (TRUE);
+}
+
+static BOOL
+load_aspi(SCSI *usalp)
+{
+#ifdef __CYGWIN32__
+       hAspiLib = dlopen("WNASPI32", RTLD_NOW);
+#else
+       hAspiLib = LoadLibrary("WNASPI32");
+#endif
+       /*
+        * Check if ASPI library is loaded correctly
+        */
+       if (hAspiLib == NULL) {
+#ifdef not_done_later
+               fprintf((FILE *)usalp->errfile, "Can not load ASPI driver! ");
+#endif
+               return (FALSE);
+       }
+
+       /*
+        * Get a pointer to GetASPI32SupportInfo function
+        * and a pointer to SendASPI32Command function
+        */
+#ifdef __CYGWIN32__
+       pfnGetASPI32SupportInfo = (DWORD(*)(void))dlsym(hAspiLib, "GetASPI32SupportInfo");
+       pfnSendASPI32Command = (DWORD(*)(LPSRB))dlsym(hAspiLib, "SendASPI32Command");
+#else
+       pfnGetASPI32SupportInfo = (DWORD(*)(void))GetProcAddress(hAspiLib, "GetASPI32SupportInfo");
+       pfnSendASPI32Command = (DWORD(*)(LPSRB))GetProcAddress(hAspiLib, "SendASPI32Command");
+#endif
+
+       if ((pfnGetASPI32SupportInfo == NULL) || (pfnSendASPI32Command == NULL)) {
+               fprintf((FILE *)usalp->errfile,
+                               "ASPI function not found in library! ");
+               return (FALSE);
+       }
+
+       /*
+        * The following functions are currently not used by libusal.
+        * If we start to use them, we need to check whether the founctions
+        * could be found in the ASPI library that just has been loaded.
+        */
+#ifdef __CYGWIN32__
+       pfnGetASPI32Buffer = (BOOL(*)(PASPI32BUFF))dlsym(hAspiLib, "GetASPI32Buffer");
+       pfnFreeASPI32Buffer = (BOOL(*)(PASPI32BUFF))dlsym(hAspiLib, "FreeASPI32Buffer");
+       pfnTranslateASPI32Address = (BOOL(*)(PDWORD, PDWORD))dlsym(hAspiLib, "TranslateASPI32Address");
+#else
+       pfnGetASPI32Buffer = (BOOL(*)(PASPI32BUFF))GetProcAddress(hAspiLib, "GetASPI32Buffer");
+       pfnFreeASPI32Buffer = (BOOL(*)(PASPI32BUFF))GetProcAddress(hAspiLib, "FreeASPI32Buffer");
+       pfnTranslateASPI32Address = (BOOL(*)(PDWORD, PDWORD))GetProcAddress(hAspiLib, "TranslateASPI32Address");
+#endif
+       return (TRUE);
+}
+
+/***************************************************************************
+ *                                                                        *
+ *  BOOL close_driver()                                                           *
+ *                                                                        *
+ *  Closes the device driver                                              *
+ *  Returns:                                                              *
+ *    TRUE - Success                                                      *
+ *    FALSE - Unsuccessful closing of device driver                       *
+ *                                                                        *
+ *  Preconditions: ASPI Router driver has be opened with open_driver      *
+ *                                                                        *
+ ***************************************************************************/
+static BOOL
+close_driver()
+{
+       if (--DriverLoaded > 0)
+               return (TRUE);
+       /*
+        * If library is loaded
+        */
+       DeinitSCSIPT();
+       /*
+        * Clear all variables
+        */
+       if (hAspiLib) {
+               pfnGetASPI32SupportInfo = NULL;
+               pfnSendASPI32Command    = NULL;
+               pfnGetASPI32Buffer      = NULL;
+               pfnFreeASPI32Buffer     = NULL;
+               pfnTranslateASPI32Address = NULL;
+
+               /*
+                * Free ASPI library, we do not need it any longer
+                */
+#ifdef __CYGWIN32__
+               dlclose(hAspiLib);
+#else
+               FreeLibrary(hAspiLib);
+#endif
+               hAspiLib = NULL;
+       }
+
+       /*
+        * Indicate that shutdown has been finished properly
+        */
+       return (TRUE);
+}
+
+static int
+ha_inquiry(SCSI *usalp, int id, SRB_HAInquiry *ip)
+{
+       DWORD           Status;
+
+       ip->SRB_Cmd      = SC_HA_INQUIRY;
+       ip->SRB_HaId     = id;
+       ip->SRB_Flags    = 0;
+       ip->SRB_Hdr_Rsvd = 0;
+
+       if (UsingSPTI)
+               Status = SPTIHandleHaInquiry(ip);
+       else
+               Status = pfnSendASPI32Command((LPSRB)ip);
+
+       if (usalp->debug > 0) {
+               fprintf((FILE *)usalp->errfile, "Status : %ld\n",       Status);
+               fprintf((FILE *)usalp->errfile, "hacount: %d\n", ip->HA_Count);
+               fprintf((FILE *)usalp->errfile, "SCSI id: %d\n", ip->HA_SCSI_ID);
+               fprintf((FILE *)usalp->errfile, "Manager: '%.16s'\n", ip->HA_ManagerId);
+               fprintf((FILE *)usalp->errfile, "Identif: '%.16s'\n", ip->HA_Identifier);
+               usal_prbytes("Unique:", ip->HA_Unique, 16);
+       }
+       if (ip->SRB_Status != SS_COMP)
+               return (-1);
+       return (0);
+}
+
+#ifdef __USED__
+static int
+resetSCSIBus(SCSI *usalp)
+{
+       DWORD                   Status;
+       HANDLE                  Event;
+       SRB_BusDeviceReset      s;
+
+       if (UsingSPTI) {
+               fprintf((FILE *)usalp->errfile,
+                                       "Reset SCSI bus not implemented with SPTI\n");
+               return (FALSE);
+       }
+
+       fprintf((FILE *)usalp->errfile, "Attempting to reset SCSI bus\n");
+
+       Event = CreateEvent(NULL, TRUE, FALSE, NULL);
+
+       memset(&s, 0, sizeof (s));      /* Clear SRB_BesDeviceReset structure */
+
+       /*
+        * Set structure variables
+        */
+       s.SRB_Cmd = SC_RESET_DEV;
+       s.SRB_PostProc = (LPVOID)Event;
+
+       /*
+        * Clear event
+        */
+       ResetEvent(Event);
+
+       /*
+        * Initiate SCSI command
+        */
+       Status = pfnSendASPI32Command((LPSRB)&s);
+
+       /*
+        * Check status
+        */
+       if (Status == SS_PENDING) {
+               /*
+                * Wait till command completes
+                */
+               WaitForSingleObject(Event, INFINITE);
+       }
+
+       /*
+        * Close the event handle
+        */
+       CloseHandle(Event);
+
+       /*
+        * Check condition
+        */
+       if (s.SRB_Status != SS_COMP) {
+               fprintf((FILE *)usalp->errfile, "ERROR  0x%08X\n", s.SRB_Status);
+
+               /*
+                * Indicate that error has occured
+                */
+               return (FALSE);
+       }
+
+       /*
+        * Everything went OK
+        */
+       return (TRUE);
+}
+#endif /* __USED__ */
+
+static int
+scsiabort(SCSI *usalp, SRB_ExecSCSICmd *sp)
+{
+       DWORD                   Status = 0;
+       SRB_Abort               s;
+
+       if (UsingSPTI) {
+               fprintf((FILE *)usalp->errfile,
+                                       "Abort SCSI not implemented with SPTI\n");
+               return (FALSE);
+       }
+
+       if (usalp->debug > 0) {
+               fprintf((FILE *)usalp->errfile,
+                               "Attempting to abort SCSI command\n");
+       }
+
+       /*
+        * Check if ASPI library is loaded
+        */
+       if (DriverLoaded <= 0) {
+               fprintf((FILE *)usalp->errfile,
+                               "error in scsiabort: ASPI driver not loaded !\n");
+               return (FALSE);
+       }
+
+       /*
+        * Set structure variables
+        */
+       s.SRB_Cmd       = SC_ABORT_SRB;                 /* ASPI command code = SC_ABORT_SRB     */
+       s.SRB_HaId      = usal_scsibus(usalp);          /* ASPI host adapter number             */
+       s.SRB_Flags     = 0;                            /* Flags                                */
+       s.SRB_ToAbort   = (LPSRB)&sp;                   /* sp                                   */
+
+       /*
+        * Initiate SCSI abort
+        */
+       Status = pfnSendASPI32Command((LPSRB)&s);
+
+       /*
+        * Check condition
+        */
+       if (s.SRB_Status != SS_COMP) {
+               fprintf((FILE *)usalp->errfile, "Abort ERROR! 0x%08X\n", s.SRB_Status);
+
+               /*
+                * Indicate that error has occured
+                */
+               return (FALSE);
+       }
+
+       if (usalp->debug > 0)
+               fprintf((FILE *)usalp->errfile, "Abort SCSI command completed\n");
+
+       /*
+        * Everything went OK
+        */
+       return (TRUE);
+}
+
+
+#define HAVE_NAT_NAMES
+static char * usalo_natname(SCSI *usalp, int busno, int tgt, int tlun) {
+       int i;
+       static char name[3];
+       printf("hm, %d, %d, %d\n", busno, tgt, tlun);
+       if (busno >= MAX_SCG || tgt >= MAX_TGT || tlun >= MAX_LUN)
+               return "BADID";
+       for (i = NUM_FLOPPY_DRIVES; i < NUM_MAX_NTSCSI_DRIVES; i++) {
+               if(sptiglobal.drive[i].bUsed &&
+                               tlun == sptiglobal.drive[i].lun &&
+                               tgt == sptiglobal.drive[i].tgt && 
+                               busno == sptiglobal.drive[i].ha)
+               {
+                       snprintf(name, 3, "%c:", 'A'+sptiglobal.drive[i].driveLetter);
+                       return name;
+               }
+       }
+       return "BADID";
+}
+
diff --git a/libusal/scsierrs.c b/libusal/scsierrs.c
new file mode 100644 (file)
index 0000000..154e418
--- /dev/null
@@ -0,0 +1,1008 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)scsierrs.c      2.29 04/06/17 Copyright 1987-1996 J. Schilling */
+/*
+ *     Error printing for scsitransp.c
+ *
+ *     Copyright (c) 1987-1996 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <mconfig.h>
+
+#include <stdio.h>
+#include <unixstd.h>   /* for sys/types.h needed in schily.h for sprintf() */
+#include <standard.h>
+#include <schily.h>
+
+#include <usal/scsireg.h>
+#include <usal/scsidefs.h>
+#include <usal/usalcmd.h>      /*XXX JS wird eigentlich nicht benoetigt!!      */
+                       /*XXX JS kommt weg, wenn struct sense und status */
+                       /*XXX JS von usalio.h nach scsireg.h kommen     */
+#include <usal/scsitransp.h>
+
+#define        CTYPE_CCS       0
+#define        CTYPE_MD21      1
+#define        CTYPE_ACB4000   2
+#define        CTYPE_SMO_C501  3
+
+#define        SMO_C501
+
+const char     *usal_sensemsg(int, int, int, const char **, char *, int maxcnt);
+int usal__errmsg(SCSI *usalp, char *obuf, int maxcnt, struct scsi_sense *, 
+                                        struct scsi_status *, int);
+#if 0
+/*
+ * Map old non extended sense to sense key.
+ */
+static Uchar sd_adaptec_keys[] = {
+       0, 4, 4, 4,  2, 2, 4, 4,                /* 0x00-0x07 */
+       4, 4, 4, 4,  4, 4, 4, 4,                /* 0x08-0x0f */
+       4, 3, 3, 3,  3, 4, 3, 1,                /* 0x10-0x17 */
+       1, 1, 3, 4,  3, 4, 3, 3,                /* 0x18-0x1f */
+       5, 5, 5, 5,  5, 5, 5, 7,                /* 0x20-0x27 */
+       6, 6, 6, 5,  4,11,11,11                 /* 0x28-0x2f */
+};
+#define        MAX_ADAPTEC_KEYS (sizeof (sd_adaptec_keys))
+#endif
+
+/*
+ * Deviations to CCS found on old pre CCS devices
+ */
+static const char *sd_adaptec_error_str[] = {
+       "\031\000ECC error during verify",              /* 0x19 */
+       "\032\000interleave error",                     /* 0x1a */
+       "\034\000bad format on drive",                  /* 0x1c */
+       "\035\000self test failed",                     /* 0x1d */
+       "\036\000defective track",                      /* 0x1e */
+       "\043\000volume overflow",                      /* 0x23 */
+       "\053\000set limit violation",                  /* 0x2b */
+       "\054\000error counter overflow",               /* 0x2c */
+       "\055\000initiator detected error",             /* 0x2d */
+       "\056\000scsi parity error",                    /* 0x2e */
+       "\057\000adapter parity error",                 /* 0x2f */
+       NULL
+};
+
+/*
+ * The sense codes of SCSI-1/CCS, SCSI-2 and SCSI-3 devices.
+ */
+static const char *sd_ccs_error_str[] = {
+       "\000\000no additional sense information",              /* 00 00 */
+       "\000\001filemark detected",                            /* 00 01 */
+       "\000\002end-of-partition/medium detected",             /* 00 02 */
+       "\000\003setmark detected",                             /* 00 03 */
+       "\000\004beginning-of-partition/medium detected",       /* 00 04 */
+       "\000\005end-of-data detected",                         /* 00 05 */
+       "\000\006i/o process terminated",                       /* 00 06 */
+       "\000\021audio play operation in progress",             /* 00 11 */
+       "\000\022audio play operation paused",                  /* 00 12 */
+       "\000\023audio play operation successfully completed",  /* 00 13 */
+       "\000\024audio play operation stopped due to error",    /* 00 14 */
+       "\000\025no current audio status to return",            /* 00 15 */
+       "\000\026operation in progress",                        /* 00 16 */
+       "\000\027cleaning requested",                           /* 00 17 */
+       "\001\000no index/sector signal",                       /* 01 00 */
+       "\002\000no seek complete",                             /* 02 00 */
+       "\003\000peripheral device write fault",                /* 03 00 */
+       "\003\001no write current",                             /* 03 01 */
+       "\003\002excessive write errors",                       /* 03 02 */
+       "\004\000logical unit not ready, cause not reportable", /* 04 00 */
+       "\004\001logical unit is in process of becoming ready", /* 04 01 */
+       "\004\002logical unit not ready, initializing cmd. required",   /* 04 02 */
+       "\004\003logical unit not ready, manual intervention required", /* 04 03 */
+       "\004\004logical unit not ready, format in progress",   /* 04 04 */
+       "\004\005logical unit not ready, rebuild in progress",  /* 04 05 */
+       "\004\006logical unit not ready, recalculation in progress",    /* 04 06 */
+       "\004\007logical unit not ready, operation in progress",/* 04 07 */
+       "\004\010logical unit not ready, long write in progress",       /* 04 08 */
+       "\004\011logical unit not ready, self-test in progress",/* 04 09 */
+       "\004\012asymmetric access code 3 (00-232) [proposed]", /* 04 0A */
+       "\004\013asymmetric access code 1 (00-232) [proposed]", /* 04 0B */
+       "\004\014asymmetric access code 2 (00-232) [proposed]", /* 04 0C */
+       "\004\020auxiliary memory code 2 (99-148) [proposed]",  /* 04 10 */
+       "\005\000logical unit does not respond to selection",   /* 05 00 */
+       "\006\000no reference position found",                  /* 06 00 */
+       "\007\000multiple peripheral devices selected",         /* 07 00 */
+       "\010\000logical unit communication failure",           /* 08 00 */
+       "\010\001logical unit communication time-out",          /* 08 01 */
+       "\010\002logical unit communication parity error",      /* 08 02 */
+       "\010\003logical unit communication crc error (ultra-dma/32)",  /* 08 03 */
+       "\010\004unreachable copy target",                      /* 08 04 */
+       "\011\000track following error",                        /* 09 00 */
+       "\011\001tracking servo failure",                       /* 09 01 */
+       "\011\002focus servo failure",                          /* 09 02 */
+       "\011\003spindle servo failure",                        /* 09 03 */
+       "\011\004head select fault",                            /* 09 04 */
+       "\012\000error log overflow",                           /* 0A 00 */
+       "\013\000warning",                                      /* 0B 00 */
+       "\013\001warning - specified temperature exceeded",     /* 0B 01 */
+       "\013\002warning - enclosure degraded",                 /* 0B 02 */
+       "\014\000write error",                                  /* 0C 00 */
+       "\014\001write error - recovered with auto reallocation",       /* 0C 01 */
+       "\014\002write error - auto reallocation failed",       /* 0C 02 */
+       "\014\003write error - recommend reassignment",         /* 0C 03 */
+       "\014\004compression check miscompare error",           /* 0C 04 */
+       "\014\005data expansion occurred during compression",   /* 0C 05 */
+       "\014\006block not compressible",                       /* 0C 06 */
+       "\014\007write error - recovery needed",                /* 0C 07 */
+       "\014\010write error - recovery failed",                /* 0C 08 */
+       "\014\011write error - loss of streaming",              /* 0C 09 */
+       "\014\012write error - padding blocks added",           /* 0C 0A */
+       "\014\013auxiliary memory code 4 (99-148) [proposed]",  /* 0C 0B */
+       "\015\000error detected by third party temporary initiator",    /* 0D 00 */
+       "\015\001third party device failure",                   /* 0D 01 */
+       "\015\002copy target device not reachable",             /* 0D 02 */
+       "\015\003incorrect copy target device type",            /* 0D 03 */
+       "\015\004copy target device data underrun",             /* 0D 04 */
+       "\015\005copy target device data overrun",              /* 0D 05 */
+#ifdef __used__
+       "\016\000",                                             /* 0E 00 */
+       "\017\000",                                             /* 0F 00 */
+#endif
+       "\020\000id crc or ecc error",                          /* 10 00 */
+       "\021\000unrecovered read error",                       /* 11 00 */
+       "\021\001read retries exhausted",                       /* 11 01 */
+       "\021\002error too long to correct",                    /* 11 02 */
+       "\021\003multiple read errors",                         /* 11 03 */
+       "\021\004unrecovered read error - auto reallocate failed",      /* 11 04 */
+       "\021\005l-ec uncorrectable error",                     /* 11 05 */
+       "\021\006circ unrecovered error",                       /* 11 06 */
+       "\021\007data re-synchronization error",                /* 11 07 */
+       "\021\010incomplete block read",                        /* 11 08 */
+       "\021\011no gap found",                                 /* 11 09 */
+       "\021\012miscorrected error",                           /* 11 0A */
+       "\021\013unrecovered read error - recommend reassignment",      /* 11 0B */
+       "\021\014unrecovered read error - recommend rewrite the data",  /* 11 0C */
+       "\021\015de-compression crc error",                     /* 11 0D */
+       "\021\016cannot decompress using declared algorithm",   /* 11 0E */
+       "\021\017error reading upc/ean number",                 /* 11 0F */
+       "\021\020error reading isrc number",                    /* 11 10 */
+       "\021\021read error - loss of streaming",               /* 11 11 */
+       "\021\022auxiliary memory code 3 (99-148) [proposed]",  /* 11 12 */
+       "\022\000address mark not found for id field",          /* 12 00 */
+       "\023\000address mark not found for data field",        /* 13 00 */
+       "\024\000recorded entity not found",                    /* 14 00 */
+       "\024\001record not found",                             /* 14 01 */
+       "\024\002filemark or setmark not found",                /* 14 02 */
+       "\024\003end-of-data not found",                        /* 14 03 */
+       "\024\004block sequence error",                         /* 14 04 */
+       "\024\005record not found - recommend reassignment",    /* 14 05 */
+       "\024\006record not found - data auto-reallocated",     /* 14 06 */
+       "\025\000random positioning error",                     /* 15 00 */
+       "\025\001mechanical positioning error",                 /* 15 01 */
+       "\025\002positioning error detected by read of medium", /* 15 02 */
+       "\026\000data synchronization mark error",              /* 16 00 */
+       "\026\001data sync error - data rewritten",             /* 16 01 */
+       "\026\002data sync error - recommend rewrite",          /* 16 02 */
+       "\026\003data sync error - data auto-reallocated",      /* 16 03 */
+       "\026\004data sync error - recommend reassignment",     /* 16 04 */
+       "\027\000recovered data with no error correction applied",      /* 17 00 */
+       "\027\001recovered data with retries",                  /* 17 01 */
+       "\027\002recovered data with positive head offset",     /* 17 02 */
+       "\027\003recovered data with negative head offset",     /* 17 03 */
+       "\027\004recovered data with retries and/or circ applied",      /* 17 04 */
+       "\027\005recovered data using previous sector id",      /* 17 05 */
+       "\027\006recovered data without ecc - data auto-reallocated",   /* 17 06 */
+       "\027\007recovered data without ecc - recommend reassignment",  /* 17 07 */
+       "\027\010recovered data without ecc - recommend rewrite",       /* 17 08 */
+       "\027\011recovered data without ecc - data rewritten",  /* 17 09 */
+       "\030\000recovered data with error correction applied", /* 18 00 */
+       "\030\001recovered data with error corr. & retries applied",    /* 18 01 */
+       "\030\002recovered data - data auto-reallocated",       /* 18 02 */
+       "\030\003recovered data with circ",                     /* 18 03 */
+       "\030\004recovered data with l-ec",                     /* 18 04 */
+       "\030\005recovered data - recommend reassignment",      /* 18 05 */
+       "\030\006recovered data - recommend rewrite",           /* 18 06 */
+       "\030\007recovered data with ecc - data rewritten",     /* 18 07 */
+       "\030\010recovered data with linking",                  /* 18 08 */
+       "\031\000defect list error",                            /* 19 00 */
+       "\031\001defect list not available",                    /* 19 01 */
+       "\031\002defect list error in primary list",            /* 19 02 */
+       "\031\003defect list error in grown list",              /* 19 03 */
+       "\032\000parameter list length error",                  /* 1A 00 */
+       "\033\000synchronous data transfer error",              /* 1B 00 */
+       "\034\000defect list not found",                        /* 1C 00 */
+       "\034\001primary defect list not found",                /* 1C 01 */
+       "\034\002grown defect list not found",                  /* 1C 02 */
+       "\035\000miscompare during verify operation",           /* 1D 00 */
+       "\036\000recovered id with ecc correction",             /* 1E 00 */
+       "\037\000partial defect list transfer",                 /* 1F 00 */
+       "\040\000invalid command operation code",               /* 20 00 */
+       "\040\001access controls code 1 (99-314) [proposed]",   /* 20 01 */
+       "\040\002access controls code 2 (99-314) [proposed]",   /* 20 02 */
+       "\040\003access controls code 3 (99-314) [proposed]",   /* 20 03 */
+       "\040\004read type operation while in write capable state",     /* 20 04 */
+       "\040\005write type operation while in read capable state",     /* 20 05 */
+       "\040\006illegal command while in explicit address model",      /* 20 06 */
+       "\040\007illegal command while in implicit address model",      /* 20 07 */
+       "\040\010access controls code 5 (99-245) [proposed]",   /* 20 08 */
+       "\040\011access controls code 6 (99-245) [proposed]",   /* 20 09 */
+       "\040\012access controls code 7 (99-245) [proposed]",   /* 20 0A */
+       "\040\013access controls code 8 (99-245) [proposed]",   /* 20 0B */
+       "\041\000logical block address out of range",           /* 21 00 */
+       "\041\001invalid element address",                      /* 21 01 */
+       "\041\002invalid address for write",                    /* 21 02 */
+       "\042\000illegal function (use 20 00, 24 00, or 26 00)",/* 22 00 */
+#ifdef __used__
+       "\043\000",                                             /* 23 00 */
+#endif
+       "\044\000invalid field in cdb",                         /* 24 00 */
+       "\044\001cdb decryption error",                         /* 24 01 */
+       "\044\002invalid cdb field while in explicit block address model",      /* 24 02 */
+       "\044\003invalid cdb field while in implicit block address model",      /* 24 03 */
+       "\045\000logical unit not supported",                   /* 25 00 */
+       "\046\000invalid field in parameter list",              /* 26 00 */
+       "\046\001parameter not supported",                      /* 26 01 */
+       "\046\002parameter value invalid",                      /* 26 02 */
+       "\046\003threshold parameters not supported",           /* 26 03 */
+       "\046\004invalid release of persistent reservation",    /* 26 04 */
+       "\046\005data decryption error",                        /* 26 05 */
+       "\046\006too many target descriptors",                  /* 26 06 */
+       "\046\007unsupported target descriptor type code",      /* 26 07 */
+       "\046\010too many segment descriptors",                 /* 26 08 */
+       "\046\011unsupported segment descriptor type code",     /* 26 09 */
+       "\046\012unexpected inexact segment",                   /* 26 0A */
+       "\046\013inline data length exceeded",                  /* 26 0B */
+       "\046\014invalid operation for copy source or destination",     /* 26 0C */
+       "\046\015copy segment granularity violation",           /* 26 0D */
+       "\047\000write protected",                              /* 27 00 */
+       "\047\001hardware write protected",                     /* 27 01 */
+       "\047\002logical unit software write protected",        /* 27 02 */
+       "\047\003associated write protect",                     /* 27 03 */
+       "\047\004persistent write protect",                     /* 27 04 */
+       "\047\005permanent write protect",                      /* 27 05 */
+       "\047\006conditional write protect",                    /* 27 06 */
+       "\050\000not ready to ready change, medium may have changed",   /* 28 00 */
+       "\050\001import or export element accessed",            /* 28 01 */
+       "\051\000power on, reset, or bus device reset occurred",/* 29 00 */
+       "\051\001power on occurred",                            /* 29 01 */
+       "\051\002scsi bus reset occurred",                      /* 29 02 */
+       "\051\003bus device reset function occurred",           /* 29 03 */
+       "\051\004device internal reset",                        /* 29 04 */
+       "\051\005transceiver mode changed to single-ended",     /* 29 05 */
+       "\051\006transceiver mode changed to lvd",              /* 29 06 */
+       "\052\000parameters changed",                           /* 2A 00 */
+       "\052\001mode parameters changed",                      /* 2A 01 */
+       "\052\002log parameters changed",                       /* 2A 02 */
+       "\052\003reservations preempted",                       /* 2A 03 */
+       "\052\004reservations released",                        /* 2A 04 */
+       "\052\005registrations preempted",                      /* 2A 05 */
+       "\052\006asymmetric access code 6 (00-232) [proposed]", /* 2A 06 */
+       "\052\007asymmetric access code 7 (00-232) [proposed]", /* 2A 07 */
+       "\053\000copy cannot execute since host cannot disconnect",     /* 2B 00 */
+       "\054\000command sequence error",                       /* 2C 00 */
+       "\054\001too many windows specified",                   /* 2C 01 */
+       "\054\002invalid combination of windows specified",     /* 2C 02 */
+       "\054\003current program area is not empty",            /* 2C 03 */
+       "\054\004current program area is empty",                /* 2C 04 */
+       "\054\005illegal power condition request",              /* 2C 05 */
+       "\054\006persistent prevent conflict",                  /* 2C 06 */
+       "\055\000overwrite error on update in place",           /* 2D 00 */
+       "\056\000insufficient time for operation",              /* 2E 00 */
+       "\057\000commands cleared by another initiator",        /* 2F 00 */
+       "\060\000incompatible medium installed",                /* 30 00 */
+       "\060\001cannot read medium - unknown format",          /* 30 01 */
+       "\060\002cannot read medium - incompatible format",     /* 30 02 */
+       "\060\003cleaning cartridge installed",                 /* 30 03 */
+       "\060\004cannot write medium - unknown format",         /* 30 04 */
+       "\060\005cannot write medium - incompatible format",    /* 30 05 */
+       "\060\006cannot format medium - incompatible medium",   /* 30 06 */
+       "\060\007cleaning failure",                             /* 30 07 */
+       "\060\010cannot write - application code mismatch",     /* 30 08 */
+       "\060\011current session not fixated for append",       /* 30 09 */
+       "\060\020medium not formatted",                         /* 30 10 */
+       "\061\000medium format corrupted",                      /* 31 00 */
+       "\061\001format command failed",                        /* 31 01 */
+       "\061\002zoned formatting failed due to spare linking", /* 31 02 */
+       "\062\000no defect spare location available",           /* 32 00 */
+       "\062\001defect list update failure",                   /* 32 01 */
+       "\063\000tape length error",                            /* 33 00 */
+       "\064\000enclosure failure",                            /* 34 00 */
+       "\065\000enclosure services failure",                   /* 35 00 */
+       "\065\001unsupported enclosure function",               /* 35 01 */
+       "\065\002enclosure services unavailable",               /* 35 02 */
+       "\065\003enclosure services transfer failure",          /* 35 03 */
+       "\065\004enclosure services transfer refused",          /* 35 04 */
+       "\066\000ribbon, ink, or toner failure",                /* 36 00 */
+       "\067\000rounded parameter",                            /* 37 00 */
+       "\070\000event status notification",                    /* 38 00 */
+       "\070\002esn - power management class event",           /* 38 02 */
+       "\070\004esn - media class event",                      /* 38 04 */
+       "\070\006esn - device busy class event",                /* 38 06 */
+       "\071\000saving parameters not supported",              /* 39 00 */
+       "\072\000medium not present",                           /* 3A 00 */
+       "\072\001medium not present - tray closed",             /* 3A 01 */
+       "\072\002medium not present - tray open",               /* 3A 02 */
+       "\072\003medium not present - loadable",                /* 3A 03 */
+       "\072\004medium not present - medium auxiliary memory accessible",      /* 3A 04 */
+       "\073\000sequential positioning error",                 /* 3B 00 */
+       "\073\001tape position error at beginning-of-medium",   /* 3B 01 */
+       "\073\002tape position error at end-of-medium",         /* 3B 02 */
+       "\073\003tape or electronic vertical forms unit not ready",     /* 3B 03 */
+       "\073\004slew failure",                                 /* 3B 04 */
+       "\073\005paper jam",                                    /* 3B 05 */
+       "\073\006failed to sense top-of-form",                  /* 3B 06 */
+       "\073\007failed to sense bottom-of-form",               /* 3B 07 */
+       "\073\010reposition error",                             /* 3B 08 */
+       "\073\011read past end of medium",                      /* 3B 09 */
+       "\073\012read past beginning of medium",                /* 3B 0A */
+       "\073\013position past end of medium",                  /* 3B 0B */
+       "\073\014position past beginning of medium",            /* 3B 0C */
+       "\073\015medium destination element full",              /* 3B 0D */
+       "\073\016medium source element empty",                  /* 3B 0E */
+       "\073\017end of medium reached",                        /* 3B 0F */
+       "\073\021medium magazine not accessible",               /* 3B 11 */
+       "\073\022medium magazine removed",                      /* 3B 12 */
+       "\073\023medium magazine inserted",                     /* 3B 13 */
+       "\073\024medium magazine locked",                       /* 3B 14 */
+       "\073\025medium magazine unlocked",                     /* 3B 15 */
+       "\073\026mechanical positioning or changer error",      /* 3B 16 */
+#ifdef __used__
+       "\074\000",                                             /* 3C 00 */
+#endif
+       "\075\000invalid bits in identify message",             /* 3D 00 */
+       "\076\000logical unit has not self-configured yet",     /* 3E 00 */
+       "\076\001logical unit failure",                         /* 3E 01 */
+       "\076\002timeout on logical unit",                      /* 3E 02 */
+       "\076\003logical unit failed self-test",                /* 3E 03 */
+       "\076\004logical unit unable to update self-test log",  /* 3E 04 */
+       "\077\000target operating conditions have changed",     /* 3F 00 */
+       "\077\001microcode has been changed",                   /* 3F 01 */
+       "\077\002changed operating definition",                 /* 3F 02 */
+       "\077\003inquiry data has changed",                     /* 3F 03 */
+       "\077\004component device attached",                    /* 3F 04 */
+       "\077\005device identifier changed",                    /* 3F 05 */
+       "\077\006redundancy group created or modified",         /* 3F 06 */
+       "\077\007redundancy group deleted",                     /* 3F 07 */
+       "\077\010spare created or modified",                    /* 3F 08 */
+       "\077\011spare deleted",                                /* 3F 09 */
+       "\077\012volume set created or modified",               /* 3F 0A */
+       "\077\013volume set deleted",                           /* 3F 0B */
+       "\077\014volume set deassigned",                        /* 3F 0C */
+       "\077\015volume set reassigned",                        /* 3F 0D */
+       "\077\016reported luns data has changed",               /* 3F 0E */
+       "\077\017echo buffer overwritten",                      /* 3F 0F */
+       "\077\020medium loadable",                              /* 3F 10 */
+       "\077\021medium auxiliary memory accessible",           /* 3F 11 */
+       "\100\000ram failure (should use 40 nn)",               /* 40 00 */
+#ifdef XXX
+       "\100\000nn diagnostic failure on component nn (80h-ffh)",      /* 40 00 */
+#endif
+       "\100\000diagnostic failure on component nn (80h-ffh)", /* 40 00 */
+       "\101\000data path failure (should use 40 nn)",         /* 41 00 */
+       "\102\000power-on or self-test failure (should use 40 nn)",     /* 42 00 */
+       "\103\000message error",                                /* 43 00 */
+       "\104\000internal target failure",                      /* 44 00 */
+       "\105\000select or reselect failure",                   /* 45 00 */
+       "\106\000unsuccessful soft reset",                      /* 46 00 */
+       "\107\000scsi parity error",                            /* 47 00 */
+       "\107\001data phase crc error detected",                /* 47 01 */
+       "\107\002scsi parity error detected during st data phase",      /* 47 02 */
+       "\107\003information unit crc error detected",          /* 47 03 */
+       "\107\004asynchronous information protection error detected",   /* 47 04 */
+       "\110\000initiator detected error message received",    /* 48 00 */
+       "\111\000invalid message error",                        /* 49 00 */
+       "\112\000command phase error",                          /* 4A 00 */
+       "\113\000data phase error",                             /* 4B 00 */
+       "\114\000logical unit failed self-configuration",       /* 4C 00 */
+#ifdef XXX
+       "\115\000nn tagged overlapped commands (nn = queue tag)",       /* 4D 00 */
+#endif
+       "\115\000tagged overlapped commands (nn = queue tag)",  /* 4D 00 */
+       "\116\000overlapped commands attempted",                /* 4E 00 */
+#ifdef __used__
+       "\117\000",                                             /* 4F 00 */
+#endif
+       "\120\000write append error",                           /* 50 00 */
+       "\120\001write append position error",                  /* 50 01 */
+       "\120\002position error related to timing",             /* 50 02 */
+       "\121\000erase failure",                                /* 51 00 */
+       "\121\001erase failure - incomplete erase operation detected",  /* 51 01 */
+       "\122\000cartridge fault",                              /* 52 00 */
+       "\123\000media load or eject failed",                   /* 53 00 */
+       "\123\001unload tape failure",                          /* 53 01 */
+       "\123\002medium removal prevented",                     /* 53 02 */
+       "\124\000scsi to host system interface failure",        /* 54 00 */
+       "\125\000system resource failure",                      /* 55 00 */
+       "\125\001system buffer full",                           /* 55 01 */
+       "\125\002insufficient reservation resources",           /* 55 02 */
+       "\125\003insufficient resources",                       /* 55 03 */
+       "\125\004insufficient registration resources",          /* 55 04 */
+       "\125\005access controls code 4 (99-314) [proposed]",   /* 55 05 */
+       "\125\006auxiliary memory code 1 (99-148) [proposed]",  /* 55 06 */
+#ifdef __used__
+       "\126\000",                                             /* 56 00 */
+#endif
+       "\127\000unable to recover table-of-contents",          /* 57 00 */
+       "\130\000generation does not exist",                    /* 58 00 */
+       "\131\000updated block read",                           /* 59 00 */
+       "\132\000operator request or state change input",       /* 5A 00 */
+       "\132\001operator medium removal request",              /* 5A 01 */
+       "\132\002operator selected write protect",              /* 5A 02 */
+       "\132\003operator selected write permit",               /* 5A 03 */
+       "\133\000log exception",                                /* 5B 00 */
+       "\133\001threshold condition met",                      /* 5B 01 */
+       "\133\002log counter at maximum",                       /* 5B 02 */
+       "\133\003log list codes exhausted",                     /* 5B 03 */
+       "\134\000rpl status change",                            /* 5C 00 */
+       "\134\001spindles synchronized",                        /* 5C 01 */
+       "\134\002spindles not synchronized",                    /* 5C 02 */
+       "\135\000failure prediction threshold exceeded",        /* 5D 00 */
+       "\135\001media failure prediction threshold exceeded",  /* 5D 01 */
+       "\135\002logical unit failure prediction threshold exceeded",   /* 5D 02 */
+       "\135\003spare area exhaustion prediction threshold exceeded",  /* 5D 03 */
+       "\135\020hardware impending failure general hard drive failure",/* 5D 10 */
+       "\135\021hardware impending failure drive error rate too high", /* 5D 11 */
+       "\135\022hardware impending failure data error rate too high",  /* 5D 12 */
+       "\135\023hardware impending failure seek error rate too high",  /* 5D 13 */
+       "\135\024hardware impending failure too many block reassigns",  /* 5D 14 */
+       "\135\025hardware impending failure access times too high",     /* 5D 15 */
+       "\135\026hardware impending failure start unit times too high", /* 5D 16 */
+       "\135\027hardware impending failure channel parametrics",/* 5D 17 */
+       "\135\030hardware impending failure controller detected",/* 5D 18 */
+       "\135\031hardware impending failure throughput performance",    /* 5D 19 */
+       "\135\032hardware impending failure seek time performance",     /* 5D 1A */
+       "\135\033hardware impending failure spin-up retry count",       /* 5D 1B */
+       "\135\034hardware impending failure drive calibration retry count",     /* 5D 1C */
+       "\135\040controller impending failure general hard drive failure",      /* 5D 20 */
+       "\135\041controller impending failure drive error rate too high",       /* 5D 21 */
+       "\135\042controller impending failure data error rate too high",/* 5D 22 */
+       "\135\043controller impending failure seek error rate too high",/* 5D 23 */
+       "\135\044controller impending failure too many block reassigns",/* 5D 24 */
+       "\135\045controller impending failure access times too high",   /* 5D 25 */
+       "\135\046controller impending failure start unit times too high",       /* 5D 26 */
+       "\135\047controller impending failure channel parametrics",     /* 5D 27 */
+       "\135\050controller impending failure controller detected",     /* 5D 28 */
+       "\135\051controller impending failure throughput performance",  /* 5D 29 */
+       "\135\052controller impending failure seek time performance",   /* 5D 2A */
+       "\135\053controller impending failure spin-up retry count",     /* 5D 2B */
+       "\135\054controller impending failure drive calibration retry count",   /* 5D 2C */
+       "\135\060data channel impending failure general hard drive failure",    /* 5D 30 */
+       "\135\061data channel impending failure drive error rate too high",     /* 5D 31 */
+       "\135\062data channel impending failure data error rate too high",      /* 5D 32 */
+       "\135\063data channel impending failure seek error rate too high",      /* 5D 33 */
+       "\135\064data channel impending failure too many block reassigns",      /* 5D 34 */
+       "\135\065data channel impending failure access times too high", /* 5D 35 */
+       "\135\066data channel impending failure start unit times too high",     /* 5D 36 */
+       "\135\067data channel impending failure channel parametrics",   /* 5D 37 */
+       "\135\070data channel impending failure controller detected",   /* 5D 38 */
+       "\135\071data channel impending failure throughput performance",/* 5D 39 */
+       "\135\072data channel impending failure seek time performance", /* 5D 3A */
+       "\135\073data channel impending failure spin-up retry count",   /* 5D 3B */
+       "\135\074data channel impending failure drive calibration retry count", /* 5D 3C */
+       "\135\100servo impending failure general hard drive failure",   /* 5D 40 */
+       "\135\101servo impending failure drive error rate too high",    /* 5D 41 */
+       "\135\102servo impending failure data error rate too high",     /* 5D 42 */
+       "\135\103servo impending failure seek error rate too high",     /* 5D 43 */
+       "\135\104servo impending failure too many block reassigns",     /* 5D 44 */
+       "\135\105servo impending failure access times too high",/* 5D 45 */
+       "\135\106servo impending failure start unit times too high",    /* 5D 46 */
+       "\135\107servo impending failure channel parametrics",  /* 5D 47 */
+       "\135\110servo impending failure controller detected",  /* 5D 48 */
+       "\135\111servo impending failure throughput performance",       /* 5D 49 */
+       "\135\112servo impending failure seek time performance",/* 5D 4A */
+       "\135\113servo impending failure spin-up retry count",  /* 5D 4B */
+       "\135\114servo impending failure drive calibration retry count",/* 5D 4C */
+       "\135\120spindle impending failure general hard drive failure", /* 5D 50 */
+       "\135\121spindle impending failure drive error rate too high",  /* 5D 51 */
+       "\135\122spindle impending failure data error rate too high",   /* 5D 52 */
+       "\135\123spindle impending failure seek error rate too high",   /* 5D 53 */
+       "\135\124spindle impending failure too many block reassigns",   /* 5D 54 */
+       "\135\125spindle impending failure access times too high",      /* 5D 55 */
+       "\135\126spindle impending failure start unit times too high",  /* 5D 56 */
+       "\135\127spindle impending failure channel parametrics",/* 5D 57 */
+       "\135\130spindle impending failure controller detected",/* 5D 58 */
+       "\135\131spindle impending failure throughput performance",     /* 5D 59 */
+       "\135\132spindle impending failure seek time performance",      /* 5D 5A */
+       "\135\133spindle impending failure spin-up retry count",/* 5D 5B */
+       "\135\134spindle impending failure drive calibration retry count",      /* 5D 5C */
+       "\135\140firmware impending failure general hard drive failure",/* 5D 60 */
+       "\135\141firmware impending failure drive error rate too high", /* 5D 61 */
+       "\135\142firmware impending failure data error rate too high",  /* 5D 62 */
+       "\135\143firmware impending failure seek error rate too high",  /* 5D 63 */
+       "\135\144firmware impending failure too many block reassigns",  /* 5D 64 */
+       "\135\145firmware impending failure access times too high",     /* 5D 65 */
+       "\135\146firmware impending failure start unit times too high", /* 5D 66 */
+       "\135\147firmware impending failure channel parametrics",       /* 5D 67 */
+       "\135\150firmware impending failure controller detected",       /* 5D 68 */
+       "\135\151firmware impending failure throughput performance",    /* 5D 69 */
+       "\135\152firmware impending failure seek time performance",     /* 5D 6A */
+       "\135\153firmware impending failure spin-up retry count",       /* 5D 6B */
+       "\135\154firmware impending failure drive calibration retry count",     /* 5D 6C */
+       "\135\377failure prediction threshold exceeded (false)",/* 5D FF */
+       "\136\000low power condition on",                       /* 5E 00 */
+       "\136\001idle condition activated by timer",            /* 5E 01 */
+       "\136\002standby condition activated by timer",         /* 5E 02 */
+       "\136\003idle condition activated by command",          /* 5E 03 */
+       "\136\004standby condition activated by command",       /* 5E 04 */
+       "\136\101power state change to active",                 /* 5E 41 */
+       "\136\102power state change to idle",                   /* 5E 42 */
+       "\136\103power state change to standby",                /* 5E 43 */
+       "\136\105power state change to sleep",                  /* 5E 45 */
+       "\136\107power state change to device control",         /* 5E 47 */
+#ifdef __used__
+       "\137\000",                                             /* 5F 00 */
+#endif
+       "\140\000lamp failure",                                 /* 60 00 */
+       "\141\000video acquisition error",                      /* 61 00 */
+       "\141\001unable to acquire video",                      /* 61 01 */
+       "\141\002out of focus",                                 /* 61 02 */
+       "\142\000scan head positioning error",                  /* 62 00 */
+       "\143\000end of user area encountered on this track",   /* 63 00 */
+       "\143\001packet does not fit in available space",       /* 63 01 */
+       "\144\000illegal mode for this track",                  /* 64 00 */
+       "\144\001invalid packet size",                          /* 64 01 */
+       "\145\000voltage fault",                                /* 65 00 */
+       "\146\000automatic document feeder cover up",           /* 66 00 */
+       "\146\001automatic document feeder lift up",            /* 66 01 */
+       "\146\002document jam in automatic document feeder",    /* 66 02 */
+       "\146\003document miss feed automatic in document feeder",      /* 66 03 */
+       "\147\000configuration failure",                        /* 67 00 */
+       "\147\001configuration of incapable logical units failed",      /* 67 01 */
+       "\147\002add logical unit failed",                      /* 67 02 */
+       "\147\003modification of logical unit failed",          /* 67 03 */
+       "\147\004exchange of logical unit failed",              /* 67 04 */
+       "\147\005remove of logical unit failed",                /* 67 05 */
+       "\147\006attachment of logical unit failed",            /* 67 06 */
+       "\147\007creation of logical unit failed",              /* 67 07 */
+       "\147\010assign failure occurred",                      /* 67 08 */
+       "\147\011multiply assigned logical unit",               /* 67 09 */
+       "\147\012asymmetric access code 4 (00-232) [proposed]", /* 67 0A */
+       "\147\013asymmetric access code 5 (00-232) [proposed]", /* 67 0B */
+       "\150\000logical unit not configured",                  /* 68 00 */
+       "\151\000data loss on logical unit",                    /* 69 00 */
+       "\151\001multiple logical unit failures",               /* 69 01 */
+       "\151\002parity/data mismatch",                         /* 69 02 */
+       "\152\000informational, refer to log",                  /* 6A 00 */
+       "\153\000state change has occurred",                    /* 6B 00 */
+       "\153\001redundancy level got better",                  /* 6B 01 */
+       "\153\002redundancy level got worse",                   /* 6B 02 */
+       "\154\000rebuild failure occurred",                     /* 6C 00 */
+       "\155\000recalculate failure occurred",                 /* 6D 00 */
+       "\156\000command to logical unit failed",               /* 6E 00 */
+       "\157\000copy protection key exchange failure - authentication failure",/* 6F 00 */
+       "\157\001copy protection key exchange failure - key not present",       /* 6F 01 */
+       "\157\002copy protection key exchange failure - key not established",   /* 6F 02 */
+       "\157\003read of scrambled sector without authentication",      /* 6F 03 */
+       "\157\004media region code is mismatched to logical unit region",       /* 6F 04 */
+       "\157\005drive region must be permanent/region reset count error",      /* 6F 05 */
+#ifdef XXX
+       "\160\000nn decompression exception short algorithm id of nn",  /* 70 00 */
+#endif
+       "\160\000decompression exception short algorithm id of nn",     /* 70 00 */
+       "\161\000decompression exception long algorithm id",    /* 71 00 */
+       "\162\000session fixation error",                       /* 72 00 */
+       "\162\001session fixation error writing lead-in",       /* 72 01 */
+       "\162\002session fixation error writing lead-out",      /* 72 02 */
+       "\162\003session fixation error - incomplete track in session", /* 72 03 */
+       "\162\004empty or partially written reserved track",    /* 72 04 */
+       "\162\005no more track reservations allowed",           /* 72 05 */
+       "\163\000cd control error",                             /* 73 00 */
+       "\163\001power calibration area almost full",           /* 73 01 */
+       "\163\002power calibration area is full",               /* 73 02 */
+       "\163\003power calibration area error",                 /* 73 03 */
+       "\163\004program memory area update failure",           /* 73 04 */
+       "\163\005program memory area is full",                  /* 73 05 */
+       "\163\006rma/pma is almost full",                       /* 73 06 */
+#ifdef __used__
+       "\164\000",                                             /* 74 00 */
+       "\165\000",                                             /* 75 00 */
+       "\166\000",                                             /* 76 00 */
+       "\167\000",                                             /* 77 00 */
+       "\170\000",                                             /* 78 00 */
+       "\171\000",                                             /* 79 00 */
+       "\172\000",                                             /* 7A 00 */
+       "\173\000",                                             /* 7B 00 */
+       "\174\000",                                             /* 7C 00 */
+       "\175\000",                                             /* 7D 00 */
+       "\176\000",                                             /* 7E 00 */
+       "\177\000",                                             /* 7F 00 */
+#endif
+#ifdef XXX
+       "\200\000start vendor unique",                          /* 80 00 */
+#endif
+       NULL
+};
+
+#ifdef SMO_C501
+static const char *sd_smo_c501_error_str[] = {
+       "\012\000disk not inserted",                    /* 0x0a */
+       "\013\000load/unload failure",                  /* 0x0b */
+       "\014\000spindle failure",                      /* 0x0c */
+       "\015\000focus failure",                        /* 0x0d */
+       "\016\000tracking failure",                     /* 0x0e */
+       "\017\000bias magnet failure",                  /* 0x0f */
+       "\043\000illegal function for medium type",     /* 0x23 */
+/*XXX*/        "\070\000recoverable write error",              /* 0x38 */
+/*XXX*/        "\071\000write error recovery failed",          /* 0x39 */
+       "\072\000defect list update failed",            /* 0x3a */
+       "\075\000defect list not available",            /* 0x3d */
+       "\200\000limited laser life",                   /* 0x80 */
+       "\201\000laser focus coil over-current",        /* 0x81 */
+       "\202\000laser tracking coil over-current",     /* 0x82 */
+       "\203\000temperature alarm",                    /* 0x83 */
+       NULL
+};
+#endif
+
+static char *sd_sense_keys[] = {
+       "No Additional Sense",          /* 0x00 */
+       "Recovered Error",              /* 0x01 */
+       "Not Ready",                    /* 0x02 */
+       "Medium Error",                 /* 0x03 */
+       "Hardware Error",               /* 0x04 */
+       "Illegal Request",              /* 0x05 */
+       "Unit Attention",               /* 0x06 */
+       "Data Protect",                 /* 0x07 */
+       "Blank Check",                  /* 0x08 */
+       "Vendor Unique",                /* 0x09 */
+       "Copy Aborted",                 /* 0x0a */
+       "Aborted Command",              /* 0x0b */
+       "Equal",                        /* 0x0c */
+       "Volume Overflow",              /* 0x0d */
+       "Miscompare",                   /* 0x0e */
+       "Reserved"                      /* 0x0f */
+};
+
+#if 0
+static char *sd_cmds[] = {
+       "\000test unit ready",          /* 0x00 */
+       "\001rezero",                   /* 0x01 */
+       "\003request sense",            /* 0x03 */
+       "\004format",                   /* 0x04 */
+       "\007reassign",                 /* 0x07 */
+       "\010read",                     /* 0x08 */
+       "\012write",                    /* 0x0a */
+       "\013seek",                     /* 0x0b */
+       "\022inquiry",                  /* 0x12 */
+       "\025mode select",              /* 0x15 */
+       "\026reserve",                  /* 0x16 */
+       "\027release",                  /* 0x17 */
+       "\030copy",                     /* 0x18 */
+       "\032mode sense",               /* 0x1a */
+       "\033start/stop",               /* 0x1b */
+       "\036door lock",                /* 0x1e */
+       "\067read defect data",         /* 0x37 */
+       NULL
+};
+#endif
+
+
+const char *
+usal_sensemsg(register int ctype, register int code, register int qual, 
+                                register const char **vec, char *sbuf, int maxcnt)
+{
+       register int i;
+
+       /*
+        * Ignore controller type if error vec is supplied.
+        */
+       if (vec == (const char **)NULL) switch (ctype) {
+       case DEV_MD21:
+               vec = sd_ccs_error_str;
+               break;
+
+       case DEV_ACB40X0:
+       case DEV_ACB4000:
+       case DEV_ACB4010:
+       case DEV_ACB4070:
+       case DEV_ACB5500:
+               vec = sd_adaptec_error_str;
+               break;
+
+#ifdef SMO_C501
+       case DEV_SONY_SMO:
+               vec = sd_smo_c501_error_str;
+               break;
+#endif
+
+       default:
+               vec = sd_ccs_error_str;
+       }
+       if (vec == (const char **)NULL)
+               return ("");
+
+       for (i = 0; i < 2; i++) {
+               while (*vec != (char *) NULL) {
+                       if (code == (Uchar)(*vec)[0] &&
+                                       qual == (Uchar)(*vec)[1]) {
+                               return (&(*vec)[2]);
+                       } else {
+                               vec++;          /* Next entry */
+                       }
+               }
+               if (*vec == (char *) NULL)      /* End of List: switch over */
+                       vec = sd_ccs_error_str;
+       }
+       if (code == 0x40) {
+               snprintf(sbuf, maxcnt,
+                       "diagnostic failure on component 0x%X", qual);
+               return (sbuf);
+       }
+       if (code == 0x4D) {
+               snprintf(sbuf, maxcnt,
+                       "tagged overlapped commands, queue tag is 0x%X",
+                                                                       qual);
+               return (sbuf);
+       }
+       if (code == 0x70) {
+               snprintf(sbuf, maxcnt,
+                       "decompression exception short algorithm id of 0x%X",
+                                                                       qual);
+               return (sbuf);
+       }
+       if (qual != 0)
+               return ((char *)NULL);
+
+       if (code < 0x80) {
+               snprintf(sbuf, maxcnt, "invalid sense code 0x%X", code);
+               return (sbuf);
+       }
+       snprintf(sbuf, maxcnt, "vendor unique sense code 0x%X", code);
+       return (sbuf);
+}
+
+#undef sense   /*XXX JS Hack, solange usalio.h noch nicht fertig ist */
+int
+usal__errmsg(SCSI *usalp, char *obuf, int maxcnt, 
+                               register struct scsi_sense *sense, 
+                               register struct scsi_status *status, int sense_code)
+{
+       char    sbuf[80];
+       const char *sensemsg, *cmdname, *sensekey;
+#define        ext_sense       ((struct scsi_ext_sense* ) sense)
+       register int blkno = 0;
+       register int code;
+       int     badqual = 0;
+       int     qual = 0;
+       int     fru = 0;
+       int     key = 0;
+       int     segment = 0;
+       int     blkvalid = 0;
+       int     fm = 0;
+       int     eom = 0;
+       int     ili = 0;
+       int     sksv = 0;
+       int     n;
+       int     sizeleft = maxcnt;
+
+       sensekey = sensemsg = "[]";
+       if (sense->code >= 0x70) {
+               if (sense_code >= 0)
+                       code = sense_code;
+               else
+                       code = ext_sense->sense_code;
+               segment = ext_sense->seg_num;
+               qual = ext_sense->qual_code;
+               fru = ext_sense->fru_code;
+               sksv = ext_sense->sksv;
+       } else {
+               code = sense->code;
+       }
+       if (status->chk == 0) {
+               sensemsg = "no sense";
+       } else {
+               if (sense->code >= 0x70) {
+                       key = ext_sense->key;
+                       if (key < 0x10)
+                               sensekey = sd_sense_keys[ext_sense->key];
+                       else
+                               sensekey = "invalid sensekey";
+                       blkno = (ext_sense->info_1 << 24) |
+                               (ext_sense->info_2 << 16) |
+                               (ext_sense->info_3 << 8) |
+                               ext_sense->info_4;
+                       fm = ext_sense->fil_mk;
+                       eom = ext_sense->eom;
+                       ili = ext_sense->ili;
+               } else {
+                       key = -1;
+                       sensekey = "[]";
+                       blkno = (sense->high_addr << 16) |
+                               (sense->mid_addr << 8) |
+                               sense->low_addr;
+                       fm = eom = 0;
+               }
+               blkvalid = sense->adr_val;
+
+               sensemsg = usal_sensemsg(usalp->dev, code, qual, usalp->nonstderrs, sbuf, sizeof(sbuf));
+               if (sensemsg == NULL) {
+                       sensemsg = usal_sensemsg(usalp->dev, code, 0, usalp->nonstderrs, sbuf, sizeof(sbuf));
+                       badqual = 1;
+               }
+       }
+/*
+       if (un->un_cmd < sizeof(scsi_cmds)) {
+               cmdname = scsi_cmds[un->un_cmd];
+       } else {
+               cmdname = "unknown cmd";
+       }
+*/
+       cmdname = "";
+       n = snprintf(obuf, sizeleft, "%sSense Key: 0x%X %s%s, Segment %d\n",
+               cmdname, key, sensekey,
+               (sense->code == 0x71)?", deferred error":"",
+               segment);
+       if (n <= 0) {
+               obuf[0] = '\0';
+               return (maxcnt - sizeleft);
+       }
+       obuf += n;
+       sizeleft -= n;
+       n = snprintf(obuf, sizeleft, "Sense Code: 0x%02X Qual 0x%02X %s%s%s%s Fru 0x%X\n",
+               code, qual, *sensemsg?"(":"", sensemsg, *sensemsg?")":"",
+               badqual? " [No matching qualifier]":"",
+               fru);
+       if (n <= 0) {
+               obuf[0] = '\0';
+               return (maxcnt - sizeleft);
+       }
+       obuf += n;
+       sizeleft -= n;
+       n = snprintf(obuf, sizeleft, "Sense flags: Blk %d %s%s%s%s",
+               blkno, blkvalid?"(valid) ":"(not valid) ",
+               fm?"file mark detected ":"",
+               eom?"end of medium ":"",
+               ili?"illegal block length ":"");
+       if (n <= 0) {
+               obuf[0] = '\0';
+               return (maxcnt - sizeleft);
+       }
+       obuf += n;
+       sizeleft -= n;
+       if (!sksv) {
+               n = snprintf(obuf, sizeleft, "\n");
+               if (n <= 0) {
+                       obuf[0] = '\0';
+                       return (maxcnt - sizeleft);
+               }
+               obuf += n;
+               sizeleft -= n;
+               return (maxcnt - sizeleft);
+       }
+       switch (key) {
+
+       case SC_ILLEGAL_REQUEST:
+               n = snprintf(obuf, sizeleft, "error refers to %s part, bit ptr %d %s field ptr %d",
+                       ext_sense->cd? "command":"data",
+                       (int)ext_sense->bptr,
+                       ext_sense->bpv? "(valid)":"(not valid)",
+                       ext_sense->field_ptr[0] << 8 |
+                       ext_sense->field_ptr[1]);
+               if (n <= 0) {
+                       obuf[0] = '\0';
+                       return (maxcnt - sizeleft);
+               }
+               obuf += n;
+               sizeleft -= n;
+               break;
+
+       case SC_RECOVERABLE_ERROR:
+       case SC_HARDWARE_ERROR:
+       case SC_MEDIUM_ERROR:
+               n = snprintf(obuf, sizeleft, "actual retry count %d",
+                       ext_sense->field_ptr[0] << 8 |
+                       ext_sense->field_ptr[1]);
+               if (n <= 0) {
+                       obuf[0] = '\0';
+                       return (maxcnt - sizeleft);
+               }
+               obuf += n;
+               sizeleft -= n;
+               break;
+
+       case SC_NOT_READY:
+               n = snprintf(obuf, sizeleft, "operation %d%% done",
+                       (100*(ext_sense->field_ptr[0] << 8 |
+                             ext_sense->field_ptr[1]))/(unsigned)65536);
+               if (n < 0) {
+                       obuf[0] = '\0';
+                       return (maxcnt - sizeleft);
+               }
+               obuf += n;
+               sizeleft -= n;
+               break;
+       }
+       n = snprintf(obuf, sizeleft, "\n");
+       if (n <= 0) {
+               obuf[0] = '\0';
+               return (maxcnt - sizeleft);
+       }
+       obuf += n;
+       sizeleft -= n;
+       return (maxcnt - sizeleft);
+}
+
+#ifdef DEBUG
+print_err(code, ctype)
+{
+       register int i;
+       register char **vec  = (char **)NULL;
+
+       switch (ctype) {
+       case CTYPE_MD21:
+       case CTYPE_CCS:
+               vec = sd_ccs_error_str;
+               break;
+
+       case CTYPE_ACB4000:
+               vec = sd_adaptec_error_str;
+               break;
+
+#ifdef SMO_C501
+       case CTYPE_SMO_C501:
+               vec = sd_smo_c501_error_str;
+               break;
+#endif
+
+#ifdef CDD_521
+       case DEV_CDD_521:
+               vec = sd_cdd_521_error_str;
+               break;
+#endif
+       }
+       printf("error code: 0x%x", code);
+       if (vec == (char **)NULL)
+               return;
+
+       for (i = 0; i < 2; i++) {
+               while (*vec != (char *) NULL) {
+                       if (code == (Uchar)*vec[0]) {
+                               printf(" (%s)", (char *)((int)(*vec)+1));
+                               return;
+                       } else
+                               vec++;
+               }
+               if (*vec == (char *) NULL)
+                       vec = sd_ccs_error_str;
+       }
+}
+
+
+int main(int argc, char *argv[])
+{
+       int     i;
+
+#ifdef ACB
+       for (i = 0; i < 0x30; i++) {
+/*             printf("Code: 0x%x      Key: 0x%x       ", i, sd_adaptec_keys[i]);*/
+               printf("Key: 0x%x %-16s ", sd_adaptec_keys[i],
+                                       sd_sense_keys[sd_adaptec_keys[i]] );
+               js_print_err(i, CTYPE_ACB4000);
+               printf("\n");
+       }
+#else
+/*     for (i = 0; i < 0x84; i++) {*/
+       for (i = 0; i < 0xd8; i++) {
+/*             print_err(i, CTYPE_SMO_C501);*/
+               print_err(i, DEV_CDD_521);
+               printf("\n");
+       }
+#endif
+}
+#endif
diff --git a/libusal/scsihack.c b/libusal/scsihack.c
new file mode 100644 (file)
index 0000000..5427ad0
--- /dev/null
@@ -0,0 +1,483 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)scsihack.c      1.44 06/01/30 Copyright 1997,2000,2001 J. Schilling */
+/*
+ *     Interface for other generic SCSI implementations.
+ *     Emulate the functionality of /dev/usal? with the local
+ *     SCSI user land implementation.
+ *
+ *     To add a new hack, add something like:
+ *
+ *     #ifdef  __FreeBSD__
+ *     #define SCSI_IMPL
+ *     #include some code
+ *     #endif
+ *
+ *     Warning: you may change this source or add new SCSI tranport
+ *     implementations, but if you do that you need to change the
+ *     _usal_version and _usal_auth* string that are returned by the
+ *     SCSI transport code.
+ *     Choose your name instead of "schily" and make clear that the version
+ *     string is related to a modified source.
+ *     If your version has been integrated into the main steam release,
+ *     the return value will be set to "schily".
+ *
+ *     Copyright (c) 1997,2000,2001 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <mconfig.h>
+
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h> /* Include various defs needed with some OS */
+#endif
+#include <stdio.h>
+#include <standard.h>
+#include <stdxlib.h>
+#include <unixstd.h>
+#include <errno.h>
+#include <timedefs.h>
+#include <sys/ioctl.h>
+#include <fctldefs.h>
+#include <strdefs.h>
+#include <schily.h>
+
+#include <usal/usalcmd.h>
+#include <usal/scsitransp.h>
+#include "usaltimes.h"
+
+#ifndef        HAVE_ERRNO_DEF
+extern int     errno;
+#endif
+
+static int     usalo_send(SCSI *usalp);
+static char *usalo_version(SCSI *usalp, int what);
+static int     usalo_help(SCSI *usalp, FILE *f);
+static int     usalo_open(SCSI *usalp, char *device);
+static int     usalo_close(SCSI *usalp);
+static long    usalo_maxdma(SCSI *usalp, long amt);
+static void *usalo_getbuf(SCSI *usalp, long amt);
+static void    usalo_freebuf(SCSI *usalp);
+
+static BOOL    usalo_havebus(SCSI *usalp, int busno);
+static int     usalo_fileno(SCSI *usalp, int busno, int tgt, int tlun);
+static char * usalo_natname(SCSI *usalp, int busno, int tgt, int tlun);
+static int     usalo_initiator_id(SCSI *usalp);
+static int     usalo_isatapi(SCSI *usalp);
+static int     usalo_reset(SCSI *usalp, int what);
+
+static char    _usal_auth_cdrkit[]     = "cdrkit-team";        /* The author for this module   */
+
+usal_ops_t usal_std_ops = {
+       usalo_send,
+       usalo_version,
+       usalo_help,
+       usalo_open,
+       usalo_close,
+       usalo_maxdma,
+       usalo_getbuf,
+       usalo_freebuf,
+       usalo_havebus,
+       usalo_fileno,
+       usalo_initiator_id,
+       usalo_isatapi,
+       usalo_reset,
+       usalo_natname,
+};
+
+/*#undef sun*/
+/*#undef __sun*/
+/*#undef __sun__*/
+
+#if defined(sun) || defined(__sun) || defined(__sun__)
+#define        SCSI_IMPL               /* We have a SCSI implementation for Sun */
+
+#include "scsi-sun.c"
+
+#endif /* Sun */
+
+
+#ifdef linux
+#define        SCSI_IMPL               /* We have a SCSI implementation for Linux */
+
+#ifdef not_needed              /* We now have a local vrersion of pg.h  */
+#ifndef        HAVE_LINUX_PG_H         /* If we are compiling on an old version */
+#      undef   USE_PG_ONLY     /* there is no 'pg' driver and we cannot */
+#      undef   USE_PG          /* include <linux/pg.h> which is needed  */
+#endif                         /* by the pg transport code.             */
+#endif
+
+#ifdef USE_PG_ONLY
+#include "scsi-linux-pg.c"
+#else
+#include "scsi-linux-sg.c"
+#endif
+
+#endif /* linux */
+
+#if    defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)  || defined(__FreeBSD_kernel__) 
+#define        SCSI_IMPL               /* We have a SCSI implementation for *BSD */
+
+#include "scsi-bsd.c"
+
+#endif /* *BSD */
+
+#if    defined(__bsdi__)       /* We have a SCSI implementation for BSD/OS 3.x (and later?) */
+# include <sys/param.h>
+# if (_BSDI_VERSION >= 199701)
+#  define      SCSI_IMPL
+
+#  include "scsi-bsd-os.c"
+
+# endif        /* BSD/OS >= 3.0 */
+#endif /* BSD/OS */
+
+#ifdef __sgi
+#define        SCSI_IMPL               /* We have a SCSI implementation for SGI */
+
+#include "scsi-sgi.c"
+
+#endif /* SGI */
+
+#ifdef __hpux
+#define        SCSI_IMPL               /* We have a SCSI implementation for HP-UX */
+
+#include "scsi-hpux.c"
+
+#endif /* HP-UX */
+
+#if    defined(_IBMR2) || defined(_AIX)
+#define        SCSI_IMPL               /* We have a SCSI implementation for AIX */
+
+#include "scsi-aix.c"
+
+#endif /* AIX */
+
+#if    defined(__NeXT__) || defined(IS_MACOS_X)
+#if    defined(HAVE_BSD_DEV_SCSIREG_H)
+/*
+ *     This is the
+ */
+#define        SCSI_IMPL               /* We found a SCSI implementation for NextStep and Mac OS X */
+
+#include "scsi-next.c"
+#else
+
+#define        SCSI_IMPL               /* We found a SCSI implementation for Mac OS X (Darwin-1.4) */
+
+#include "scsi-mac-iokit.c"
+
+#endif /* HAVE_BSD_DEV_SCSIREG_H */
+
+#endif /* NEXT / Mac OS X */
+
+#if    defined(__osf__)
+#define        SCSI_IMPL               /* We have a SCSI implementation for OSF/1 */
+
+#include "scsi-osf.c"
+
+#endif /* OSF/1 */
+
+#ifdef VMS
+#define        SCSI_IMPL               /* We have a SCSI implementation for VMS */
+
+#include "scsi-vms.c"
+
+#endif /* VMS */
+
+#ifdef OPENSERVER
+#define        SCSI_IMPL               /* We have a SCSI implementation for SCO OpenServer */
+
+#include "scsi-openserver.c"
+
+#endif  /* SCO */
+
+#ifdef UNIXWARE
+#define        SCSI_IMPL               /* We have a SCSI implementation for SCO UnixWare */
+
+#include "scsi-unixware.c"
+
+#endif  /* UNIXWARE */
+
+#ifdef __OS2
+#define        SCSI_IMPL               /* We have a SCSI implementation for OS/2 */
+
+#include "scsi-os2.c"
+
+#endif  /* OS/2 */
+
+#ifdef __BEOS__
+#define        SCSI_IMPL               /* Yep, BeOS does that funky scsi stuff */
+#include "scsi-beos.c"
+#endif
+
+#ifdef __CYGWIN32__
+#define        SCSI_IMPL               /* Yep, we support WNT and W9? */
+#include "scsi-wnt.c"
+#endif
+
+#ifdef apollo
+#define        SCSI_IMPL               /* We have a SCSI implementation for Apollo Domain/OS */
+#include "scsi-apollo.c"
+#endif
+
+#ifdef AMIGA                   /* We have a SCSI implementation for AmigaOS */
+#define        SCSI_IMPL
+#include "scsi-amigaos.c"
+#endif
+
+#if    defined(__QNXNTO__) || defined(__QNX__)
+#define        SCSI_IMPL               /* We have a SCSI implementation for QNX */
+#include "scsi-qnx.c"
+#endif /* QNX */
+
+#ifdef __DJGPP__               /* We have a SCSI implementation for MS-DOS/DJGPP */
+#define        SCSI_IMPL
+#include "scsi-dos.c"
+#endif
+
+#ifdef __NEW_ARCHITECTURE
+#define        SCSI_IMPL               /* We have a SCSI implementation for XXX */
+/*
+ * Add new hacks here
+ */
+#include "scsi-new-arch.c"
+#endif
+
+
+#ifndef        SCSI_IMPL
+/*
+ * To make scsihack.c compile on all architectures.
+ * This does not mean that you may use it, but you can see
+ * if other problems exist.
+ */
+#define        usalo_dversion          usalo_version
+#define        usalo_dhelp             usalo_help
+#define        usalo_dopen             usalo_open
+#define        usalo_dclose            usalo_close
+#define        usalo_dmaxdma           usalo_maxdma
+#define        usalo_dgetbuf           usalo_getbuf
+#define        usalo_dfreebuf          usalo_freebuf
+#define        usalo_dhavebus          usalo_havebus
+#define        usalo_dfileno           usalo_fileno
+#define        usalo_dinitiator_id     usalo_initiator_id
+#define        usalo_disatapi          usalo_isatapi
+#define        usalo_dreset            usalo_reset
+#define        usalo_dsend             usalo_send
+#endif /* SCSI_IMPL */
+
+static int     usalo_dsend(SCSI *usalp);
+static char *usalo_dversion(SCSI *usalp, int what);
+static int     usalo_dhelp(SCSI *usalp, FILE *f);
+static int     usalo_nohelp(SCSI *usalp, FILE *f);
+static int     usalo_ropen(SCSI *usalp, char *device);
+static int     usalo_dopen(SCSI *usalp, char *device);
+static int     usalo_dclose(SCSI *usalp);
+static long    usalo_dmaxdma(SCSI *usalp, long amt);
+static void *usalo_dgetbuf(SCSI *usalp, long amt);
+static void    usalo_dfreebuf(SCSI *usalp);
+static BOOL    usalo_dhavebus(SCSI *usalp, int busno);
+static int     usalo_dfileno(SCSI *usalp, int busno, int tgt, int tlun);
+static int     usalo_dinitiator_id(SCSI *usalp);
+static int     usalo_disatapi(SCSI *usalp);
+static int     usalo_dreset(SCSI *usalp, int what);
+
+usal_ops_t usal_remote_ops = {
+       usalo_dsend,
+       usalo_dversion,
+       usalo_nohelp,
+       usalo_ropen,
+       usalo_dclose,
+       usalo_dmaxdma,
+       usalo_dgetbuf,
+       usalo_dfreebuf,
+       usalo_dhavebus,
+       usalo_dfileno,
+       usalo_dinitiator_id,
+       usalo_disatapi,
+       usalo_dreset,
+  usalo_natname,
+};
+
+usal_ops_t usal_dummy_ops = {
+       usalo_dsend,
+       usalo_dversion,
+       usalo_dhelp,
+       usalo_dopen,
+       usalo_dclose,
+       usalo_dmaxdma,
+       usalo_dgetbuf,
+       usalo_dfreebuf,
+       usalo_dhavebus,
+       usalo_dfileno,
+       usalo_dinitiator_id,
+       usalo_disatapi,
+       usalo_dreset,
+  usalo_natname,
+};
+
+/*
+ *     Warning: you may change this source, but if you do that
+ *     you need to change the _usal_version and _usal_auth* string below.
+ *     You may not return "schily" for an SCG_AUTHOR request anymore.
+ *     Choose your name instead of "schily" and make clear that the version
+ *     string is related to a modified source.
+ */
+static char    _usal_trans_dversion[] = "scsihack.c-1.44";     /* The version for this transport*/
+
+/*
+ * Return version information for the low level SCSI transport code.
+ * This has been introduced to make it easier to trace down problems
+ * in applications.
+ */
+static char *
+usalo_dversion(SCSI *usalp, int what)
+{
+       if (usalp != (SCSI *)0) {
+               switch (what) {
+
+               case SCG_VERSION:
+                       return (_usal_trans_dversion);
+               /*
+                * If you changed this source, you are not allowed to
+                * return "schily" for the SCG_AUTHOR request.
+                */
+               case SCG_AUTHOR:
+                       return (_usal_auth_cdrkit);
+               case SCG_SCCS_ID:
+                       return (_sccsid);
+               }
+       }
+       return ((char *)0);
+}
+
+static int
+usalo_dhelp(SCSI *usalp, FILE *f)
+{
+       printf("None.\n");
+       return (0);
+}
+
+static int
+usalo_nohelp(SCSI *usalp, FILE *f)
+{
+       return (0);
+}
+
+static int
+usalo_ropen(SCSI *usalp, char *device)
+{
+       comerrno(EX_BAD, "No remote SCSI transport available.\n");
+       return (-1);    /* Keep lint happy */
+}
+
+#ifndef        SCSI_IMPL
+static int
+usalo_dopen(SCSI *usalp, char *device)
+{
+       comerrno(EX_BAD, "No local SCSI transport implementation for this architecture.\n");
+       return (-1);    /* Keep lint happy */
+}
+#else
+static int
+usalo_dopen(SCSI *usalp, char *device)
+{
+       comerrno(EX_BAD, "SCSI open usage error.\n");
+       return (-1);    /* Keep lint happy */
+}
+#endif /* SCSI_IMPL */
+
+static int
+usalo_dclose(SCSI *usalp)
+{
+       errno = EINVAL;
+       return (-1);
+}
+
+static long
+usalo_dmaxdma(SCSI *usalp, long amt)
+{
+       errno = EINVAL;
+       return  (0L);
+}
+
+static void *
+usalo_dgetbuf(SCSI *usalp, long amt)
+{
+       errno = EINVAL;
+       return ((void *)0);
+}
+
+static void
+usalo_dfreebuf(SCSI *usalp)
+{
+}
+
+static BOOL
+usalo_dhavebus(SCSI *usalp, int busno)
+{
+       return (FALSE);
+}
+
+static int
+usalo_dfileno(SCSI *usalp, int busno, int tgt, int tlun)
+{
+       return (-1);
+}
+
+#ifndef HAVE_NAT_NAMES /* to be defined in included source if supported */
+static char * usalo_natname(SCSI *usalp, int busno, int tgt, int tlun) {
+   static char namebuf[81];
+   snprintf(namebuf, 80, "%d,%d,%d", usal_scsibus(usalp), usal_target(usalp), usal_lun(usalp));
+   return namebuf;
+}
+#endif
+
+static int
+usalo_dinitiator_id(SCSI *usalp)
+{
+       return (-1);
+}
+
+static int
+usalo_disatapi(SCSI *usalp)
+{
+       return (FALSE);
+}
+
+static int
+usalo_dreset(SCSI *usalp, int what)
+{
+       errno = EINVAL;
+       return (-1);
+}
+
+static int
+usalo_dsend(SCSI *usalp)
+{
+       errno = EINVAL;
+       return (-1);
+}
diff --git a/libusal/scsihelp.c b/libusal/scsihelp.c
new file mode 100644 (file)
index 0000000..4ddebfa
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)scsihelp.c      1.4 04/01/14 Copyright 2002 J. Schilling */
+/*
+ *     usal Library
+ *     Help subsystem
+ *
+ *     Copyright (c) 2002 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <mconfig.h>
+#include <stdio.h>
+#include <standard.h>
+#include <schily.h>
+
+#include <usal/scsitransp.h>
+
+void   __usal_help(FILE *f, char *name, char *tcomment, char *tind, char *tspec,
+                                         char *texample, BOOL mayscan, BOOL bydev);
+
+void
+__usal_help(FILE *f, char *name, char *tcomment, char *tind, char *tspec, 
+                         char *texample, BOOL mayscan, BOOL bydev)
+{
+       fprintf(f, "\nTransport name:           %s\n", name);
+       fprintf(f, "Transport descr.:   %s\n", tcomment);
+       fprintf(f, "Transp. layer ind.: %s\n", tind);
+       fprintf(f, "Target specifier:   %s\n", tspec);
+       fprintf(f, "Target example:             %s\n", texample);
+       fprintf(f, "SCSI Bus scanning:  %ssupported\n", mayscan? "":"not ");
+       fprintf(f, "Open via UNIX device:       %ssupported\n", bydev? "":"not ");
+}
diff --git a/libusal/scsiopen.c b/libusal/scsiopen.c
new file mode 100644 (file)
index 0000000..41dd1e9
--- /dev/null
@@ -0,0 +1,464 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)scsiopen.c      1.95 04/01/14 Copyright 1995,2000 J. Schilling */
+/*
+ *     SCSI command functions for cdrecord
+ *
+ *     Copyright (c) 1995,2000 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * NOTICE:     The Philips CDD 521 has several firmware bugs.
+ *             One of them is not to respond to a SCSI selection
+ *             within 200ms if the general load on the
+ *             SCSI bus is high. To deal with this problem
+ *             most of the SCSI commands are send with the
+ *             SCG_CMD_RETRY flag enabled.
+ *
+ *             Note that the only legal place to assign
+ *             values to usal_scsibus() usal_target() and usal_lun()
+ *             is usal_settarget().
+ */
+#include <mconfig.h>
+
+#include <stdio.h>
+#include <standard.h>
+#include <stdxlib.h>
+#include <unixstd.h>
+#include <fctldefs.h>
+#include <errno.h>
+#include <strdefs.h>
+#include <timedefs.h>
+
+#include <utypes.h>
+#include <btorder.h>
+#include <schily.h>
+
+#include <usal/usalcmd.h>
+#include <usal/scsidefs.h>
+#include <usal/scsireg.h>
+#include <usal/scsitransp.h>
+
+#if    defined(linux) || defined(__linux) || defined(__linux__)
+extern BOOL check_linux_26();
+#endif
+
+#define        strbeg(s1, s2)  (strstr((s2), (s1)) == (s2))
+
+extern int     lverbose;
+
+SCSI   *usal_open(char *scsidev, char *errs, int slen, int debug, int be_verbose);
+int    usal_help(FILE *f);
+static int     usal_scandev(char *devp, char *errs, int slen, int *busp, 
+                                                                       int *tgtp, int *lunp);
+int    usal_close(SCSI * usalp);
+
+void   usal_settimeout(SCSI * usalp, int timeout);
+
+SCSI   *usal_smalloc(void);
+void   usal_sfree(SCSI *usalp);
+
+/*
+ * Open a SCSI device.
+ *
+ * Possible syntax is:
+ *
+ * Preferred:
+ *     dev=target,lun / dev=scsibus,target,lun
+ *
+ * Needed on some systems:
+ *     dev=devicename:target,lun / dev=devicename:scsibus,target,lun
+ *
+ * On systems that don't support SCSI Bus scanning this syntax helps:
+ *     dev=devicename:@ / dev=devicename:@,lun
+ * or  dev=devicename (undocumented)
+ *
+ * NOTE: As the 'lun' is part of the SCSI command descriptor block, it
+ *      must always be known. If the OS cannot map it, it must be
+ *      specified on command line.
+ */
+SCSI *
+usal_open(char *scsidev, char *errs, int slen, int debug, int be_verbose)
+{
+       char    devname[256];
+       char    *devp = NULL;
+       char    *sdev = NULL;
+       int     x1;
+       int     bus = 0;
+       int     tgt = 0;
+       int     lun = 0;
+       int     n = 0;
+       SCSI    *usalp;
+
+       if (errs)
+               errs[0] = '\0';
+       usalp = usal_smalloc();
+       if (usalp == NULL) {
+               if (errs)
+                       snprintf(errs, slen, "No memory for SCSI structure");
+               return ((SCSI *)0);
+       }
+       usalp->debug = debug;
+       usalp->overbose = be_verbose;
+       devname[0] = '\0';
+       if (scsidev != NULL && scsidev[0] != '\0') {
+               sdev = scsidev;
+               if ((strncmp(scsidev, "HELP", 4) == 0) ||
+                   (strncmp(scsidev, "help", 4) == 0)) {
+
+                       return ((SCSI *)0);
+               }
+               if (strncmp(scsidev, "REMOTE", 6) == 0) {
+                       /*
+                        * REMOTE:user@host:scsidev or
+                        * REMOTE(transp):user@host:scsidev
+                        * e.g.: REMOTE(/usr/bin/ssh):user@host:scsidev
+                        *
+                        * We must send the complete device spec to the remote
+                        * site to allow parsing on both sites.
+                        */
+                       strncpy(devname, scsidev, sizeof (devname)-1);
+                       devname[sizeof (devname)-1] = '\0';
+                       if (sdev[6] == '(' || sdev[6] == ':')
+                               sdev = strchr(sdev, ':');
+                       else
+                               sdev = NULL;
+
+                       if (sdev == NULL) {
+                               /*
+                                * This seems to be an illegal remote dev spec.
+                                * Give it a chance with a standard parsing.
+                                */
+                               sdev = scsidev;
+                               devname[0] = '\0';
+                       } else {
+                               /*
+                                * Now try to go past user@host spec.
+                                */
+                               if (sdev)
+                                       sdev = strchr(&sdev[1], ':');
+                               if (sdev)
+                                       sdev++; /* Device name follows ... */
+                               else
+                                       goto nulldevice;
+                       }
+               }
+               if ((devp = strchr(sdev, ':')) == NULL) {
+                       if (strchr(sdev, ',') == NULL) {
+                               /* Notation form: 'devname' (undocumented)  */
+                               /* Forward complete name to usal__open()            */
+                               /* Fetch bus/tgt/lun values from OS         */
+                               /* We may come here too with 'USCSI'        */
+                               n = -1;
+                               lun  = -2;      /* Lun must be known        */
+                               if (devname[0] == '\0') {
+                                       strncpy(devname, scsidev,
+                                                       sizeof (devname)-1);
+                                       devname[sizeof (devname)-1] = '\0';
+                               }
+                       } else {
+                               /* Basic notation form: 'bus,tgt,lun'       */
+                               devp = sdev;
+                       }
+               } else {
+                       /* Notation form: 'devname:bus,tgt,lun'/'devname:@' */
+                       /* We may come here too with 'USCSI:'               */
+                       if (devname[0] == '\0') {
+                               /*
+                                * Copy over the part before the ':'
+                                */
+                               x1 = devp - scsidev;
+                               if (x1 >= (int)sizeof (devname))
+                                       x1 = sizeof (devname)-1;
+                               strncpy(devname, scsidev, x1);
+                               devname[x1] = '\0';
+                       }
+                       devp++;
+                       /* Check for a notation in the form 'devname:@'     */
+                       if (devp[0] == '@') {
+                               if (devp[1] == '\0') {
+                                       lun = -2;
+                               } else if (devp[1] == ',') {
+                                       if (*astoi(&devp[2], &lun) != '\0') {
+                                               errno = EINVAL;
+                                               if (errs)
+                                                       snprintf(errs, slen,
+                                                               "Invalid lun specifier '%s'",
+                                                                               &devp[2]);
+                                               return ((SCSI *)0);
+                                       }
+                               }
+                               n = -1;
+                               /*
+                                * Got device:@ or device:@,lun
+                                * Make sure not to call usal_scandev()
+                                */
+                               devp = NULL;
+                       } else if (devp[0] == '\0') {
+                               /*
+                                * Got USCSI: or ATAPI:
+                                * Make sure not to call usal_scandev()
+                                */
+                               devp = NULL;
+                       } else if (strchr(sdev, ',') == NULL) {
+                               /* We may come here with 'ATAPI:/dev/hdc'   */
+                               strncpy(devname, scsidev,
+                                               sizeof (devname)-1);
+                               devname[sizeof (devname)-1] = '\0';
+                               n = -1;
+                               lun  = -2;      /* Lun must be known        */
+                               /*
+                                * Make sure not to call usal_scandev()
+                                */
+                               devp = NULL;
+                       }
+               }
+       }
+nulldevice:
+
+/*fprintf(stderr, "10 scsidev '%s' sdev '%s' devp '%s' b: %d t: %d l: %d\n", scsidev, sdev, devp, bus, tgt, lun);*/
+
+       if (devp != NULL) {
+               n = usal_scandev(devp, errs, slen, &bus, &tgt, &lun);
+               if (n < 0) {
+                       errno = EINVAL;
+                       return ((SCSI *)0);
+               }
+       }
+       if (n >= 1 && n <= 3) { /* Got bus,target,lun or target,lun or tgt*/
+               usal_settarget(usalp, bus, tgt, lun);
+       } else if (n == -1) {   /* Got device:@, fetch bus/lun from OS  */
+               usal_settarget(usalp, -2, -2, lun);
+       } else if (devp != NULL) {
+               /*
+                * XXX May this happen after we allow tgt to repesent tgt,0 ?
+                */
+               fprintf(stderr, "WARNING: device not valid, trying to use default target...\n");
+               usal_settarget(usalp, 0, 6, 0);
+       }
+       if (be_verbose && scsidev != NULL) {
+               fprintf(stderr, "scsidev: '%s'\n", scsidev);
+               if (devname[0] != '\0')
+                       fprintf(stderr, "devname: '%s'\n", devname);
+               fprintf(stderr, "scsibus: %d target: %d lun: %d\n",
+                                       usal_scsibus(usalp), usal_target(usalp), usal_lun(usalp));
+       }
+       if (debug > 0) {
+               fprintf(stderr, "usal__open(%s) %d,%d,%d\n",
+                       devname,
+                       usal_scsibus(usalp), usal_target(usalp), usal_lun(usalp));
+       }
+       if (usal__open(usalp, devname) <= 0) {
+               if (errs && usalp->errstr)
+                       snprintf(errs, slen, "%s", usalp->errstr);
+               usal_sfree(usalp);
+               return ((SCSI *)0);
+       }
+       return (usalp);
+}
+
+int
+usal_help(FILE *f)
+{
+       SCSI    *usalp;
+
+       usalp = usal_smalloc();
+       if (usalp != NULL) {
+extern usal_ops_t usal_std_ops;
+
+               usalp->ops = &usal_std_ops;
+
+               printf("Supported SCSI transports for this platform:\n");
+               SCGO_HELP(usalp, f);
+               usal_remote()->usalo_help(usalp, f);
+               usal_sfree(usalp);
+       }
+       return (0);
+}
+
+/*
+ * Convert target,lun or scsibus,target,lun syntax.
+ * Check for bad syntax and invalid values.
+ * This is definitely better than using scanf() as it checks for syntax errors.
+ */
+static int
+usal_scandev(char *devp, char *errs, int slen, int *busp, int *tgtp, int *lunp)
+{
+       int     x1, x2, x3;
+       int     n = 0;
+       char    *p = devp;
+
+       x1 = x2 = x3 = 0;
+       *busp = *tgtp = *lunp = 0;
+
+       if (*p != '\0') {
+               p = astoi(p, &x1);
+               if (*p == ',') {
+                       p++;
+                       n++;
+               } else {
+                       if (errs)
+                               snprintf(errs, slen, "Invalid bus or target specifier in '%s'", devp);
+                       return (-1);
+               }
+       }
+       if (*p != '\0') {
+               p = astoi(p, &x2);
+               if (*p == ',' || *p == '\0') {
+                       if (*p != '\0')
+                               p++;
+                       n++;
+               } else {
+                       if (errs)
+                               snprintf(errs, slen, "Invalid target or lun specifier in '%s'", devp);
+                       return (-1);
+               }
+       }
+       if (*p != '\0') {
+               p = astoi(p, &x3);
+               if (*p == '\0') {
+                       n++;
+               } else {
+                       if (errs)
+                               snprintf(errs, slen, "Invalid lun specifier in '%s'", devp);
+                       return (-1);
+               }
+       }
+       if (n == 3) {
+               *busp = x1;
+               *tgtp = x2;
+               *lunp = x3;
+       }
+       if (n == 2) {
+               *tgtp = x1;
+               *lunp = x2;
+       }
+       if (n == 1) {
+               *tgtp = x1;
+       }
+
+       if (x1 < 0 || x2 < 0 || x3 < 0) {
+               if (errs)
+                       snprintf(errs, slen, "Invalid value for bus, target or lun (%d,%d,%d)",
+                               *busp, *tgtp, *lunp);
+               return (-1);
+       }
+       return (n);
+}
+
+int
+usal_close(SCSI *usalp)
+{
+       usal__close(usalp);
+       usal_sfree(usalp);
+       return (0);
+}
+
+char * usal_natname(SCSI *usalp, int busno, int tgt, int tlun) {
+       return usalp->ops->usalo_natname(usalp, busno, tgt, tlun);
+}
+
+int usal_fileno(SCSI *usalp, int busno, int tgt, int tlun) {
+       return usalp->ops->usalo_fileno(usalp, busno, tgt, tlun);
+}
+
+void
+usal_settimeout(SCSI *usalp, int timeout)
+{
+#ifdef nonono
+       if (timeout >= 0)
+               usalp->deftimeout = timeout;
+#else
+       usalp->deftimeout = timeout;
+#endif
+}
+
+SCSI *
+usal_smalloc()
+{
+       SCSI    *usalp;
+extern usal_ops_t usal_dummy_ops;
+
+       usalp = (SCSI *)malloc(sizeof (*usalp));
+       if (usalp == NULL)
+               return ((SCSI *)0);
+
+       fillbytes(usalp, sizeof (*usalp), 0);
+       usalp->ops      = &usal_dummy_ops;
+       usal_settarget(usalp, -1, -1, -1);
+       usalp->fd       = -1;
+       usalp->deftimeout = 20;
+       usalp->running  = FALSE;
+
+       usalp->cmdstart = (struct timeval *)malloc(sizeof (struct timeval));
+       if (usalp->cmdstart == NULL)
+               goto err;
+       usalp->cmdstop = (struct timeval *)malloc(sizeof (struct timeval));
+       if (usalp->cmdstop == NULL)
+               goto err;
+       usalp->scmd = (struct usal_cmd *)malloc(sizeof (struct usal_cmd));
+       if (usalp->scmd == NULL)
+               goto err;
+       usalp->errstr = malloc(SCSI_ERRSTR_SIZE);
+       if (usalp->errstr == NULL)
+               goto err;
+       usalp->errptr = usalp->errbeg = usalp->errstr;
+       usalp->errstr[0] = '\0';
+       usalp->errfile = (void *)stderr;
+       usalp->inq = (struct scsi_inquiry *)malloc(sizeof (struct scsi_inquiry));
+       if (usalp->inq == NULL)
+               goto err;
+       usalp->cap = (struct scsi_capacity *)malloc(sizeof (struct scsi_capacity));
+       if (usalp->cap == NULL)
+               goto err;
+
+       return (usalp);
+err:
+       usal_sfree(usalp);
+       return ((SCSI *)0);
+}
+
+void
+usal_sfree(SCSI *usalp)
+{
+       if (usalp->cmdstart)
+               free(usalp->cmdstart);
+       if (usalp->cmdstop)
+               free(usalp->cmdstop);
+       if (usalp->scmd)
+               free(usalp->scmd);
+       if (usalp->inq)
+               free(usalp->inq);
+       if (usalp->cap)
+               free(usalp->cap);
+       if (usalp->local)
+               free(usalp->local);
+       usal_freebuf(usalp);
+       if (usalp->errstr)
+               free(usalp->errstr);
+       free(usalp);
+}
diff --git a/libusal/scsitransp.c b/libusal/scsitransp.c
new file mode 100644 (file)
index 0000000..b3cc502
--- /dev/null
@@ -0,0 +1,1345 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)scsitransp.c    1.91 04/06/17 Copyright 1988,1995,2000-2004 J. Schilling */
+/*#ifndef lint*/
+static char sccsid[] =
+       "@(#)scsitransp.c       1.91 04/06/17 Copyright 1988,1995,2000-2004 J. Schilling";
+/*#endif*/
+/*
+ *     SCSI user level command transport routines (generic part).
+ *
+ *     Warning: you may change this source, but if you do that
+ *     you need to change the _usal_version and _usal_auth* string below.
+ *     You may not return "schily" for an SCG_AUTHOR request anymore.
+ *     Choose your name instead of "schily" and make clear that the version
+ *     string is related to a modified source.
+ *
+ *     Copyright (c) 1988,1995,2000-2004 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <mconfig.h>
+#include <stdio.h>
+#include <standard.h>
+#include <stdxlib.h>
+#include <unixstd.h>
+#include <errno.h>
+#include <timedefs.h>
+#include <strdefs.h>
+#include <schily.h>
+
+#include <usal/usalcmd.h>
+#include <usal/scsireg.h>
+#include <usal/scsitransp.h>
+#include "usaltimes.h"
+
+#include <stdarg.h>
+
+
+/*
+ *     Warning: you may change this source, but if you do that
+ *     you need to change the _usal_version and _usal_auth* string below.
+ *     You may not return "schily" for an SCG_AUTHOR request anymore.
+ *     Choose your name instead of "schily" and make clear that the version
+ *     string is related to a modified source.
+ */
+static char    _usal_version[]         = CDRKIT_VERSION;       /* The global libusal version   */
+static char    _usal_auth_cdrkit[]     = "Cdrkit";     /* The author for this module   */
+
+#define        DEFTIMEOUT      20      /* Default timeout for SCSI command transport */
+
+char   *usal_version(SCSI *usalp, int what);
+int    usal__open(SCSI *usalp, char *device);
+int    usal__close(SCSI *usalp);
+BOOL   usal_havebus(SCSI *usalp, int);
+int    usal_initiator_id(SCSI *usalp);
+int    usal_isatapi(SCSI *usalp);
+int    usal_reset(SCSI *usalp, int what);
+void   *usal_getbuf(SCSI *usalp, long);
+void   usal_freebuf(SCSI *usalp);
+long   usal_bufsize(SCSI *usalp, long);
+void   usal_setnonstderrs(SCSI *usalp, const char **);
+BOOL   usal_yes(char *);
+#ifdef nonono
+static void    usal_sighandler(int);
+#endif
+int    usal_cmd(SCSI *usalp);
+void   usal_vhead(SCSI *usalp);
+int    usal_svhead(SCSI *usalp, char *buf, int maxcnt);
+int    usal_vtail(SCSI *usalp);
+int    usal_svtail(SCSI *usalp, int *retp, char *buf, int maxcnt);
+void   usal_vsetup(SCSI *usalp);
+int    usal_getresid(SCSI *usalp);
+int    usal_getdmacnt(SCSI *usalp);
+BOOL   usal_cmd_err(SCSI *usalp);
+void   usal_printerr(SCSI *usalp);
+void   usal_fprinterr(SCSI *usalp, FILE *f);
+int    usal_sprinterr(SCSI *usalp, char *buf, int maxcnt);
+int    usal__sprinterr(SCSI *usalp, char *buf, int maxcnt);
+void   usal_printcdb(SCSI *usalp);
+int    usal_sprintcdb(SCSI *usalp, char *buf, int maxcnt);
+void   usal_printwdata(SCSI *usalp);
+int    usal_sprintwdata(SCSI *usalp, char *buf, int maxcnt);
+void   usal_printrdata(SCSI *usalp);
+int    usal_sprintrdata(SCSI *usalp, char *buf, int maxcnt);
+void   usal_printresult(SCSI *usalp);
+int    usal_sprintresult(SCSI *usalp, char *buf, int maxcnt);
+void   usal_printstatus(SCSI *usalp);
+int    usal_sprintstatus(SCSI *usalp, char *buf, int maxcnt);
+void   usal_fprbytes(FILE *, char *, unsigned char *, int);
+void   usal_fprascii(FILE *, char *, unsigned char *, int);
+void   usal_prbytes(char *, unsigned char *, int);
+void   usal_prascii(char *, unsigned char *, int);
+int    usal_sprbytes(char *buf, int maxcnt, char *, unsigned char *, int);
+int    usal_sprascii(char *buf, int maxcnt, char *, unsigned char *, int);
+void   usal_fprsense(FILE *f, unsigned char *, int);
+int    usal_sprsense(char *buf, int maxcnt, unsigned char *, int);
+void   usal_prsense(unsigned char *, int);
+int    usal_cmd_status(SCSI *usalp);
+int    usal_sense_key(SCSI *usalp);
+int    usal_sense_code(SCSI *usalp);
+int    usal_sense_qual(SCSI *usalp);
+unsigned char *usal_sense_table(SCSI *usalp);
+void   usal_fprintdev(FILE *, struct scsi_inquiry *);
+void   usal_printdev(struct scsi_inquiry *);
+int    usal_printf(SCSI *usalp, const char *form, ...);
+int    usal_errflush(SCSI *usalp);
+int    usal_errfflush(SCSI *usalp, FILE *f);
+
+/*
+ * Return version information for the SCSI transport code.
+ * This has been introduced to make it easier to trace down problems
+ * in applications.
+ *
+ * If usalp is NULL, return general library version information.
+ * If usalp is != NULL, return version information for the low level transport.
+ */
+char *
+usal_version(SCSI *usalp, int what)
+{
+       if (usalp == (SCSI *)0) {
+               switch (what) {
+
+               case SCG_VERSION:
+                       return (_usal_version);
+               /*
+                * If you changed this source, you are not allowed to
+                * return "schily" for the SCG_AUTHOR request.
+                */
+               case SCG_AUTHOR:
+                       return (_usal_auth_cdrkit);
+               case SCG_SCCS_ID:
+                       return (sccsid);
+               default:
+                       return ((char *)0);
+               }
+       }
+       return (SCGO_VERSION(usalp, what));
+}
+
+/*
+ * Call low level SCSI open routine from transport abstraction layer.
+ */
+int
+usal__open(SCSI *usalp, char *device)
+{
+       int     ret;
+       usal_ops_t *ops;
+extern usal_ops_t usal_std_ops;
+
+       usalp->ops = &usal_std_ops;
+
+       if (device && strncmp(device, "REMOTE", 6) == 0) {
+               ops = usal_remote();
+               if (ops != NULL)
+                       usalp->ops = ops;
+       }
+
+       ret = SCGO_OPEN(usalp, device);
+       if (ret < 0)
+               return (ret);
+
+       /*
+        * Now make usalp->fd valid if possible.
+        * Note that usal_scsibus(usalp)/usal_target(usalp)/usal_lun(usalp) may have
+        * changed in SCGO_OPEN().
+        */
+       usal_settarget(usalp, usal_scsibus(usalp), usal_target(usalp), usal_lun(usalp));
+       return (ret);
+}
+
+/*
+ * Call low level SCSI close routine from transport abstraction layer.
+ */
+int
+usal__close(SCSI *usalp)
+{
+       return (SCGO_CLOSE(usalp));
+}
+
+/*
+ * Retrieve max DMA count for this target.
+ */
+long
+usal_bufsize(SCSI *usalp, long amt)
+{
+       long    maxdma;
+
+       maxdma = SCGO_MAXDMA(usalp, amt);
+       if (amt <= 0 || amt > maxdma)
+               amt = maxdma;
+
+       usalp->maxdma = maxdma; /* Max possible  */
+       usalp->maxbuf = amt;    /* Current value */
+
+       return (amt);
+}
+
+/*
+ * Allocate a buffer that may be used for DMA.
+ */
+void *
+usal_getbuf(SCSI *usalp, long amt)
+{
+       void    *buf;
+
+       if (amt <= 0 || amt > usal_bufsize(usalp, amt))
+               return ((void *)0);
+
+       buf = SCGO_GETBUF(usalp, amt);
+       usalp->bufptr = buf;
+       return (buf);
+}
+
+/*
+ * Free DMA buffer.
+ */
+void
+usal_freebuf(SCSI *usalp)
+{
+       SCGO_FREEBUF(usalp);
+       usalp->bufptr = NULL;
+}
+
+/*
+ * Check if 'busno' is a valid SCSI bus number.
+ */
+BOOL
+usal_havebus(SCSI *usalp, int busno)
+{
+       return (SCGO_HAVEBUS(usalp, busno));
+}
+
+/*
+ * Return SCSI initiator ID for current SCSI bus if available.
+ */
+int
+usal_initiator_id(SCSI *usalp)
+{
+       return (SCGO_INITIATOR_ID(usalp));
+}
+
+/*
+ * Return a hint whether current SCSI target refers to a ATAPI device.
+ */
+int
+usal_isatapi(SCSI *usalp)
+{
+       return (SCGO_ISATAPI(usalp));
+}
+
+/*
+ * Reset SCSI bus or target.
+ */
+int
+usal_reset(SCSI *usalp, int what)
+{
+       return (SCGO_RESET(usalp, what));
+}
+
+/*
+ * Set up nonstd error vector for curren target.
+ * To clear additional error table, call usal_setnonstderrs(usalp, NULL);
+ * Note: do not use this when scanning the SCSI bus.
+ */
+void
+usal_setnonstderrs(SCSI *usalp, const char **vec)
+{
+       usalp->nonstderrs = vec;
+}
+
+/*
+ * Simple Yes/No answer checker.
+ */
+BOOL
+usal_yes(char *msg)
+{
+       char okbuf[10];
+
+       printf("%s", msg);
+       flush();
+       if (rols_getline(okbuf, sizeof (okbuf)) == EOF)
+               exit(EX_BAD);
+       if (streql(okbuf, "y") || streql(okbuf, "yes") ||
+           streql(okbuf, "Y") || streql(okbuf, "YES"))
+               return (TRUE);
+       else
+               return (FALSE);
+}
+
+#ifdef nonono
+static void
+usal_sighandler(int sig)
+{
+       printf("\n");
+       if (scsi_running) {
+               printf("Running command: %s\n", scsi_command);
+               printf("Resetting SCSI - Bus.\n");
+               if (usal_reset(usalp) < 0)
+                       errmsg("Cannot reset SCSI - Bus.\n");
+       }
+       if (usal_yes("EXIT ? "))
+               exit(sig);
+}
+#endif
+
+/*
+ * Send a SCSI command.
+ * Do error checking and reporting depending on the values of
+ * usalp->verbose, usalp->debug and usalp->silent.
+ */
+int
+usal_cmd(SCSI *usalp)
+{
+               int             ret;
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       /*
+        * Reset old error messages in usalp->errstr
+        */
+       usalp->errptr = usalp->errbeg = usalp->errstr;
+
+       scmd->kdebug = usalp->kdebug;
+       if (scmd->timeout == 0 || scmd->timeout < usalp->deftimeout)
+               scmd->timeout = usalp->deftimeout;
+       if (usalp->disre_disable)
+               scmd->flags &= ~SCG_DISRE_ENA;
+       if (usalp->noparity)
+               scmd->flags |= SCG_NOPARITY;
+
+       scmd->u_sense.cmd_sense[0] = 0;         /* Paranioa */
+       if (scmd->sense_len > SCG_MAX_SENSE)
+               scmd->sense_len = SCG_MAX_SENSE;
+       else if (scmd->sense_len < 0)
+               scmd->sense_len = 0;
+
+       if (usalp->verbose) {
+               usal_vhead(usalp);
+               usal_errflush(usalp);
+       }
+
+       if (usalp->running) {
+               if (usalp->curcmdname) {
+                       fprintf(stderr, "Currently running '%s' command.\n",
+                                                       usalp->curcmdname);
+               }
+               raisecond("SCSI ALREADY RUNNING !!", 0L);
+       }
+       usalp->cb_fun = NULL;
+       gettimeofday(usalp->cmdstart, (struct timezone *)0);
+       usalp->curcmdname = usalp->cmdname;
+       usalp->running = TRUE;
+       ret = SCGO_SEND(usalp);
+       usalp->running = FALSE;
+       __usal_times(usalp);
+       if (ret < 0) {
+               /*
+                * Old /dev/usal versions will not allow to access targets > 7.
+                * Include a workaround to make this non fatal.
+                */
+               if (usal_target(usalp) < 8 || geterrno() != EINVAL)
+                       comerr("Cannot send SCSI cmd via ioctl\n");
+               if (scmd->ux_errno == 0)
+                       scmd->ux_errno = geterrno();
+               if (scmd->error == SCG_NO_ERROR)
+                       scmd->error = SCG_FATAL;
+               if (usalp->debug > 0) {
+                       errmsg("ret < 0 errno: %d ux_errno: %d error: %d\n",
+                                       geterrno(), scmd->ux_errno, scmd->error);
+               }
+       }
+
+       ret = usal_vtail(usalp);
+       usal_errflush(usalp);
+       if (usalp->cb_fun != NULL)
+               (*usalp->cb_fun)(usalp->cb_arg);
+       return (ret);
+}
+
+/*
+ * Fill the head of verbose printing into the SCSI error buffer.
+ * Action depends on SCSI verbose status.
+ */
+void
+usal_vhead(SCSI *usalp)
+{
+       usalp->errptr += usal_svhead(usalp, usalp->errptr, usal_errrsize(usalp));
+}
+
+/*
+ * Fill the head of verbose printing into a buffer.
+ * Action depends on SCSI verbose status.
+ */
+int
+usal_svhead(SCSI *usalp, char *buf, int maxcnt)
+{
+       register char   *p = buf;
+       register int    amt;
+
+       if (usalp->verbose <= 0)
+               return (0);
+
+       amt = snprintf(p, maxcnt,
+               "\nExecuting '%s' command on Bus %d Target %d, Lun %d timeout %ds\n",
+                                                               /* XXX Really this ??? */
+/*             usalp->cmdname, usal_scsibus(usalp), usal_target(usalp), usalp->scmd->cdb.g0_cdb.lun,*/
+               usalp->cmdname, usal_scsibus(usalp), usal_target(usalp), usal_lun(usalp),
+               usalp->scmd->timeout);
+       if (amt < 0)
+               return (amt);
+       p += amt;
+       maxcnt -= amt;
+
+       amt = usal_sprintcdb(usalp, p, maxcnt);
+       if (amt < 0)
+               return (amt);
+       p += amt;
+       maxcnt -= amt;
+
+       if (usalp->verbose > 1) {
+               amt = usal_sprintwdata(usalp, p, maxcnt);
+               if (amt < 0)
+                       return (amt);
+               p += amt;
+               maxcnt -= amt;
+       }
+       return (p - buf);
+}
+
+/*
+ * Fill the tail of verbose printing into the SCSI error buffer.
+ * Action depends on SCSI verbose status.
+ */
+int
+usal_vtail(SCSI *usalp)
+{
+       int     ret;
+
+       usalp->errptr += usal_svtail(usalp, &ret, usalp->errptr, usal_errrsize(usalp));
+       return (ret);
+}
+
+/*
+ * Fill the tail of verbose printing into a buffer.
+ * Action depends on SCSI verbose status.
+ */
+int
+usal_svtail(SCSI *usalp, int *retp, char *buf, int maxcnt)
+{
+       register char   *p = buf;
+       register int    amt;
+       int     ret;
+
+       ret = usal_cmd_err(usalp) ? -1 : 0;
+       if (retp)
+               *retp = ret;
+       if (ret) {
+               if (usalp->silent <= 0 || usalp->verbose) {
+                       amt = usal__sprinterr(usalp, p, maxcnt);
+                       if (amt < 0)
+                               return (amt);
+                       p += amt;
+                       maxcnt -= amt;
+               }
+       }
+       if ((usalp->silent <= 0 || usalp->verbose) && usalp->scmd->resid) {
+               if (usalp->scmd->resid < 0) {
+                       /*
+                        * An operating system that does DMA the right way
+                        * will not allow DMA overruns - it will stop DMA
+                        * before bad things happen.
+                        * A DMA residual count < 0 (-1) is a hint for a DMA
+                        * overrun but does not affect the transfer count.
+                        */
+                       amt = snprintf(p, maxcnt, "DMA overrun, ");
+                       if (amt < 0)
+                               return (amt);
+                       p += amt;
+                       maxcnt -= amt;
+               }
+               amt = snprintf(p, maxcnt, "resid: %d\n", usalp->scmd->resid);
+               if (amt < 0)
+                       return (amt);
+               p += amt;
+               maxcnt -= amt;
+       }
+       if (usalp->verbose > 0 || (ret < 0 && usalp->silent <= 0)) {
+               amt = usal_sprintresult(usalp, p, maxcnt);
+               if (amt < 0)
+                       return (amt);
+               p += amt;
+               maxcnt -= amt;
+       }
+       return (p - buf);
+}
+
+/*
+ * Set up SCSI error buffer with verbose print data.
+ * Action depends on SCSI verbose status.
+ */
+void
+usal_vsetup(SCSI *usalp)
+{
+       usal_vhead(usalp);
+       usal_vtail(usalp);
+}
+
+/*
+ * Return the residual DMA count for last command.
+ * If this count is < 0, then a DMA overrun occured.
+ */
+int
+usal_getresid(SCSI *usalp)
+{
+       return (usalp->scmd->resid);
+}
+
+/*
+ * Return the actual DMA count for last command.
+ */
+int
+usal_getdmacnt(SCSI *usalp)
+{
+       register struct usal_cmd *scmd = usalp->scmd;
+
+       if (scmd->resid < 0)
+               return (scmd->size);
+
+       return (scmd->size - scmd->resid);
+}
+
+/*
+ * Test if last SCSI command got an error.
+ */
+BOOL
+usal_cmd_err(SCSI *usalp)
+{
+       register struct usal_cmd *cp = usalp->scmd;
+
+       if (cp->error != SCG_NO_ERROR ||
+                               cp->ux_errno != 0 ||
+                               *(Uchar *)&cp->scb != 0 ||
+                               cp->u_sense.cmd_sense[0] != 0)  /* Paranioa */
+               return (TRUE);
+       return (FALSE);
+}
+
+/*
+ * Used to print error messges if the command itself has been run silently.
+ *
+ * print the following SCSI codes:
+ *
+ * -   command transport status
+ * -   CDB
+ * -   SCSI status byte
+ * -   Sense Bytes
+ * -   Decoded Sense data
+ * -   DMA status
+ * -   SCSI timing
+ *
+ * to SCSI errfile.
+ */
+void
+usal_printerr(SCSI *usalp)
+{
+       usal_fprinterr(usalp, (FILE *)usalp->errfile);
+}
+
+/*
+ * print the following SCSI codes:
+ *
+ * -   command transport status
+ * -   CDB
+ * -   SCSI status byte
+ * -   Sense Bytes
+ * -   Decoded Sense data
+ * -   DMA status
+ * -   SCSI timing
+ *
+ * to a file.
+ */
+void
+usal_fprinterr(SCSI *usalp, FILE *f)
+{
+       char    errbuf[SCSI_ERRSTR_SIZE];
+       int     amt;
+
+       amt = usal_sprinterr(usalp, errbuf, sizeof (errbuf));
+       if (amt > 0) {
+               filewrite(f, errbuf, amt);
+               fflush(f);
+       }
+}
+
+/*
+ * print the following SCSI codes:
+ *
+ * -   command transport status
+ * -   CDB
+ * -   SCSI status byte
+ * -   Sense Bytes
+ * -   Decoded Sense data
+ * -   DMA status
+ * -   SCSI timing
+ *
+ * into a buffer.
+ */
+int
+usal_sprinterr(SCSI *usalp, char *buf, int maxcnt)
+{
+       int     amt;
+       int     osilent = usalp->silent;
+       int     overbose = usalp->verbose;
+
+       usalp->silent = 0;
+       usalp->verbose = 0;
+       amt = usal_svtail(usalp, NULL, buf, maxcnt);
+       usalp->silent = osilent;
+       usalp->verbose = overbose;
+       return (amt);
+}
+
+/*
+ * print the following SCSI codes:
+ *
+ * -   command transport status
+ * -   CDB
+ * -   SCSI status byte
+ * -   Sense Bytes
+ * -   Decoded Sense data
+ *
+ * into a buffer.
+ */
+int
+usal__sprinterr(SCSI *usalp, char *buf, int maxcnt)
+{
+       register struct usal_cmd *cp = usalp->scmd;
+       register char           *err;
+               char            *cmdname = "SCSI command name not set by caller";
+               char            errbuf[64];
+       register char           *p = buf;
+       register int            amt;
+
+       switch (cp->error) {
+
+       case SCG_NO_ERROR :     err = "no error"; break;
+       case SCG_RETRYABLE:     err = "retryable error"; break;
+       case SCG_FATAL    :     err = "fatal error"; break;
+                               /*
+                                * We need to cast timeval->* to long because
+                                * of the broken sys/time.h in Linux.
+                                */
+       case SCG_TIMEOUT  :     snprintf(errbuf, sizeof (errbuf),
+                                       "cmd timeout after %ld.%03ld (%d) s",
+                                       (long)usalp->cmdstop->tv_sec,
+                                       (long)usalp->cmdstop->tv_usec/1000,
+                                                               cp->timeout);
+                               err = errbuf;
+                               break;
+       default:                snprintf(errbuf, sizeof (errbuf),
+                                       "error: %d", cp->error);
+                               err = errbuf;
+       }
+
+       if (usalp->cmdname != NULL && usalp->cmdname[0] != '\0')
+               cmdname = usalp->cmdname;
+       /*amt = serrmsgno(cp->ux_errno, p, maxcnt, "%s: scsi sendcmd: %s\n", cmdname, err);
+       if (amt < 0)
+               return (amt);
+    */
+  amt=snprintf(p, maxcnt, "Errno: %d (%s), %s scsi sendcmd: %s\n", cp->ux_errno, strerror(cp->ux_errno), cmdname, err);
+  if(amt>=maxcnt || amt<0)
+     return (amt);
+       p += amt;
+       maxcnt -= amt;
+
+       amt = usal_sprintcdb(usalp, p, maxcnt);
+       if (amt < 0)
+               return (amt);
+       p += amt;
+       maxcnt -= amt;
+
+       if (cp->error <= SCG_RETRYABLE) {
+               amt = usal_sprintstatus(usalp, p, maxcnt);
+               if (amt < 0)
+                       return (amt);
+               p += amt;
+               maxcnt -= amt;
+       }
+
+       if (cp->scb.chk) {
+               amt = usal_sprsense(p, maxcnt, (Uchar *)&cp->sense, cp->sense_count);
+               if (amt < 0)
+                       return (amt);
+               p += amt;
+               maxcnt -= amt;
+               amt = usal__errmsg(usalp, p, maxcnt, &cp->sense, &cp->scb, -1);
+               if (amt < 0)
+                       return (amt);
+               p += amt;
+               maxcnt -= amt;
+       }
+       return (p - buf);
+}
+
+/*
+ * XXX Do we need this function?
+ *
+ * print the SCSI Command descriptor block to XXX stderr.
+ */
+void
+usal_printcdb(SCSI *usalp)
+{
+       usal_prbytes("CDB: ", usalp->scmd->cdb.cmd_cdb, usalp->scmd->cdb_len);
+}
+
+/*
+ * print the SCSI Command descriptor block into a buffer.
+ */
+int
+usal_sprintcdb(SCSI *usalp, char *buf, int maxcnt)
+{
+       int     cnt;
+
+       cnt = usal_sprbytes(buf, maxcnt, "CDB: ", usalp->scmd->cdb.cmd_cdb, usalp->scmd->cdb_len);
+       if (cnt < 0)
+               cnt = 0;
+       return (cnt);
+}
+
+/*
+ * XXX Do we need this function?
+ * XXX usal_printrdata() is used.
+ * XXX We need to check if we should write to stderr or better to usal->errfile
+ *
+ * print the SCSI send data to stderr.
+ */
+void
+usal_printwdata(SCSI *usalp)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       if (scmd->size > 0 && (scmd->flags & SCG_RECV_DATA) == 0) {
+               fprintf(stderr, "Sending %d (0x%X) bytes of data.\n",
+                       scmd->size, scmd->size);
+               usal_prbytes("Write Data: ",
+                       (Uchar *)scmd->addr,
+                       scmd->size > 100 ? 100 : scmd->size);
+       }
+}
+
+/*
+ * print the SCSI send data into a buffer.
+ */
+int
+usal_sprintwdata(SCSI *usalp, char *buf, int maxcnt)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+       register char           *p = buf;
+       register int            amt;
+
+       if (scmd->size > 0 && (scmd->flags & SCG_RECV_DATA) == 0) {
+               amt = snprintf(p, maxcnt,
+                       "Sending %d (0x%X) bytes of data.\n",
+                       scmd->size, scmd->size);
+               if (amt < 0)
+                       return (amt);
+               p += amt;
+               maxcnt -= amt;
+               amt = usal_sprbytes(p, maxcnt, "Write Data: ",
+                       (Uchar *)scmd->addr,
+                       scmd->size > 100 ? 100 : scmd->size);
+               if (amt < 0)
+                       return (amt);
+               p += amt;
+       }
+       return (p - buf);
+}
+
+/*
+ * XXX We need to check if we should write to stderr or better to usal->errfile
+ *
+ * print the SCSI received data to stderr.
+ */
+void
+usal_printrdata(SCSI *usalp)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+       register int            trcnt = usal_getdmacnt(usalp);
+
+       if (scmd->size > 0 && (scmd->flags & SCG_RECV_DATA) != 0) {
+               fprintf(stderr, "Got %d (0x%X), expecting %d (0x%X) bytes of data.\n",
+                       trcnt, trcnt,
+                       scmd->size, scmd->size);
+               usal_prbytes("Received Data: ",
+                       (Uchar *)scmd->addr,
+                       trcnt > 100 ? 100 : trcnt);
+       }
+}
+
+/*
+ * print the SCSI received data into a buffer.
+ */
+int
+usal_sprintrdata(SCSI *usalp, char *buf, int maxcnt)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+       register char           *p = buf;
+       register int            amt;
+       register int            trcnt = usal_getdmacnt(usalp);
+
+       if (scmd->size > 0 && (scmd->flags & SCG_RECV_DATA) != 0) {
+               amt = snprintf(p, maxcnt,
+                       "Got %d (0x%X), expecting %d (0x%X) bytes of data.\n",
+                       trcnt, trcnt,
+                       scmd->size, scmd->size);
+               if (amt < 0)
+                       return (amt);
+               p += amt;
+               maxcnt -= amt;
+               amt = usal_sprbytes(p, maxcnt,
+                       "Received Data: ",
+                       (Uchar *)scmd->addr,
+                       trcnt > 100 ? 100 : trcnt);
+               if (amt < 0)
+                       return (amt);
+               p += amt;
+       }
+       return (p - buf);
+}
+
+/*
+ * XXX We need to check if we should write to stderr or better to usal->errfile
+ *
+ * print the SCSI timings and (depending on verbose) received data to stderr.
+ */
+void
+usal_printresult(SCSI *usalp)
+{
+       fprintf(stderr, "cmd finished after %ld.%03lds timeout %ds\n",
+               (long)usalp->cmdstop->tv_sec,
+               (long)usalp->cmdstop->tv_usec/1000,
+               usalp->scmd->timeout);
+       if (usalp->verbose > 1)
+               usal_printrdata(usalp);
+       flush();
+}
+
+/*
+ * print the SCSI timings and (depending on verbose) received data into a buffer.
+ */
+int
+usal_sprintresult(SCSI *usalp, char *buf, int maxcnt)
+{
+       register char           *p = buf;
+       register int            amt;
+
+       amt = snprintf(p, maxcnt,
+               "cmd finished after %ld.%03lds timeout %ds\n",
+               (long)usalp->cmdstop->tv_sec,
+               (long)usalp->cmdstop->tv_usec/1000,
+               usalp->scmd->timeout);
+       if (amt < 0)
+               return (amt);
+       p += amt;
+       maxcnt -= amt;
+       if (usalp->verbose > 1) {
+               amt = usal_sprintrdata(usalp, p, maxcnt);
+               if (amt < 0)
+                       return (amt);
+               p += amt;
+       }
+       return (p - buf);
+}
+
+/*
+ * XXX Do we need this function?
+ *
+ * print the SCSI status byte in human readable form to the SCSI error file.
+ */
+void
+usal_printstatus(SCSI *usalp)
+{
+       char    errbuf[SCSI_ERRSTR_SIZE];
+       int     amt;
+
+       amt = usal_sprintstatus(usalp, errbuf, sizeof (errbuf));
+       if (amt > 0) {
+               filewrite((FILE *)usalp->errfile, errbuf, amt);
+               fflush((FILE *)usalp->errfile);
+       }
+}
+
+/*
+ * print the SCSI status byte in human readable form into a buffer.
+ */
+int
+usal_sprintstatus(SCSI *usalp, char *buf, int maxcnt)
+{
+       register struct usal_cmd *cp = usalp->scmd;
+               char    *err;
+               char    *err2 = "";
+       register char   *p = buf;
+       register int    amt;
+
+       amt = snprintf(p, maxcnt, "status: 0x%x ", *(Uchar *)&cp->scb);
+       if (amt < 0)
+               return (amt);
+       p += amt;
+       maxcnt -= amt;
+#ifdef SCSI_EXTENDED_STATUS
+       if (cp->scb.ext_st1) {
+               amt = snprintf(p, maxcnt, "0x%x ", ((Uchar *)&cp->scb)[1]);
+               if (amt < 0)
+                       return (amt);
+               p += amt;
+               maxcnt -= amt;
+       }
+       if (cp->scb.ext_st2) {
+               amt = snprintf(p, maxcnt, "0x%x ", ((Uchar *)&cp->scb)[2]);
+               if (amt < 0)
+                       return (amt);
+               p += amt;
+               maxcnt -= amt;
+       }
+#endif
+       switch (*(Uchar *)&cp->scb & 036) {
+
+       case 0  : err = "GOOD STATUS";                  break;
+       case 02 : err = "CHECK CONDITION";              break;
+       case 04 : err = "CONDITION MET/GOOD";           break;
+       case 010: err = "BUSY";                         break;
+       case 020: err = "INTERMEDIATE GOOD STATUS";     break;
+       case 024: err = "INTERMEDIATE CONDITION MET/GOOD"; break;
+       case 030: err = "RESERVATION CONFLICT";         break;
+       default : err = "Reserved";                     break;
+       }
+#ifdef SCSI_EXTENDED_STATUS
+       if (cp->scb.ext_st1 && cp->scb.ha_er)
+               err2 = " host adapter detected error";
+#endif
+       amt = snprintf(p, maxcnt, "(%s%s)\n", err, err2);
+       if (amt < 0)
+               return (amt);
+       p += amt;
+       return (p - buf);
+}
+
+/*
+ * print some bytes in hex to a file.
+ */
+void
+usal_fprbytes(FILE *f, char *s, register Uchar *cp, register int n)
+{
+       fprintf(f, "%s", s);
+       while (--n >= 0)
+               fprintf(f, " %02X", *cp++);
+       fprintf(f, "\n");
+}
+
+/*
+ * print some bytes in ascii to a file.
+ */
+void
+usal_fprascii(FILE *f, char *s, register Uchar *cp, register int n)
+{
+       register int    c;
+
+       fprintf(f, "%s", s);
+       while (--n >= 0) {
+               c = *cp++;
+               if (c >= ' ' && c < 0177)
+                       fprintf(f, "%c", c);
+               else
+                       fprintf(f, ".");
+       }
+       fprintf(f, "\n");
+}
+
+/*
+ * XXX We need to check if we should write to stderr or better to usal->errfile
+ *
+ * print some bytes in hex to stderr.
+ */
+void
+usal_prbytes(char *s, register Uchar *cp, register int n)
+{
+       usal_fprbytes(stderr, s, cp, n);
+}
+
+/*
+ * XXX We need to check if we should write to stderr or better to usal->errfile
+ *
+ * print some bytes in ascii to stderr.
+ */
+void
+usal_prascii(char *s, register Uchar *cp, register int n)
+{
+       usal_fprascii(stderr, s, cp, n);
+}
+
+/*
+ * print some bytes in hex into a buffer.
+ */
+int
+usal_sprbytes(char *buf, int maxcnt, char *s, register Uchar *cp, register int n)
+{
+       register char   *p = buf;
+       register int    amt;
+
+       amt = snprintf(p, maxcnt, "%s", s);
+       if (amt < 0)
+               return (amt);
+       p += amt;
+       maxcnt -= amt;
+
+       while (--n >= 0) {
+               amt = snprintf(p, maxcnt, " %02X", *cp++);
+               if (amt < 0)
+                       return (amt);
+               p += amt;
+               maxcnt -= amt;
+       }
+       amt = snprintf(p, maxcnt, "\n");
+       if (amt < 0)
+               return (amt);
+       p += amt;
+       return (p - buf);
+}
+
+/*
+ * print some bytes in ascii into a buffer.
+ */
+int
+usal_sprascii(char *buf, int maxcnt, char *s, register Uchar *cp, register int n)
+{
+       register char   *p = buf;
+       register int    amt;
+       register int    c;
+
+       amt = snprintf(p, maxcnt, "%s", s);
+       if (amt < 0)
+               return (amt);
+       p += amt;
+       maxcnt -= amt;
+
+       while (--n >= 0) {
+               c = *cp++;
+               if (c >= ' ' && c < 0177)
+                       amt = snprintf(p, maxcnt, "%c", c);
+               else
+                       amt = snprintf(p, maxcnt, ".");
+               if (amt < 0)
+                       return (amt);
+               p += amt;
+               maxcnt -= amt;
+       }
+       amt = snprintf(p, maxcnt, "\n");
+       if (amt < 0)
+               return (amt);
+       p += amt;
+       return (p - buf);
+}
+
+/*
+ * print the SCSI sense data for last command in hex to a file.
+ */
+void
+usal_fprsense(FILE *f, Uchar *cp, int n)
+{
+       usal_fprbytes(f, "Sense Bytes:", cp, n);
+}
+
+/*
+ * XXX We need to check if we should write to stderr or better to usal->errfile
+ *
+ * print the SCSI sense data for last command in hex to stderr.
+ */
+void
+usal_prsense(Uchar *cp, int n)
+{
+       usal_fprsense(stderr, cp, n);
+}
+
+/*
+ * print the SCSI sense data for last command in hex into a buffer.
+ */
+int
+usal_sprsense(char *buf, int maxcnt, Uchar *cp, int n)
+{
+       return (usal_sprbytes(buf, maxcnt, "Sense Bytes:", cp, n));
+}
+
+/*
+ * Return the SCSI status byte for last command.
+ */
+int
+usal_cmd_status(SCSI *usalp)
+{
+       struct usal_cmd *cp = usalp->scmd;
+       int             cmdstatus = *(Uchar *)&cp->scb;
+
+       return (cmdstatus);
+}
+
+/*
+ * Return the SCSI sense key for last command.
+ */
+int
+usal_sense_key(SCSI *usalp)
+{
+       register struct usal_cmd *cp = usalp->scmd;
+       int     key = -1;
+
+       if (!usal_cmd_err(usalp))
+               return (0);
+
+       if (cp->sense.code >= 0x70)
+               key = ((struct scsi_ext_sense *)&(cp->sense))->key;
+       return (key);
+}
+
+/*
+ * Return all the SCSI sense table last command.
+ */
+unsigned char *
+usal_sense_table(SCSI *usalp)
+{
+       register struct usal_cmd *cp = usalp->scmd;
+
+       if(!usal_cmd_err(usalp))
+               return (0);
+
+       /* if (cp->sense.code >= 0x70) */
+       return (unsigned char *) &(cp->sense);
+}
+
+
+/*
+ * Return the SCSI sense code for last command.
+ */
+int
+usal_sense_code(SCSI *usalp)
+{
+       register struct usal_cmd *cp = usalp->scmd;
+       int     code = -1;
+
+       if (!usal_cmd_err(usalp))
+               return (0);
+
+       if (cp->sense.code >= 0x70)
+               code = ((struct scsi_ext_sense *)&(cp->sense))->sense_code;
+       else
+               code = cp->sense.code;
+       return (code);
+}
+
+/*
+ * Return the SCSI sense qualifier for last command.
+ */
+int
+usal_sense_qual(SCSI *usalp)
+{
+       register struct usal_cmd *cp = usalp->scmd;
+
+       if (!usal_cmd_err(usalp))
+               return (0);
+
+       if (cp->sense.code >= 0x70)
+               return (((struct scsi_ext_sense *)&(cp->sense))->qual_code);
+       else
+               return (0);
+}
+
+/*
+ * Print the device type from the SCSI inquiry buffer to file.
+ */
+void
+usal_fprintdev(FILE *f, struct scsi_inquiry *ip)
+{
+       if (ip->removable)
+               fprintf(f, "Removable ");
+       if (ip->data_format >= 2) {
+               switch (ip->qualifier) {
+
+               case INQ_DEV_PRESENT:
+                       break;
+               case INQ_DEV_NOTPR:
+                       fprintf(f, "not present ");
+                       break;
+               case INQ_DEV_RES:
+                       fprintf(f, "reserved ");
+                       break;
+               case INQ_DEV_NOTSUP:
+                       if (ip->type == INQ_NODEV) {
+                               fprintf(f, "unsupported\n"); return;
+                       }
+                       fprintf(f, "unsupported ");
+                       break;
+               default:
+                       fprintf(f, "vendor specific %d ",
+                                               (int)ip->qualifier);
+               }
+       }
+       switch (ip->type) {
+
+       case INQ_DASD:
+               fprintf(f, "Disk");             break;
+       case INQ_SEQD:
+               fprintf(f, "Tape");             break;
+       case INQ_PRTD:
+               fprintf(f, "Printer");  break;
+       case INQ_PROCD:
+               fprintf(f, "Processor");        break;
+       case INQ_WORM:
+               fprintf(f, "WORM");             break;
+       case INQ_ROMD:
+               fprintf(f, "CD-ROM");   break;
+       case INQ_SCAN:
+               fprintf(f, "Scanner");  break;
+       case INQ_OMEM:
+               fprintf(f, "Optical Storage"); break;
+       case INQ_JUKE:
+               fprintf(f, "Juke Box"); break;
+       case INQ_COMM:
+               fprintf(f, "Communication");    break;
+       case INQ_IT8_1:
+               fprintf(f, "IT8 1");            break;
+       case INQ_IT8_2:
+               fprintf(f, "IT8 2");            break;
+       case INQ_STARR:
+               fprintf(f, "Storage array");    break;
+       case INQ_ENCL:
+               fprintf(f, "Enclosure services"); break;
+       case INQ_SDAD:
+               fprintf(f, "Simple direct access"); break;
+       case INQ_OCRW:
+               fprintf(f, "Optical card r/w"); break;
+       case INQ_BRIDGE:
+               fprintf(f, "Bridging expander"); break;
+       case INQ_OSD:
+               fprintf(f, "Object based storage"); break;
+       case INQ_ADC:
+               fprintf(f, "Automation/Drive Interface"); break;
+       case INQ_WELLKNOWN:
+               fprintf(f, "Well known lun"); break;
+
+       case INQ_NODEV:
+               if (ip->data_format >= 2) {
+                       fprintf(f, "unknown/no device");
+                       break;
+               } else if (ip->qualifier == INQ_DEV_NOTSUP) {
+                       fprintf(f, "unit not present");
+                       break;
+               }
+       default:
+               fprintf(f, "unknown device type 0x%x",
+                                               (int)ip->type);
+       }
+       fprintf(f, "\n");
+}
+
+/*
+ * Print the device type from the SCSI inquiry buffer to stdout.
+ */
+void
+usal_printdev(struct scsi_inquiry *ip)
+{
+       usal_fprintdev(stdout, ip);
+}
+
+/*
+ * print into the SCSI error buffer, adjust the next write pointer.
+ */
+/* VARARGS2 */
+int
+usal_printf(SCSI *usalp, const char *form, ...)
+{
+       int     cnt;
+       va_list args;
+
+       va_start(args, form);
+       cnt = vsnprintf(usalp->errptr, usal_errrsize(usalp), form, args);
+       va_end(args);
+
+       if (cnt < 0) {
+               usalp->errptr[0] = '\0';
+       } else {
+               usalp->errptr += cnt;
+       }
+       return (cnt);
+}
+
+/*
+ * Flush the SCSI error buffer to SCSI errfile.
+ * Clear error buffer after flushing.
+ */
+int
+usal_errflush(SCSI *usalp)
+{
+       if (usalp->errfile == NULL)
+               return (0);
+
+       return (usal_errfflush(usalp, (FILE *)usalp->errfile));
+}
+
+/*
+ * Flush the SCSI error buffer to a file.
+ * Clear error buffer after flushing.
+ */
+int
+usal_errfflush(SCSI *usalp, FILE *f)
+{
+       int     cnt;
+
+       cnt = usalp->errptr - usalp->errbeg;
+       if (cnt > 0) {
+               filewrite(f, usalp->errbeg, cnt);
+               fflush(f);
+               usalp->errbeg = usalp->errptr;
+       }
+       return (cnt);
+}
diff --git a/libusal/usal/aspi-dos.h b/libusal/usal/aspi-dos.h
new file mode 100644 (file)
index 0000000..3428ac8
--- /dev/null
@@ -0,0 +1,169 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)aspi-dos.h      1.2 05/05/15 J. Schilling */
+#ifndef        __ASPI16_H_
+#define        __ASPI16_H_
+
+#define        PACKED  __attribute__((packed))
+#define        FAR
+typedef unsigned char  BYTE;
+typedef unsigned short WORD;
+typedef unsigned long  DWORD;
+
+//*****************************************************************************
+//     %%% SCSI MISCELLANEOUS EQUATES %%%
+//*****************************************************************************
+
+#define        SENSE_LEN                       14      // Default sense buffer length
+#define        SRB_DIR_SCSI                    0x00    // Direction determined by SCSI
+#define        SRB_POSTING                     0x01    // Enable ASPI posting
+#define        SRB_ENABLE_RESIDUAL_COUNT       0x04    // Enable residual byte count reporting
+#define        SRB_DIR_IN                      0x08    // Transfer from SCSI target to host
+#define        SRB_DIR_OUT                     0x10    // Transfer from host to SCSI target
+
+//*****************************************************************************
+//      %%% ASPI Command Definitions %%%
+//*****************************************************************************
+
+#define        SC_HA_INQUIRY                   0x00    // Host adapter inquiry
+#define        SC_GET_DEV_TYPE                 0x01    // Get device type
+#define        SC_EXEC_SCSI_CMD                0x02    // Execute SCSI command
+#define        SC_ABORT_SRB                    0x03    // Abort an SRB
+#define        SC_RESET_DEV                    0x04    // SCSI bus device reset
+#define        SC_SET_HA_PARMS                 0x05    // Set HA parameters
+#define        SC_GET_DISK_INFO                0x06    // Get Disk information
+
+//*****************************************************************************
+//      %%% SRB Status %%%
+//*****************************************************************************
+
+#define        SS_PENDING                      0x00    // SRB being processed
+#define        SS_COMP                         0x01    // SRB completed without error
+#define        SS_ABORTED                      0x02    // SRB aborted
+#define        SS_ABORT_FAIL                   0x03    // Unable to abort SRB
+#define        SS_ERR                          0x04    // SRB completed with error
+
+#define        SS_INVALID_CMD                  0x80    // Invalid ASPI command
+#define        SS_INVALID_HA                   0x81    // Invalid host adapter number
+#define        SS_NO_DEVICE                    0x82    // SCSI device not installed
+
+//*****************************************************************************
+//      %%% Host Adapter Status %%%
+//*****************************************************************************
+
+#define        HASTAT_OK                       0x00    // Host adapter did not detect an
+                                               // error
+#define        HASTAT_SEL_TO                   0x11    // Selection Timeout
+#define        HASTAT_DO_DU                    0x12    // Data overrun data underrun
+#define        HASTAT_BUS_FREE                 0x13    // Unexpected bus free
+#define        HASTAT_PHASE_ERR                0x14    // Target bus phase sequence
+                                               // failure
+#define        HASTAT_TIMEOUT                  0x09    // Timed out while SRB was
+                                               // waiting to beprocessed.
+#define        HASTAT_COMMAND_TIMEOUT          0x0B    // Adapter timed out processing SRB.
+#define        HASTAT_MESSAGE_REJECT           0x0D    // While processing SRB, the
+                                               // adapter received a MESSAGE
+#define        HASTAT_BUS_RESET                0x0E    // A bus reset was detected.
+#define        HASTAT_PARITY_ERROR             0x0F    // A parity error was detected.
+#define        HASTAT_REQUEST_SENSE_FAILED     0x10    // The adapter failed in issuing
+
+typedef struct {
+
+       BYTE    Cmd;                            // 00/000 ASPI command code = SC_EXEC_SCSI_CMD
+       BYTE    Status;                         // 01/001 ASPI command status byte
+       BYTE    HaId;                           // 02/002 ASPI host adapter number
+       BYTE    Flags;                          // 03/003 ASPI request flags
+       DWORD   Hdr_Rsvd;                       // 04/004 Reserved, MUST = 0
+
+       union {
+
+       struct {
+
+               BYTE    Count;                  // 08/008 Number of host adapters present
+               BYTE    SCSI_ID;                // 09/009 SCSI ID of host adapter
+               BYTE    ManagerId[16];          // 0A/010 String describing the manager
+               BYTE    Identifier[16];         // 1A/026 String describing the host adapter
+               BYTE    Unique[16];             // 2A/042 Host Adapter Unique parameters
+               BYTE    ExtBuffer[8];           // 3A/058 Extended inquiry data
+
+       } PACKED HAInquiry;
+
+       struct {
+
+               BYTE    Target;                 // 08/008 Target's SCSI ID
+               BYTE    Lun;                    // 09/009 Target's LUN number
+               BYTE    DeviceType;             // 0A/010 Target's peripheral device type
+
+       } PACKED GetDeviceType;
+
+       struct {
+
+               BYTE    Target;                 // 08/008 Target's SCSI ID
+               BYTE    Lun;                    // 09/009 Target's LUN number
+               DWORD   BufLen;                 // 0A/010 Data Allocation Length
+               BYTE    SenseLen;               // 0E/014 Sense Allocation Length
+               BYTE    FAR *BufPointer;        // 0F/015 Data Buffer Pointer
+               DWORD   Rsvd1;                  // 13/019 Reserved, MUST = 0
+               BYTE    CDBLen;                 // 17/023 CDB Length = 6/10/12
+               BYTE    HaStat;                 // 18/024 Host Adapter Status
+               BYTE    TargStat;               // 19/025 Target Status
+               VOID    FAR *PostProc;          // 1A/026 Post routine
+               BYTE    Rsvd2[34];              // 1E/030 Reserved, MUST = 0
+
+               union {
+
+               struct {
+
+                       BYTE    CDBByte[6];             // 40/064 SCSI CDB
+                       BYTE    SenseArea[SENSE_LEN+2]; // 46/070 Request Sense buffer
+
+               } PACKED _6;
+
+               struct {
+
+                       BYTE    CDBByte[10];            // 40/064 SCSI CDB
+                       BYTE    SenseArea[SENSE_LEN+2]; // 4A/074 Request Sense buffer
+
+               } PACKED _10;
+
+               struct {
+
+                       BYTE    CDBByte[12];            // 40/064 SCSI CDB
+                       BYTE    SenseArea[SENSE_LEN+2]; // 4C/076 Request Sense buffer
+
+               } PACKED _12;
+
+               } PACKED CmdLen;
+
+       } PACKED ExecSCSICmd;
+
+       struct {
+
+               VOID    FAR     *SRBToAbort;    // 08/008 Pointer to SRB to abort
+
+       } PACKED Abort;
+
+       struct {
+               BYTE    Target;         // 08/008 Target's SCSI ID
+               BYTE    Lun;            // 09/009 Target's LUN number
+               BYTE    ResetRsvd1[14]; // 0A/010 Reserved, MUST = 0
+               BYTE    HaStat;         // 18/024 Host Adapter Status
+               BYTE    TargStat;       // 19/025 Target Status
+               VOID    FAR *PostProc;  // 1A/026 Post routine
+               BYTE    ResetRsvd2[34]; // 1E/030 Reserved, MUST = 0
+       } Reset;
+       } PACKED Type;
+
+} PACKED SRB;
+
+#endif /* __ASPI16_H_ */
diff --git a/libusal/usal/aspi-win32.h b/libusal/usal/aspi-win32.h
new file mode 100644 (file)
index 0000000..865befe
--- /dev/null
@@ -0,0 +1,208 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+#ifndef __ASPI_WIN32_H_
+#define __ASPI_WIN32_H_
+
+#include <Windows.h>
+
+/***************************************************************************
+ ** SCSI MISCELLANEOUS EQUATES
+ ***************************************************************************/
+#define SENSE_LEN                 14     /* Default sense buffer length    */
+#define SRB_DIR_SCSI              0x00   /* Direction determined by SCSI   */
+#define SRB_POSTING               0x01   /* Enable ASPI posting            */
+#define SRB_ENABLE_RESIDUAL_COUNT 0x04   /* Enable residual byte count     */
+                                         /* reporting                      */
+#define SRB_DIR_IN                0x08   /* Transfer from SCSI target to   */
+                                         /* host                           */
+#define SRB_DIR_OUT               0x10   /* Transfer from host to SCSI     */
+                                         /* target                         */
+#define SRB_EVENT_NOTIFY          0x40   /* Enable ASPI event notification */
+#define RESIDUAL_COUNT_SUPPORTED  0x02   /* Extended buffer flag           */
+#define MAX_SRB_TIMEOUT       1080001u   /* 30 hour maximum timeout in sec */
+#define DEFAULT_SRB_TIMEOUT   1080001u   /* use max.timeout by default     */
+
+/***************************************************************************
+ ** ASPI command definitions
+ ***************************************************************************/
+#define SC_HA_INQUIRY             0x00   /* Host adapter inquiry           */
+#define SC_GET_DEV_TYPE           0x01   /* Get device type                */
+#define SC_EXEC_SCSI_CMD          0x02   /* Execute SCSI command           */
+#define SC_ABORT_SRB              0x03   /* Abort an SRB                   */
+#define SC_RESET_DEV              0x04   /* SCSI bus device reset          */
+#define SC_SET_HA_PARMS           0x05   /* Set HA parameters              */
+#define SC_GET_DISK_INFO          0x06   /* Get Disk                       */
+#define SC_RESCAN_SCSI_BUS        0x07   /* Rebuild SCSI device map        */
+#define SC_GETSET_TIMEOUTS        0x08   /* Get/Set target timeouts        */
+
+
+/***************************************************************************
+ ** SRB Status
+ ***************************************************************************/
+#define SS_PENDING                0x00   /* SRB being processed            */
+#define SS_COMP                   0x01   /* SRB completed without error    */
+#define SS_ABORTED                0x02   /* SRB aborted                    */
+#define SS_ABORT_FAIL             0x03   /* Unable to abort SRB            */
+#define SS_ERR                    0x04   /* SRB completed with error       */
+#define SS_INVALID_CMD            0x80   /* Invalid ASPI command           */
+#define SS_INVALID_HA             0x81   /* Invalid host adapter number    */
+#define SS_NO_DEVICE              0x82   /* SCSI device not installed      */
+#define SS_INVALID_SRB            0xE0   /* Invalid parameter set in SRB   */
+#define SS_OLD_MANAGER            0xE1   /* ASPI manager doesn't support   */
+                                         /* windows                        */
+#define SS_BUFFER_ALIGN           0xE1   /* Buffer not aligned (replaces   */
+                                         /* SS_OLD_MANAGER in Win32)       */
+#define SS_ILLEGAL_MODE           0xE2   /* Unsupported Windows mode       */
+#define SS_NO_ASPI                0xE3   /* No ASPI managers               */
+#define SS_FAILED_INIT            0xE4   /* ASPI for windows failed init   */
+#define SS_ASPI_IS_BUSY           0xE5   /* No resources available to      */
+                                         /* execute command                */
+#define SS_BUFFER_TO_BIG          0xE6   /* Buffer size too big to handle  */
+#define SS_BUFFER_TOO_BIG         0xE6   /* Correct spelling of 'too'      */
+#define SS_MISMATCHED_COMPONENTS  0xE7   /* The DLLs/EXEs of ASPI don't    */
+                                         /* version check                  */
+#define SS_NO_ADAPTERS            0xE8   /* No host adapters to manager    */
+#define SS_INSUFFICIENT_RESOURCES 0xE9   /* Couldn't allocate resources    */
+                                         /* needed to init                 */
+#define SS_ASPI_IS_SHUTDOWN       0xEA   /* Call came to ASPI after        */
+                                         /* PROCESS_DETACH                 */
+#define SS_BAD_INSTALL            0xEB   /* The DLL or other components    */
+                                         /* are installed wrong            */
+
+/***************************************************************************
+ ** Host Adapter Status
+ ***************************************************************************/
+#define HASTAT_OK                 0x00   /* No error detected by HA        */
+#define HASTAT_SEL_TO             0x11   /* Selection Timeout              */
+#define HASTAT_DO_DU              0x12   /* Data overrun/data underrun     */
+#define HASTAT_BUS_FREE           0x13   /* Unexpected bus free            */
+#define HASTAT_PHASE_ERR          0x14   /* Target bus phase sequence      */
+#define HASTAT_TIMEOUT            0x09   /* Timed out while SRB was        */
+                                         /* waiting to be processed        */
+#define HASTAT_COMMAND_TIMEOUT    0x0B   /* Adapter timed out while        */
+                                         /* processing SRB                 */
+#define HASTAT_MESSAGE_REJECT     0x0D   /* While processing the SRB, the  */
+                                         /* adapter received a MESSAGE     */
+#define HASTAT_BUS_RESET          0x0E   /* A bus reset was detected       */
+#define HASTAT_PARITY_ERROR       0x0F   /* A parity error was detected    */
+#define HASTAT_REQUEST_SENSE_FAILED 0x10 /* The adapter failed in issuing  */
+
+
+/***************************************************************************
+ ** SRB - HOST ADAPTER INQUIRIY - SC_HA_INQUIRY (0)
+ ***************************************************************************/
+typedef struct {
+  BYTE     SRB_Cmd;           /* 00/000 ASPI command code == SC_HA_INQUIRY */
+  BYTE     SRB_Status;        /* 01/001 ASPI command status byte           */
+  BYTE     SRB_HaId;          /* 02/002 ASPI host adapter number           */
+  BYTE     SRB_Flags;         /* 03/003 ASPI request flags                 */
+  DWORD    SRB_Hdr_Rsvd;      /* 04/004 Reserved, must = 0                 */
+  BYTE     HA_Count;          /* 08/008 Number of host adapters present    */
+  BYTE     HA_SCSI_ID;        /* 09/009 SCSI ID of host adapter            */
+  BYTE     HA_ManagerId[16];  /* 0a/010 String describing the manager      */
+  BYTE     HA_Identifier[16]; /* 1a/026 String describing the host adapter */
+  BYTE     HA_Unique[16];     /* 2a/042 Host Adapter Unique parameters     */
+  WORD     HA_Rsvd1;          /* 3a/058 Reserved, must = 0                 */
+} PACKED SRB_HAInquiry, *PSRB_HAInquiry, FAR *LPSRB_HAInquiry;
+
+
+/***************************************************************************
+ ** SRB - GET DEVICE TYPE - SC_GET_DEV_TYPE (1)
+ ***************************************************************************/
+typedef struct
+{
+  BYTE     SRB_Cmd;           /* 00/000 ASPI cmd code == SC_GET_DEV_TYPE   */
+  BYTE     SRB_Status;        /* 01/001 ASPI command status byte           */
+  BYTE     SRB_HaId;          /* 02/002 ASPI host adapter number           */
+  BYTE     SRB_Flags;         /* 03/003 Reserved, must = 0                 */
+  DWORD    SRB_Hdr_Rsvd;      /* 04/004 Reserved, must = 0                 */
+  BYTE     SRB_Target;        /* 08/008 Target's SCSI ID                   */
+  BYTE     SRB_Lun;           /* 09/009 Target's LUN number                */
+  BYTE     SRB_DeviceType;    /* 0a/010 Target's peripheral device type    */
+  BYTE     SRB_Rsvd1;         /* 0b/011 Reserved, must = 0                 */
+} PACKED SRB_GDEVBlock, *PSRB_GDEVBlock, FAR *LPSRB_GDEVBlock;
+
+
+/***************************************************************************
+ ** SRB - EXECUTE SCSI COMMAND - SC_EXEC_SCSI_CMD (2)
+ ***************************************************************************/
+typedef struct
+{
+  BYTE     SRB_Cmd;           /* 00/000 ASPI cmd code == SC_EXEC_SCSI_CMD  */
+  BYTE     SRB_Status;        /* 01/001 ASPI command status byte           */
+  BYTE     SRB_HaId;          /* 02/002 ASPI host adapter number           */
+  BYTE     SRB_Flags;         /* 03/003 Reserved, must = 0                 */
+  DWORD    SRB_Hdr_Rsvd;      /* 04/004 Reserved, must = 0                 */
+  BYTE     SRB_Target;        /* 08/008 Target's SCSI ID                   */
+  BYTE     SRB_Lun;           /* 09/009 Target's LUN                       */
+  WORD     SRB_Rsvd1;         /* 0a/010 Reserved for alignment             */
+  DWORD    SRB_BufLen;        /* 0c/012 Data Allocation Length             */
+  BYTE FAR *SRB_BufPointer;   /* 10/016 Data Buffer Pointer                */
+  BYTE     SRB_SenseLen;      /* 14/020 Sense Allocation Length            */
+  BYTE     SRB_CDBLen;        /* 15/021 CDB Length                         */
+  BYTE     SRB_HaStat;        /* 16/022 Host Adapter Status                */
+  BYTE     SRB_TargStat;      /* 17/023 Target Status                      */
+  VOID FAR *SRB_PostProc;     /* 18/024 Post routine                       */
+  BYTE     SRB_Rsvd2[20];     /* 1c/028 Reserved, must = 0                 */
+  BYTE     CDBByte[16];       /* 30/048 SCSI CDB                           */
+  BYTE SenseArea[SENSE_LEN+2]; /* 40/064 Request Sense buffer              */
+} PACKED SRB_ExecSCSICmd, *PSRB_ExecSCSICmd, FAR *LPSRB_ExecSCSICmd;
+
+
+typedef struct
+{
+  BYTE     SRB_Cmd;           /* 00/000 ASPI cmd code == SC_ABORT_SRB      */
+  BYTE     SRB_Status;        /* 01/001 ASPI command status byte           */
+  BYTE     SRB_HaId;          /* 02/002 ASPI host adapter number           */
+  BYTE     SRB_Flags;         /* 03/003 Reserved, must = 0                 */
+  DWORD    SRB_Hdr_Rsvd;      /* 04/004 Reserved, must = 0                 */
+  void     *SRB_ToAbort;      /* 08/008 Pointer to SRB to abort            */
+} PACKED SRB_Abort, *PSRB_Abort, FAR *LPSRB_Abort;
+
+
+/***************************************************************************
+ ** SRB - BUS DEVICE RESET - SC_RESET_DEV (4)
+ ***************************************************************************/
+typedef struct
+{
+  BYTE     SRB_Cmd;           /* 00/000 ASPI cmd code == SC_RESET_DEV      */
+  BYTE     SRB_Status;        /* 01/001 ASPI command status byte           */
+  BYTE     SRB_HaId;          /* 02/002 ASPI host adapter number           */
+  DWORD    SRB_Flags;        /* 04/004 Reserved                           */
+  BYTE     SRB_Target;        /* 08/008 Target's SCSI ID                   */
+  BYTE     SRB_Lun;           /* 09/009 Target's LUN number                */
+  BYTE     SRB_Rsvd1[12];     /* 0A/010 Reserved for alignment             */
+  BYTE     SRB_HaStat;        /* 16/022 Host Adapter Status                */
+  BYTE     SRB_TargStat;      /* 17/023 Target Status                      */
+  VOID FAR *SRB_PostProc;     /* 18/024 Post routine                       */
+  BYTE     SRB_Rsvd2[36];     /* 1C/028 Reserved, must = 0                 */
+} SRB_BusDeviceReset, *PSRB_BusDeviceReset, FAR *LPSRB_BusDeviceReset;
+
+typedef struct tag_ASPI32BUFF
+{
+  PBYTE     AB_BufPointer;
+  DWORD     AB_BufLen;
+  DWORD     AB_ZeroFill;
+  DWORD     AB_Reserved;
+} PACKED ASPI32BUFF, *PASPI32BUFF, FAR *LPASPI32BUFF;
+
+typedef struct 
+{
+  BYTE      SRB_Cmd;
+  BYTE      SRB_Status;
+  BYTE      SRB_HaId;
+  BYTE      SRB_Flags;
+  DWORD     SRB_Hdr_Rsvd;
+} SRB, *PSRB, FAR *LPSRB;
+
+#endif
diff --git a/libusal/usal/scsicdb.h b/libusal/usal/scsicdb.h
new file mode 100644 (file)
index 0000000..2594776
--- /dev/null
@@ -0,0 +1,260 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)scsicdb.h       2.19 04/09/04 Copyright 1986 J. Schilling */
+/*
+ *     Definitions for the SCSI Command Descriptor Block
+ *
+ *     Copyright (c) 1986 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef        _SCG_SCSICDB_H
+#define        _SCG_SCSICDB_H
+
+#ifndef  _UTYPES_H
+#include <utypes.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * SCSI Operation codes.
+ */
+#define        SC_TEST_UNIT_READY      0x00
+#define        SC_REZERO_UNIT          0x01
+#define        SC_REQUEST_SENSE        0x03
+#define        SC_FORMAT               0x04
+#define        SC_FORMAT_TRACK         0x06
+#define        SC_REASSIGN_BLOCK       0x07            /* CCS only */
+#define        SC_SEEK                 0x0b
+#define        SC_TRANSLATE            0x0f            /* ACB4000 only */
+#define        SC_INQUIRY              0x12            /* CCS only */
+#define        SC_MODE_SELECT          0x15
+#define        SC_RESERVE              0x16
+#define        SC_RELEASE              0x17
+#define        SC_MODE_SENSE           0x1a
+#define        SC_START                0x1b
+#define        SC_READ_DEFECT_LIST     0x37            /* CCS only, group 1 */
+#define        SC_READ_BUFFER          0x3c            /* CCS only, group 1 */
+       /*
+        * Note, these two commands use identical command blocks for all
+        * controllers except the Adaptec ACB 4000 which sets bit 1 of byte 1.
+        */
+#define        SC_READ                 0x08
+#define        SC_WRITE                0x0a
+#define        SC_EREAD                0x28            /* 10 byte read */
+#define        SC_EWRITE               0x2a            /* 10 byte write */
+#define        SC_WRITE_VERIFY         0x2e            /* 10 byte write+verify */
+#define        SC_WRITE_FILE_MARK      0x10
+#define        SC_UNKNOWN              0xff            /* cmd list terminator */
+
+
+/*
+ * Standard SCSI control blocks.
+ * These go in or out over the SCSI bus.
+ */
+
+#if    defined(_BIT_FIELDS_LTOH)       /* Intel byteorder */
+
+struct scsi_g0cdb {            /* scsi group 0 command description block */
+       Uchar   cmd;            /* command code */
+       Ucbit   high_addr : 5;  /* high part of block address */
+       Ucbit   lun       : 3;  /* logical unit number */
+       Uchar   mid_addr;       /* middle part of block address */
+       Uchar   low_addr;       /* low part of block address */
+       Uchar   count;          /* transfer length */
+       Ucbit   link      : 1;  /* link (another command follows) */
+       Ucbit   fr        : 1;  /* flag request (interrupt at completion) */
+       Ucbit   naca      : 1;  /* Normal ACA (Auto Contingent Allegiance) */
+       Ucbit   rsvd      : 3;  /* reserved */
+       Ucbit   vu_56     : 1;  /* vendor unique (byte 5 bit 6) */
+       Ucbit   vu_57     : 1;  /* vendor unique (byte 5 bit 7) */
+};
+
+#else  /* Motorola byteorder */
+
+struct scsi_g0cdb {            /* scsi group 0 command description block */
+       Uchar   cmd;            /* command code */
+       Ucbit   lun       : 3;  /* logical unit number */
+       Ucbit   high_addr : 5;  /* high part of block address */
+       Uchar   mid_addr;       /* middle part of block address */
+       Uchar   low_addr;       /* low part of block address */
+       Uchar   count;          /* transfer length */
+       Ucbit   vu_57     : 1;  /* vendor unique (byte 5 bit 7) */
+       Ucbit   vu_56     : 1;  /* vendor unique (byte 5 bit 6) */
+       Ucbit   rsvd      : 3;  /* reserved */
+       Ucbit   naca      : 1;  /* Normal ACA (Auto Contingent Allegiance) */
+       Ucbit   fr        : 1;  /* flag request (interrupt at completion) */
+       Ucbit   link      : 1;  /* link (another command follows) */
+};
+#endif
+
+#if    defined(_BIT_FIELDS_LTOH)       /* Intel byteorder */
+
+struct scsi_g1cdb {            /* scsi group 1 command description block */
+       Uchar   cmd;            /* command code */
+       Ucbit   reladr    : 1;  /* address is relative */
+       Ucbit   res       : 4;  /* reserved bits 1-4 of byte 1 */
+       Ucbit   lun       : 3;  /* logical unit number */
+       Uchar   addr[4];        /* logical block address */
+       Uchar   res6;           /* reserved byte 6 */
+       Uchar   count[2];       /* transfer length */
+       Ucbit   link      : 1;  /* link (another command follows) */
+       Ucbit   fr        : 1;  /* flag request (interrupt at completion) */
+       Ucbit   naca      : 1;  /* Normal ACA (Auto Contingent Allegiance) */
+       Ucbit   rsvd      : 3;  /* reserved */
+       Ucbit   vu_96     : 1;  /* vendor unique (byte 5 bit 6) */
+       Ucbit   vu_97     : 1;  /* vendor unique (byte 5 bit 7) */
+};
+
+#else  /* Motorola byteorder */
+
+struct scsi_g1cdb {            /* scsi group 1 command description block */
+       Uchar   cmd;            /* command code */
+       Ucbit   lun       : 3;  /* logical unit number */
+       Ucbit   res       : 4;  /* reserved bits 1-4 of byte 1 */
+       Ucbit   reladr    : 1;  /* address is relative */
+       Uchar   addr[4];        /* logical block address */
+       Uchar   res6;           /* reserved byte 6 */
+       Uchar   count[2];       /* transfer length */
+       Ucbit   vu_97     : 1;  /* vendor unique (byte 5 bit 7) */
+       Ucbit   vu_96     : 1;  /* vendor unique (byte 5 bit 6) */
+       Ucbit   rsvd      : 3;  /* reserved */
+       Ucbit   naca      : 1;  /* Normal ACA (Auto Contingent Allegiance) */
+       Ucbit   fr        : 1;  /* flag request (interrupt at completion) */
+       Ucbit   link      : 1;  /* link (another command follows) */
+};
+#endif
+
+#if    defined(_BIT_FIELDS_LTOH)       /* Intel byteorder */
+
+struct scsi_g5cdb {            /* scsi group 5 command description block */
+       Uchar   cmd;            /* command code */
+       Ucbit   reladr    : 1;  /* address is relative */
+       Ucbit   res       : 4;  /* reserved bits 1-4 of byte 1 */
+       Ucbit   lun       : 3;  /* logical unit number */
+       Uchar   addr[4];        /* logical block address */
+       Uchar   count[4];       /* transfer length */
+       Uchar   res10;          /* reserved byte 10 */
+       Ucbit   link      : 1;  /* link (another command follows) */
+       Ucbit   fr        : 1;  /* flag request (interrupt at completion) */
+       Ucbit   naca      : 1;  /* Normal ACA (Auto Contingent Allegiance) */
+       Ucbit   rsvd      : 3;  /* reserved */
+       Ucbit   vu_B6     : 1;  /* vendor unique (byte B bit 6) */
+       Ucbit   vu_B7     : 1;  /* vendor unique (byte B bit 7) */
+};
+
+#else  /* Motorola byteorder */
+
+struct scsi_g5cdb {            /* scsi group 5 command description block */
+       Uchar   cmd;            /* command code */
+       Ucbit   lun       : 3;  /* logical unit number */
+       Ucbit   res       : 4;  /* reserved bits 1-4 of byte 1 */
+       Ucbit   reladr    : 1;  /* address is relative */
+       Uchar   addr[4];        /* logical block address */
+       Uchar   count[4];       /* transfer length */
+       Uchar   res10;          /* reserved byte 10 */
+       Ucbit   vu_B7     : 1;  /* vendor unique (byte B bit 7) */
+       Ucbit   vu_B6     : 1;  /* vendor unique (byte B bit 6) */
+       Ucbit   rsvd      : 3;  /* reserved */
+       Ucbit   naca      : 1;  /* Normal ACA (Auto Contingent Allegiance) */
+       Ucbit   fr        : 1;  /* flag request (interrupt at completion) */
+       Ucbit   link      : 1;  /* link (another command follows) */
+};
+#endif
+
+#define        g0_cdbaddr(cdb, a)      ((cdb)->high_addr   = (a) >> 16,\
+                                   (cdb)->mid_addr = ((a) >> 8) & 0xFF,\
+                                   (cdb)->low_addr = (a) & 0xFF)
+
+#define        g1_cdbaddr(cdb, a)      ((cdb)->addr[0]    = (a) >> 24,\
+                                   (cdb)->addr[1] = ((a) >> 16)& 0xFF,\
+                                   (cdb)->addr[2] = ((a) >> 8) & 0xFF,\
+                                   (cdb)->addr[3] = (a) & 0xFF)
+
+#define        g5_cdbaddr(cdb, a)      g1_cdbaddr(cdb, a)
+
+
+#define        g0_cdblen(cdb, len)     ((cdb)->count = (len))
+
+#define        g1_cdblen(cdb, len)     ((cdb)->count[0]    = ((len) >> 8) & 0xFF,\
+                                   (cdb)->count[1] = (len) & 0xFF)
+
+#define        g5_cdblen(cdb, len)     ((cdb)->count[0]    = (len) >> 24L,\
+                                   (cdb)->count[1] = ((len) >> 16L)& 0xFF,\
+                                   (cdb)->count[2] = ((len) >> 8L) & 0xFF,\
+                                   (cdb)->count[3] = (len) & 0xFF)
+
+/*#define      XXXXX*/
+#ifdef XXXXX
+#define        i_to_long(a, i)         (((Uchar    *)(a))[0] = ((i) >> 24)& 0xFF,\
+                                   ((Uchar *)(a))[1] = ((i) >> 16)& 0xFF,\
+                                   ((Uchar *)(a))[2] = ((i) >> 8) & 0xFF,\
+                                   ((Uchar *)(a))[3] = (i) & 0xFF)
+
+#define        i_to_3_byte(a, i)       (((Uchar    *)(a))[0] = ((i) >> 16)& 0xFF,\
+                                   ((Uchar *)(a))[1] = ((i) >> 8) & 0xFF,\
+                                   ((Uchar *)(a))[2] = (i) & 0xFF)
+
+#define        i_to_4_byte(a, i)       (((Uchar    *)(a))[0] = ((i) >> 24)& 0xFF,\
+                                   ((Uchar *)(a))[1] = ((i) >> 16)& 0xFF,\
+                                   ((Uchar *)(a))[2] = ((i) >> 8) & 0xFF,\
+                                   ((Uchar *)(a))[3] = (i) & 0xFF)
+
+#define        i_to_short(a, i)        (((Uchar *)(a))[0] = ((i) >> 8) & 0xFF,\
+                                   ((Uchar *)(a))[1] = (i) & 0xFF)
+
+#define        a_to_u_short(a) ((unsigned short) \
+                       ((((Uchar*)    a)[1]       & 0xFF) | \
+                           (((Uchar*) a)[0] << 8  & 0xFF00)))
+
+#define        a_to_3_byte(a)  ((Ulong) \
+                       ((((Uchar*)    a)[2]       & 0xFF) | \
+                           (((Uchar*) a)[1] << 8  & 0xFF00) | \
+                           (((Uchar*) a)[0] << 16 & 0xFF0000)))
+
+#ifdef __STDC__
+#define        a_to_u_long(a)  ((Ulong) \
+                       ((((Uchar*)    a)[3]       & 0xFF) | \
+                           (((Uchar*) a)[2] << 8  & 0xFF00) | \
+                           (((Uchar*) a)[1] << 16 & 0xFF0000) | \
+                           (((Uchar*) a)[0] << 24 & 0xFF000000UL)))
+#else
+#define        a_to_u_long(a)  ((Ulong) \
+                       ((((Uchar*)    a)[3]       & 0xFF) | \
+                           (((Uchar*) a)[2] << 8  & 0xFF00) | \
+                           (((Uchar*) a)[1] << 16 & 0xFF0000) | \
+                           (((Uchar*) a)[0] << 24 & 0xFF000000)))
+#endif
+#endif /* XXXX */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SCG_SCSICDB_H */
diff --git a/libusal/usal/scsidefs.h b/libusal/usal/scsidefs.h
new file mode 100644 (file)
index 0000000..fc57c16
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)scsidefs.h      1.28 04/09/04 Copyright 1988 J. Schilling */
+/*
+ *     Definitions for SCSI devices i.e. for error strings in scsierrs.c
+ *
+ *     Copyright (c) 1988 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef        _SCG_SCSIDEFS_H
+#define        _SCG_SCSIDEFS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Disks
+ */
+#ifdef DEV_UNKNOWN
+/*
+ * True64 defines DEV_UNKNOWN in /usr/include/sys/devio.h as "UNKNOWN"
+ */
+#undef DEV_UNKNOWN
+#endif
+#define        DEV_UNKNOWN             0
+#define        DEV_ACB40X0             1
+#define        DEV_ACB4000             2
+#define        DEV_ACB4010             3
+#define        DEV_ACB4070             4
+#define        DEV_ACB5500             5
+#define        DEV_ACB4520A            6
+#define        DEV_ACB4525             7
+#define        DEV_MD21                8
+#define        DEV_MD23                9
+#define        DEV_NON_CCS_DSK         10
+#define        DEV_CCS_GENDISK         11
+
+/*
+ * Tapes
+ */
+#define        DEV_MT02                100
+#define        DEV_SC4000              101
+
+/*
+ * Printer
+ */
+#define        DEV_PRT                 200
+
+/*
+ * Processors
+ */
+#define        DEV_PROC                300
+
+/*
+ * Worm
+ */
+#define        DEV_WORM                400
+#define        DEV_RXT800S             401
+
+/*
+ * CD-ROM
+ */
+#define        DEV_CDROM               500
+#define        DEV_MMC_CDROM           501
+#define        DEV_MMC_CDR             502
+#define        DEV_MMC_CDRW            503
+#define        DEV_MMC_DVD             504
+#define        DEV_MMC_DVD_WR          505
+
+#define        DEV_CDD_521_OLD         510
+#define        DEV_CDD_521             511
+#define        DEV_CDD_522             512
+#define        DEV_PCD_600             513
+#define        DEV_CDD_2000            514
+#define        DEV_CDD_2600            515
+#define        DEV_TYUDEN_EW50         516
+#define        DEV_YAMAHA_CDR_100      520
+#define        DEV_YAMAHA_CDR_400      521
+#define        DEV_PLASMON_RF_4100     530
+#define        DEV_SONY_CDU_924        540
+#define        DEV_RICOH_RO_1420C      550
+#define        DEV_RICOH_RO_1060C      551
+#define        DEV_TEAC_CD_R50S        560
+#define        DEV_MATSUSHITA_7501     570
+#define        DEV_MATSUSHITA_7502     571
+#define        DEV_PIONEER_DW_S114X    580
+#define        DEV_PIONEER_DVDR_S101   581
+
+/*
+ * Scanners
+ */
+#define        DEV_HRSCAN              600
+#define        DEV_MS300A              601
+
+/*
+ * Optical memory
+ */
+#define        DEV_SONY_SMO            700
+
+
+#define        old_acb(d)      (((d) == DEV_ACB40X0) || \
+                           ((d) == DEV_ACB4000) || ((d) == DEV_ACB4010) || \
+                           ((d) == DEV_ACB4070) || ((d) == DEV_ACB5500))
+
+#define        is_ccs(d)       (!old_acb(d))
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SCG_SCSIDEFS_H */
diff --git a/libusal/usal/scsireg.h b/libusal/usal/scsireg.h
new file mode 100644 (file)
index 0000000..9fc0ea3
--- /dev/null
@@ -0,0 +1,1240 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)scsireg.h       1.31 04/09/04 Copyright 1987 J. Schilling */
+/*
+ *     usefull definitions for dealing with CCS SCSI - devices
+ *
+ *     Copyright (c) 1987 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef        _SCG_SCSIREG_H
+#define        _SCG_SCSIREG_H
+
+#include <utypes.h>
+#include <btorder.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if    defined(_BIT_FIELDS_LTOH)       /* Intel byteorder */
+
+struct scsi_inquiry {
+       Ucbit   type            : 5;    /*  0 */
+       Ucbit   qualifier       : 3;    /*  0 */
+
+       Ucbit   type_modifier   : 7;    /*  1 */
+       Ucbit   removable       : 1;    /*  1 */
+
+       Ucbit   ansi_version    : 3;    /*  2 */
+       Ucbit   ecma_version    : 3;    /*  2 */
+       Ucbit   iso_version     : 2;    /*  2 */
+
+       Ucbit   data_format     : 4;    /*  3 */
+       Ucbit   res3_54         : 2;    /*  3 */
+       Ucbit   termiop         : 1;    /*  3 */
+       Ucbit   aenc            : 1;    /*  3 */
+
+       Ucbit   add_len         : 8;    /*  4 */
+       Ucbit   sense_len       : 8;    /*  5 */ /* only Emulex ??? */
+       Ucbit   res2            : 8;    /*  6 */
+
+       Ucbit   softreset       : 1;    /*  7 */
+       Ucbit   cmdque          : 1;
+       Ucbit   res7_2          : 1;
+       Ucbit   linked          : 1;
+       Ucbit   sync            : 1;
+       Ucbit   wbus16          : 1;
+       Ucbit   wbus32          : 1;
+       Ucbit   reladr          : 1;    /*  7 */
+
+       char    vendor_info[8];         /*  8 */
+       char    prod_ident[16];         /* 16 */
+       char    prod_revision[4];       /* 32 */
+#ifdef comment
+       char    vendor_uniq[20];        /* 36 */
+       char    reserved[40];           /* 56 */
+#endif
+};                                     /* 96 */
+
+#else                                  /* Motorola byteorder */
+
+struct scsi_inquiry {
+       Ucbit   qualifier       : 3;    /*  0 */
+       Ucbit   type            : 5;    /*  0 */
+
+       Ucbit   removable       : 1;    /*  1 */
+       Ucbit   type_modifier   : 7;    /*  1 */
+
+       Ucbit   iso_version     : 2;    /*  2 */
+       Ucbit   ecma_version    : 3;
+       Ucbit   ansi_version    : 3;    /*  2 */
+
+       Ucbit   aenc            : 1;    /*  3 */
+       Ucbit   termiop         : 1;
+       Ucbit   res3_54         : 2;
+       Ucbit   data_format     : 4;    /*  3 */
+
+       Ucbit   add_len         : 8;    /*  4 */
+       Ucbit   sense_len       : 8;    /*  5 */ /* only Emulex ??? */
+       Ucbit   res2            : 8;    /*  6 */
+       Ucbit   reladr          : 1;    /*  7 */
+       Ucbit   wbus32          : 1;
+       Ucbit   wbus16          : 1;
+       Ucbit   sync            : 1;
+       Ucbit   linked          : 1;
+       Ucbit   res7_2          : 1;
+       Ucbit   cmdque          : 1;
+       Ucbit   softreset       : 1;
+       char    vendor_info[8];         /*  8 */
+       char    prod_ident[16];         /* 16 */
+       char    prod_revision[4];       /* 32 */
+#ifdef comment
+       char    vendor_uniq[20];        /* 36 */
+       char    reserved[40];           /* 56 */
+#endif
+};                                     /* 96 */
+#endif
+
+#ifdef __SCG_COMPAT__
+#define        info            vendor_info
+#define        ident           prod_ident
+#define        revision        prod_revision
+#endif
+
+/* Peripheral Device Qualifier */
+
+#define        INQ_DEV_PRESENT 0x00            /* Physical device present */
+#define        INQ_DEV_NOTPR   0x01            /* Physical device not present */
+#define        INQ_DEV_RES     0x02            /* Reserved */
+#define        INQ_DEV_NOTSUP  0x03            /* Logical unit not supported */
+
+/* Peripheral Device Type */
+
+#define        INQ_DASD        0x00            /* Direct-access device (disk) */
+#define        INQ_SEQD        0x01            /* Sequential-access device (tape) */
+#define        INQ_PRTD        0x02            /* Printer device */
+#define        INQ_PROCD       0x03            /* Processor device */
+#define        INQ_OPTD        0x04            /* Write once device (optical disk) */
+#define        INQ_WORM        0x04            /* Write once device (optical disk) */
+#define        INQ_ROMD        0x05            /* CD-ROM device */
+#define        INQ_SCAN        0x06            /* Scanner device */
+#define        INQ_OMEM        0x07            /* Optical Memory device */
+#define        INQ_JUKE        0x08            /* Medium Changer device (jukebox) */
+#define        INQ_COMM        0x09            /* Communications device */
+#define        INQ_IT8_1       0x0A            /* IT8 */
+#define        INQ_IT8_2       0x0B            /* IT8 */
+#define        INQ_STARR       0x0C            /* Storage array device */
+#define        INQ_ENCL        0x0D            /* Enclosure services device */
+#define        INQ_SDAD        0x0E            /* Simplyfied direct-access device */
+#define        INQ_OCRW        0x0F            /* Optical card reader/writer device */
+#define        INQ_BRIDGE      0x10            /* Bridging expander device */
+#define        INQ_OSD         0x11            /* Object based storage device */
+#define        INQ_ADC         0x12            /* Automation/Drive interface */
+#define        INQ_WELLKNOWN   0x1E            /* Well known logical unit */
+#define        INQ_NODEV       0x1F            /* Unknown or no device */
+#define        INQ_NOTPR       0x1F            /* Logical unit not present (SCSI-1) */
+
+#if    defined(_BIT_FIELDS_LTOH)       /* Intel byteorder */
+
+struct scsi_mode_header {
+       Ucbit   sense_data_len  : 8;
+       Uchar   medium_type;
+       Ucbit   res2            : 4;
+       Ucbit   cache           : 1;
+       Ucbit   res             : 2;
+       Ucbit   write_prot      : 1;
+       Uchar   blockdesc_len;
+};
+
+#else                                  /* Motorola byteorder */
+
+struct scsi_mode_header {
+       Ucbit   sense_data_len  : 8;
+       Uchar   medium_type;
+       Ucbit   write_prot      : 1;
+       Ucbit   res             : 2;
+       Ucbit   cache           : 1;
+       Ucbit   res2            : 4;
+       Uchar   blockdesc_len;
+};
+#endif
+
+struct scsi_modesel_header {
+       Ucbit   sense_data_len  : 8;
+       Uchar   medium_type;
+       Ucbit   res2            : 8;
+       Uchar   blockdesc_len;
+};
+
+struct scsi_mode_blockdesc {
+       Uchar   density;
+       Uchar   nlblock[3];
+       Ucbit   res             : 8;
+       Uchar   lblen[3];
+};
+
+#if    defined(_BIT_FIELDS_LTOH)       /* Intel byteorder */
+
+struct acb_mode_data {
+       Uchar   listformat;
+       Uchar   ncyl[2];
+       Uchar   nhead;
+       Uchar   start_red_wcurrent[2];
+       Uchar   start_precomp[2];
+       Uchar   landing_zone;
+       Uchar   step_rate;
+       Ucbit                   : 2;
+       Ucbit   hard_sec        : 1;
+       Ucbit   fixed_media     : 1;
+       Ucbit                   : 4;
+       Uchar   sect_per_trk;
+};
+
+#else                                  /* Motorola byteorder */
+
+struct acb_mode_data {
+       Uchar   listformat;
+       Uchar   ncyl[2];
+       Uchar   nhead;
+       Uchar   start_red_wcurrent[2];
+       Uchar   start_precomp[2];
+       Uchar   landing_zone;
+       Uchar   step_rate;
+       Ucbit                   : 4;
+       Ucbit   fixed_media     : 1;
+       Ucbit   hard_sec        : 1;
+       Ucbit                   : 2;
+       Uchar   sect_per_trk;
+};
+#endif
+
+#if    defined(_BIT_FIELDS_LTOH)       /* Intel byteorder */
+
+struct scsi_mode_page_header {
+       Ucbit   p_code          : 6;
+       Ucbit   res             : 1;
+       Ucbit   parsave         : 1;
+       Uchar   p_len;
+};
+
+/*
+ * This is a hack that allows mode pages without
+ * any further bitfileds to be defined bitorder independent.
+ */
+#define        MP_P_CODE                       \
+       Ucbit   p_code          : 6;    \
+       Ucbit   p_res           : 1;    \
+       Ucbit   parsave         : 1
+
+#else                                  /* Motorola byteorder */
+
+struct scsi_mode_page_header {
+       Ucbit   parsave         : 1;
+       Ucbit   res             : 1;
+       Ucbit   p_code          : 6;
+       Uchar   p_len;
+};
+
+/*
+ * This is a hack that allows mode pages without
+ * any further bitfileds to be defined bitorder independent.
+ */
+#define        MP_P_CODE                       \
+       Ucbit   parsave         : 1;    \
+       Ucbit   p_res           : 1;    \
+       Ucbit   p_code          : 6
+
+#endif
+
+#if    defined(_BIT_FIELDS_LTOH)       /* Intel byteorder */
+
+struct scsi_mode_page_01 {             /* Error recovery Parameters */
+               MP_P_CODE;              /* parsave & pagecode */
+       Uchar   p_len;                  /* 0x0A = 12 Bytes */
+       Ucbit   disa_correction : 1;    /* Byte 2 */
+       Ucbit   term_on_rec_err : 1;
+       Ucbit   report_rec_err  : 1;
+       Ucbit   en_early_corr   : 1;
+       Ucbit   read_continuous : 1;
+       Ucbit   tranfer_block   : 1;
+       Ucbit   en_auto_reall_r : 1;
+       Ucbit   en_auto_reall_w : 1;    /* Byte 2 */
+       Uchar   rd_retry_count;         /* Byte 3 */
+       Uchar   correction_span;
+       char    head_offset_count;
+       char    data_strobe_offset;
+       Uchar   res;
+       Uchar   wr_retry_count;
+       Uchar   res_tape[2];
+       Uchar   recov_timelim[2];
+};
+
+#else                                  /* Motorola byteorder */
+
+struct scsi_mode_page_01 {             /* Error recovery Parameters */
+               MP_P_CODE;              /* parsave & pagecode */
+       Uchar   p_len;                  /* 0x0A = 12 Bytes */
+       Ucbit   en_auto_reall_w : 1;    /* Byte 2 */
+       Ucbit   en_auto_reall_r : 1;
+       Ucbit   tranfer_block   : 1;
+       Ucbit   read_continuous : 1;
+       Ucbit   en_early_corr   : 1;
+       Ucbit   report_rec_err  : 1;
+       Ucbit   term_on_rec_err : 1;
+       Ucbit   disa_correction : 1;    /* Byte 2 */
+       Uchar   rd_retry_count;         /* Byte 3 */
+       Uchar   correction_span;
+       char    head_offset_count;
+       char    data_strobe_offset;
+       Uchar   res;
+       Uchar   wr_retry_count;
+       Uchar   res_tape[2];
+       Uchar   recov_timelim[2];
+};
+#endif
+
+
+#if    defined(_BIT_FIELDS_LTOH)       /* Intel byteorder */
+
+struct scsi_mode_page_02 {             /* Device dis/re connect Parameters */
+               MP_P_CODE;              /* parsave & pagecode */
+       Uchar   p_len;                  /* 0x0E = 16 Bytes */
+       Uchar   buf_full_ratio;
+       Uchar   buf_empt_ratio;
+       Uchar   bus_inact_limit[2];
+       Uchar   disc_time_limit[2];
+       Uchar   conn_time_limit[2];
+       Uchar   max_burst_size[2];      /* Start SCSI-2 */
+       Ucbit   data_tr_dis_ctl : 2;
+       Ucbit                   : 6;
+       Uchar   res[3];
+};
+
+#else                                  /* Motorola byteorder */
+
+struct scsi_mode_page_02 {             /* Device dis/re connect Parameters */
+               MP_P_CODE;              /* parsave & pagecode */
+       Uchar   p_len;                  /* 0x0E = 16 Bytes */
+       Uchar   buf_full_ratio;
+       Uchar   buf_empt_ratio;
+       Uchar   bus_inact_limit[2];
+       Uchar   disc_time_limit[2];
+       Uchar   conn_time_limit[2];
+       Uchar   max_burst_size[2];      /* Start SCSI-2 */
+       Ucbit                   : 6;
+       Ucbit   data_tr_dis_ctl : 2;
+       Uchar   res[3];
+};
+#endif
+
+#define        DTDC_DATADONE   0x01            /*
+                                        * Target may not disconnect once
+                                        * data transfer is started until
+                                        * all data successfully transferred.
+                                        */
+
+#define        DTDC_CMDDONE    0x03            /*
+                                        * Target may not disconnect once
+                                        * data transfer is started until
+                                        * command completed.
+                                        */
+
+
+#if    defined(_BIT_FIELDS_LTOH)       /* Intel byteorder */
+
+struct scsi_mode_page_03 {             /* Direct access format Paramters */
+               MP_P_CODE;              /* parsave & pagecode */
+       Uchar   p_len;                  /* 0x16 = 24 Bytes */
+       Uchar   trk_per_zone[2];
+       Uchar   alt_sec_per_zone[2];
+       Uchar   alt_trk_per_zone[2];
+       Uchar   alt_trk_per_vol[2];
+       Uchar   sect_per_trk[2];
+       Uchar   bytes_per_phys_sect[2];
+       Uchar   interleave[2];
+       Uchar   trk_skew[2];
+       Uchar   cyl_skew[2];
+       Ucbit                   : 3;
+       Ucbit   inhibit_save    : 1;
+       Ucbit   fmt_by_surface  : 1;
+       Ucbit   removable       : 1;
+       Ucbit   hard_sec        : 1;
+       Ucbit   soft_sec        : 1;
+       Uchar   res[3];
+};
+
+#else                                  /* Motorola byteorder */
+
+struct scsi_mode_page_03 {             /* Direct access format Paramters */
+               MP_P_CODE;              /* parsave & pagecode */
+       Uchar   p_len;                  /* 0x16 = 24 Bytes */
+       Uchar   trk_per_zone[2];
+       Uchar   alt_sec_per_zone[2];
+       Uchar   alt_trk_per_zone[2];
+       Uchar   alt_trk_per_vol[2];
+       Uchar   sect_per_trk[2];
+       Uchar   bytes_per_phys_sect[2];
+       Uchar   interleave[2];
+       Uchar   trk_skew[2];
+       Uchar   cyl_skew[2];
+       Ucbit   soft_sec        : 1;
+       Ucbit   hard_sec        : 1;
+       Ucbit   removable       : 1;
+       Ucbit   fmt_by_surface  : 1;
+       Ucbit   inhibit_save    : 1;
+       Ucbit                   : 3;
+       Uchar   res[3];
+};
+#endif
+
+#if    defined(_BIT_FIELDS_LTOH)       /* Intel byteorder */
+
+struct scsi_mode_page_04 {             /* Rigid disk Geometry Parameters */
+               MP_P_CODE;              /* parsave & pagecode */
+       Uchar   p_len;                  /* 0x16 = 24 Bytes */
+       Uchar   ncyl[3];
+       Uchar   nhead;
+       Uchar   start_precomp[3];
+       Uchar   start_red_wcurrent[3];
+       Uchar   step_rate[2];
+       Uchar   landing_zone[3];
+       Ucbit   rot_pos_locking : 2;    /* Start SCSI-2 */
+       Ucbit                   : 6;    /* Start SCSI-2 */
+       Uchar   rotational_off;
+       Uchar   res1;
+       Uchar   rotation_rate[2];
+       Uchar   res2[2];
+};
+
+#else                                  /* Motorola byteorder */
+
+struct scsi_mode_page_04 {             /* Rigid disk Geometry Parameters */
+               MP_P_CODE;              /* parsave & pagecode */
+       Uchar   p_len;                  /* 0x16 = 24 Bytes */
+       Uchar   ncyl[3];
+       Uchar   nhead;
+       Uchar   start_precomp[3];
+       Uchar   start_red_wcurrent[3];
+       Uchar   step_rate[2];
+       Uchar   landing_zone[3];
+       Ucbit                   : 6;    /* Start SCSI-2 */
+       Ucbit   rot_pos_locking : 2;    /* Start SCSI-2 */
+       Uchar   rotational_off;
+       Uchar   res1;
+       Uchar   rotation_rate[2];
+       Uchar   res2[2];
+};
+#endif
+
+#if    defined(_BIT_FIELDS_LTOH)       /* Intel byteorder */
+
+struct scsi_mode_page_05 {             /* Flexible disk Parameters */
+               MP_P_CODE;              /* parsave & pagecode */
+       Uchar   p_len;                  /* 0x1E = 32 Bytes */
+       Uchar   transfer_rate[2];
+       Uchar   nhead;
+       Uchar   sect_per_trk;
+       Uchar   bytes_per_phys_sect[2];
+       Uchar   ncyl[2];
+       Uchar   start_precomp[2];
+       Uchar   start_red_wcurrent[2];
+       Uchar   step_rate[2];
+       Uchar   step_pulse_width;
+       Uchar   head_settle_delay[2];
+       Uchar   motor_on_delay;
+       Uchar   motor_off_delay;
+       Ucbit   spc             : 4;
+       Ucbit                   : 4;
+       Ucbit                   : 5;
+       Ucbit   mo              : 1;
+       Ucbit   ssn             : 1;
+       Ucbit   trdy            : 1;
+       Uchar   write_compensation;
+       Uchar   head_load_delay;
+       Uchar   head_unload_delay;
+       Ucbit   pin_2_use       : 4;
+       Ucbit   pin_34_use      : 4;
+       Ucbit   pin_1_use       : 4;
+       Ucbit   pin_4_use       : 4;
+       Uchar   rotation_rate[2];
+       Uchar   res[2];
+};
+
+#else                                  /* Motorola byteorder */
+
+struct scsi_mode_page_05 {             /* Flexible disk Parameters */
+               MP_P_CODE;              /* parsave & pagecode */
+       Uchar   p_len;                  /* 0x1E = 32 Bytes */
+       Uchar   transfer_rate[2];
+       Uchar   nhead;
+       Uchar   sect_per_trk;
+       Uchar   bytes_per_phys_sect[2];
+       Uchar   ncyl[2];
+       Uchar   start_precomp[2];
+       Uchar   start_red_wcurrent[2];
+       Uchar   step_rate[2];
+       Uchar   step_pulse_width;
+       Uchar   head_settle_delay[2];
+       Uchar   motor_on_delay;
+       Uchar   motor_off_delay;
+       Ucbit   trdy            : 1;
+       Ucbit   ssn             : 1;
+       Ucbit   mo              : 1;
+       Ucbit                   : 5;
+       Ucbit                   : 4;
+       Ucbit   spc             : 4;
+       Uchar   write_compensation;
+       Uchar   head_load_delay;
+       Uchar   head_unload_delay;
+       Ucbit   pin_34_use      : 4;
+       Ucbit   pin_2_use       : 4;
+       Ucbit   pin_4_use       : 4;
+       Ucbit   pin_1_use       : 4;
+       Uchar   rotation_rate[2];
+       Uchar   res[2];
+};
+#endif
+
+#if    defined(_BIT_FIELDS_LTOH)       /* Intel byteorder */
+
+struct scsi_mode_page_07 {             /* Verify Error recovery */
+               MP_P_CODE;              /* parsave & pagecode */
+       Uchar   p_len;                  /* 0x0A = 12 Bytes */
+       Ucbit   disa_correction : 1;    /* Byte 2 */
+       Ucbit   term_on_rec_err : 1;
+       Ucbit   report_rec_err  : 1;
+       Ucbit   en_early_corr   : 1;
+       Ucbit   res             : 4;    /* Byte 2 */
+       Uchar   ve_retry_count;         /* Byte 3 */
+       Uchar   ve_correction_span;
+       char    res2[5];                /* Byte 5 */
+       Uchar   ve_recov_timelim[2];    /* Byte 10 */
+};
+
+#else                                  /* Motorola byteorder */
+
+struct scsi_mode_page_07 {             /* Verify Error recovery */
+               MP_P_CODE;              /* parsave & pagecode */
+       Uchar   p_len;                  /* 0x0A = 12 Bytes */
+       Ucbit   res             : 4;    /* Byte 2 */
+       Ucbit   en_early_corr   : 1;
+       Ucbit   report_rec_err  : 1;
+       Ucbit   term_on_rec_err : 1;
+       Ucbit   disa_correction : 1;    /* Byte 2 */
+       Uchar   ve_retry_count;         /* Byte 3 */
+       Uchar   ve_correction_span;
+       char    res2[5];                /* Byte 5 */
+       Uchar   ve_recov_timelim[2];    /* Byte 10 */
+};
+#endif
+
+#if    defined(_BIT_FIELDS_LTOH)       /* Intel byteorder */
+
+struct scsi_mode_page_08 {             /* Caching Parameters */
+               MP_P_CODE;              /* parsave & pagecode */
+       Uchar   p_len;                  /* 0x0A = 12 Bytes */
+       Ucbit   disa_rd_cache   : 1;    /* Byte 2 */
+       Ucbit   muliple_fact    : 1;
+       Ucbit   en_wt_cache     : 1;
+       Ucbit   res             : 5;    /* Byte 2 */
+       Ucbit   wt_ret_pri      : 4;    /* Byte 3 */
+       Ucbit   demand_rd_ret_pri: 4;   /* Byte 3 */
+       Uchar   disa_pref_tr_len[2];    /* Byte 4 */
+       Uchar   min_pref[2];            /* Byte 6 */
+       Uchar   max_pref[2];            /* Byte 8 */
+       Uchar   max_pref_ceiling[2];    /* Byte 10 */
+};
+
+#else                                  /* Motorola byteorder */
+
+struct scsi_mode_page_08 {             /* Caching Parameters */
+               MP_P_CODE;              /* parsave & pagecode */
+       Uchar   p_len;                  /* 0x0A = 12 Bytes */
+       Ucbit   res             : 5;    /* Byte 2 */
+       Ucbit   en_wt_cache     : 1;
+       Ucbit   muliple_fact    : 1;
+       Ucbit   disa_rd_cache   : 1;    /* Byte 2 */
+       Ucbit   demand_rd_ret_pri: 4;   /* Byte 3 */
+       Ucbit   wt_ret_pri      : 4;
+       Uchar   disa_pref_tr_len[2];    /* Byte 4 */
+       Uchar   min_pref[2];            /* Byte 6 */
+       Uchar   max_pref[2];            /* Byte 8 */
+       Uchar   max_pref_ceiling[2];    /* Byte 10 */
+};
+#endif
+
+struct scsi_mode_page_09 {             /* Peripheral device Parameters */
+               MP_P_CODE;              /* parsave & pagecode */
+       Uchar   p_len;                  /* >= 0x06 = 8 Bytes */
+       Uchar   interface_id[2];        /* Byte 2 */
+       Uchar   res[4];                 /* Byte 4 */
+       Uchar   vendor_specific[1];     /* Byte 8 */
+};
+
+#define        PDEV_SCSI       0x0000          /* scsi interface */
+#define        PDEV_SMD        0x0001          /* SMD interface */
+#define        PDEV_ESDI       0x0002          /* ESDI interface */
+#define        PDEV_IPI2       0x0003          /* IPI-2 interface */
+#define        PDEV_IPI3       0x0004          /* IPI-3 interface */
+
+#if    defined(_BIT_FIELDS_LTOH)       /* Intel byteorder */
+
+struct scsi_mode_page_0A {             /* Common device Control Parameters */
+               MP_P_CODE;              /* parsave & pagecode */
+       Uchar   p_len;                  /* 0x06 = 8 Bytes */
+       Ucbit   rep_log_exeption: 1;    /* Byte 2 */
+       Ucbit   res             : 7;    /* Byte 2 */
+       Ucbit   dis_queuing     : 1;    /* Byte 3 */
+       Ucbit   queuing_err_man : 1;
+       Ucbit   res2            : 2;
+       Ucbit   queue_alg_mod   : 4;    /* Byte 3 */
+       Ucbit   EAENP           : 1;    /* Byte 4 */
+       Ucbit   UAENP           : 1;
+       Ucbit   RAENP           : 1;
+       Ucbit   res3            : 4;
+       Ucbit   en_ext_cont_all : 1;    /* Byte 4 */
+       Ucbit   res4            : 8;
+       Uchar   ready_aen_hold_per[2];  /* Byte 6 */
+};
+
+#else                                  /* Motorola byteorder */
+
+struct scsi_mode_page_0A {             /* Common device Control Parameters */
+               MP_P_CODE;              /* parsave & pagecode */
+       Uchar   p_len;                  /* 0x06 = 8 Bytes */
+       Ucbit   res             : 7;    /* Byte 2 */
+       Ucbit   rep_log_exeption: 1;    /* Byte 2 */
+       Ucbit   queue_alg_mod   : 4;    /* Byte 3 */
+       Ucbit   res2            : 2;
+       Ucbit   queuing_err_man : 1;
+       Ucbit   dis_queuing     : 1;    /* Byte 3 */
+       Ucbit   en_ext_cont_all : 1;    /* Byte 4 */
+       Ucbit   res3            : 4;
+       Ucbit   RAENP           : 1;
+       Ucbit   UAENP           : 1;
+       Ucbit   EAENP           : 1;    /* Byte 4 */
+       Ucbit   res4            : 8;
+       Uchar   ready_aen_hold_per[2];  /* Byte 6 */
+};
+#endif
+
+#define        CTRL_QMOD_RESTRICT      0x0
+#define        CTRL_QMOD_UNRESTRICT    0x1
+
+
+struct scsi_mode_page_0B {             /* Medium Types Supported Parameters */
+               MP_P_CODE;              /* parsave & pagecode */
+       Uchar   p_len;                  /* 0x06 = 8 Bytes */
+       Uchar   res[2];                 /* Byte 2 */
+       Uchar   medium_one_supp;        /* Byte 4 */
+       Uchar   medium_two_supp;        /* Byte 5 */
+       Uchar   medium_three_supp;      /* Byte 6 */
+       Uchar   medium_four_supp;       /* Byte 7 */
+};
+
+#if    defined(_BIT_FIELDS_LTOH)       /* Intel byteorder */
+
+struct scsi_mode_page_0C {             /* Notch & Partition Parameters */
+               MP_P_CODE;              /* parsave & pagecode */
+       Uchar   p_len;                  /* 0x16 = 24 Bytes */
+       Ucbit   res             : 6;    /* Byte 2 */
+       Ucbit   logical_notch   : 1;
+       Ucbit   notched_drive   : 1;    /* Byte 2 */
+       Uchar   res2;                   /* Byte 3 */
+       Uchar   max_notches[2];         /* Byte 4  */
+       Uchar   active_notch[2];        /* Byte 6  */
+       Uchar   starting_boundary[4];   /* Byte 8  */
+       Uchar   ending_boundary[4];     /* Byte 12 */
+       Uchar   pages_notched[8];       /* Byte 16 */
+};
+
+#else                                  /* Motorola byteorder */
+
+struct scsi_mode_page_0C {             /* Notch & Partition Parameters */
+               MP_P_CODE;              /* parsave & pagecode */
+       Uchar   p_len;                  /* 0x16 = 24 Bytes */
+       Ucbit   notched_drive   : 1;    /* Byte 2 */
+       Ucbit   logical_notch   : 1;
+       Ucbit   res             : 6;    /* Byte 2 */
+       Uchar   res2;                   /* Byte 3 */
+       Uchar   max_notches[2];         /* Byte 4  */
+       Uchar   active_notch[2];        /* Byte 6  */
+       Uchar   starting_boundary[4];   /* Byte 8  */
+       Uchar   ending_boundary[4];     /* Byte 12 */
+       Uchar   pages_notched[8];       /* Byte 16 */
+};
+#endif
+
+#if    defined(_BIT_FIELDS_LTOH)       /* Intel byteorder */
+
+struct scsi_mode_page_0D {             /* CD-ROM Parameters */
+               MP_P_CODE;              /* parsave & pagecode */
+       Uchar   p_len;                  /* 0x06 = 8 Bytes */
+       Uchar   res;                    /* Byte 2 */
+       Ucbit   inact_timer_mult: 4;    /* Byte 3 */
+       Ucbit   res2            : 4;    /* Byte 3 */
+       Uchar   s_un_per_m_un[2];       /* Byte 4  */
+       Uchar   f_un_per_s_un[2];       /* Byte 6  */
+};
+
+#else                                  /* Motorola byteorder */
+
+struct scsi_mode_page_0D {             /* CD-ROM Parameters */
+               MP_P_CODE;              /* parsave & pagecode */
+       Uchar   p_len;                  /* 0x06 = 8 Bytes */
+       Uchar   res;                    /* Byte 2 */
+       Ucbit   res2            : 4;    /* Byte 3 */
+       Ucbit   inact_timer_mult: 4;    /* Byte 3 */
+       Uchar   s_un_per_m_un[2];       /* Byte 4  */
+       Uchar   f_un_per_s_un[2];       /* Byte 6  */
+};
+#endif
+
+struct sony_mode_page_20 {             /* Sony Format Mode Parameters */
+               MP_P_CODE;              /* parsave & pagecode */
+       Uchar   p_len;                  /* 0x0A = 12 Bytes */
+       Uchar   format_mode;
+       Uchar   format_type;
+#define        num_bands       user_band_size  /* Gilt bei Type 1 */
+       Uchar   user_band_size[4];      /* Gilt bei Type 0 */
+       Uchar   spare_band_size[2];
+       Uchar   res[2];
+};
+
+#if    defined(_BIT_FIELDS_LTOH)       /* Intel byteorder */
+
+struct toshiba_mode_page_20 {          /* Toshiba Speed Control Parameters */
+               MP_P_CODE;              /* parsave & pagecode */
+       Uchar   p_len;                  /* 0x01 = 3 Bytes */
+       Ucbit   speed           : 1;
+       Ucbit   res             : 7;
+};
+
+#else                                  /* Motorola byteorder */
+
+struct toshiba_mode_page_20 {          /* Toshiba Speed Control Parameters */
+               MP_P_CODE;              /* parsave & pagecode */
+       Uchar   p_len;                  /* 0x01 = 3 Bytes */
+       Ucbit   res             : 7;
+       Ucbit   speed           : 1;
+};
+#endif
+
+#if    defined(_BIT_FIELDS_LTOH)       /* Intel byteorder */
+
+struct ccs_mode_page_38 {              /* CCS Caching Parameters */
+               MP_P_CODE;              /* parsave & pagecode */
+       Uchar   p_len;                  /* 0x0E = 14 Bytes */
+
+       Ucbit   cache_table_size: 4;    /* Byte 3 */
+       Ucbit   cache_en        : 1;
+       Ucbit   res2            : 1;
+       Ucbit   wr_index_en     : 1;
+       Ucbit   res             : 1;    /* Byte 3 */
+       Uchar   threshold;              /* Byte 4 Prefetch threshold */
+       Uchar   max_prefetch;           /* Byte 5 Max. prefetch */
+       Uchar   max_multiplier;         /* Byte 6 Max. prefetch multiplier */
+       Uchar   min_prefetch;           /* Byte 7 Min. prefetch */
+       Uchar   min_multiplier;         /* Byte 8 Min. prefetch multiplier */
+       Uchar   res3[8];                /* Byte 9 */
+};
+
+#else                                  /* Motorola byteorder */
+
+struct ccs_mode_page_38 {              /* CCS Caching Parameters */
+               MP_P_CODE;              /* parsave & pagecode */
+       Uchar   p_len;                  /* 0x0E = 14 Bytes */
+
+       Ucbit   res             : 1;    /* Byte 3 */
+       Ucbit   wr_index_en     : 1;
+       Ucbit   res2            : 1;
+       Ucbit   cache_en        : 1;
+       Ucbit   cache_table_size: 4;    /* Byte 3 */
+       Uchar   threshold;              /* Byte 4 Prefetch threshold */
+       Uchar   max_prefetch;           /* Byte 5 Max. prefetch */
+       Uchar   max_multiplier;         /* Byte 6 Max. prefetch multiplier */
+       Uchar   min_prefetch;           /* Byte 7 Min. prefetch */
+       Uchar   min_multiplier;         /* Byte 8 Min. prefetch multiplier */
+       Uchar   res3[8];                /* Byte 9 */
+};
+#endif
+
+#if defined(_BIT_FIELDS_LTOH)  /* Intel byteorder */
+
+struct cd_mode_page_05 {               /* write parameters */
+               MP_P_CODE;              /* parsave & pagecode */
+       Uchar   p_len;                  /* 0x32 = 50 Bytes */
+       Ucbit   write_type      : 4;    /* Session write type (PACKET/TAO...)*/
+       Ucbit   test_write      : 1;    /* Do not actually write data       */
+       Ucbit   LS_V            : 1;    /* Link size valid                  */
+       Ucbit   BUFE            : 1;    /* Enable Bufunderrun free rec.     */
+       Ucbit   res_2_7         : 1;
+       Ucbit   track_mode      : 4;    /* Track mode (Q-sub control nibble) */
+       Ucbit   copy            : 1;    /* 1st higher gen of copy prot track ~*/
+       Ucbit   fp              : 1;    /* Fixed packed (if in packet mode) */
+       Ucbit   multi_session   : 2;    /* Multi session write type         */
+       Ucbit   dbtype          : 4;    /* Data block type                  */
+       Ucbit   res_4           : 4;    /* Reserved                         */
+       Uchar   link_size;              /* Link Size (default is 7)         */
+       Uchar   res_6;                  /* Reserved                         */
+       Ucbit   host_appl_code  : 6;    /* Host application code of disk    */
+       Ucbit   res_7           : 2;    /* Reserved                         */
+       Uchar   session_format;         /* Session format (DA/CDI/XA)       */
+       Uchar   res_9;                  /* Reserved                         */
+       Uchar   packet_size[4];         /* # of user datablocks/fixed packet */
+       Uchar   audio_pause_len[2];     /* # of blocks where index is zero  */
+       Uchar   media_cat_number[16];   /* Media catalog Number (MCN)       */
+       Uchar   ISRC[14];               /* ISRC for this track              */
+       Uchar   sub_header[4];
+       Uchar   vendor_uniq[4];
+};
+
+#else                          /* Motorola byteorder */
+
+struct cd_mode_page_05 {               /* write parameters */
+               MP_P_CODE;              /* parsave & pagecode */
+       Uchar   p_len;                  /* 0x32 = 50 Bytes */
+       Ucbit   res_2_7         : 1;
+       Ucbit   BUFE            : 1;    /* Enable Bufunderrun free rec.     */
+       Ucbit   LS_V            : 1;    /* Link size valid                  */
+       Ucbit   test_write      : 1;    /* Do not actually write data       */
+       Ucbit   write_type      : 4;    /* Session write type (PACKET/TAO...)*/
+       Ucbit   multi_session   : 2;    /* Multi session write type         */
+       Ucbit   fp              : 1;    /* Fixed packed (if in packet mode) */
+       Ucbit   copy            : 1;    /* 1st higher gen of copy prot track */
+       Ucbit   track_mode      : 4;    /* Track mode (Q-sub control nibble) */
+       Ucbit   res_4           : 4;    /* Reserved                         */
+       Ucbit   dbtype          : 4;    /* Data block type                  */
+       Uchar   link_size;              /* Link Size (default is 7)         */
+       Uchar   res_6;                  /* Reserved                         */
+       Ucbit   res_7           : 2;    /* Reserved                         */
+       Ucbit   host_appl_code  : 6;    /* Host application code of disk    */
+       Uchar   session_format;         /* Session format (DA/CDI/XA)       */
+       Uchar   res_9;                  /* Reserved                         */
+       Uchar   packet_size[4];         /* # of user datablocks/fixed packet */
+       Uchar   audio_pause_len[2];     /* # of blocks where index is zero  */
+       Uchar   media_cat_number[16];   /* Media catalog Number (MCN)       */
+       Uchar   ISRC[14];               /* ISRC for this track              */
+       Uchar   sub_header[4];
+       Uchar   vendor_uniq[4];
+};
+
+#endif
+
+#if defined(_BIT_FIELDS_LTOH)  /* Intel byteorder */
+
+struct cd_wr_speed_performance {
+       Uchar   res0;                   /* Reserved                         */
+       Ucbit   rot_ctl_sel     : 2;    /* Rotational control selected      */
+       Ucbit   res_1_27        : 6;    /* Reserved                         */
+       Uchar   wr_speed_supp[2];       /* Supported write speed            */
+};
+
+struct cd_mode_page_2A {               /* CD Cap / mech status */
+               MP_P_CODE;              /* parsave & pagecode */
+       Uchar   p_len;                  /* 0x14 = 20 Bytes (MMC) */
+                                       /* 0x18 = 24 Bytes (MMC-2) */
+                                       /* 0x1C >= 28 Bytes (MMC-3) */
+       Ucbit   cd_r_read       : 1;    /* Reads CD-R  media                */
+       Ucbit   cd_rw_read      : 1;    /* Reads CD-RW media                */
+       Ucbit   method2         : 1;    /* Reads fixed packet method2 media */
+       Ucbit   dvd_rom_read    : 1;    /* Reads DVD ROM media              */
+       Ucbit   dvd_r_read      : 1;    /* Reads DVD-R media                */
+       Ucbit   dvd_ram_read    : 1;    /* Reads DVD-RAM media              */
+       Ucbit   res_2_67        : 2;    /* Reserved                         */
+       Ucbit   cd_r_write      : 1;    /* Supports writing CD-R  media     */
+       Ucbit   cd_rw_write     : 1;    /* Supports writing CD-RW media     */
+       Ucbit   test_write      : 1;    /* Supports emulation write         */
+       Ucbit   res_3_3         : 1;    /* Reserved                         */
+       Ucbit   dvd_r_write     : 1;    /* Supports writing DVD-R media     */
+       Ucbit   dvd_ram_write   : 1;    /* Supports writing DVD-RAM media   */
+       Ucbit   res_3_67        : 2;    /* Reserved                         */
+       Ucbit   audio_play      : 1;    /* Supports Audio play operation    */
+       Ucbit   composite       : 1;    /* Deliveres composite A/V stream   */
+       Ucbit   digital_port_2  : 1;    /* Supports digital output on port 2 */
+       Ucbit   digital_port_1  : 1;    /* Supports digital output on port 1 */
+       Ucbit   mode_2_form_1   : 1;    /* Reads Mode-2 form 1 media (XA)   */
+       Ucbit   mode_2_form_2   : 1;    /* Reads Mode-2 form 2 media        */
+       Ucbit   multi_session   : 1;    /* Reads multi-session media        */
+       Ucbit   BUF             : 1;    /* Supports Buffer under. free rec. */
+       Ucbit   cd_da_supported : 1;    /* Reads audio data with READ CD cmd */
+       Ucbit   cd_da_accurate  : 1;    /* READ CD data stream is accurate   */
+       Ucbit   rw_supported    : 1;    /* Reads R-W sub channel information */
+       Ucbit   rw_deint_corr   : 1;    /* Reads de-interleved R-W sub chan  */
+       Ucbit   c2_pointers     : 1;    /* Supports C2 error pointers       */
+       Ucbit   ISRC            : 1;    /* Reads ISRC information           */
+       Ucbit   UPC             : 1;    /* Reads media catalog number (UPC) */
+       Ucbit   read_bar_code   : 1;    /* Supports reading bar codes       */
+       Ucbit   lock            : 1;    /* PREVENT/ALLOW may lock media     */
+       Ucbit   lock_state      : 1;    /* Lock state 0=unlocked 1=locked   */
+       Ucbit   prevent_jumper  : 1;    /* State of prev/allow jumper 0=pres */
+       Ucbit   eject           : 1;    /* Ejects disc/cartr with STOP LoEj  */
+       Ucbit   res_6_4         : 1;    /* Reserved                         */
+       Ucbit   loading_type    : 3;    /* Loading mechanism type           */
+       Ucbit   sep_chan_vol    : 1;    /* Vol controls each channel separat */
+       Ucbit   sep_chan_mute   : 1;    /* Mute controls each channel separat*/
+       Ucbit   disk_present_rep: 1;    /* Changer supports disk present rep */
+       Ucbit   sw_slot_sel     : 1;    /* Load empty slot in changer       */
+       Ucbit   side_change     : 1;    /* Side change capable              */
+       Ucbit   pw_in_lead_in   : 1;    /* Reads raw P-W sucode from lead in */
+       Ucbit   res_7           : 2;    /* Reserved                         */
+       Uchar   max_read_speed[2];      /* Max. read speed in KB/s          */
+       Uchar   num_vol_levels[2];      /* # of supported volume levels     */
+       Uchar   buffer_size[2];         /* Buffer size for the data in KB   */
+       Uchar   cur_read_speed[2];      /* Current read speed in KB/s       */
+       Uchar   res_16;                 /* Reserved                         */
+       Ucbit   res_17_0        : 1;    /* Reserved                         */
+       Ucbit   BCK             : 1;    /* Data valid on falling edge of BCK */
+       Ucbit   RCK             : 1;    /* Set: HIGH high LRCK=left channel  */
+       Ucbit   LSBF            : 1;    /* Set: LSB first Clear: MSB first  */
+       Ucbit   length          : 2;    /* 0=32BCKs 1=16BCKs 2=24BCKs 3=24I2c*/
+       Ucbit   res_17          : 2;    /* Reserved                         */
+       Uchar   max_write_speed[2];     /* Max. write speed supported in KB/s*/
+       Uchar   cur_write_speed[2];     /* Current write speed in KB/s      */
+
+                                       /* Byte 22 ... Only in MMC-2        */
+       Uchar   copy_man_rev[2];        /* Copy management revision supported*/
+       Uchar   res_24;                 /* Reserved                         */
+       Uchar   res_25;                 /* Reserved                         */
+
+                                       /* Byte 26 ... Only in MMC-3        */
+       Uchar   res_26;                 /* Reserved                         */
+       Ucbit   res_27_27       : 6;    /* Reserved                         */
+       Ucbit   rot_ctl_sel     : 2;    /* Rotational control selected      */
+       Uchar   v3_cur_write_speed[2];  /* Current write speed in KB/s      */
+       Uchar   num_wr_speed_des[2];    /* # of wr speed perf descr. tables */
+       struct cd_wr_speed_performance
+               wr_speed_des[1];        /* wr speed performance descriptor  */
+                                       /* Actually more (num_wr_speed_des) */
+};
+
+#else                          /* Motorola byteorder */
+
+struct cd_wr_speed_performance {
+       Uchar   res0;                   /* Reserved                         */
+       Ucbit   res_1_27        : 6;    /* Reserved                         */
+       Ucbit   rot_ctl_sel     : 2;    /* Rotational control selected      */
+       Uchar   wr_speed_supp[2];       /* Supported write speed            */
+};
+
+struct cd_mode_page_2A {               /* CD Cap / mech status */
+               MP_P_CODE;              /* parsave & pagecode */
+       Uchar   p_len;                  /* 0x14 = 20 Bytes (MMC) */
+                                       /* 0x18 = 24 Bytes (MMC-2) */
+                                       /* 0x1C >= 28 Bytes (MMC-3) */
+       Ucbit   res_2_67        : 2;    /* Reserved                         */
+       Ucbit   dvd_ram_read    : 1;    /* Reads DVD-RAM media              */
+       Ucbit   dvd_r_read      : 1;    /* Reads DVD-R media                */
+       Ucbit   dvd_rom_read    : 1;    /* Reads DVD ROM media              */
+       Ucbit   method2         : 1;    /* Reads fixed packet method2 media */
+       Ucbit   cd_rw_read      : 1;    /* Reads CD-RW media                */
+       Ucbit   cd_r_read       : 1;    /* Reads CD-R  media                */
+       Ucbit   res_3_67        : 2;    /* Reserved                         */
+       Ucbit   dvd_ram_write   : 1;    /* Supports writing DVD-RAM media   */
+       Ucbit   dvd_r_write     : 1;    /* Supports writing DVD-R media     */
+       Ucbit   res_3_3         : 1;    /* Reserved                         */
+       Ucbit   test_write      : 1;    /* Supports emulation write         */
+       Ucbit   cd_rw_write     : 1;    /* Supports writing CD-RW media     */
+       Ucbit   cd_r_write      : 1;    /* Supports writing CD-R  media     */
+       Ucbit   BUF             : 1;    /* Supports Buffer under. free rec. */
+       Ucbit   multi_session   : 1;    /* Reads multi-session media        */
+       Ucbit   mode_2_form_2   : 1;    /* Reads Mode-2 form 2 media        */
+       Ucbit   mode_2_form_1   : 1;    /* Reads Mode-2 form 1 media (XA)   */
+       Ucbit   digital_port_1  : 1;    /* Supports digital output on port 1 */
+       Ucbit   digital_port_2  : 1;    /* Supports digital output on port 2 */
+       Ucbit   composite       : 1;    /* Deliveres composite A/V stream   */
+       Ucbit   audio_play      : 1;    /* Supports Audio play operation    */
+       Ucbit   read_bar_code   : 1;    /* Supports reading bar codes       */
+       Ucbit   UPC             : 1;    /* Reads media catalog number (UPC) */
+       Ucbit   ISRC            : 1;    /* Reads ISRC information           */
+       Ucbit   c2_pointers     : 1;    /* Supports C2 error pointers       */
+       Ucbit   rw_deint_corr   : 1;    /* Reads de-interleved R-W sub chan */
+       Ucbit   rw_supported    : 1;    /* Reads R-W sub channel information */
+       Ucbit   cd_da_accurate  : 1;    /* READ CD data stream is accurate   */
+       Ucbit   cd_da_supported : 1;    /* Reads audio data with READ CD cmd */
+       Ucbit   loading_type    : 3;    /* Loading mechanism type           */
+       Ucbit   res_6_4         : 1;    /* Reserved                         */
+       Ucbit   eject           : 1;    /* Ejects disc/cartr with STOP LoEj */
+       Ucbit   prevent_jumper  : 1;    /* State of prev/allow jumper 0=pres */
+       Ucbit   lock_state      : 1;    /* Lock state 0=unlocked 1=locked   */
+       Ucbit   lock            : 1;    /* PREVENT/ALLOW may lock media     */
+       Ucbit   res_7           : 2;    /* Reserved                         */
+       Ucbit   pw_in_lead_in   : 1;    /* Reads raw P-W sucode from lead in */
+       Ucbit   side_change     : 1;    /* Side change capable              */
+       Ucbit   sw_slot_sel     : 1;    /* Load empty slot in changer       */
+       Ucbit   disk_present_rep: 1;    /* Changer supports disk present rep */
+       Ucbit   sep_chan_mute   : 1;    /* Mute controls each channel separat*/
+       Ucbit   sep_chan_vol    : 1;    /* Vol controls each channel separat */
+       Uchar   max_read_speed[2];      /* Max. read speed in KB/s          */
+       Uchar   num_vol_levels[2];      /* # of supported volume levels     */
+       Uchar   buffer_size[2];         /* Buffer size for the data in KB   */
+       Uchar   cur_read_speed[2];      /* Current read speed in KB/s       */
+       Uchar   res_16;                 /* Reserved                         */
+       Ucbit   res_17          : 2;    /* Reserved                         */
+       Ucbit   length          : 2;    /* 0=32BCKs 1=16BCKs 2=24BCKs 3=24I2c*/
+       Ucbit   LSBF            : 1;    /* Set: LSB first Clear: MSB first  */
+       Ucbit   RCK             : 1;    /* Set: HIGH high LRCK=left channel */
+       Ucbit   BCK             : 1;    /* Data valid on falling edge of BCK */
+       Ucbit   res_17_0        : 1;    /* Reserved                         */
+       Uchar   max_write_speed[2];     /* Max. write speed supported in KB/s*/
+       Uchar   cur_write_speed[2];     /* Current write speed in KB/s      */
+
+                                       /* Byte 22 ... Only in MMC-2        */
+       Uchar   copy_man_rev[2];        /* Copy management revision supported*/
+       Uchar   res_24;                 /* Reserved                         */
+       Uchar   res_25;                 /* Reserved                         */
+
+                                       /* Byte 26 ... Only in MMC-3        */
+       Uchar   res_26;                 /* Reserved                         */
+       Ucbit   res_27_27       : 6;    /* Reserved                         */
+       Ucbit   rot_ctl_sel     : 2;    /* Rotational control selected      */
+       Uchar   v3_cur_write_speed[2];  /* Current write speed in KB/s      */
+       Uchar   num_wr_speed_des[2];    /* # of wr speed perf descr. tables */
+       struct cd_wr_speed_performance
+               wr_speed_des[1];        /* wr speed performance descriptor  */
+                                       /* Actually more (num_wr_speed_des) */
+};
+
+#endif
+
+#define        LT_CADDY        0
+#define        LT_TRAY         1
+#define        LT_POP_UP       2
+#define        LT_RES3         3
+#define        LT_CHANGER_IND  4
+#define        LT_CHANGER_CART 5
+#define        LT_RES6         6
+#define        LT_RES7         7
+
+
+struct scsi_mode_data {
+       struct scsi_mode_header         header;
+       struct scsi_mode_blockdesc      blockdesc;
+       union   pagex   {
+               struct acb_mode_data            acb;
+               struct scsi_mode_page_01        page1;
+               struct scsi_mode_page_02        page2;
+               struct scsi_mode_page_03        page3;
+               struct scsi_mode_page_04        page4;
+               struct scsi_mode_page_05        page5;
+               struct scsi_mode_page_07        page7;
+               struct scsi_mode_page_08        page8;
+               struct scsi_mode_page_09        page9;
+               struct scsi_mode_page_0A        pageA;
+               struct scsi_mode_page_0B        pageB;
+               struct scsi_mode_page_0C        pageC;
+               struct scsi_mode_page_0D        pageD;
+               struct sony_mode_page_20        sony20;
+               struct toshiba_mode_page_20     toshiba20;
+               struct ccs_mode_page_38         ccs38;
+       } pagex;
+};
+
+struct scsi_capacity {
+       Int32_t c_baddr;                /* must convert byteorder!! */
+       Int32_t c_bsize;                /* must convert byteorder!! */
+};
+
+#if    defined(_BIT_FIELDS_LTOH)       /* Intel byteorder */
+
+struct scsi_def_header {
+       Ucbit           : 8;
+       Ucbit   format  : 3;
+       Ucbit   gdl     : 1;
+       Ucbit   mdl     : 1;
+       Ucbit           : 3;
+       Uchar   length[2];
+};
+
+#else                                  /* Motorola byteorder */
+
+struct scsi_def_header {
+       Ucbit           : 8;
+       Ucbit           : 3;
+       Ucbit   mdl     : 1;
+       Ucbit   gdl     : 1;
+       Ucbit   format  : 3;
+       Uchar   length[2];
+};
+#endif
+
+
+#if    defined(_BIT_FIELDS_LTOH)       /* Intel byteorder */
+
+struct scsi_format_header {
+       Ucbit   res             : 8;    /* Adaptec 5500: 1 --> format track */
+       Ucbit   vu              : 1;    /* Vendor Unique                    */
+       Ucbit   immed           : 1;    /* Return Immediately from Format   */
+       Ucbit   tryout          : 1;    /* Check if format parameters OK    */
+       Ucbit   ipattern        : 1;    /* Init patter descriptor present   */
+       Ucbit   serr            : 1;    /* Stop on error                    */
+       Ucbit   dcert           : 1;    /* Disable certification            */
+       Ucbit   dmdl            : 1;    /* Disable manufacturer defect list */
+       Ucbit   enable          : 1;    /* Enable to use the next 3 bits    */
+       Uchar   length[2];              /* Length of following list in bytes*/
+};
+
+#else                                  /* Motorola byteorder */
+
+struct scsi_format_header {
+       Ucbit   res             : 8;    /* Adaptec 5500: 1 --> format track */
+       Ucbit   enable          : 1;    /* Enable to use the next 3 bits    */
+       Ucbit   dmdl            : 1;    /* Disable manufacturer defect list */
+       Ucbit   dcert           : 1;    /* Disable certification            */
+       Ucbit   serr            : 1;    /* Stop on error                    */
+       Ucbit   ipattern        : 1;    /* Init patter descriptor present   */
+       Ucbit   tryout          : 1;    /* Check if format parameters OK    */
+       Ucbit   immed           : 1;    /* Return Immediately from Format   */
+       Ucbit   vu              : 1;    /* Vendor Unique                    */
+       Uchar   length[2];              /* Length of following list in bytes*/
+};
+#endif
+
+struct scsi_def_bfi {
+       Uchar   cyl[3];
+       Uchar   head;
+       Uchar   bfi[4];
+};
+
+struct scsi_def_phys {
+       Uchar   cyl[3];
+       Uchar   head;
+       Uchar   sec[4];
+};
+
+struct scsi_def_list {
+       struct  scsi_def_header hd;
+       union {
+                       Uchar           list_block[1][4];
+               struct  scsi_def_bfi    list_bfi[1];
+               struct  scsi_def_phys   list_phys[1];
+       } def_list;
+};
+
+struct scsi_format_data {
+       struct scsi_format_header hd;
+       union {
+                       Uchar           list_block[1][4];
+               struct  scsi_def_bfi    list_bfi[1];
+               struct  scsi_def_phys   list_phys[1];
+       } def_list;
+};
+
+#define        def_block       def_list.list_block
+#define        def_bfi         def_list.list_bfi
+#define        def_phys        def_list.list_phys
+
+#define        SC_DEF_BLOCK    0
+#define        SC_DEF_BFI      4
+#define        SC_DEF_PHYS     5
+#define        SC_DEF_VU       6
+#define        SC_DEF_RES      7
+
+struct scsi_format_cap_header {
+       Uchar   res[3];                 /* Reserved                     */
+       Uchar   len;                    /* Len (a multiple of 8)        */
+};
+
+#if    defined(_BIT_FIELDS_LTOH)       /* Intel byteorder */
+
+struct scsi_format_cap_desc {
+       Uchar   nblock[4];              /* Number of blocks             */
+       Ucbit   desc_type       : 2;    /* Descriptor type              */
+       Ucbit   fmt_type        : 6;    /* Format Taype                 */
+       Uchar   blen[3];                /* Logical block length         */
+};
+
+#else                                  /* Motorola byteorder */
+
+struct scsi_format_cap_desc {
+       Uchar   nblock[4];              /* Number of blocks             */
+       Ucbit   fmt_type        : 6;    /* Format Taype                 */
+       Ucbit   desc_type       : 2;    /* Descriptor type              */
+       Uchar   blen[3];                /* Logical block length         */
+};
+#endif
+
+/*
+ * Defines for 'fmt_type'.
+ */
+#define        FCAP_TYPE_DVDPLUS_FULL  0x26    /* DVD+RW Full Format           */
+
+/*
+ * Defines for 'desc_type'.
+ * In case of FCAP_DESC_RES, the descriptor is a formatted capacity descriptor
+ * and the 'blen' field is type dependent.
+ * For all other cases, this is the Current/Maximum Capacity descriptor and
+ * the value of 'fmt_type' is reserved and must be zero.
+ */
+#define        FCAP_DESC_RES           0       /* Reserved                     */
+#define        FCAP_DESC_UNFORM        1       /* Unformatted Media            */
+#define        FCAP_DESC_FORM          2       /* Formatted Media              */
+#define        FCAP_DESC_NOMEDIA       3       /* No Media                     */
+
+struct scsi_cap_data {
+       struct scsi_format_cap_header   hd;
+       struct scsi_format_cap_desc     list[1];
+};
+
+
+struct scsi_send_diag_cmd {
+       Uchar   cmd;
+       Uchar   addr[4];
+       Ucbit           : 8;
+};
+
+#if    defined(_BIT_FIELDS_LTOH)       /* Intel byteorder */
+
+struct scsi_sector_header {
+       Uchar   cyl[2];
+       Uchar   head;
+       Uchar   sec;
+       Ucbit           : 5;
+       Ucbit   rp      : 1;
+       Ucbit   sp      : 1;
+       Ucbit   dt      : 1;
+};
+
+#else                                  /* Motorola byteorder */
+
+struct scsi_sector_header {
+       Uchar   cyl[2];
+       Uchar   head;
+       Uchar   sec;
+       Ucbit   dt      : 1;
+       Ucbit   sp      : 1;
+       Ucbit   rp      : 1;
+       Ucbit           : 5;
+};
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SCG_SCSIREG_H */
diff --git a/libusal/usal/scsisense.h b/libusal/usal/scsisense.h
new file mode 100644 (file)
index 0000000..c5ee6ab
--- /dev/null
@@ -0,0 +1,216 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)scsisense.h     2.18 04/09/04 Copyright 1986 J. Schilling */
+/*
+ *     Definitions for the SCSI status code and sense structure
+ *
+ *     Copyright (c) 1986 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef        _SCG_SCSISENSE_H
+#define        _SCG_SCSISENSE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * SCSI status completion block.
+ */
+#define        SCSI_EXTENDED_STATUS
+
+#if    defined(_BIT_FIELDS_LTOH)       /* Intel byteorder */
+
+struct scsi_status {
+       Ucbit   vu_00   : 1;    /* vendor unique */
+       Ucbit   chk     : 1;    /* check condition: sense data available */
+       Ucbit   cm      : 1;    /* condition met */
+       Ucbit   busy    : 1;    /* device busy or reserved */
+       Ucbit   is      : 1;    /* intermediate status sent */
+       Ucbit   vu_05   : 1;    /* vendor unique */
+#define        st_scsi2        vu_05   /* SCSI-2 modifier bit */
+       Ucbit   vu_06   : 1;    /* vendor unique */
+       Ucbit   st_rsvd : 1;    /* reserved */
+
+#ifdef SCSI_EXTENDED_STATUS
+#define        ext_st1 st_rsvd         /* extended status (next byte valid) */
+       /* byte 1 */
+       Ucbit   ha_er   : 1;    /* host adapter detected error */
+       Ucbit   reserved: 6;    /* reserved */
+       Ucbit   ext_st2 : 1;    /* extended status (next byte valid) */
+       /* byte 2 */
+       Uchar   byte2;          /* third byte */
+#endif /* SCSI_EXTENDED_STATUS */
+};
+
+#else  /* Motorola byteorder */
+
+struct scsi_status {
+       Ucbit   st_rsvd : 1;    /* reserved */
+       Ucbit   vu_06   : 1;    /* vendor unique */
+       Ucbit   vu_05   : 1;    /* vendor unique */
+#define        st_scsi2        vu_05   /* SCSI-2 modifier bit */
+       Ucbit   is      : 1;    /* intermediate status sent */
+       Ucbit   busy    : 1;    /* device busy or reserved */
+       Ucbit   cm      : 1;    /* condition met */
+       Ucbit   chk     : 1;    /* check condition: sense data available */
+       Ucbit   vu_00   : 1;    /* vendor unique */
+#ifdef SCSI_EXTENDED_STATUS
+#define        ext_st1 st_rsvd         /* extended status (next byte valid) */
+       /* byte 1 */
+       Ucbit   ext_st2 : 1;    /* extended status (next byte valid) */
+       Ucbit   reserved: 6;    /* reserved */
+       Ucbit   ha_er   : 1;    /* host adapter detected error */
+       /* byte 2 */
+       Uchar   byte2;          /* third byte */
+#endif /* SCSI_EXTENDED_STATUS */
+};
+#endif
+
+/*
+ * OLD Standard (Non Extended) SCSI Sense. Used mainly by the
+ * Adaptec ACB 4000 which is the only controller that
+ * does not support the Extended sense format.
+ */
+#if    defined(_BIT_FIELDS_LTOH)       /* Intel byteorder */
+
+struct scsi_sense {            /* scsi sense for error classes 0-6 */
+       Ucbit   code    : 7;    /* error class/code */
+       Ucbit   adr_val : 1;    /* sense data is valid */
+#ifdef comment
+       Ucbit   high_addr:5;    /* high byte of block addr */
+       Ucbit   rsvd    : 3;
+#else
+       Uchar   high_addr;      /* high byte of block addr */
+#endif
+       Uchar   mid_addr;       /* middle byte of block addr */
+       Uchar   low_addr;       /* low byte of block addr */
+};
+
+#else  /* Motorola byteorder */
+
+struct scsi_sense {            /* scsi sense for error classes 0-6 */
+       Ucbit   adr_val : 1;    /* sense data is valid */
+       Ucbit   code    : 7;    /* error class/code */
+#ifdef comment
+       Ucbit   rsvd    : 3;
+       Ucbit   high_addr:5;    /* high byte of block addr */
+#else
+       Uchar   high_addr;      /* high byte of block addr */
+#endif
+       Uchar   mid_addr;       /* middle byte of block addr */
+       Uchar   low_addr;       /* low byte of block addr */
+};
+#endif
+
+/*
+ * SCSI extended sense parameter block.
+ */
+#ifdef comment
+#define        SC_CLASS_EXTENDED_SENSE 0x7     /* indicates extended sense */
+#endif
+
+#if    defined(_BIT_FIELDS_LTOH)       /* Intel byteorder */
+
+struct scsi_ext_sense {        /* scsi extended sense for error class 7 */
+       /* byte 0 */
+       Ucbit   type    : 7;    /* fixed at 0x70 */
+       Ucbit   adr_val : 1;    /* sense data is valid */
+       /* byte 1 */
+       Uchar   seg_num;        /* segment number, applies to copy cmd only */
+       /* byte 2 */
+       Ucbit   key     : 4;    /* sense key, see below */
+       Ucbit           : 1;    /* reserved */
+       Ucbit   ili     : 1;    /* incorrect length indicator */
+       Ucbit   eom     : 1;    /* end of media */
+       Ucbit   fil_mk  : 1;    /* file mark on device */
+       /* bytes 3 through 7 */
+       Uchar   info_1;         /* information byte 1 */
+       Uchar   info_2;         /* information byte 2 */
+       Uchar   info_3;         /* information byte 3 */
+       Uchar   info_4;         /* information byte 4 */
+       Uchar   add_len;        /* number of additional bytes */
+       /* bytes 8 through 13, CCS additions */
+       Uchar   optional_8;     /* CCS search and copy only */
+       Uchar   optional_9;     /* CCS search and copy only */
+       Uchar   optional_10;    /* CCS search and copy only */
+       Uchar   optional_11;    /* CCS search and copy only */
+       Uchar   sense_code;     /* sense code */
+       Uchar   qual_code;      /* sense code qualifier */
+       Uchar   fru_code;       /* Field replacable unit code */
+       Ucbit   bptr    : 3;    /* bit pointer for failure (if bpv) */
+       Ucbit   bpv     : 1;    /* bit pointer is valid */
+       Ucbit           : 2;
+       Ucbit   cd      : 1;    /* pointers refer to command not data */
+       Ucbit   sksv    : 1;    /* sense key specific valid */
+       Uchar   field_ptr[2];   /* field pointer for failure */
+       Uchar   add_info[2];    /* round up to 20 bytes */
+};
+
+#else  /* Motorola byteorder */
+
+struct scsi_ext_sense {        /* scsi extended sense for error class 7 */
+       /* byte 0 */
+       Ucbit   adr_val : 1;    /* sense data is valid */
+       Ucbit   type    : 7;    /* fixed at 0x70 */
+       /* byte 1 */
+       Uchar   seg_num;        /* segment number, applies to copy cmd only */
+       /* byte 2 */
+       Ucbit   fil_mk  : 1;    /* file mark on device */
+       Ucbit   eom     : 1;    /* end of media */
+       Ucbit   ili     : 1;    /* incorrect length indicator */
+       Ucbit           : 1;    /* reserved */
+       Ucbit   key     : 4;    /* sense key, see below */
+       /* bytes 3 through 7 */
+       Uchar   info_1;         /* information byte 1 */
+       Uchar   info_2;         /* information byte 2 */
+       Uchar   info_3;         /* information byte 3 */
+       Uchar   info_4;         /* information byte 4 */
+       Uchar   add_len;        /* number of additional bytes */
+       /* bytes 8 through 13, CCS additions */
+       Uchar   optional_8;     /* CCS search and copy only */
+       Uchar   optional_9;     /* CCS search and copy only */
+       Uchar   optional_10;    /* CCS search and copy only */
+       Uchar   optional_11;    /* CCS search and copy only */
+       Uchar   sense_code;     /* sense code */
+       Uchar   qual_code;      /* sense code qualifier */
+       Uchar   fru_code;       /* Field replacable unit code */
+       Ucbit   sksv    : 1;    /* sense key specific valid */
+       Ucbit   cd      : 1;    /* pointers refer to command not data */
+       Ucbit           : 2;
+       Ucbit   bpv     : 1;    /* bit pointer is valid */
+       Ucbit   bptr    : 3;    /* bit pointer for failure (if bpv) */
+       Uchar   field_ptr[2];   /* field pointer for failure */
+       Uchar   add_info[2];    /* round up to 20 bytes */
+};
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SCG_SCSISENSE_H */
diff --git a/libusal/usal/scsitransp.h b/libusal/usal/scsitransp.h
new file mode 100644 (file)
index 0000000..a4f2327
--- /dev/null
@@ -0,0 +1,264 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)scsitransp.h    1.54 03/05/03 Copyright 1995 J. Schilling */
+/*
+ *     Definitions for commands that use functions from scsitransp.c
+ *
+ *     Copyright (c) 1995 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef        _SCG_SCSITRANSP_H
+#define        _SCG_SCSITRANSP_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef        struct usal_scsi        SCSI;
+
+typedef struct {
+       int     scsibus;        /* SCSI bus #    for next I/O           */
+       int     target;         /* SCSI target # for next I/O           */
+       int     lun;            /* SCSI lun #    for next I/O           */
+} usal_addr_t;
+
+#ifndef        _SCG_SCGOPS_H
+#include <usal/usalops.h>
+#endif
+
+typedef        int     (*usal_cb_t)(void *);
+
+struct usal_scsi {
+       usal_ops_t *ops;                /* Ptr to low level SCSI transport ops  */
+       int     fd;             /* File descriptor for next I/O         */
+       usal_addr_t     addr;   /* SCSI address for next I/O            */
+       int     flags;          /* Libusal flags (see below)            */
+       int     dflags;         /* Drive specific flags (see below)     */
+       int     kdebug;         /* Kernel debug value for next I/O      */
+       int     debug;          /* Debug value for SCSI library         */
+       int     silent;         /* Be silent if value > 0               */
+       int     verbose;        /* Be verbose if value > 0              */
+       int     overbose;       /* Be verbose in open() if value > 0    */
+       int     disre_disable;
+       int     deftimeout;
+       int     noparity;       /* Do not use SCSI parity fo next I/O   */
+       int     dev;            /* from scsi_cdr.c                      */
+       struct usal_cmd *scmd;
+       char    *cmdname;
+       char    *curcmdname;
+       BOOL    running;
+       int     error;          /* libusal error number                 */
+
+       long    maxdma;         /* Max DMA limit for this open instance */
+       long    maxbuf;         /* Cur DMA buffer limit for this inst.  */
+                               /* This is the size behind bufptr       */
+       struct timeval  *cmdstart;
+       struct timeval  *cmdstop;
+       const char      **nonstderrs;
+       void    *local;         /* Local data from the low level code   */
+       void    *bufbase;       /* needed for scsi_freebuf()            */
+       void    *bufptr;        /* DMA buffer pointer for appl. use     */
+       char    *errstr;        /* Error string for scsi_open/sendmcd   */
+       char    *errbeg;        /* Pointer to begin of not flushed data */
+       char    *errptr;        /* Actual write pointer into errstr     */
+       void    *errfile;       /* FILE to write errors to. NULL for not*/
+                               /* writing and leaving errs in errstr   */
+       usal_cb_t cb_fun;
+       void    *cb_arg;
+
+       struct scsi_inquiry *inq;
+       struct scsi_capacity *cap;
+};
+
+/*
+ * Macros for accessing members of the usal address structure.
+ * usal_settarget() is the only function that is allowed to modify
+ * the values of the SCSI address.
+ */
+#define        usal_scsibus(usalp)     (usalp)->addr.scsibus
+#define        usal_target(usalp)      (usalp)->addr.target
+#define        usal_lun(usalp)         (usalp)->addr.lun
+
+/*
+ * Flags for struct SCSI:
+ */
+/* NONE yet */
+
+/*
+ * Drive specific flags for struct SCSI:
+ */
+#define        DRF_MODE_DMA_OVR        0x0001          /* Drive gives DMA overrun */
+                                               /* on mode sense           */
+
+#define        SCSI_ERRSTR_SIZE        4096
+
+/*
+ * Libusal error codes:
+ */
+#define        SCG_ERRBASE             1000000
+#define        SCG_NOMEM               1000001
+
+/*
+ * Function codes for usal_version():
+ */
+#define        SCG_VERSION             0       /* libusal or transport version */
+#define        SCG_AUTHOR              1       /* Author of above */
+#define        SCG_SCCS_ID             2       /* SCCS id of above */
+#define        SCG_RVERSION            10      /* Remote transport version */
+#define        SCG_RAUTHOR             11      /* Remote transport author */
+#define        SCG_RSCCS_ID            12      /* Remote transport SCCS ID */
+#define        SCG_KVERSION            20      /* Kernel transport version */
+
+/*
+ * Function codes for usal_reset():
+ */
+#define        SCG_RESET_NOP           0       /* Test if reset is supported */
+#define        SCG_RESET_TGT           1       /* Reset Target only */
+#define        SCG_RESET_BUS           2       /* Reset complete SCSI Bus */
+
+/*
+ * Helpers for the error buffer in SCSI*
+ */
+#define        usal_errsize(usalp)     ((usalp)->errptr - (usalp)->errstr)
+#define        usal_errrsize(usalp)    (SCSI_ERRSTR_SIZE - usal_errsize(usalp))
+
+/*
+ * From scsitransp.c:
+ */
+extern char    *usal_version(SCSI *usalp, int what);
+extern int     usal__open(SCSI *usalp, char *device);
+extern int     usal__close(SCSI *usalp);
+extern BOOL    usal_havebus(SCSI *usalp, int);
+extern int     usal_initiator_id(SCSI *usalp);
+extern int     usal_isatapi(SCSI *usalp);
+extern int     usal_reset(SCSI *usalp, int what);
+extern void    *usal_getbuf(SCSI *usalp, long);
+extern void    usal_freebuf(SCSI *usalp);
+extern long    usal_bufsize(SCSI *usalp, long);
+extern void    usal_setnonstderrs(SCSI *usalp, const char **);
+extern BOOL    usal_yes(char *);
+extern int     usal_cmd(SCSI *usalp);
+extern void    usal_vhead(SCSI *usalp);
+extern int     usal_svhead(SCSI *usalp, char *buf, int maxcnt);
+extern int     usal_vtail(SCSI *usalp);
+extern int     usal_svtail(SCSI *usalp, int *retp, char *buf, int maxcnt);
+extern void    usal_vsetup(SCSI *usalp);
+extern int     usal_getresid(SCSI *usalp);
+extern int     usal_getdmacnt(SCSI *usalp);
+extern BOOL    usal_cmd_err(SCSI *usalp);
+extern void    usal_printerr(SCSI *usalp);
+#ifdef EOF     /* stdio.h has been included */
+extern void    usal_fprinterr(SCSI *usalp, FILE *f);
+#endif
+extern int     usal_sprinterr(SCSI *usalp, char *buf, int maxcnt);
+extern int     usal__sprinterr(SCSI *usalp, char *buf, int maxcnt);
+extern void    usal_printcdb(SCSI *usalp);
+extern int     usal_sprintcdb(SCSI *usalp, char *buf, int maxcnt);
+extern void    usal_printwdata(SCSI *usalp);
+extern int     usal_sprintwdata(SCSI *usalp, char *buf, int maxcnt);
+extern void    usal_printrdata(SCSI *usalp);
+extern int     usal_sprintrdata(SCSI *usalp, char *buf, int maxcnt);
+extern void    usal_printresult(SCSI *usalp);
+extern int     usal_sprintresult(SCSI *usalp, char *buf, int maxcnt);
+extern void    usal_printstatus(SCSI *usalp);
+extern int     usal_sprintstatus(SCSI *usalp, char *buf, int maxcnt);
+#ifdef EOF     /* stdio.h has been included */
+extern void    usal_fprbytes(FILE *, char *, unsigned char *, int);
+extern void    usal_fprascii(FILE *, char *, unsigned char *, int);
+#endif
+extern void    usal_prbytes(char *, unsigned char *, int);
+extern void    usal_prascii(char *, unsigned char *, int);
+extern int     usal_sprbytes(char *buf, int maxcnt, char *, unsigned char *, int);
+extern int     usal_sprascii(char *buf, int maxcnt, char *, unsigned char *, int);
+#ifdef EOF     /* stdio.h has been included */
+extern void    usal_fprsense(FILE *f, unsigned char *, int);
+#endif
+extern void    usal_prsense(unsigned char *, int);
+extern int     usal_sprsense(char *buf, int maxcnt, unsigned char *, int);
+extern int     usal_cmd_status(SCSI *usalp);
+extern int     usal_sense_key(SCSI *usalp);
+extern int     usal_sense_code(SCSI *usalp);
+extern int     usal_sense_qual(SCSI *usalp);
+#ifdef _SCG_SCSIREG_H
+#ifdef EOF     /* stdio.h has been included */
+extern void    usal_fprintdev(FILE *, struct scsi_inquiry *);
+#endif
+extern void    usal_printdev(struct scsi_inquiry *);
+#endif
+extern int     usal_printf(SCSI *usalp, const char *form, ...);
+extern int     usal_errflush(SCSI *usalp);
+#ifdef EOF     /* stdio.h has been included */
+extern int     usal_errfflush(SCSI *usalp, FILE *f);
+#endif
+
+/*
+ * From scsierrmsg.c:
+ */
+extern const char      *usal_sensemsg(int, int, int, const char **, char *, 
+                                                                                         int maxcnt);
+#ifdef _SCG_SCSISENSE_H
+extern int             usal__errmsg(SCSI *usalp, char *obuf, int maxcnt,
+                                                                               struct scsi_sense *, struct scsi_status *, int);
+#endif
+
+/*
+ * From scsiopen.c:
+ */
+#ifdef EOF     /* stdio.h has been included */
+extern int     usal_help(FILE *f);
+#endif
+extern SCSI    *usal_open(char *scsidev, char *errs, int slen, int odebug, 
+                                                                int be_verbose);
+extern int     usal_close(SCSI * usalp);
+extern void    usal_settimeout(SCSI * usalp, int timeout);
+extern SCSI    *usal_smalloc(void);
+extern void    usal_sfree(SCSI *usalp);
+
+/*
+ * From usalsettarget.c:
+ */
+extern int     usal_settarget(SCSI *usalp, int scsibus, int target, int lun);
+
+/*
+ * From scsi-remote.c:
+ */
+extern usal_ops_t *usal_remote(void);
+
+/*
+ * From scsihelp.c:
+ */
+#ifdef EOF     /* stdio.h has been included */
+extern void    __usal_help(FILE *f, char *name, char *tcomment, char *tind,
+                                                                 char *tspec, char *texample, BOOL mayscan, 
+                                                                 BOOL bydev);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SCG_SCSITRANSP_H */
diff --git a/libusal/usal/spti-wnt.h b/libusal/usal/spti-wnt.h
new file mode 100644 (file)
index 0000000..3edbe8f
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/*
+ * distilled information from various header files from Microsoft's
+ * DDK for Windows NT 4.0
+ */
+#ifndef        _SCSIPT_H_INC
+#define        _SCSIPT_H_INC
+
+#include <windows.h>
+
+typedef struct {
+       USHORT          Length;
+       UCHAR           ScsiStatus;
+       UCHAR           PathId;
+       UCHAR           TargetId;
+       UCHAR           Lun;
+       UCHAR           CdbLength;
+       UCHAR           SenseInfoLength;
+       UCHAR           DataIn;
+       ULONG           DataTransferLength;
+       ULONG           TimeOutValue;
+       ULONG           DataBufferOffset;
+       ULONG           SenseInfoOffset;
+       UCHAR           Cdb[16];
+} SCSI_PASS_THROUGH, *PSCSI_PASS_THROUGH;
+
+
+typedef struct {
+       USHORT          Length;
+       UCHAR           ScsiStatus;
+       UCHAR           PathId;
+       UCHAR           TargetId;
+       UCHAR           Lun;
+       UCHAR           CdbLength;
+       UCHAR           SenseInfoLength;
+       UCHAR           DataIn;
+       ULONG           DataTransferLength;
+       ULONG           TimeOutValue;
+       PVOID           DataBuffer;
+       ULONG           SenseInfoOffset;
+       UCHAR           Cdb[16];
+} SCSI_PASS_THROUGH_DIRECT, *PSCSI_PASS_THROUGH_DIRECT;
+
+
+typedef struct {
+       SCSI_PASS_THROUGH spt;
+       ULONG           Filler;
+       UCHAR           ucSenseBuf[32];
+       UCHAR           ucDataBuf[512];
+} SCSI_PASS_THROUGH_WITH_BUFFERS, *PSCSI_PASS_THROUGH_WITH_BUFFERS;
+
+
+typedef struct {
+       SCSI_PASS_THROUGH_DIRECT spt;
+       ULONG           Filler;
+       UCHAR           ucSenseBuf[32];
+} SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER, *PSCSI_PASS_THROUGH_DIRECT_WITH_BUFFER;
+
+
+
+typedef struct {
+       UCHAR           NumberOfLogicalUnits;
+       UCHAR           InitiatorBusId;
+       ULONG           InquiryDataOffset;
+} SCSI_BUS_DATA, *PSCSI_BUS_DATA;
+
+
+typedef struct {
+       UCHAR           NumberOfBusses;
+       SCSI_BUS_DATA   BusData[1];
+} SCSI_ADAPTER_BUS_INFO, *PSCSI_ADAPTER_BUS_INFO;
+
+
+typedef struct {
+       UCHAR           PathId;
+       UCHAR           TargetId;
+       UCHAR           Lun;
+       BOOLEAN         DeviceClaimed;
+       ULONG           InquiryDataLength;
+       ULONG           NextInquiryDataOffset;
+       UCHAR           InquiryData[1];
+} SCSI_INQUIRY_DATA, *PSCSI_INQUIRY_DATA;
+
+
+typedef struct {
+       ULONG           Length;
+       UCHAR           PortNumber;
+       UCHAR           PathId;
+       UCHAR           TargetId;
+       UCHAR           Lun;
+} SCSI_ADDRESS, *PSCSI_ADDRESS;
+
+
+/*
+ * method codes
+ */
+#define        METHOD_BUFFERED         0
+#define        METHOD_IN_DIRECT        1
+#define        METHOD_OUT_DIRECT       2
+#define        METHOD_NEITHER          3
+
+/*
+ * file access values
+ */
+#define        FILE_ANY_ACCESS         0
+#define        FILE_READ_ACCESS        0x0001
+#define        FILE_WRITE_ACCESS       0x0002
+
+
+#define        IOCTL_SCSI_BASE    0x00000004
+
+/*
+ * constants for DataIn member of SCSI_PASS_THROUGH* structures
+ */
+#define        SCSI_IOCTL_DATA_OUT             0
+#define        SCSI_IOCTL_DATA_IN              1
+#define        SCSI_IOCTL_DATA_UNSPECIFIED     2
+
+/*
+ * Standard IOCTL define
+ */
+#define        CTL_CODE(DevType, Function, Method, Access)             \
+       (((DevType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method))
+
+#define        IOCTL_SCSI_PASS_THROUGH         CTL_CODE(IOCTL_SCSI_BASE, 0x0401, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
+#define        IOCTL_SCSI_MINIPORT             CTL_CODE(IOCTL_SCSI_BASE, 0x0402, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
+#define        IOCTL_SCSI_GET_INQUIRY_DATA     CTL_CODE(IOCTL_SCSI_BASE, 0x0403, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define        IOCTL_SCSI_GET_CAPABILITIES     CTL_CODE(IOCTL_SCSI_BASE, 0x0404, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define        IOCTL_SCSI_PASS_THROUGH_DIRECT  CTL_CODE(IOCTL_SCSI_BASE, 0x0405, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
+#define        IOCTL_SCSI_GET_ADDRESS          CTL_CODE(IOCTL_SCSI_BASE, 0x0406, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#endif
diff --git a/libusal/usal/srb_os2.h b/libusal/usal/srb_os2.h
new file mode 100644 (file)
index 0000000..54f57ca
--- /dev/null
@@ -0,0 +1,179 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)srb_os2.h       1.1 98/11/01 Copyright 1998 D. Dorau, C. Wohlgemuth J. Schilling */
+/*
+ *     Definitions for ASPI-Router (ASPIROUT.SYS).
+ *
+ *     Copyright (c) 1998 D. Dorau, C. Wohlgemuth
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#pragma pack(1)
+
+        /* SRB command */
+#define SRB_Inquiry     0x00
+#define SRB_Device      0x01
+#define SRB_Command     0x02
+#define SRB_Abort       0x03
+#define SRB_Reset       0x04
+#define SRB_Param       0x05
+
+        /* SRB status */
+#define SRB_Busy        0x00    /* SCSI request in progress */
+#define SRB_Done        0x01    /* SCSI request completed without error */
+#define SRB_Aborted     0x02    /* SCSI aborted by host */
+#define SRB_BadAbort    0x03    /* Unable to abort SCSI request */
+#define SRB_Error       0x04    /* SCSI request completed with error */
+#define SRB_BusyPost    0x10    /* SCSI request in progress with POST - Nokia */
+#define SRB_InvalidCmd  0x80    /* Invalid SCSI request */
+#define SRB_InvalidHA   0x81    /* Invalid Hhost adapter number */
+#define SRB_BadDevice   0x82    /* SCSI device not installed */
+
+        /* SRB flags */
+#define SRB_Post        0x01    /* Post vector valid */
+#define SRB_Link        0x02    /* Link vector valid */
+#define SRB_SG          0x04    /* Nokia: scatter/gather */
+                                /* S/G: n * (4 bytes length, 4 bytes addr) */
+                                /* No of s/g items not limited by HA spec. */
+#define SRB_NoCheck     0x00    /* determined by command, not checked  */
+#define SRB_Read        0x08    /* target to host, length checked  */
+#define SRB_Write       0x10    /* host to target, length checked  */
+#define SRB_NoTransfer  0x18    /* no data transfer  */
+#define SRB_DirMask     0x18    /* bit mask */
+
+        /* SRB host adapter status */
+#define SRB_NoError     0x00    /* No host adapter detected error */
+#define SRB_Timeout     0x11    /* Selection timeout */
+#define SRB_DataLength  0x12    /* Data over/underrun */
+#define SRB_BusFree     0x13    /* Unexpected bus free */
+#define SRB_BusSequence 0x14    /* Target bus sequence failure */
+
+        /* SRB target status field */
+#define SRB_NoStatus    0x00    /* No target status */
+#define SRB_CheckStatus 0x02    /* Check status (sense data valid) */
+#define SRB_LUN_Busy    0x08    /* Specified LUN is busy */
+#define SRB_Reserved    0x18    /* Reservation conflict */
+
+#define MaxCDBStatus    64      /* max size of CDB + status */
+
+
+typedef struct SRb {
+        unsigned char   cmd,                            /* 00 */
+                        status,                         /* 01 */
+                        ha_num,                         /* 02 */
+                        flags;                          /* 03 */
+        unsigned long   res_04_07;                      /* 04..07 */
+        union {                                         /* 08 */
+
+        /* SRB_Inquiry */
+                struct {
+                        unsigned char   num_ha,         /* 08 */
+                                        ha_target,      /* 09 */
+                                        aspimgr_id[16], /* 0A..19 */
+                                        host_id[16],    /* 1A..29 */
+                                        unique_id[16];  /* 2A..39 */
+                } inq;
+
+        /* SRB_Device */
+                struct {
+                        unsigned char   target,         /* 08 */
+                                        lun,            /* 09 */
+                                        devtype;        /* 0A */
+                } dev;
+
+        /* SRB_Command */
+                struct {
+                        unsigned char   target,         /* 08 */
+                                        lun;            /* 09 */
+                        unsigned long   data_len;       /* 0A..0D */
+                        unsigned char   sense_len;      /* 0E */
+                       unsigned long data_ptr;       /* 0F..12 */
+                       unsigned long link_ptr;       /* 13..16 */
+               //      void * _Seg16     data_ptr;       /* 0F..12 */
+                  //      void * _Seg16     link_ptr;       /* 13..16 */
+                        unsigned char   cdb_len,        /* 17 */
+                                        ha_status,      /* 18 */
+                                        target_status;  /* 19 */
+                       unsigned char   _Seg16postSRB[4];
+               //   void    (* _Seg16 post) (SRB *);  /* 1A..1D */
+                        unsigned char   res_1E_29[12];  /* 1E..29 */
+                        unsigned char   res_2A_3F[22];  /* 2A..3F */
+                        unsigned char   cdb_st[64];     /* 40..7F CDB+status */
+                        unsigned char   res_80_BF[64];  /* 80..BF */
+                } cmd;
+
+        /* SRB_Abort */
+                struct {
+                       unsigned char _Seg16srb[4];
+               //     void * _Seg16     srb;            /* 08..0B */
+                } abt;
+
+        /* SRB_Reset */
+                struct {
+                        unsigned char   target,         /* 08 */
+                                        lun,            /* 09 */
+                                        res_0A_17[14],  /* 0A..17 */
+                                        ha_status,      /* 18 */
+                                        target_status;  /* 19 */
+                } res;
+
+        /* SRB_Param - unused by ASPI4OS2 */
+                struct {
+                        unsigned char   unique[16];     /* 08..17 */
+                } par;
+
+        } u;
+} SRB;
+
+
+// SCSI sense codes
+// Note! This list may not be complete. I did this compilation for use with tape drives.
+
+#define Sense_Current   0x70;   // Current Error
+#define Sense_Deferred  0x71;   // Deferred Error
+#define Sense_Filemark  0x80;   // Filemark detected
+#define Sense_EOM       0x40;   // End of medium detected
+#define Sense_ILI       0x20;   // Incorrect length indicator
+
+// Sense Keys
+
+#define SK_NoSense      0x00;   // No Sense
+#define SK_RcvrdErr     0x01;   // Recovered Error
+#define SK_NotReady     0x02;   // Not ready
+#define SK_MedErr       0x03;   // Medium Error
+#define SK_HWErr        0x04;   // Hardware Error
+#define SK_IllReq       0x05;   // Illegal Request
+#define SK_UnitAtt      0x06;   // Unit attention
+#define SK_DataProt     0x07:   // Data Protect
+#define SK_BlankChk     0x08:   // Blank Check
+#define SK_VndSpec      0x09;   // Vendor Specific
+#define SK_CopyAbort    0x0A;   // Copy Aborted
+#define SK_AbtdCmd      0x0B;   // Aborted Command
+#define SK_Equal        0x0C;   // Equal
+#define SK_VolOvfl      0x0D;   // Volume Overflow
+#define SK_MisComp      0x0E;   // Miscompare
+#define SK_Reserved     0x0F;   // Reserved
diff --git a/libusal/usal/usalcmd.h b/libusal/usal/usalcmd.h
new file mode 100644 (file)
index 0000000..47893ee
--- /dev/null
@@ -0,0 +1,211 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)usalcmd.h       2.22 04/09/04 Copyright 1986 J. Schilling */
+/*
+ *     Definitions for the SCSI 'usal_cmd' structure that has been created
+ *     for the SCSI general driver 'usal' for SunOS and Solaris but
+ *     now is used for wrapping general libusal SCSI transport requests.
+ *
+ *     Copyright (c) 1986 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef        _SCG_SCGCMD_H
+#define        _SCG_SCGCMD_H
+
+#include <utypes.h>
+#include <btorder.h>
+
+#if    defined(_BIT_FIELDS_LTOH)       /* Intel byteorder */
+#else
+# if   defined(_BIT_FIELDS_HTOL)       /* Motorola byteorder */
+# else
+/*
+ * #error will not work for all compilers (e.g. sunos4)
+ * The following line will abort compilation on all compilers
+ * if none of the above is defines. And that's  what we want.
+ */
+error  One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
+# endif
+#endif
+
+#include <usal/scsisense.h>
+#include <usal/scsicdb.h>
+#include <intcvt.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Leave these definitions here if possible to avoid the need to
+ * include scsireg.h which makes problems on some OS because these
+ * OS define the same types as in scsireg.h
+ */
+
+/*
+ * SCSI status bits.
+ */
+#define        ST_VU_00        0x01    /* Vendor unique                */
+#define        ST_CHK_COND     0x02    /* Check condition              */
+#define        ST_COND_MET     0x04    /* Condition met                */
+#define        ST_BUSY         0x08    /* Busy                         */
+#define        ST_IS_SEND      0x10    /* Intermediate status send     */
+#define        ST_VU_05        0x20    /* Vendor unique                */
+#define        ST_VU_06        0x40    /* Vendor unique                */
+#define        ST_RSVD_07      0x80    /* Reserved                     */
+
+/*
+ * Sense key values for extended sense.
+ */
+#define        SC_NO_SENSE             0x00
+#define        SC_RECOVERABLE_ERROR    0x01
+#define        SC_NOT_READY            0x02
+#define        SC_MEDIUM_ERROR         0x03
+#define        SC_HARDWARE_ERROR       0x04
+#define        SC_ILLEGAL_REQUEST      0x05
+#define        SC_UNIT_ATTENTION       0x06
+#define        SC_WRITE_PROTECT        0x07
+#define        SC_BLANK_CHECK          0x08
+#define        SC_VENDOR_UNIQUE        0x09
+#define        SC_COPY_ABORTED         0x0A
+#define        SC_ABORTED_COMMAND      0x0B
+#define        SC_EQUAL                0x0C
+#define        SC_VOLUME_OVERFLOW      0x0D
+#define        SC_MISCOMPARE           0x0E
+#define        SC_RESERVED             0x0F
+
+/*
+ * Messages that SCSI can send.
+ */
+#define        SC_COMMAND_COMPLETE     0x00
+#define        SC_SYNCHRONOUS          0x01
+#define        SC_SAVE_DATA_PTR        0x02
+#define        SC_RESTORE_PTRS         0x03
+#define        SC_DISCONNECT           0x04
+#define        SC_ABORT                0x06
+#define        SC_MSG_REJECT           0x07
+#define        SC_NO_OP                0x08
+#define        SC_PARITY               0x09
+#define        SC_IDENTIFY             0x80
+#define        SC_DR_IDENTIFY          0xc0
+#define        SC_DEVICE_RESET         0x0c
+
+#define        SC_G0_CDBLEN    6       /* Len of Group 0 commands */
+#define        SC_G1_CDBLEN    10      /* Len of Group 1 commands */
+#define        SC_G5_CDBLEN    12      /* Len of Group 5 commands */
+
+#define        SCG_MAX_CMD     24      /* 24 bytes max. size is supported */
+#define        SCG_MAX_STATUS  3       /* XXX (sollte 4 allign.) Mamimum Status Len */
+#define        SCG_MAX_SENSE   32      /* Mamimum Sense Len for auto Req. Sense */
+
+#define        DEF_SENSE_LEN   16      /* Default Sense Len */
+#define        CCS_SENSE_LEN   18      /* Sense Len for CCS compatible devices */
+
+struct usal_cmd {
+       caddr_t addr;                   /* Address of data in user space */
+       int     size;                   /* DMA count for data transfer */
+       int     flags;                  /* see below for definition */
+       int     cdb_len;                /* Size of SCSI command in bytes */
+                                       /* NOTE: rel 4 uses this field only */
+                                       /* with commands not in group 1 or 2*/
+       int     sense_len;              /* for intr() if -1 don't get sense */
+       int     timeout;                /* timeout in seconds */
+                                       /* NOTE: actual resolution depends */
+                                       /* on driver implementation */
+       int     kdebug;                 /* driver kernel debug level */
+       int     resid;                  /* Bytes not transfered */
+       int     error;                  /* Error code from usalintr() */
+       int     ux_errno;               /* UNIX error code */
+#ifdef comment
+XXX    struct  scsi_status scb; ???    /* Status returnd by command */
+#endif
+       union {
+               struct  scsi_status Scb; /* Status returnd by command */
+               Uchar   cmd_scb[SCG_MAX_STATUS];
+       } u_scb;
+#define        scb     u_scb.Scb
+#ifdef comment
+XXX    struct  scsi_sense sense; ???   /* Sense bytes from command */
+#endif
+       union {
+               struct  scsi_sense Sense; /* Sense bytes from command */
+               Uchar   cmd_sense[SCG_MAX_SENSE];
+       } u_sense;
+#define        sense   u_sense.Sense
+       int     sense_count;            /* Number of bytes valid in sense */
+       int     target;                 /* SCSI target id */
+                                       /* NOTE: The SCSI target id field   */
+                                       /* does not need to be filled unless */
+                                       /* the low level transport is a real */
+                                       /* usal driver. In this case the low */
+                                       /* level transport routine of libusal */
+                                       /* will fill in the needed value    */
+       union {                         /* SCSI command descriptor block */
+               struct  scsi_g0cdb g0_cdb;
+               struct  scsi_g1cdb g1_cdb;
+               struct  scsi_g5cdb g5_cdb;
+               Uchar   cmd_cdb[SCG_MAX_CMD];
+       } cdb;                          /* 24 bytes max. size is supported */
+};
+
+#define        dma_read        flags           /* 1 if DMA to Sun, 0 otherwise */
+
+/*
+ * definition for flags field in usal_cmd struct
+ */
+#define        SCG_RECV_DATA   0x0001          /* DMA direction to Sun */
+#define        SCG_DISRE_ENA   0x0002          /* enable disconnect/reconnect */
+#define        SCG_SILENT      0x0004          /* be silent on errors */
+#define        SCG_CMD_RETRY   0x0008          /* enable retries */
+#define        SCG_NOPARITY    0x0010          /* disable parity for this command */
+
+/*
+ * definition for error field in usal_cmd struct
+ *
+ * The codes refer to SCSI general errors, not to device
+ * specific errors.  Device specific errors are discovered
+ * by checking the sense data.
+ * The distinction between retryable and fatal is somewhat ad hoc.
+ */
+#define        SCG_NO_ERROR    0               /* cdb transported without error    */
+                                       /* SCG_NO_ERROR incudes all commands */
+                                       /* where the SCSI status is valid   */
+
+#define        SCG_RETRYABLE   1               /* any other case e.g. SCSI bus busy */
+                                       /* SCSI cdb could not be send,      */
+                                       /* includes DMA errors other than   */
+                                       /* DMA underrun                     */
+
+#define        SCG_FATAL       2               /* could not select target          */
+#define        SCG_TIMEOUT     3               /* driver timed out                 */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SCG_SCGCMD_H */
diff --git a/libusal/usal/usalio.h b/libusal/usal/usalio.h
new file mode 100644 (file)
index 0000000..7624775
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)usalio.h        2.16 00/11/07 Copyright 1986 J. Schilling */
+/*
+ *     Definitions for the SCSI general driver 'usal'
+ *
+ *     Copyright (c) 1986 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef        _SCG_SCGIO_H
+#define        _SCG_SCGIO_H
+
+#ifndef        _SCG_SCGCMD_H
+#include <usal/usalcmd.h>
+#endif
+
+#if    defined(SVR4)
+#include <sys/ioccom.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if    defined(__STDC__) || defined(SVR4)
+#define        SCGIOCMD        _IOWR('G', 1, struct usal_cmd)  /* do a SCSI cmd   */
+#define        SCGIORESET      _IO('G', 2)                     /* reset SCSI bus  */
+#define        SCGIOGDISRE     _IOR('G', 4, int)               /* get sc disre Val*/
+#define        SCGIOSDISRE     _IOW('G', 5, int)               /* set sc disre Val*/
+#define        SCGIOIDBG       _IO('G', 100)                   /* Inc Debug Val   */
+#define        SCGIODDBG       _IO('G', 101)                   /* Dec Debug Val   */
+#define        SCGIOGDBG       _IOR('G', 102, int)             /* get Debug Val   */
+#define        SCGIOSDBG       _IOW('G', 103, int)             /* set Debug Val   */
+#define        SCIOGDBG        _IOR('G', 104, int)             /* get sc Debug Val*/
+#define        SCIOSDBG        _IOW('G', 105, int)             /* set sc Debug Val*/
+#else
+#define        SCGIOCMD        _IOWR(G, 1, struct usal_cmd)    /* do a SCSI cmd   */
+#define        SCGIORESET      _IO(G, 2)                       /* reset SCSI bus  */
+#define        SCGIOGDISRE     _IOR(G, 4, int)                 /* get sc disre Val*/
+#define        SCGIOSDISRE     _IOW(G, 5, int)                 /* set sc disre Val*/
+#define        SCGIOIDBG       _IO(G, 100)                     /* Inc Debug Val   */
+#define        SCGIODDBG       _IO(G, 101)                     /* Dec Debug Val   */
+#define        SCGIOGDBG       _IOR(G, 102, int)               /* get Debug Val   */
+#define        SCGIOSDBG       _IOW(G, 103, int)               /* set Debug Val   */
+#define        SCIOGDBG        _IOR(G, 104, int)               /* get sc Debug Val*/
+#define        SCIOSDBG        _IOW(G, 105, int)               /* set sc Debug Val*/
+#endif
+
+#define        SCGIO_CMD       SCGIOCMD        /* backward ccompatibility */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SCG_SCGIO_H */
diff --git a/libusal/usal/usalops.h b/libusal/usal/usalops.h
new file mode 100644 (file)
index 0000000..5e367a6
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)usalops.h       1.5 02/10/19 Copyright 2000 J. Schilling */
+/*
+ *     Copyright (c) 2000 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef        _SCG_SCGOPS_H
+#define        _SCG_SCGOPS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct usal_ops {
+       int     (*usalo_send)(SCSI *usalp);
+
+       char *  (*usalo_version)(SCSI *usalp, int what);
+#ifdef EOF     /* stdio.h has been included */
+       int     (*usalo_help)(SCSI *usalp, FILE *f);
+#else
+       int     (*usalo_help)(SCSI *usalp, void *f);
+#endif
+       int     (*usalo_open)(SCSI *usalp, char *device);
+       int     (*usalo_close)(SCSI *usalp);
+       long    (*usalo_maxdma)(SCSI *usalp, long amt);
+       void *  (*usalo_getbuf)(SCSI *usalp, long amt);
+       void    (*usalo_freebuf)(SCSI *usalp);
+
+
+       BOOL    (*usalo_havebus)(SCSI *usalp, int busno);
+       int     (*usalo_fileno)(SCSI *usalp, int busno, int tgt, int tlun);
+
+       int     (*usalo_initiator_id)(SCSI *usalp);
+       int     (*usalo_isatapi)(SCSI *usalp);
+       int     (*usalo_reset)(SCSI *usalp, int what);
+
+       char *  (*usalo_natname)(SCSI *usalp, int busno, int tgt, int tlun);
+} usal_ops_t;
+
+#define        SCGO_SEND(usalp)                                (*(usalp)->ops->usalo_send)(usalp)
+#define        SCGO_VERSION(usalp, what)               (*(usalp)->ops->usalo_version)(usalp, what)
+#define        SCGO_HELP(usalp, f)                     (*(usalp)->ops->usalo_help)(usalp, f)
+#define        SCGO_OPEN(usalp, device)                        (*(usalp)->ops->usalo_open)(usalp, device)
+#define        SCGO_CLOSE(usalp)                       (*(usalp)->ops->usalo_close)(usalp)
+#define        SCGO_MAXDMA(usalp, amt)                 (*(usalp)->ops->usalo_maxdma)(usalp, amt)
+#define        SCGO_GETBUF(usalp, amt)                 (*(usalp)->ops->usalo_getbuf)(usalp, amt)
+#define        SCGO_FREEBUF(usalp)                     (*(usalp)->ops->usalo_freebuf)(usalp)
+#define        SCGO_HAVEBUS(usalp, busno)              (*(usalp)->ops->usalo_havebus)(usalp, busno)
+#define        SCGO_FILENO(usalp, busno, tgt, tlun)    (*(usalp)->ops->usalo_fileno)(usalp, busno, tgt, tlun)
+#define        SCGO_INITIATOR_ID(usalp)                        (*(usalp)->ops->usalo_initiator_id)(usalp)
+#define        SCGO_ISATAPI(usalp)                     (*(usalp)->ops->usalo_isatapi)(usalp)
+#define        SCGO_RESET(usalp, what)                 (*(usalp)->ops->usalo_reset)(usalp, what)
+
+extern int usal_fileno(SCSI *usalp, int busno, int tgt, int tlun);
+extern char * usal_natname(SCSI *usalp, int busno, int tgt, int tlun);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SCG_SCGOPS_H */
diff --git a/libusal/usalsettarget.c b/libusal/usalsettarget.c
new file mode 100644 (file)
index 0000000..009805c
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)usalsettarget.c 1.2 04/01/14 Copyright 2000 J. Schilling */
+/*
+ *     usal Library
+ *     set target SCSI address
+ *
+ *     This is the only place in libusal that is allowed to assign
+ *     values to the usal address structure.
+ *
+ *     Copyright (c) 2000 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <mconfig.h>
+#include <standard.h>
+#include <schily.h>
+
+#include <usal/scsitransp.h>
+
+int    usal_settarget(SCSI *usalp, int, int, int);
+
+int
+usal_settarget(SCSI *usalp, int busno, int tgt, int tlun)
+{
+       int fd = -1;
+
+       if (usalp->ops != NULL)
+               fd = SCGO_FILENO(usalp, busno, tgt, tlun);
+       usalp->fd = fd;
+       usal_scsibus(usalp) = busno;
+       usal_target(usalp)  = tgt;
+       usal_lun(usalp)   = tlun;
+       return (fd);
+}
diff --git a/libusal/usaltimes.c b/libusal/usaltimes.c
new file mode 100644 (file)
index 0000000..d8e28d7
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)usaltimes.c     1.1 00/08/25 Copyright 1995,2000 J. Schilling */
+/*
+ *     SCSI user level command timing
+ *
+ *     Copyright (c) 1995,2000 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <mconfig.h>
+#include <standard.h>
+#include <timedefs.h>
+#include <schily.h>
+
+#include <usal/scsitransp.h>
+#include "usaltimes.h"
+
+void   __usal_times(SCSI *usalp);
+
+/*
+ * We don't like to make this a public interface to prevent bad users
+ * from making our timing incorrect.
+ */
+void
+__usal_times(SCSI *usalp)
+{
+       struct timeval  *stp = usalp->cmdstop;
+
+       gettimeofday(stp, (struct timezone *)0);
+       stp->tv_sec -= usalp->cmdstart->tv_sec;
+       stp->tv_usec -= usalp->cmdstart->tv_usec;
+       while (stp->tv_usec < 0) {
+               stp->tv_sec -= 1;
+               stp->tv_usec += 1000000;
+       }
+}
diff --git a/libusal/usaltimes.h b/libusal/usaltimes.h
new file mode 100644 (file)
index 0000000..cf0a207
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)usaltimes.h     1.1 00/08/25 Copyright 1995,2000 J. Schilling */
+/*
+ *     SCSI user level command timing
+ *
+ *     Copyright (c) 1995,2000 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+extern void    __usal_times(SCSI *usalp);
diff --git a/misc/MKNOD.hpux b/misc/MKNOD.hpux
new file mode 100755 (executable)
index 0000000..92f812a
--- /dev/null
@@ -0,0 +1,59 @@
+#!/bin/sh
+################################################################
+# make SCSI device files according to: man scsi_ctl
+#
+# Copyright (c) 1997 J. Schilling
+################################################################
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2
+# as published by the Free Software Foundation.
+#
+# 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; see the file COPYING.  If not, write to the Free Software
+# Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+################################################################
+
+mknod="echo mknod"
+mkdir="echo mkdir -p"
+chmod="echo chmod"
+
+mknod="/usr/sbin/mknod"
+mkdir="mkdir -p"
+chmod="chmod"
+
+scsi=/dev/scsi
+rscsi=/dev/rscsi
+
+${mkdir}  ${scsi}
+${mkdir} ${rscsi}
+
+bus=0
+target=0
+lun=0
+
+for bus in 0 1 2 3 4 5 6 7 8 9 a b c d e f; do
+       for target in 0 1 2 3 4 5 6 7 8 9 a b c d e f; do
+               for lun in 0 1 2 3 4 5 6 7; do
+#
+#      Newer HP-UX versions seem to have
+#      /dev/rscsi/citxdy
+#      but it uses the "non-raw" interface type
+#                      dev=c${bus}t${target}d${lun} 
+#      We follow the HP-UX documentation and create
+#      /dev/rscsi/citxty with the raw bit set
+
+                       dev=c${bus}t${target}l${lun} 
+
+                       $mknod  ${scsi}/${dev} c 203 0x${bus}${target}${lun}00
+                       $chmod 0600  ${scsi}/${dev}
+
+                       $mknod ${rscsi}/${dev} c 203 0x${bus}${target}${lun}02
+                       $chmod 0600  ${rscsi}/${dev}
+               done
+       done
+done
diff --git a/misc/MKNOD.hpux-800 b/misc/MKNOD.hpux-800
new file mode 100755 (executable)
index 0000000..f439412
--- /dev/null
@@ -0,0 +1,92 @@
+#!/bin/sh
+################################################################
+# mk node boot script for HP9000 800 series following man scsi_pt
+#
+# This script is provided WITHOUT ANY WARRANTY.
+################################################################
+
+PATH=/sbin:/usr/sbin:/usr/bin:.
+export PATH
+
+case $1 in
+
+start_msg)
+       echo "Creating SCSI passthru (spt) driver nodes"
+       ;;
+
+stop_msg)
+       echo "Removing SCSI passthru (spt) driver nodes"
+       ;;
+
+start)
+
+       hpser=`uname -m | awk -F / '{print substr($2, 1, 1);}'`
+       if [ $hpser -ne "8" ]; then
+               echo "spt driver only needed on HP 9000/800 series."
+               exit 0
+       fi
+
+       #mknod="echo mknod"
+       #mkdir="echo mkdir -p"
+       #chmod="echo chmod"
+    
+       mknod="/usr/sbin/mknod"
+       mkdir="mkdir -p"
+       chmod="chmod"
+    
+       sptlist="/tmp/spt.$$"
+       echo "Searching SCSI passthru drivers (spt) ..."
+       ioscan -kf -d spt | sed '1,2d' | awk '{print $3;}' > $sptlist
+       nctl=`wc -l < $sptlist`
+       echo "... found $nctl"
+
+       if [ ! -s $sptlist ]; then
+               rm -f $sptlist
+               exit 0
+       fi
+
+       scsi=/dev/scsi
+       ${mkdir} ${scsi}
+    
+       rscsi=/dev/rscsi
+       ${mkdir} ${rscsi}
+    
+       cmajor=`lsdev -h -d spt | awk '{print $1;}'`
+    
+       for line in `cat $sptlist` ; do
+
+               ctl=`echo $line | awk -F . '{print $1;}'`
+               bus=`ioscan -f -k -H $ctl -C ext_bus | sed '1,2d' | awk '{print $2;}'`
+               tgt=`echo $line | awk -F . '{print $2;}'`
+               hextgt=`printf "%x" $tgt`
+
+               # make first scsi nodes
+               name="${scsi}/c${bus}t${tgt}l0"
+               echo "Creating $name"
+               ${mknod} $name c $cmajor 0x${bus}${hextgt}000 > /dev/null 2>&1
+               ${chmod} 0600 $name > /dev/null 2>&1
+
+               # then rscsi nodes
+               rname="${rscsi}/c${bus}t${tgt}l0"
+               echo "Creating $rname"
+               # Old version, not working!
+               #${mknod} $rname c $cmajor 0x${bus}${hextgt}020 > /dev/null 2>&1
+               ${mknod} $rname c $cmajor 0x${bus}${hextgt}000 > /dev/null 2>&1
+               ${chmod} 0600 $rname > /dev/null 2>&1
+       done
+
+       rm -f $sptlist
+       exit 0
+    
+       ;;
+
+stop)
+       ;;
+
+*)
+       echo usage: $0 "{start|stop}"
+       ;;
+esac
+
+exit 0
+
diff --git a/misc/burnstuff b/misc/burnstuff
new file mode 100755 (executable)
index 0000000..ce3cf82
--- /dev/null
@@ -0,0 +1,25 @@
+#!/bin/sh
+# (C) Eduard Bloch, License: BSD, 3-clause
+# very simple script to burn files on-the-fly in SAO mode;
+# either from a certain directory, or from a list with graft-points
+# ISO name is generated from the basename of the list/directory
+
+set -e
+
+case "$1" in
+  *.list)
+   name=${1%.list}
+   set -- -D -graft-points -path-list "$1"
+   ;;
+  *)
+   name="$1"
+   ;;
+esac
+
+MOPTS=${MOPTS:-" -joliet-long -r -q -f -V $name "}
+COPTS=${COPTS:-" fs=64m gracetime=5 -v -sao speed=16 -eject -multi -v -force - "}
+
+SIZE=$(genisoimage $MOPTS -print-size "$@")s
+
+echo "genisoimage $MOPTS $@ | wodim tsize=$SIZE $COPTS"
+genisoimage $MOPTS "$@" | wodim tsize=$SIZE $COPTS
diff --git a/misc/make_diskt@2.sh b/misc/make_diskt@2.sh
new file mode 100644 (file)
index 0000000..a93c8ed
--- /dev/null
@@ -0,0 +1,56 @@
+#!/bin/sh
+
+# exit on all errors
+set -e
+
+if [ ! -f "$1" ];then
+       echo "Usage: `basename $0` [imagefile.ext] [-o|-i]"
+       echo "-o will make the bottom of the image be on the outside of the disk"
+       echo "-i will make the bottom of the image be on the inside of the disk"
+       echo
+       echo "Image must be greyscale"
+       echo
+       echo "make sure the imagefile has the right x-y format"
+       echo "run cdrecord driveropts=tattooinfo -checkdrive"
+       echo "to find out"
+       exit 1
+fi
+
+
+case "$2" in 
+       -i)
+               convopts="-flip"
+       ;;
+       -o)
+               convopts="-flop"
+       ;;
+       *)
+               echo "error: arg2 must be -o or -i"
+               exit 1
+       ;;
+esac
+
+echo "Make sure the imagefile has the right size"
+echo "run cdrecord dev=a,b,c driveropts=tattooinfo -checkdrive"
+echo "to find out"
+echo
+echo -n "Converting $1 to disktattoo_image format: "
+
+## convert it tp ppm format
+## note.. -flop = flip horizontally
+convert $convopts "$1" "$1-TMP-$$.ppm"
+
+## We only need the data, which is the last line in a ppm file
+## tail works mighty fine for this (insert evil dirty-coder-laughter here)
+tail -n+4 "$1-TMP-$$.ppm" > "$1.disktattoo_image"
+
+## clean up like a good boy
+rm "$1-TMP-$$.ppm"
+
+## notify user that we're done converting
+echo "done"
+echo
+
+## stop with stupid code commenting
+echo "You may now burn '$1.disktattoo_image' to your cd with the command:"
+echo "cdrecord driveropts=tattoofile=\"$1.disktattoo_image\" -checkdrive"
diff --git a/misc/rc.pp b/misc/rc.pp
new file mode 100755 (executable)
index 0000000..734cfd5
--- /dev/null
@@ -0,0 +1,76 @@
+#!/bin/sh
+
+#
+# Note: The adapter shell var must updated in order to reflect your actual hardware.
+#      The current value "friq" is the right value for the FreeCom PP adapter.
+#      See paride documentation for the list of other drivers.
+#
+adapter=friq
+
+case "$1" in
+
+'start')
+       echo "Starting Parallel Port IDE/ATAPI"
+       modprobe paride
+       modprobe "$adapter"
+#      modprobe pg
+#      modprobe pg verbose=2 drive0=0x378,0,0,-1,-1,0
+       modprobe pg verbose=0 drive0=0x378,0,0,-1,-1,0
+       ;;
+
+'stop')
+       echo "Stopping Parallel Port IDE/ATAPI"
+       rmmod pg
+       rmmod "$adapter"
+       rmmod paride
+       ;;
+
+*)
+       echo "Usage: rc.pp start|stop"
+esac
+
+exit
+
+###############################################################################
+When you load pg, you need to specify some parameters like:
+
+        drive0=0x378,0,0,4,0,0
+
+The parameters are:
+
+ <prt>,<pro>,<uni>,<mod>,<slv>,<dly>
+
+                        Where,
+
+                <prt>   is the base of the parallel port address for
+                        the corresponding drive.  (required)
+
+                <pro>   is the protocol number for the adapter that
+                        supports this drive.  These numbers are
+                        logged by 'paride' when the protocol modules
+                        are initialised.  (0 if not given)
+
+                <uni>   for those adapters that support chained
+                        devices, this is the unit selector for the
+                        chain of devices on the given port.  It should
+                        be zero for devices that don't support chaining.
+                        (0 if not given)
+
+                <mod>   this can be -1 to choose the best mode, or one
+                        of the mode numbers supported by the adapter.
+                        (-1 if not given)
+
+                <slv>   ATAPI devices can be jumpered to master or slave.
+                        Set this to 0 to choose the master drive, 1 to
+                        choose the slave, -1 (the default) to choose the
+                        first drive found.
+
+                <dly>   some parallel ports require the driver to 
+                        go more slowly.  -1 sets a default value that
+                        should work with the chosen protocol.  Otherwise,
+                        set this to a small integer, the larger it is
+                        the slower the port i/o.  In some cases, setting
+                        this to zero will speed up the device. (default -1)
+
+EPP mode is best.  Your BIOS may not give you that option, unfortunately.
+What options does it support ?
diff --git a/misc/shared_lib_patch_incomplete.diff b/misc/shared_lib_patch_incomplete.diff
new file mode 100644 (file)
index 0000000..7921305
--- /dev/null
@@ -0,0 +1,138 @@
+Index: wodim/CMakeLists.txt
+===================================================================
+--- wodim/CMakeLists.txt       (Revision 579)
++++ wodim/CMakeLists.txt       (Arbeitskopie)
+@@ -21,7 +21,17 @@
+ ADD_DEFINITIONS(-DHAVE_LIB_EDC_ECC -DCLONE_WRITE)
+-ADD_EXECUTABLE (wodim ${CDRECORD_SRCS})
++SET(CDRECORD_SRCS wodim.c audiosize.c auinfo.c  cdr_drv.c cdtext.c clone.c crc16.c cue.c  diskid.c drv_7501.c drv_jvc.c drv_mmc.c drv_philips.c drv_simul.c drv_sony.c fifo.c  isosize.c scsi_cdr_mmc4.c scsi_mmc4.c sector.c subchan.c wm_packet.c wm_session.c wm_track.c xio.c)
++SET(CDRECORD_COMMON_SRCS cd_misc.c defaults.c getnum.c misc.c modes.c movesect.c scsi_cdr.c scsi_mmc.c scsi_scan.c)
++
++IF(SHLIB_STYLE)
++   ADD_EXECUTABLE (wodim ${CDRECORD_SRCS})
++   ADD_LIBRARY (wodimstuff SHARED ${CDRECORD_COMMON_SRCS})
++   LIST(APPEND EXTRA_LIBS wodimstuff)
++ELSE(SHLIB_STYLE)
++   ADD_EXECUTABLE (wodim ${CDRECORD_SRCS} ${CDRECORD_COMMON_SRCS})
++ENDIF(SHLIB_STYLE)
++
+ TARGET_LINK_LIBRARIES(wodim ${EXTRA_LIBS} deflt edc)
+ SET_TARGET_PROPERTIES(wodim PROPERTIES SKIP_BUILD_RPATH TRUE)
+Index: genisoimage/CMakeLists.txt
+===================================================================
+--- genisoimage/CMakeLists.txt (Revision 579)
++++ genisoimage/CMakeLists.txt (Arbeitskopie)
+@@ -27,6 +27,13 @@
+ SET(MKISOFS_MOST_SRCS apple.c boot.c cd_misc.c defaults.c desktop.c dvd_file.c dvd_reader.c eltorito.c exclude.c files.c fnmatch.c getnum.c hash.c ifo_read.c joliet.c mac_label.c match.c modes.c multi.c name.c rock.c scsi.c scsi_cdr.c stream.c tree.c udf.c vms.c volume.c write.c boot-alpha.c boot-hppa.c boot-mips.c md5.c jte.c rsync.c
+       boot-mipsel.c endian.c )
++
++IF(SHLIB_STYLE)
++   SET(MKISOFS_MOST_SRCS apple.c boot.c cd_misc.c defaults.c desktop.c dvd_file.c dvd_reader.c eltorito.c exclude.c files.c fnmatch.c getnum.c hash.c ifo_read.c joliet.c mac_label.c match.c modes.c multi.c name.c rock.c scsi.c scsi_cdr.c stream.c tree.c udf.c vms.c volume.c write.c boot-alpha.c boot-hppa.c boot-mips.c md5.c jte.c rsync.c
++      boot-mipsel.c endian.c )
++   LIST ( APPEND EXTRA_LIBS  wodimstuff )
++   message(FATAL_ERROR "fixme, half done, see experimental branch, needs to change other tools to libwodimstuff, etc.")
++ENDIF(SHLIB_STYLE)
+   
+ INCLUDE(CheckFunctionExists)
+ SET(CMAKE_REQUIRED_DEFINITIONS -D_GNU_SOURCE)
+@@ -37,7 +44,7 @@
+  
+ #SET_SOURCE_FILES_PROPERTIES(${MKISOFS_MOST_SRCS} PROPERTIES )
+-LINK_DIRECTORIES(../libhfs_iso ../librols ../libusal ../libunls ../libdeflt)
++LINK_DIRECTORIES(../libhfs_iso ../librols ../libusal ../libunls ../libdeflt ../wodim)
+ ADD_EXECUTABLE (genisoimage genisoimage.c ${MKISOFS_MOST_SRCS})
+ TARGET_LINK_LIBRARIES(genisoimage hfs_iso deflt ${MAGICLIBS} c unls z ${EXTRA_LIBICONV} ${EXTRA_LIBS})
+Index: libusal/CMakeLists.txt
+===================================================================
+--- libusal/CMakeLists.txt     (Revision 579)
++++ libusal/CMakeLists.txt     (Arbeitskopie)
+@@ -6,5 +6,9 @@
+ #SET(LIBSCG_SRCS rdummy.c usalsettarget.c usaltimes.c scsi-linux-ata.c scsi-linux-pg.c scsi-linux-sg.c scsierrs.c scsihack.c scsihelp.c scsiopen.c scsitransp.c)
+ SET(LIBSCG_SRCS usalsettarget.c usaltimes.c scsierrs.c scsihack.c scsihelp.c scsiopen.c scsitransp.c scsi-remote.c)
+ LINK_DIRECTORIES(../librols)
++IF(SHLIB_STYLE)
++ADD_LIBRARY (usal SHARED ${LIBSCG_SRCS})
++ELSE(SHLIB_STYLE)
+ ADD_LIBRARY (usal STATIC ${LIBSCG_SRCS})
++ENDIF(SHLIB_STYLE)
+ TARGET_LINK_LIBRARIES(usal ${SCG_SELF_LIBS})
+Index: misc/shared_lib_patch_incomplete.diff
+===================================================================
+--- misc/shared_lib_patch_incomplete.diff      (Revision 579)
++++ misc/shared_lib_patch_incomplete.diff      (Arbeitskopie)
+@@ -1,31 +1,29 @@
+ Index: wodim/CMakeLists.txt
+ ===================================================================
+---- wodim/CMakeLists.txt      (Revision 556)
++--- wodim/CMakeLists.txt      (Revision 579)
+ +++ wodim/CMakeLists.txt      (Arbeitskopie)
+-@@ -21,8 +21,18 @@
++@@ -21,7 +21,17 @@
+  
+  ADD_DEFINITIONS(-DHAVE_LIB_EDC_ECC -DCLONE_WRITE)
+  
+ -ADD_EXECUTABLE (wodim ${CDRECORD_SRCS})
+--TARGET_LINK_LIBRARIES(wodim ${EXTRA_LIBS} deflt edc)
+++SET(CDRECORD_SRCS wodim.c audiosize.c auinfo.c  cdr_drv.c cdtext.c clone.c crc16.c cue.c  diskid.c drv_7501.c drv_jvc.c drv_mmc.c drv_philips.c drv_simul.c drv_sony.c fifo.c  isosize.c scsi_cdr_mmc4.c scsi_mmc4.c sector.c subchan.c wm_packet.c wm_session.c wm_track.c xio.c)
+++SET(CDRECORD_COMMON_SRCS cd_misc.c defaults.c getnum.c misc.c modes.c movesect.c scsi_cdr.c scsi_mmc.c scsi_scan.c)
+ +
+ +IF(SHLIB_STYLE)
+-+   SET(CDRECORD_SRCS wodim.c audiosize.c auinfo.c  cdr_drv.c cdtext.c clone.c crc16.c cue.c  diskid.c drv_7501.c drv_jvc.c drv_mmc.c drv_philips.c drv_simul.c drv_sony.c fifo.c  isosize.c scsi_cdr_mmc4.c scsi_mmc4.c sector.c subchan.c wm_packet.c wm_session.c wm_track.c xio.c)
+-+   SET(CDRECORD_COMMON_SRCS cd_misc.c defaults.c getnum.c misc.c modes.c movesect.c scsi_cdr.c scsi_mmc.c scsi_scan.c)
+ +   ADD_EXECUTABLE (wodim ${CDRECORD_SRCS})
+ +   ADD_LIBRARY (wodimstuff SHARED ${CDRECORD_COMMON_SRCS})
+-+   TARGET_LINK_LIBRARIES(wodim ${EXTRA_LIBS} deflt edc wodimstuff)
+++   LIST(APPEND EXTRA_LIBS wodimstuff)
+ +ELSE(SHLIB_STYLE)
+-+   ADD_EXECUTABLE (wodim ${CDRECORD_SRCS})
+-+   TARGET_LINK_LIBRARIES(wodim ${EXTRA_LIBS} deflt edc)
+++   ADD_EXECUTABLE (wodim ${CDRECORD_SRCS} ${CDRECORD_COMMON_SRCS})
+ +ENDIF(SHLIB_STYLE)
+ +
++ TARGET_LINK_LIBRARIES(wodim ${EXTRA_LIBS} deflt edc)
+  SET_TARGET_PROPERTIES(wodim PROPERTIES SKIP_BUILD_RPATH TRUE)
+  
+- INSTALL(TARGETS wodim DESTINATION bin)
+ Index: genisoimage/CMakeLists.txt
+ ===================================================================
+---- genisoimage/CMakeLists.txt        (Revision 556)
++--- genisoimage/CMakeLists.txt        (Revision 579)
+ +++ genisoimage/CMakeLists.txt        (Arbeitskopie)
+ @@ -27,6 +27,13 @@
+  
+@@ -52,7 +50,7 @@
+  TARGET_LINK_LIBRARIES(genisoimage hfs_iso deflt ${MAGICLIBS} c unls z ${EXTRA_LIBICONV} ${EXTRA_LIBS})
+ Index: libusal/CMakeLists.txt
+ ===================================================================
+---- libusal/CMakeLists.txt    (Revision 556)
++--- libusal/CMakeLists.txt    (Revision 579)
+ +++ libusal/CMakeLists.txt    (Arbeitskopie)
+ @@ -6,5 +6,9 @@
+  #SET(LIBSCG_SRCS rdummy.c usalsettarget.c usaltimes.c scsi-linux-ata.c scsi-linux-pg.c scsi-linux-sg.c scsierrs.c scsihack.c scsihelp.c scsiopen.c scsitransp.c)
+@@ -64,20 +62,3 @@
+  ADD_LIBRARY (usal STATIC ${LIBSCG_SRCS})
+ +ENDIF(SHLIB_STYLE)
+  TARGET_LINK_LIBRARIES(usal ${SCG_SELF_LIBS})
+-Index: librols/CMakeLists.txt
+-===================================================================
+---- librols/CMakeLists.txt    (Revision 556)
+-+++ librols/CMakeLists.txt    (Arbeitskopie)
+-@@ -1,7 +1,11 @@
+- PROJECT (LIBROLS)
+- INCLUDE_DIRECTORIES(../include ../libhfs_iso ${CMAKE_BINARY_DIR} ../wodim)
+- 
+--SET(LIBROLS_SRCS  astoi.c astoll.c astoull.c breakline.c cmpbytes.c comerr.c error.c fexec.c fillbytes.c getargs.c getav0.c getdomainname.c geterrno.c gethostid.c gethostname.c getpagesize.c handlecond.c movebytes.c raisecond.c rename.c saveargs.c seterrno.c spawn.c strcatl.c strdup.c streql.c swabbytes.c usleep.c stdio/cvmod.c stdio/dat.c stdio/fcons.c stdio/fcons64.c stdio/fdown.c stdio/fdup.c stdio/fdup64.c stdio/ffileread.c stdio/ffilewrite.c stdio/fgetline.c stdio/file_raise.c stdio/fileclose.c stdio/fileluopen.c stdio/fileluopen64.c stdio/filemopen.c stdio/filemopen64.c stdio/fileopen.c stdio/fileopen64.c stdio/filepos.c stdio/filepos64.c stdio/fileread.c stdio/filereopen.c stdio/filereopen64.c stdio/fileseek.c stdio/fileseek64.c stdio/filesize.c stdio/filesize64.c stdio/filestat.c stdio/filestat64.c stdio/filewrite.c stdio/flag.c stdio/flush.c stdio/fpipe.c stdio/niread.c stdio/niwrite.c stdio/nixread.c stdio/nixwrite.c stdio/openfd.c stdio/openfd64.c stdio/peekc.c )
+-+SET(LIBROLS_SRCS  astoi.c astoll.c astoull.c breakline.c cmpbytes.c comerr.c error.c fexec.c fillbytes.c getargs.c getav0.c getdomainname.c geterrno.c gethostid.c gethostname.c getpagesize.c handlecond.c movebytes.c raisecond.c rename.c saveargs.c seterrno.c spawn.c strcatl.c strdup.c streql.c swabbytes.c usleep.c stdio/cvmod.c stdio/dat.c stdio/fcons.c stdio/fdown.c stdio/fdup.c stdio/ffileread.c stdio/ffilewrite.c stdio/fgetline.c stdio/file_raise.c stdio/fileclose.c stdio/fileluopen.c stdio/filemopen.c stdio/fileopen.c stdio/filepos.c stdio/fileread.c stdio/filereopen.c stdio/fileseek.c stdio/filesize.c stdio/filestat.c stdio/filewrite.c stdio/flag.c stdio/flush.c stdio/fpipe.c stdio/niread.c stdio/niwrite.c stdio/nixread.c stdio/nixwrite.c stdio/openfd.c stdio/peekc.c )
+- 
+-+IF(SHLIB_STYLE)
+-+ADD_LIBRARY (rols SHARED ${CMAKE_CURRENT_SOURCE_DIR}/../include/xconfig.h  ${CMAKE_CURRENT_SOURCE_DIR}/../include/align.h ${LIBROLS_SRCS})
+-+ELSE(SHLIB_STYLE)
+- ADD_LIBRARY (rols STATIC ${CMAKE_CURRENT_SOURCE_DIR}/../include/xconfig.h  ${CMAKE_CURRENT_SOURCE_DIR}/../include/align.h ${LIBROLS_SRCS})
+-+ENDIF(SHLIB_STYLE)
+- 
diff --git a/netscsid/CMakeLists.txt b/netscsid/CMakeLists.txt
new file mode 100644 (file)
index 0000000..f6bddf1
--- /dev/null
@@ -0,0 +1,13 @@
+PROJECT (netscsid C)
+INCLUDE_DIRECTORIES(../include ../wodim ${CMAKE_BINARY_DIR} ${CMAKE_BINARY_DIR}/include)
+INCLUDE(../include/AddScgBits.cmake)
+INCLUDE(../include/AddSchilyBits.cmake)
+INCLUDE(../include/AddNetworkBits.cmake)
+
+LINK_DIRECTORIES(../librols ../libusal )
+ADD_EXECUTABLE (netscsid netscsid.c)
+#SET_SOURCE_FILES_PROPERTIES(netscsid.c )
+TARGET_LINK_LIBRARIES(netscsid ${EXTRA_LIBS} )
+#SET_TARGET_PROPERTIES(netscsid PROPERTIES  SKIP_BUILD_RPATH TRUE)
+INSTALL(TARGETS netscsid DESTINATION sbin)
+
diff --git a/netscsid/netscsid.c b/netscsid/netscsid.c
new file mode 100644 (file)
index 0000000..df2f6b4
--- /dev/null
@@ -0,0 +1,972 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)rscsi.c 1.29 05/05/16 Copyright 1994,2000-2002 J. Schilling*/
+/*
+ *     Remote SCSI server
+ *
+ *     Copyright (c) 1994,2000-2002 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*#define      FORCE_DEBUG*/
+
+#include <mconfig.h>
+
+#include <stdio.h>
+#include <stdxlib.h>
+#include <unixstd.h>   /* includes <sys/types.h> */
+#include <utypes.h>
+#include <fctldefs.h>
+#include <statdefs.h>
+#include <strdefs.h>
+#ifdef HAVE_SYS_SOCKET_H
+#define        USE_REMOTE
+#include <sys/socket.h>
+#endif
+#ifdef  HAVE_SYS_PARAM_H
+#include <sys/param.h> /* BSD-4.2 & Linux need this for MAXHOSTNAMELEN */
+#endif
+#include <errno.h>
+#include <pwd.h>
+
+#include <standard.h>
+#include <deflts.h>
+#include <patmatch.h>
+#include <schily.h>
+
+#include <usal/usalcmd.h>
+#include <usal/scsitransp.h>
+
+#include <netinet/in.h>
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>         /* BeOS does not have <arpa/inet.h> */
+#endif                         /* but inet_ntaoa() is in <netdb.h> */
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+
+#ifdef USE_REMOTE
+static void    checkuser(void);
+static char    *getpeer(void);
+static BOOL    checktarget(void);
+static void    dorscsi(void);
+static void    scsiversion(void);
+static void    openscsi(void);
+static void    closescsi(void);
+static void    maxdma(void);
+static void    getbuf(void);
+static void    freebuf(void);
+static void    havebus(void);
+static void    scsifileno(void);
+static void    initiator_id(void);
+static void    isatapi(void);
+static void    scsireset(void);
+static void    sendcmd(void);
+
+static int     fillrdbuf(void);
+static int     readchar(char *cp);
+
+static void    readbuf(char *buf, int n);
+static void    voidarg(int n);
+static void    readarg(char *buf, int n);
+static char *preparebuffer(int size);
+static int     checkscsi(char *decive);
+static void    rscsirespond(int ret, int err);
+static void    rscsireply(int ret);
+static void    rscsierror(int err, char *str, char *xstr);
+
+#define        CMD_SIZE        80
+
+static SCSI    *scsi_ptr = NULL;
+static char    *Sbuf;
+static long    Sbufsize;
+
+static char    *username;
+static char    *peername;
+
+static char    *debug_name;
+static FILE    *debug_file;
+
+#define        DEBUG(fmt)              if (debug_file) fprintf(debug_file, fmt)
+#define        DEBUG1(fmt,a)           if (debug_file) fprintf(debug_file, fmt, a)
+#define        DEBUG2(fmt,a1,a2)       if (debug_file) fprintf(debug_file, fmt, a1, a2)
+#define        DEBUG3(fmt,a1,a2,a3)    if (debug_file) fprintf(debug_file, fmt, a1, a2, a3)
+#define        DEBUG4(fmt,a1,a2,a3,a4) if (debug_file) fprintf(debug_file, fmt, a1, a2, a3, a4)
+#define        DEBUG5(fmt,a1,a2,a3,a4,a5)      if (debug_file) fprintf(debug_file, fmt, a1, a2, a3, a4, a5)
+#define        DEBUG6(fmt,a1,a2,a3,a4,a5,a6)   if (debug_file) fprintf(debug_file, fmt, a1, a2, a3, a4, a5, a6)
+#endif /* USE_REMOTE */
+
+int
+main(int argc, char *argv[])
+{
+       save_args(argc, argv);
+#ifndef        USE_REMOTE
+       comerrno(EX_BAD, "No remote SCSI support on this platform.\n");
+#else
+       argc--, argv++;
+       if (argc > 0 && strcmp(*argv, "-c") == 0) {
+               /*
+                * Skip params in case we have been installed as shell.
+                */
+               argc--, argv++;
+               argc--, argv++;
+       }
+       /*
+        * WARNING you are only allowed to change the defaults configuration
+        * filename if you also change the documentation and add a statement
+        * that makes clear where the official location of the file is, why you
+        * did choose a nonstandard location and that the nonstandard location
+        * only refers to inofficial rscsi versions.
+        *
+        * I was forced to add this because some people change cdrecord without
+        * rational reason and then publish the result. As those people
+        * don't contribute work and don't give support, they are causing extra
+        * work for me and this way slow down the development.
+        */
+       if (cfg_open("/etc/netscsid.conf") < 0) {
+               rscsierror(geterrno(), errmsgstr(geterrno()),
+                       "Remote configuration error: Cannot open /etc/netscsid.conf");
+/*             rscsirespond(-1, geterrno());*/
+               exit(EX_BAD);
+       }
+       debug_name=cfg_get("DEBUG");
+#ifdef FORCE_DEBUG
+       if (debug_name == NULL && argc <= 0)
+               debug_name = "/tmp/RSCSI";
+#endif
+#ifdef NONONO
+       /*
+        * Should we allow root to shoot himself into the foot?
+        * Allowing to write arbitrary files may be a security risk.
+        */
+       if (argc > 0 && getuid() == 0)
+               debug_name = *argv;
+#endif
+
+       /*
+        * XXX If someone sets up debugging and allows the debug file to be
+        * XXX replaced by a symlink to e.g. /etc/passwd this would be a
+        * XXX security risk. But /etc/rscsi.conf is only writable by root
+        * XXX and for this reason a possible security risk would have been
+        * XXX introduced by the administrator.
+        */
+    if (debug_name != NULL) {
+        /* Try to be careful when opening debug files, might be
+         * created in an unsafe location 
+         * */
+        int fd = open(debug_name, O_CREAT | O_EXCL | O_TRUNC | O_RDWR, 0600);
+        if (fd > -1) 
+            debug_file = fdopen(fd, "w");
+        else {
+            rscsirespond(-1, geterrno());
+            exit(EX_BAD);
+        }
+    } 
+               
+       if (argc > 0) {
+               if (debug_file == 0) {
+                       rscsirespond(-1, geterrno());
+                       exit(EX_BAD);
+               }
+               (void) setbuf(debug_file, (char *)0);
+       }
+       checkuser();            /* Check if we are called by a bad guy  */
+       peername = getpeer();   /* Get host name of caller              */
+       dorscsi();
+#endif /* USE_REMOTE */
+       return (0);
+}
+
+#ifdef USE_REMOTE
+static void
+checkuser()
+{
+       uid_t   uid = getuid();
+       char    *uname;
+       struct passwd *pw;
+
+       if (uid == 0) {
+               username = "root";
+               DEBUG("rscsid: user id 0, name root\n");
+               return;
+       }
+       pw = getpwuid(uid);
+       if (pw == NULL)
+               goto notfound;
+
+       username = pw->pw_name;
+       DEBUG2("rscsid: user id %ld, name %s\n", (long)uid, username);
+
+       cfg_restart();
+       while ((uname = cfg_get_next("USER")) != NULL) {
+               if (0==strcmp(username, uname))
+                       return;
+       }
+notfound:
+       DEBUG2("rscsid: Illegal user '%s' id %ld for RSCSI server\n",
+                                               username, (long)uid);
+       rscsierror(0, "Illegal user id for RSCSI server", NULL);
+       exit(EX_BAD);
+}
+
+#ifndef        NI_MAXHOST
+#ifdef MAXHOSTNAMELEN                  /* XXX remove this and sys/param.h */
+#define        NI_MAXHOST      MAXHOSTNAMELEN
+#else
+#define        NI_MAXHOST      64
+#endif
+#endif
+
+static char *
+getpeer()
+{
+#ifdef HAVE_GETNAMEINFO
+#ifdef HAVE_SOCKADDR_STORAGE
+       struct sockaddr_storage sa;
+#else
+       char                    sa[256];
+#endif
+#else
+       struct  sockaddr sa;
+       struct hostent  *he;
+#endif
+       struct  sockaddr *sap;
+       struct  sockaddr_in *s;
+       socklen_t        sasize = sizeof (sa);
+static char            buffer[NI_MAXHOST];
+
+       sap = (struct  sockaddr *)&sa;
+       if (getpeername(STDIN_FILENO, sap, &sasize) < 0) {
+               int             errsav = geterrno();
+               struct stat     sb;
+
+               if (fstat(STDIN_FILENO, &sb) >= 0) {
+                       if (S_ISFIFO(sb.st_mode)) {
+                               DEBUG("rmt: stdin is a PIPE\n");
+                               return ("PIPE");
+                       }
+                       DEBUG1("rscsid: stdin st_mode %0llo\n", (Llong)sb.st_mode);
+               }
+
+               DEBUG1("rscsid: peername %s\n", errmsgstr(errsav));
+               return ("ILLEGAL_SOCKET");
+       } else {
+               s = (struct sockaddr_in *)&sa;
+#ifdef AF_INET6
+               if (s->sin_family != AF_INET && s->sin_family != AF_INET6) {
+#else
+               if (s->sin_family != AF_INET) {
+#endif
+#ifdef AF_UNIX
+                       /*
+                        * AF_UNIX is not defined on BeOS
+                        */
+                       if (s->sin_family == AF_UNIX) {
+                               DEBUG("rmt: stdin is a PIPE (UNIX domain socket)\n");
+                               return ("PIPE");
+                       }
+#endif
+                       DEBUG1("rmt: stdin NOT_IP socket (sin_family: %d)\n",
+                                                       s->sin_family);
+                       return ("NOT_IP");
+               }
+               
+#ifdef HAVE_GETNAMEINFO
+               buffer[0] = '\0';
+               if (debug_file &&
+                   getnameinfo(sap, sasize, buffer, sizeof (buffer), NULL, 0,
+                   NI_NUMERICHOST) == 0) {
+                       DEBUG1("rmt: peername %s\n", buffer);
+               }
+               buffer[0] = '\0';
+               if (getnameinfo(sap, sasize, buffer, sizeof (buffer), NULL, 0,
+                   0) == 0) {
+                       DEBUG1("rmt: peername %s\n", buffer);
+                       return (buffer);
+               }
+               return ("CANNOT_MAP_ADDRESS");
+#else  /* HAVE_GETNAMEINFO */
+#ifdef HAVE_INET_NTOA
+               (void) snprintf(buffer, sizeof(buffer), "%s", inet_ntoa(s->sin_addr));
+#else
+               (void) snprintf(buffer, sizeof(buffer), "%x", s->sin_addr.s_addr);
+#endif
+               DEBUG1("rscsid: peername %s\n", buffer);
+               he = gethostbyaddr((char *)&s->sin_addr.s_addr, 4, AF_INET);
+               DEBUG1("rscsid: peername %s\n", he!=NULL?he->h_name:buffer);
+               if (he != NULL)
+                       return (he->h_name);
+               return (buffer);
+#endif /* HAVE_GETNAMEINFO */
+       }
+}
+
+static BOOL
+checktarget()
+{
+       char    *target;
+       char    *user;
+       char    *host;
+       char    *p;
+       int     bus;
+       int     chan;
+       int     tgt;
+       int     lun;
+
+       if (peername == NULL)
+               return (FALSE);
+  cfg_restart();
+       while ((target = cfg_get_next("ACCESS")) != NULL) {
+               p = target;
+               while (*p == '\t')
+                       p++;
+               user = p;
+               if ((p = strchr(p, '\t')) != NULL)
+                       *p++ = '\0';
+               else
+                       continue;
+               if (0!=strcmp(username, user))
+                       continue;
+
+               while (*p == '\t')
+                       p++;
+               host = p;
+               if ((p = strchr(p, '\t')) != NULL)
+                       *p++ = '\0';
+               else
+                       continue;
+               if (0!=strcmp(peername, host))
+                       continue;
+
+               p = astoi(p, &bus);
+               if (*p != '\t')
+                       continue;
+               p = astoi(p, &chan);
+               if (*p != '\t')
+                       continue;
+               p = astoi(p, &tgt);
+               if (*p != '\t')
+                       continue;
+               p = astoi(p, &lun);
+
+               if (*p != '\t' && *p != '\n' && *p != '\r' && *p != '\0') 
+                       continue;
+               DEBUG6("ACCESS %s %s %d.%d,%d,%d\n", user, host, bus, chan, tgt, lun);
+
+               if (bus != -1 && bus != usal_scsibus(scsi_ptr))
+                       continue;
+               if (tgt != -1 && tgt != usal_target(scsi_ptr))
+                       continue;
+               if (lun != -1 && lun != usal_lun(scsi_ptr))
+                       continue;
+               return (TRUE);
+       }
+       return (FALSE);
+}
+
+static void
+dorscsi()
+{
+       char    c;
+
+       while (readchar(&c) == 1) {
+               seterrno(0);
+
+               switch (c) {
+
+               case 'V':               /* "V" ersion   */
+                       scsiversion();
+                       break;
+               case 'O':               /* "O" pen      */
+                       openscsi();
+                       break;
+               case 'C':               /* "C" lose     */
+                       closescsi();
+                       break;
+               case 'D':               /* "D" MA       */
+                       maxdma();
+                       break;
+               case 'M':               /* "M" alloc    */
+                       getbuf();
+                       break;
+               case 'F':               /* "F" free     */
+                       freebuf();
+                       break;
+               case 'B':               /* "B" us       */
+                       havebus();
+                       break;
+               case 'T':               /* "T" arget    */
+                       scsifileno();
+                       break;
+               case 'I':               /* "I" nitiator */
+                       initiator_id();
+                       break;
+               case 'A':               /* "A" tapi     */
+                       isatapi();
+                       break;
+               case 'R':               /* "R" eset     */
+                       scsireset();
+                       break;
+               case 'S':               /* "S" end      */
+                       sendcmd();
+                       break;
+
+               default:
+                       DEBUG1("rscsid: garbage command '%c'\n", c);
+                       rscsierror(0, "Garbage command", NULL);
+                       exit(EX_BAD);
+               }
+       }
+       exit(0);
+}
+
+static void
+scsiversion()
+{
+       int     ret;
+       char    *str;
+       char    what[CMD_SIZE];
+
+       readarg(what, sizeof(what));
+       DEBUG1("rscsid: V %s\n", what);
+       if (scsi_ptr == NULL) {
+               rscsirespond(-1, EBADF);
+               return;
+       }
+       str = usal_version(scsi_ptr, atoi(what));
+       ret = strlen(str);
+       ret++;  /* Include null char */
+       rscsirespond(ret, geterrno());
+       _nixwrite(STDOUT_FILENO, str, ret);
+}
+
+static void
+openscsi()
+{
+       char    device[CMD_SIZE];
+       char    errstr[80];
+       int     debug = 0;
+       int     lverbose = 0;
+       int     ret = 0;
+       char    rbuf[1600];
+
+       if (scsi_ptr != NULL)
+               (void) usal_close(scsi_ptr);
+
+       readarg(device, sizeof(device));
+       DEBUG1("rscsid: O %s\n", device);
+       if (strncmp(device, "REMOTE", 6) == 0) {
+               scsi_ptr = NULL;
+               seterrno(EINVAL);
+       } else if (!checkscsi(device)) {
+               scsi_ptr = NULL;
+               seterrno(EACCES);
+       } else {
+               scsi_ptr = usal_open(device, errstr, sizeof(errstr), debug, lverbose);
+               if (scsi_ptr == NULL) {
+                       ret = -1;
+               } else {
+                       scsi_ptr->silent = 1;
+                       scsi_ptr->verbose = 0;
+                       scsi_ptr->debug = 0;
+                       scsi_ptr->kdebug = 0;
+               }
+       }
+       if (ret < 0) {
+               /*
+                * XXX This is currently the only place where we use the
+                * XXX extended error string.
+                */
+               rscsierror(geterrno(), errmsgstr(geterrno()), errstr);
+/*             rscsirespond(ret, geterrno());*/
+               return;
+       }
+       DEBUG4("rscsid:>A 0 %d.%d,%d,%d\n", 
+               usal_scsibus(scsi_ptr),
+               0,
+               usal_target(scsi_ptr),
+               usal_lun(scsi_ptr));
+
+       ret = snprintf(rbuf, sizeof(rbuf), "A0\n%d\n%d\n%d\n%d\n",
+               usal_scsibus(scsi_ptr),
+               0,
+               usal_target(scsi_ptr),
+               usal_lun(scsi_ptr));
+       (void) _nixwrite(STDOUT_FILENO, rbuf, ret);
+}
+
+static void
+closescsi()
+{
+       int     ret;
+       char    device[CMD_SIZE];
+
+       readarg(device, sizeof(device));
+       DEBUG1("rscsid: C %s\n", device);
+       ret = usal_close(scsi_ptr);
+       rscsirespond(ret, geterrno());
+       scsi_ptr = NULL;
+}
+
+static void
+maxdma()
+{
+       int     ret;
+       char    amt[CMD_SIZE];
+
+       readarg(amt, sizeof(amt));
+       DEBUG1("rscsid: D %s\n", amt);
+       if (scsi_ptr == NULL) {
+               rscsirespond(-1, EBADF);
+               return;
+       }
+       ret = usal_bufsize(scsi_ptr, atol(amt));
+       rscsirespond(ret, geterrno());
+}
+
+static void
+getbuf()
+{
+       int     ret = 0;
+       char    amt[CMD_SIZE];
+
+       readarg(amt, sizeof(amt));
+       DEBUG1("rscsid: M %s\n", amt);
+       if (scsi_ptr == NULL) {
+               rscsirespond(-1, EBADF);
+               return;
+       }
+       ret = usal_bufsize(scsi_ptr, atol(amt));
+       if (preparebuffer(ret) == NULL)
+               ret = -1;
+       rscsirespond(ret, geterrno());
+}
+
+static void
+freebuf()
+{
+       int     ret = 0;
+       char    dummy[CMD_SIZE];
+
+       readarg(dummy, sizeof(dummy));
+       DEBUG1("rscsid: F %s\n", dummy);
+       if (scsi_ptr == NULL) {
+               rscsirespond(-1, EBADF);
+               return;
+       }
+       usal_freebuf(scsi_ptr);
+       Sbuf = NULL;
+       rscsirespond(ret, geterrno());
+}
+
+static void
+havebus()
+{
+       int     ret;
+       char    bus[CMD_SIZE];
+       char    chan[CMD_SIZE];
+
+       readarg(bus, sizeof(bus));
+       readarg(chan, sizeof(chan));
+       DEBUG2("rscsid: B %s.%s\n", bus, chan);
+       if (scsi_ptr == NULL) {
+               rscsirespond(-1, EBADF);
+               return;
+       }
+       ret = usal_havebus(scsi_ptr, atol(bus));
+       rscsirespond(ret, geterrno());
+}
+
+static void
+scsifileno()
+{
+       int     ret;
+       char    bus[CMD_SIZE];
+       char    chan[CMD_SIZE];
+       char    tgt[CMD_SIZE];
+       char    lun[CMD_SIZE];
+
+       readarg(bus, sizeof(bus));
+       readarg(chan, sizeof(chan));
+       readarg(tgt, sizeof(tgt));
+       readarg(lun, sizeof(lun));
+       DEBUG4("rscsid: T %s.%s,%s,%s\n", bus, chan, tgt, lun);
+       if (scsi_ptr == NULL) {
+               rscsirespond(-1, EBADF);
+               return;
+       }
+       seterrno(0);
+       ret = usal_settarget(scsi_ptr, atoi(bus), atoi(tgt), atoi(lun));
+       if (!checktarget()) {
+               usal_settarget(scsi_ptr, -1, -1, -1);
+               ret = -1;
+       }
+       if (geterrno() != 0)
+               rscsirespond(ret, geterrno());
+       else
+               rscsireply(ret);
+}
+
+static void
+initiator_id()
+{
+       int     ret;
+       char    dummy[CMD_SIZE];
+
+       readarg(dummy, sizeof(dummy));
+       DEBUG1("rscsid: I %s\n", dummy);
+       if (scsi_ptr == NULL) {
+               rscsirespond(-1, EBADF);
+               return;
+       }
+       seterrno(0);
+       ret = usal_initiator_id(scsi_ptr);
+       if (geterrno() != 0)
+               rscsirespond(ret, geterrno());
+       else
+               rscsireply(ret);
+}
+
+static void
+isatapi()
+{
+       int     ret;
+       char    dummy[CMD_SIZE];
+
+       readarg(dummy, sizeof(dummy));
+       DEBUG1("rscsid: A %s\n", dummy);
+       if (scsi_ptr == NULL) {
+               rscsirespond(-1, EBADF);
+               return;
+       }
+       seterrno(0);
+       ret = usal_isatapi(scsi_ptr);
+       if (geterrno() != 0)
+               rscsirespond(ret, geterrno());
+       else
+               rscsireply(ret);
+}
+
+static void
+scsireset()
+{
+       int     ret;
+       char    what[CMD_SIZE];
+
+       readarg(what, sizeof(what));
+       DEBUG1("rscsid: R %s\n", what);
+       if (scsi_ptr == NULL) {
+               rscsirespond(-1, EBADF);
+               return;
+       }
+       ret = usal_reset(scsi_ptr, atoi(what));
+       rscsirespond(ret, geterrno());
+}
+
+static void
+sendcmd()
+{
+       register struct usal_cmd        *scmd;
+       int     n;
+       int     ret;
+       char    count[CMD_SIZE];
+       char    flags[CMD_SIZE];
+       char    cdb_len[CMD_SIZE];
+       char    sense_len[CMD_SIZE];
+       char    timeout[CMD_SIZE];
+       int     csize;
+       int     cflags;
+       int     clen;
+       int     ctimeout;
+       char    rbuf[1600];
+       char    *p;
+
+       /*
+        *      S count\n
+        *      flags\n
+        *      cdb_len\n
+        *      sense_len\n
+        *      timeout\n
+        *      <data if available>
+        *
+        *      Timeout:
+        *      -       sss     (e.g. 10)
+        *      -       sss.uuu (e.g. 10.23)
+        */
+       readarg(count, sizeof(count));
+       readarg(flags, sizeof(flags));
+       readarg(cdb_len, sizeof(cdb_len));
+       readarg(sense_len, sizeof(sense_len));
+       readarg(timeout, sizeof(timeout));
+       DEBUG5("rscsid: S %s %s %s %s %s", count, flags, cdb_len, sense_len, timeout);
+       csize = atoi(count);
+       cflags = atoi(flags);
+       clen = atoi(cdb_len);
+
+       p = strchr(timeout, '.');
+       if (p)
+               *p = '\0';
+       ctimeout = atoi(timeout);
+
+       if (scsi_ptr == NULL || clen > SCG_MAX_CMD || csize > Sbufsize) {
+               DEBUG("\n");
+               voidarg(clen);
+               if ((cflags & SCG_RECV_DATA) == 0 && csize > 0)
+                       voidarg(csize);
+               rscsirespond(-1, scsi_ptr==NULL ? EBADF : EINVAL);
+               return;
+       }
+
+       scmd = scsi_ptr->scmd;
+       fillbytes((caddr_t)scmd, sizeof(*scmd), '\0');
+       scmd->addr = (caddr_t)Sbuf;
+       scmd->size = csize;
+       scmd->flags = cflags;
+       scmd->cdb_len = clen;
+       scmd->sense_len = atoi(sense_len);
+       scmd->timeout = ctimeout;
+       readbuf((char *)scmd->cdb.cmd_cdb, clen);
+       DEBUG6(" 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X\n",
+               scmd->cdb.cmd_cdb[0],
+               scmd->cdb.cmd_cdb[1],
+               scmd->cdb.cmd_cdb[2],
+               scmd->cdb.cmd_cdb[3],
+               scmd->cdb.cmd_cdb[4],
+               scmd->cdb.cmd_cdb[5]);
+
+       if ((cflags & SCG_RECV_DATA) == 0 && csize > 0)
+               readbuf(Sbuf, scmd->size);
+
+       scsi_ptr->cmdname = "";
+
+       ret = usal_cmd(scsi_ptr);
+
+       n = 0;
+       if ((csize - scmd->resid) > 0)
+               n = csize - scmd->resid;
+
+       /*
+        *      A count\n
+        *      error\n
+        *      errno\n
+        *      scb\n
+        *      sense_count\n
+        *      <data if available>
+        */
+       DEBUG5("rscsid:>A %d %d %d %d %d\n",
+               n,
+               scmd->error,
+               scmd->ux_errno,
+               *(Uchar *)&scmd->scb,
+               scmd->sense_count);
+
+       ret = snprintf(rbuf, sizeof(rbuf), "A%d\n%d\n%d\n%d\n%d\n",
+               n,
+               scmd->error,
+               scmd->ux_errno,
+               *(Uchar *)&scmd->scb,
+               scmd->sense_count);
+
+       if (scmd->sense_count > 0) {
+               movebytes(scmd->u_sense.cmd_sense, &rbuf[ret], scmd->sense_count);
+               ret += scmd->sense_count;
+       }
+       if ((cflags & SCG_RECV_DATA) == 0)
+               n = 0;
+       if (n > 0 && ((ret + n) <= sizeof(rbuf))) {
+               movebytes(Sbuf, &rbuf[ret], n);
+               ret += n;
+               n = 0;
+       }
+       (void) _nixwrite(STDOUT_FILENO, rbuf, ret);
+
+       if (n > 0)
+               (void) _nixwrite(STDOUT_FILENO, Sbuf, n);
+}
+
+#define        READB_SIZE      128
+static char            readb[READB_SIZE];
+static char            *readbptr;
+static int             readbcnt;
+
+static int
+fillrdbuf()
+{
+       readbptr = readb;
+
+       return (readbcnt = _niread(STDIN_FILENO, readb, READB_SIZE));
+}
+
+static int
+readchar(char *cp)
+{
+       if (--readbcnt < 0) {
+               if (fillrdbuf() <= 0)
+                       return (readbcnt);
+               --readbcnt;
+       }
+       *cp = *readbptr++;
+       return (1);
+}
+
+static void
+readbuf(register char *buf, register int n)
+{
+       register int    i = 0;
+       register int    amt;
+
+       if (readbcnt > 0) {
+               amt = readbcnt;
+               if (amt > n)
+                       amt = n;
+               movebytes(readbptr, buf, amt);
+               readbptr += amt;
+               readbcnt -= amt;
+               i += amt;
+       }
+
+       for (; i < n; i += amt) {
+               amt = _niread(STDIN_FILENO, &buf[i], n - i);
+               if (amt <= 0) {
+                       DEBUG("rscsid: premature eof\n");
+                       rscsierror(0, "Premature eof", NULL);
+                       exit(EX_BAD);
+               }
+       }
+}
+
+static void
+voidarg(register int n)
+{
+       register int    i;
+       register int    amt;
+                char   buf[512];
+
+       for (i = 0; i < n; i += amt) {
+               amt = sizeof(buf);
+               if ((n - i) < amt)
+                       amt = n - i;
+               readbuf(buf, amt);
+       }
+}
+
+static void
+readarg(char *buf, int n)
+{
+       int     i;
+
+       for (i = 0; i < n; i++) {
+               if (readchar(&buf[i]) != 1)
+                       exit(0);
+               if (buf[i] == '\n')
+                       break;
+       }
+       buf[i] = '\0';
+}
+
+static char *
+preparebuffer(int size)
+{
+       Sbufsize = size;
+       if ((Sbuf = usal_getbuf(scsi_ptr, Sbufsize)) == NULL) {
+               Sbufsize = 0L;
+               return (Sbuf);
+       }
+       size = Sbufsize + 1024; /* Add protocol overhead */
+
+#ifdef SO_SNDBUF
+       while (size > 512 &&
+              setsockopt(STDOUT_FILENO, SOL_SOCKET, SO_SNDBUF, (char *)&size, sizeof (size)) < 0)
+               size -= 512;
+       DEBUG1("rscsid: sndsize: %d\n", size);
+#endif
+#ifdef SO_RCVBUF
+       while (size > 512 &&
+              setsockopt(STDIN_FILENO, SOL_SOCKET, SO_RCVBUF, (char *)&size, sizeof (size)) < 0)
+               size -= 512;
+       DEBUG1("rscsid: rcvsize: %d\n", size);
+#endif
+       return (Sbuf);
+}
+
+static int
+checkscsi(char *device)
+{
+#ifdef CHECKTAPE
+       if (strncmp(device, "/dev/rst", 8) == 0 ||
+           strncmp(device, "/dev/nrst", 9) == 0 ||
+           strcmp(device, "/dev/zero") == 0 ||
+           strcmp(device, "/dev/null") == 0)
+               return (1);
+       return (0);
+#else
+       return (1);
+#endif
+}
+
+static void
+rscsirespond(int ret, int err)
+{
+       if (ret < 0) {
+               rscsierror(err, errmsgstr(err), NULL);
+       } else {
+               rscsireply(ret);
+       }
+}
+
+static void
+rscsireply(int ret)
+{
+       char    rbuf[CMD_SIZE];
+
+       DEBUG1("rscsid:>A %d\n", ret);
+       (void) snprintf(rbuf, sizeof(rbuf), "A%d\n", ret);
+       (void) _nixwrite(STDOUT_FILENO, rbuf, strlen(rbuf));
+}
+
+static void
+rscsierror(int err, char *str, char *xstr)
+{
+       char    rbuf[1600];
+       int     xlen = 0;
+       int     n;
+
+       if (xstr != NULL)
+               xlen = strlen(xstr) + 1;
+
+       DEBUG3("rscsid:>E %d (%s) [%s]\n", err, str, xstr?xstr:"");
+       n = snprintf(rbuf, sizeof(rbuf), "E%d\n%s\n%d\n", err, str, xlen);
+
+       if (xlen > 0 && ((xlen + n) <= sizeof(rbuf))) {
+               movebytes(xstr, &rbuf[n], xlen);
+               n += xlen;
+               xlen = 0;
+       }
+       (void) _nixwrite(STDOUT_FILENO, rbuf, n);
+       if (xlen > 0)
+               (void) _nixwrite(STDOUT_FILENO, xstr, xlen);
+}
+#endif /* USE_REMOTE */
diff --git a/netscsid/netscsid.dfl b/netscsid/netscsid.dfl
new file mode 100644 (file)
index 0000000..fe8c12b
--- /dev/null
@@ -0,0 +1,62 @@
+#ident @(#)rscsi.dfl   1.3 05/08/09 Copyr 2000 J. Schilling
+#
+# This file is /etc/rscsi.conf
+#
+# NOTE: If this file is not present, rscsi will reject to work.
+#
+# If no USER= entry is present, only root is allowed to run rscsi.
+# If no ACCESS= entry is present, no device may to be used by remote users.
+
+# 
+# The file where debug info should go to.
+# This is commented out by default to speed up the program.
+# If you enable it make sure you substitute SAFE_DIR to a safe directory
+# to debug to.
+#
+# Note that rscsi runs as root and thus may be able to overwrite any file.
+# Be sure not to allow other people to replace the debug file by a symlink
+# to e.g. /etc/passwd. 
+#
+#DEBUG=SAFE_DIR/rscsi.dbg
+
+#
+# Each USER= entry adds the listed user to the users who may run rscsi
+#
+# A typical passwd entry looks like this:
+# rscsi:x:1999:1000:Remote SCSI:/export/home/rscsi:/opt/schily/sbin/rscsi
+#
+# Add entries for all valid remote users to /export/home/rscsi/.rhosts
+#
+# USER= entries are checked with a pattern matcher. USER=* matches all users.
+#
+USER=rscsi
+#USER=joerg
+
+#
+# Each ACCESS= entry adds a target or group of targets to the list of visible
+# targets for all users that do remote SCSI access from a specific host.
+#
+#      Username is the name of the user that runs rscsi. If you create
+#      different users, you may assign different permissions to different
+#      users from the same host.
+#
+#      Hostname must be in the same notation as needed for .rhosts (e.g. in
+#      the way you will be listed by 'who' if you log in from this host).
+#
+#      bus/chan/target/lun are the numbers from the scanbus output from
+#      cdrecord or sformat. If you use -1, you allow any value for this
+#      placeholder.
+#
+#      local user name and remote host name are checked with a pattern matcher.
+#      ACCESS=*        * .... matches all users from all hosts.
+#
+#      NOTE: chan is currently not implementd (set it to 0 or -1)
+#
+#      local   remote
+#      user    host    bus     chan    target  lun
+#      name    name
+#
+#ACCESS=rscsi  sparky  -1      -1      -1      -1
+#ACCESS=rscsi  sparky  0       -1      6       -1
+#ACCESS=rscsi  sparky  1       -1      3       -1
+#ACCESS=rscsi  sparky  1       -1      4       -1
diff --git a/readom/CMakeLists.txt b/readom/CMakeLists.txt
new file mode 100644 (file)
index 0000000..81536d8
--- /dev/null
@@ -0,0 +1,19 @@
+PROJECT (READECD C)
+INCLUDE_DIRECTORIES(../include ../wodim ${CMAKE_BINARY_DIR} ${CMAKE_BINARY_DIR}/include)
+INCLUDE(../include/AddScgBits.cmake)
+INCLUDE(../include/AddSchilyBits.cmake)
+
+AUX_SOURCE_DIRECTORY(. readom_SRCS)
+
+LINK_DIRECTORIES(../librols ../libusal  ../wodim)
+
+ADD_DEFINITIONS(-DCLONE_WRITE)
+
+ADD_EXECUTABLE (readom ${readom_SRCS})
+TARGET_LINK_LIBRARIES(readom wodimstuff ${EXTRA_LIBS})
+SET_TARGET_PROPERTIES(readom PROPERTIES  SKIP_BUILD_RPATH TRUE)
+
+INSTALL(TARGETS readom DESTINATION bin)
+INSTALL(FILES 
+readom.1
+DESTINATION ${MANSUBDIR}/man1)
diff --git a/readom/io.c b/readom/io.c
new file mode 100644 (file)
index 0000000..364e0ed
--- /dev/null
@@ -0,0 +1,193 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)io.c    1.19 98/10/10 Copyright 1988 J. Schilling */
+/*
+ *     Copyright (c) 1988 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <mconfig.h>
+#include <stdio.h>
+#include <standard.h>
+#include <vadefs.h>
+#include <stdxlib.h>
+#include <strdefs.h>
+#include <utypes.h>
+#include <schily.h>
+#include <ctype.h>
+
+struct disk {
+       int     dummy;
+};
+
+static char    *skipwhite(const char *);
+static void    prt_std(char *, long, long, long, struct disk *);
+BOOL   cvt_std(char *, long *, long, long, struct disk *);
+extern BOOL    getvalue(char *, long *, long, long,
+                                                               void (*)(char *, long, long, long, struct disk *),
+                                                               BOOL (*)(char *, long *, long, long, struct disk *),
+                                                               struct disk *);
+extern BOOL    getlong(char *, long *, long, long);
+extern BOOL    getint(char *, int *, int, int);
+extern BOOL    yes(char *, ...);
+
+static
+char *skipwhite(const char *s)
+{
+       register const Uchar    *p = (const Uchar *)s;
+
+       while (*p) {
+               if (!isspace(*p))
+                       break;
+               p++;
+       }
+       return ((char *)p);
+}
+
+/* ARGSUSED */
+
+BOOL
+cvt_std(char *linep, long *lp, long mini, long maxi, struct disk *dp)
+{
+       long    l       = -1L;
+
+/*     printf("cvt_std(\"%s\", %d, %d, %d);\n", linep, *lp, mini, maxi);*/
+
+       if (linep[0] == '?') {
+               printf("Enter a number in the range from %ld to %ld\n",
+                                                               mini, maxi);
+               printf("The default radix is 10\n");
+               printf("Precede number with '0x' for hexadecimal or with '0' for octal\n");
+               printf("Shorthands are:\n");
+               printf("\t'^' for minimum value (%ld)\n", mini);
+               printf("\t'$' for maximum value (%ld)\n", maxi);
+               printf("\t'+' for incrementing value to %ld\n", *lp + 1);
+               printf("\t'-' for decrementing value to %ld\n", *lp - 1);
+               return (FALSE);
+       }
+       if (linep[0] == '^' && *skipwhite(&linep[1]) == '\0') {
+               l = mini;
+       } else if (linep[0] == '$' && *skipwhite(&linep[1]) == '\0') {
+               l = maxi;
+       } else if (linep[0] == '+' && *skipwhite(&linep[1]) == '\0') {
+               if (*lp < maxi)
+                       l = *lp + 1;
+       } else if (linep[0] == '-' && *skipwhite(&linep[1]) == '\0') {
+               if (*lp > mini)
+                       l = *lp - 1;
+       } else if (*astol(linep, &l)) {
+               printf("Not a number: '%s'.\n", linep);
+               return (FALSE);
+       }
+       if (l < mini || l > maxi) {
+               printf("'%s' is out of range.\n", linep);
+               return (FALSE);
+       }
+       *lp = l;
+       return (TRUE);
+}
+
+/* ARGSUSED */
+static void
+prt_std(char *s, long l, long mini, long maxi, struct disk *dp)
+{
+       printf("%s %ld (%ld - %ld)/<cr>:", s, l, mini, maxi);
+}
+
+
+BOOL getvalue(char *s, long *lp, long mini, long maxi, 
+                                 void  (*prt)(char *, long, long, long, struct disk *), 
+                                 BOOL  (*cvt)(char *, long *, long, long, struct disk *), 
+                                 struct disk *dp)
+{
+       char    line[128];
+       char    *linep;
+
+       for(;;) {
+               (*prt)(s, *lp, mini, maxi, dp);
+               flush();
+               line[0] = '\0';
+               if (rols_getline(line, 80) == EOF)
+                       exit(EX_BAD);
+
+               linep = skipwhite(line);
+               /*
+                * Nicht initialisierte Variablen
+                * duerfen nicht uebernommen werden
+                */
+               if (linep[0] == '\0' && *lp != -1L)
+                       return (FALSE);
+
+               if (strlen(linep) == 0) {
+                       /* Leere Eingabe */
+                       /* EMPTY */
+               } else if ((*cvt)(linep, lp, mini, maxi, dp))
+                       return (TRUE);
+       }
+       /* NOTREACHED */
+}
+
+
+BOOL getlong(char *s, long *lp, long mini, long maxi)
+{
+       return (getvalue(s, lp, mini, maxi, prt_std, cvt_std, (void *)0));
+}
+
+
+BOOL getint(char *s, int *ip, int mini, int maxi)
+{
+       long    l = *ip;
+       BOOL    ret;
+
+       ret = getlong(s, &l, (long)mini, (long)maxi);
+       *ip = l;
+       return (ret);
+}
+
+/* VARARGS1 */
+BOOL yes(char *form, ...)
+{
+       va_list args;
+       char okbuf[10];
+
+again:
+       va_start(args, form);
+       vprintf(form, args);
+       va_end(args);
+       flush();
+       if (rols_getline(okbuf, sizeof(okbuf)) == EOF)
+               exit(EX_BAD);
+       if (okbuf[0] == '?') {
+               printf("Enter 'y', 'Y', 'yes' or 'YES' if you agree with the previous asked question.\n");
+               printf("All other input will be handled as if the question has beed answered with 'no'.\n");
+               goto again;
+       }
+       if(streql(okbuf, "y") || streql(okbuf, "yes") ||
+          streql(okbuf, "Y") || streql(okbuf, "YES"))
+               return(TRUE);
+       else
+               return(FALSE);
+}
diff --git a/readom/readom.1 b/readom/readom.1
new file mode 100644 (file)
index 0000000..3bdc47b
--- /dev/null
@@ -0,0 +1,497 @@
+.\" @(#)readom.1       1.23 06/01/12 Copyright 1996-2006 J. Schilling
+.\" 
+.\" Modified version of readcd.1 by J. Schilling, 11/2006
+.\" 
+.\" This program is free software; you can redistribute it and/or modify
+.\" it under the terms of the GNU General Public License version 2
+.\" as published by the Free Software Foundation.
+.\"
+.\" The GNU General Public License's references to "object code"
+.\" and "executables" are to be interpreted as the output of any
+.\" document formatting or typesetting system, including
+.\" intermediate and printed output.
+.\"
+.\" This manual 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; see the file COPYING.  If not, write to the Free Software
+.\" Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+.if t .ds a \v'-0.55m'\h'0.00n'\z.\h'0.40n'\z.\v'0.55m'\h'-0.40n'a
+.if t .ds o \v'-0.55m'\h'0.00n'\z.\h'0.45n'\z.\v'0.55m'\h'-0.45n'o
+.if t .ds u \v'-0.55m'\h'0.00n'\z.\h'0.40n'\z.\v'0.55m'\h'-0.40n'u
+.if t .ds A \v'-0.77m'\h'0.25n'\z.\h'0.45n'\z.\v'0.77m'\h'-0.70n'A
+.if t .ds O \v'-0.77m'\h'0.25n'\z.\h'0.45n'\z.\v'0.77m'\h'-0.70n'O
+.if t .ds U \v'-0.77m'\h'0.30n'\z.\h'0.45n'\z.\v'0.77m'\h'-0.75n'U
+.if t .ds s \\(*b
+.if t .ds S SS
+.if n .ds a ae
+.if n .ds o oe
+.if n .ds u ue
+.if n .ds s sz
+.TH READOM 1 "Version 2.0" "J\*org Schilling" "Schily\'s USER COMMANDS"
+.SH NAME
+readom \- read or write data Compact Discs
+.SH SYNOPSIS
+.B readom
+.BI dev= device
+[
+.I options
+]
+
+.SH DESCRIPTION
+.B Readom
+is used to read or write Compact Discs.
+.PP
+The
+.I device
+refers to a device location similar to the one used in the wodim command. Refer to its manpage for details.
+.PP
+Also note that this version of readom uses a modified libusal library which has
+a different behaviour compared to the one distributed by its original author.
+
+.SH OPTIONS
+.PP
+If no options except the 
+.I dev=
+option have been specified, 
+.B readom
+goes into interactive mode.
+Select a primary function and then follow the instructions.
+.PP
+.TP
+.B \-version
+Print version information and exit.
+.TP
+.BI dev= target
+Sets the SCSI target for the drive, see notes above.
+A typical device specification is
+.BI dev= 6,0
+\&.
+If a filename must be provided together with the numerical target 
+specification, the filename is implementation specific.
+The correct filename in this case can be found in the system specific
+manuals of the target operating system.
+On a 
+.I FreeBSD
+system without 
+.I CAM
+support, you need to use the control device (e.g.
+.IR /dev/rcd0.ctl ).
+A correct device specification in this case may be
+.BI dev= /dev/rcd0.ctl:@
+\&.
+.sp
+On Linux, drives connected to a parallel port adapter are mapped
+to a virtual SCSI bus. Different adapters are mapped to different
+targets on this virtual SCSI bus.
+.sp
+If no 
+.I dev
+option is present, 
+.B readom
+will try to get the device from the 
+.B CDR_DEVICE
+environment.
+.sp
+If the argument to the
+.B dev=
+option does not contain the characters ',', '/', '@' or ':',
+it is interpreted as an label name that may be found in the file
+/etc/wodim.conf (see FILES section).
+.TP
+.BI timeout= #
+Set the default SCSI command timeout value to 
+.IR # " seconds.
+The default SCSI command timeout is the minimum timeout used for sending
+SCSI commands.
+If a SCSI command fails due to a timeout, you may try to raise the
+default SCSI command timeout above the timeout value of the failed command.
+If the command runs correctly with a raised command timeout,
+please report the better timeout value and the corresponding command to 
+the author of the program.
+If no 
+.I timeout 
+option is present, a default timeout of 40 seconds is used.
+.TP
+.BI debug= "#, " -d
+Set the misc debug value to # (with debug=#) or increment
+the misc debug level by one (with -d). If you specify
+.I -dd,
+this equals to 
+.BI debug= 2.
+This may help to find problems while opening a driver for libusal.
+as well as with sector sizes and sector types.
+Using
+.B \-debug
+slows down the process and may be the reason for a buffer underrun.
+.TP
+.BR kdebug= "#, " kd= #
+Tell the 
+.BR usal -driver
+to modify the kernel debug value while SCSI commands are running.
+.TP
+.BR \-silent ", " \-s
+Do not print out a status report for failed SCSI commands.
+.TP
+.B \-v
+Increment the level of general verbosity by one.
+This is used e.g. to display the progress of the process.
+.TP
+.B \-V
+Increment the verbose level with respect of SCSI command transport by one.
+This helps to debug problems
+during the process, that occur in the CD-Recorder. 
+If you get incomprehensible error messages you should use this flag
+to get more detailed output.
+.B \-VV
+will show data buffer content in addition.
+Using
+.B \-V
+or
+.B \-VV
+slows down the process.
+.TP
+.BI f= file
+Specify the filename where the output should be written or the input should
+be taken from. Using '-' as filename will cause
+.B readom
+to use 
+.BR stdout " resp. " stdin .
+.TP
+.B \-w
+Switch to write mode. If this option is not present,
+.B readom
+reads from the specified device.
+.TP
+.B \-c2scan
+Scans the whole CD or the range specified by the 
+.BI sectors= range
+for C2 errors. C2 errors are errors that are uncorrectable after the second
+stage of the 24/28 + 28/32 Reed Solomon correction system at audio level
+(2352 bytes sector size). If an audio CD has C2 errors, interpolation is needed
+to hide the errors. If a data CD has C2 errors, these errors are in most
+cases corrected by the ECC/EDC code that makes 2352 bytes out of 2048 data
+bytes. The ECC/EDC code should be able to correct about 100 C2 error bytes
+per sector.
+.sp
+If you find C2 errors you may want to reduce the speed using the
+.B speed=
+option as C2 errors may be a result of dynamic unbalance on the medium.
+.TP
+.B \-scanbus
+Scan all SCSI devices on all SCSI busses and print the inquiry
+strings. This option may be used to find SCSI address of the 
+devices on a system.
+The numbers printed out as labels are computed by: 
+.B "bus * 100 + target
+.TP
+.BI sectors= range
+Specify a sector range that should be read.
+The range is specified by the starting sector number, a minus sign and the
+ending sector number.
+The end sector is not included in the list, so 
+.BR sectors= 0-0
+will not read anything and may be used to check for a CD in the drive.
+.TP
+.BR speed= #
+Set the speed factor of the read or write process to #.
+# is an integer, representing a multiple of the audio speed.
+This is about 150 KB/s for CD-ROM and about 172 KB/s for CD-Audio.
+If no 
+.I speed
+option is present, 
+.B readom
+will use maximum speed.
+Only MMC compliant drives will benefit from this option.
+The speed of non MMC drives is not changed.
+.sp
+Using a lower speed may increase the readability of a CD or DVD.
+.TP
+.BR ts= #
+Set the maximum transfer size for a single SCSI command to #.
+The syntax for the 
+.B ts=
+option is the same as for wodim fs=# or sdd bs=#.
+.sp
+If no 
+.B ts=
+option has been specified,
+.B readom
+defaults to a transfer size of 256 kB. If libusal gets lower values from the
+operating system, the value is reduced to the maximum value that is possible
+with the current operating system.
+Sometimes, it may help to further reduce the transfer size or to enhance it,
+but note that it may take a long time to find a better value by experimenting
+with the
+.B ts=
+option.
+.TP
+.B \-notrunc
+Do not truncate the output file when opening it.
+.TP
+.B \-fulltoc
+Retrieve a full TOC from the current disk and print it in hex.
+.TP
+.B \-clone
+Do a clone read. Read the CD with all sub-channel data and a full TOC.
+The full TOC data will be put into a file with similar name as with the
+.B f=
+option but the suffix 
+.B .toc
+added.
+.TP
+.B \-noerror
+Do not abort if the high level error checking in
+.B readom
+found an uncorrectable error in the data stream.
+.TP
+.B \-nocorr
+Switch the drive into a mode where it ignores read errors in data sectors that
+are a result of uncorrectable ECC/EDC errors before reading.
+If
+.B readom
+completes, the error recovery mode of the drive is switched back to the remembered 
+old mode.
+.TP
+.BI retries= #
+Set the retry count for high level retries in
+.B readom
+to 
+.IR # .
+The default is to do 128 retries which may be too much if you like to read a CD
+with many unreadable sectors.
+.TP
+.B \-overhead
+Meter the SCSI command overhead time.
+This is done by executing several commands 1000 times and printing the
+total time used. If you divide the displayed times by 1000, you get 
+the average overhead time for a single command.
+.TP
+.BR meshpoints= #
+Print read-speed at # locations.
+The purpose of this option is to create a list of read speed values suitable
+for e.g.
+.BR gnuplot .
+The speed values are calculated assuming that 1000 bytes are one kilobyte
+as documented in the SCSI standard.
+The output data created for this purpose is written to 
+.IR stdout .
+.TP
+.B \-factor
+Output the speed values for
+.BR meshpoints= #
+as factor based on 
+.I "single speed
+of the current medium.
+This only works if
+.B readom
+is able to determine the current medium type.
+.SH EXAMPLES
+.PP
+For all examples below, it will be assumed that the drive is
+connected to the primary SCSI bus of the machine. The SCSI target id is
+set to 2.
+.PP
+To read the complete media from a CD-ROM writing the data to the file
+.IR cdimage.raw :
+.PP
+    readom dev=2,0 f=cdimage.raw
+.PP
+To read sectors from range 150 ... 10000 from a CD-ROM writing the data to the file
+.IR cdimage.raw :
+.PP
+    readom dev=2,0 sectors=150-10000 f=cdimage.raw
+.PP
+To write the data from the file
+.I cdimage.raw
+(e.g. a filesystem image from 
+.BR genisoimage )
+to a DVD-RAM, call:
+.PP
+    readom dev=2,0 -w f=cdimage.raw
+
+.SH ENVIRONMENT
+.TP
+.B RSH
+If the 
+.B RSH
+environment is present, the remote connection will not be created via
+.BR rcmd (3)
+but by calling the program pointed to by
+.BR RSH .
+Use e.g. 
+.BR RSH= /usr/bin/ssh
+to create a secure shell connection.
+.sp
+Note that this forces 
+.B wodim
+to create a pipe to the 
+.B rsh(1)
+program and disallows
+.B wodim
+to directly access the network socket to the remote server.
+This makes it impossible to set up performance parameters and slows down
+the connection compared to a 
+.B root
+initiated
+.B rcmd(3)
+connection.
+.TP
+.B RSCSI
+If the 
+.B RSCSI
+environment is present, the remote SCSI server will not be the program
+.B /opt/schily/sbin/rscsi
+but the program pointed to by
+.BR RSCSI .
+Note that the remote SCSI server program name will be ignored if you log in
+using an account that has been created with a remote SCSI server program as
+login shell.
+.SH SEE ALSO
+.BR wodim (1),
+.BR genisoimage (1),
+.BR rcmd (3),
+.BR ssh (1).
+
+.SH NOTES
+.PP
+Unless you want to risk getting problems,
+.B readom
+should be run as root. If you don't want to allow users to become root on your system,
+.B readom
+may safely be installed suid root.
+For more information see the additional notes of your system/program
+distribution or README.suidroot which is part of the Cdrkit source.
+.PP
+Documentation of the
+.B wodim
+program contains more technical details which could also apply to
+.B readom.
+
+.SH DIAGNOSTICS
+.PP
+.PP
+A typical error message for a SCSI command looks like:
+.sp
+.RS
+.nf
+readom: I/O error. test unit ready: scsi sendcmd: no error
+CDB:  00 20 00 00 00 00
+status: 0x2 (CHECK CONDITION)
+Sense Bytes: 70 00 05 00 00 00 00 0A 00 00 00 00 25 00 00 00 00 00
+Sense Key: 0x5 Illegal Request, Segment 0
+Sense Code: 0x25 Qual 0x00 (logical unit not supported) Fru 0x0
+Sense flags: Blk 0 (not valid)
+cmd finished after 0.002s timeout 40s
+.fi
+.sp
+.RE
+The first line gives information about the transport of the command.
+The text after the first colon gives the error text for the system call
+from the view of the kernel. It usually is:
+.B "I/O error
+unless other problems happen. The next words contain a short description for
+the SCSI command that fails. The rest of the line tells you if there were
+any problems for the transport of the command over the SCSI bus.
+.B "fatal error
+means that it was not possible to transport the command (i.e. no device present
+at the requested SCSI address).
+.PP
+The second line prints the SCSI command descriptor block for the failed command.
+.PP
+The third line gives information on the SCSI status code returned by the 
+command, if the transport of the command succeeds. 
+This is error information from the SCSI device.
+.PP
+The fourth line is a hex dump of the auto request sense information for the 
+command.
+.PP
+The fifth line is the error text for the sense key if available, followed
+by the segment number that is only valid if the command was a
+.I copy
+command. If the error message is not directly related to the current command,
+the text
+.I deferred error
+is appended.
+.PP
+The sixth line is the error text for the sense code and the sense qualifier if available.
+If the type of the device is known, the sense data is decoded from tables
+in
+.IR scsierrs.c " .
+The text is followed by the error value for a field replaceable unit.
+.PP
+The seventh line prints the block number that is related to the failed command
+and text for several error flags. The block number may not be valid.
+.PP
+The eight line reports the timeout set up for this command and the time
+that the command really needed to complete.
+
+.SH BUGS
+.PP
+The 
+.B readom
+program described here is the Cdrkit spinoff from the original
+.B readcd
+application (see AUTHOR section for details). It may contain bugs not present
+in the original implementation.
+.PP
+It is definitely less portable than the original implementation.
+.PP
+For platform specific bugs, see the corresponding README.platform file in the
+Cdrkit documentation (eg. README.linux).
+
+.SH "MAILING LISTS
+If you want to actively take part on the development of readom,
+you may join the developer mailing list via this URL:
+.sp
+.B
+http://alioth.debian.org/mail/?group_id=31006
+.PP
+The mail address of the list is:
+.B
+debburn-devel@lists.alioth.debian.org
+
+
+
+
+.SH AUTHOR
+.nf
+J\*org Schilling
+Seestr. 110
+D-13353 Berlin
+Germany
+.fi
+
+.PP
+This is application is a spinoff from the original implementation of readcd delivered in
+the cdrtools package [1] created by Joerg Schilling, who deserves the most credits
+for its success. However, he is not involved into the development
+of this spinoff and therefore he shall not be made responsible for any problem
+caused by it. Do not try to get support from the original author!
+.PP
+Additional information can be found on:
+.br
+https://alioth.debian.org/projects/debburn/
+.PP
+If you have support questions, send them to
+.PP
+.B
+debburn-devel@lists.alioth.debian.org
+.br
+.PP
+If you have definitely found a bug, send a mail to this list or to
+.PP
+.B
+submit@bugs.debian.org
+.br
+.PP
+writing at least a short description into the Subject and "Package: cdrkit"
+into the first line of the mail body.
+.SH SOURCES
+.PP
+.br
+[1] Cdrtools 2.01.01a08 from May 2006, http://cdrecord.berlios.de
+
diff --git a/readom/readom.c b/readom/readom.c
new file mode 100644 (file)
index 0000000..d52fe5d
--- /dev/null
@@ -0,0 +1,2194 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)readcd.c        1.80 06/02/05 Copyright 1987, 1995-2006 J. Schilling */
+/*
+ *     Skeleton for the use of the usal genearal SCSI - driver
+ *
+ *     Copyright (c) 1987, 1995-2004 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <mconfig.h>
+#include <stdio.h>
+#include <standard.h>
+#include <unixstd.h>
+#include <stdxlib.h>
+#include <strdefs.h>
+#include <fctldefs.h>
+#include <timedefs.h>
+#include <signal.h>
+#include <schily.h>
+#ifdef HAVE_PRIV_H
+#include <priv.h>
+#endif
+
+#ifdef NEED_O_BINARY
+#include <io.h>                                        /* for setmode() prototype */
+#endif
+
+#include <usal/usalcmd.h>
+#include <usal/scsireg.h>
+#include <usal/scsitransp.h>
+
+#include "scsi_scan.h"
+#include "scsimmc.h"
+#define        qpto96  __nothing__
+#include "wodim.h"
+#include "defaults.h"
+#undef qpto96
+#include "movesect.h"
+
+char   cdr_version[] = "2.01.01a05";
+
+#if    defined(PROTOTYPES)
+#define        UINT_C(a)       (a##u)
+#define        ULONG_C(a)      (a##ul)
+#define        USHORT_C(a)     (a##uh)
+#define        CONCAT(a, b)    a##b
+#else
+#define        UINT_C(a)       ((unsigned)(a))
+#define        ULONG_C(a)      ((unsigned long)(a))
+#define        USHORT_C(a)     ((unsigned short)(a))
+/* CSTYLED */
+#define        CONCAT(a, b)    a/**/b
+#endif
+
+extern BOOL    getlong(char *, long *, long, long);
+extern BOOL    getint(char *, int *, int, int);
+
+typedef struct {
+       long    start;
+       long    end;
+       long    sptr;           /* sectors per transfer */
+       BOOL    askrange;
+       char    *name;
+} parm_t;
+
+typedef struct {
+       int     errors;
+       int     c2_errors;
+       int     c2_maxerrs;
+       int     c2_errsecs;
+       int     c2_badsecs;
+       int     secsize;
+       BOOL    ismmc;
+} rparm_t;
+
+struct exargs {
+       SCSI    *usalp;
+       int     old_secsize;
+       int     flags;
+       int     exflags;
+       char    oerr[3];
+} exargs;
+
+BOOL   cvt_cyls(void);
+BOOL   cvt_bcyls(void);
+void   print_defect_list(void);
+static void    usage(int ret);
+static void    intr(int sig);
+static void    exscsi(int excode, void *arg);
+static void    excdr(int excode, void *arg);
+static int     prstats(void);
+static int     prstats_silent(void);
+static void    dorw(SCSI *usalp, char *filename, char *sectors);
+static void    doit(SCSI *usalp);
+static void    read_disk(SCSI *usalp, parm_t *parmp);
+#ifdef CLONE_WRITE
+static void    readcd_disk(SCSI *usalp, parm_t *parmp);
+static void    read_lin(SCSI *usalp, parm_t *parmp);
+static int     read_secheader(SCSI *usalp, long addr);
+static int     read_ftoc(SCSI *usalp, parm_t *parmp, BOOL do_sectype);
+static void    read_sectypes(SCSI *usalp, FILE *f);
+static void    get_sectype(SCSI *usalp, long addr, char *st);
+#endif
+
+static void    readc2_disk(SCSI *usalp, parm_t *parmp);
+static int     fread_data(SCSI *usalp, rparm_t *rp, caddr_t bp, long addr, 
+                                                                 int cnt);
+#ifdef CLONE_WRITE
+static int     fread_2448(SCSI *usalp, rparm_t *rp, caddr_t bp, long addr, 
+                                                                 int cnt);
+static int     fread_2448_16(SCSI *usalp, rparm_t *rp, caddr_t bp, long addr, 
+                                                                         int cnt);
+static int     fread_2352(SCSI *usalp, rparm_t *rp, caddr_t bp, long addr, 
+                                                                 int cnt);
+static int     fread_lin(SCSI *usalp, rparm_t *rp, caddr_t bp, long addr, 
+                                                                int cnt);
+#endif
+static int     bits(int c);
+static int     bitidx(int c);
+static int     fread_c2(SCSI *usalp, rparm_t *rp, caddr_t bp, long addr, 
+                                                               int cnt);
+
+static int     fdata_null(rparm_t *rp, caddr_t bp, long addr, int cnt);
+static int     fdata_c2(rparm_t *rp, caddr_t bp, long addr, int cnt);
+
+#ifdef used
+static int read_scsi_g1(SCSI *usalp, caddr_t bp, long addr, int cnt);
+#endif
+
+int    write_scsi(SCSI *usalp, caddr_t bp, long addr, int cnt);
+int    write_g0(SCSI *usalp, caddr_t bp, long addr, int cnt);
+int    write_g1(SCSI *usalp, caddr_t bp, long addr, int cnt);
+
+#ifdef used
+static void    Xrequest_sense(SCSI *usalp);
+#endif
+static int     read_retry(SCSI *usalp, caddr_t bp, long addr, long cnt,
+                                                                 int (*rfunc)(SCSI *usalp, rparm_t *rp, caddr_t bp, long addr, int cnt),
+                                                                 rparm_t *rp);
+static void    read_generic(SCSI *usalp, parm_t *parmp,
+                                                                        int (*rfunc)(SCSI *usalp, rparm_t *rp, caddr_t bp, long addr, int cnt),
+                                                                        rparm_t *rp,
+                                                                        int (*dfunc)(rparm_t *rp, caddr_t bp, long addr, int cnt));
+static void    write_disk(SCSI *usalp, parm_t *parmp);
+static int     choice(int n);
+static void    ra(SCSI *usalp);
+
+int    read_da(SCSI *usalp, caddr_t bp, long addr, int cnt, int framesize, 
+                                 int subcode);
+int    read_cd(SCSI *usalp, caddr_t bp, long addr, int cnt, int framesize, 
+                                 int data, int subch);
+
+static void    oldmode(SCSI *usalp, int *errp, int *retrp);
+static void    domode(SCSI *usalp, int err, int retr);
+
+static void    qpto96(Uchar *sub, Uchar *subq, int dop);
+static void    ovtime(SCSI *usalp);
+static void    add_bad(long addr);
+static void    print_bad(void);
+
+struct timeval starttime;
+struct timeval stoptime;
+int    didintr;
+int    exsig;
+
+char   *Sbuf;
+long   Sbufsize;
+
+/*#define      MAX_RETRY       32*/
+#define        MAX_RETRY       128
+
+int    help;
+int    xdebug;
+int    lverbose;
+int    quiet;
+BOOL   is_suid;
+BOOL   is_cdrom;
+BOOL   is_dvd;
+BOOL   do_write;
+BOOL   c2scan;
+BOOL   fulltoc;
+BOOL   clonemode;
+BOOL   noerror;
+BOOL   nocorr;
+BOOL   notrunc;
+int    retries = MAX_RETRY;
+int    maxtry = 0;
+int    meshpoints;
+BOOL   do_factor;
+
+struct scsi_format_data fmt;
+
+/*XXX*/EXPORT  BOOL cvt_cyls(void) { return (FALSE); }
+/*XXX*/EXPORT  BOOL cvt_bcyls(void) { return (FALSE); }
+/*XXX*/EXPORT  void print_defect_list(void) {}
+
+static void
+usage(int ret)
+{
+       fprintf(stderr, "Usage:\treadom [options]\n");
+       fprintf(stderr, "options:\n");
+       fprintf(stderr, "\t-version     print version information and exit\n");
+       fprintf(stderr, "\tdev=target   SCSI target to use\n");
+       fprintf(stderr, "\tf=filename   Name of file to read/write\n");
+       fprintf(stderr, "\tsectors=range        Range of sectors to read/write\n");
+       fprintf(stderr, "\tspeed=#              set speed of drive (MMC only)\n");
+       fprintf(stderr, "\tts=#         set maximum transfer size for a single SCSI command\n");
+       fprintf(stderr, "\t-w           Switch to write mode\n");
+       fprintf(stderr, "\t-c2scan              Do a C2 error scan\n");
+#ifdef CLONE_WRITE
+       fprintf(stderr, "\t-fulltoc     Retrieve the full TOC\n");
+       fprintf(stderr, "\t-clone               Retrieve the full TOC and all data\n");
+#endif
+       fprintf(stderr, "\ttimeout=#    set the default SCSI command timeout to #.\n");
+       fprintf(stderr, "\tdebug=#,-d   Set to # or increment misc debug level\n");
+       fprintf(stderr, "\tkdebug=#,kd=#        do Kernel debugging\n");
+       fprintf(stderr, "\t-quiet,-q    be more quiet in error retry mode\n");
+       fprintf(stderr, "\t-verbose,-v  increment general verbose level by one\n");
+       fprintf(stderr, "\t-Verbose,-V  increment SCSI command transport verbose level by one\n");
+       fprintf(stderr, "\t-silent,-s   do not print status of failed SCSI commands\n");
+       fprintf(stderr, "\t-scanbus     scan the SCSI bus and exit\n");
+       fprintf(stderr, "\t-noerror     do not abort on error\n");
+#ifdef CLONE_WRITE
+       fprintf(stderr, "\t-nocorr              do not apply error correction in drive\n");
+#endif
+       fprintf(stderr, "\t-notrunc     do not truncate outputfile in read mode\n");
+       fprintf(stderr, "\tretries=#    set retry count (default is %d)\n", retries);
+       fprintf(stderr, "\t-overhead    meter SCSI command overhead times\n");
+       fprintf(stderr, "\tmeshpoints=# print read-speed at # locations\n");
+       fprintf(stderr, "\t-factor              try to use speed factor with meshpoints=# if possible\n");
+       fprintf(stderr, "\n");
+       fprintf(stderr, "sectors=0-0 will read nothing, sectors=0-1 will read one sector starting from 0\n");
+       exit(ret);
+}      
+
+/* CSTYLED */
+char   opts[]   = "debug#,d+,kdebug#,kd#,timeout#,quiet,q,verbose+,v+,Verbose+,V+,x+,xd#,silent,s,help,h,version,scanbus,dev*,sectors*,w,c2scan,fulltoc,clone,noerror,nocorr,notrunc,retries#,factor,f*,speed#,ts&,overhead,meshpoints#";
+
+int
+main(int argc, char *argv[])
+{
+       char    *dev = NULL;
+       int     fcount;
+       int     cac;
+       char    * const *cav;
+       int     scsibus = -1;
+       int     target  = -1;
+       int     lun     = -1;
+       int     silent  = 0;
+       int     verbose = 0;
+       int     kdebug  = 0;
+       int     debug   = 0;
+       int     deftimeout = 40;
+       int     pversion = 0;
+       int     scanbus = 0;
+       int     speed   = -1;
+       int     dooverhead = 0;
+       SCSI    *usalp;
+       char    *filename = NULL;
+       char    *sectors = NULL;
+
+       save_args(argc, argv);
+
+       cac = --argc;
+       cav = ++argv;
+
+       if (getallargs(&cac, &cav, opts,
+                       &debug, &debug,
+                       &kdebug, &kdebug,
+                       &deftimeout,
+                       &quiet, &quiet,
+                       &lverbose, &lverbose,
+                       &verbose, &verbose,
+                       &xdebug, &xdebug,
+                       &silent, &silent,
+                       &help, &help, &pversion,
+                       &scanbus, &dev, &sectors, &do_write,
+                       &c2scan,
+                       &fulltoc, &clonemode,
+                       &noerror, &nocorr,
+                       &notrunc, &retries, &do_factor, &filename,
+                       &speed, getnum, &Sbufsize,
+                       &dooverhead, &meshpoints) < 0) {
+               errmsgno(EX_BAD, "Bad flag: %s.\n", cav[0]);
+               usage(EX_BAD);
+       }
+       if (help)
+               usage(0);
+       if (pversion) {
+               printf("readcd %s is not what you see here. This line is only a fake for too clever\n"
+                               "GUIs and other frontend applications. In fact, this program is:\n", cdr_version);
+
+               printf("readom " CDRKIT_VERSION " (" HOST_SYSTEM ")\n"
+                               "Copyright (C) 1987, 1995-2006 Joerg Schilling\n"
+                               "Copyright (C) 2006 Cdrkit maintainers\n"
+                               "(modified version of <censored> -- "
+                               "don't bother Joerg Schilling with problems)\n");
+               exit(0);
+       }
+
+       fcount = 0;
+       cac = argc;
+       cav = argv;
+
+       while (getfiles(&cac, &cav, opts) > 0) {
+               fcount++;
+               if (fcount == 1) {
+                       if (*astoi(cav[0], &target) != '\0') {
+                               errmsgno(EX_BAD,
+                                       "Target '%s' is not a Number.\n",
+                                                               cav[0]);
+                               usage(EX_BAD);
+                               /* NOTREACHED */
+                       }
+               }
+               if (fcount == 2) {
+                       if (*astoi(cav[0], &lun) != '\0') {
+                               errmsgno(EX_BAD,
+                                       "Lun is '%s' not a Number.\n",
+                                                               cav[0]);
+                               usage(EX_BAD);
+                               /* NOTREACHED */
+                       }
+               }
+               if (fcount == 3) {
+                       if (*astoi(cav[0], &scsibus) != '\0') {
+                               errmsgno(EX_BAD,
+                                       "Scsibus is '%s' not a Number.\n",
+                                                               cav[0]);
+                               usage(EX_BAD);
+                               /* NOTREACHED */
+                       }
+               }
+               cac--;
+               cav++;
+       }
+/*fprintf(stderr, "dev: '%s'\n", dev);*/
+       if (!scanbus)
+               cdr_defaults(&dev, NULL, NULL, NULL);
+       if (debug) {
+               printf("dev: '%s'\n", dev);
+       }
+       if (!scanbus && dev == NULL &&
+           scsibus == -1 && (target == -1 || lun == -1)) {
+               errmsgno(EX_BAD, "No SCSI device specified.\n");
+               usage(EX_BAD);
+       }
+       if (dev || scanbus) {
+               char    errstr[80];
+
+               /*
+                * Call usal_remote() to force loading the remote SCSI transport
+                * library code that is located in librusal instead of the dummy
+                * remote routines that are located inside libusal.
+                */
+               usal_remote();
+               if (dev != NULL &&
+                   ((strncmp(dev, "HELP", 4) == 0) ||
+                   (strncmp(dev, "help", 4) == 0))) {
+                       usal_help(stderr);
+                       exit(0);
+               }
+               if ((usalp = usal_open(dev, errstr, sizeof (errstr), debug, lverbose)) == (SCSI *)0) {
+                       int     err = geterrno();
+
+                       errmsgno(err, "%s%sCannot open SCSI driver.\n", errstr, errstr[0]?". ":"");
+                       errmsgno(EX_BAD, "For possible targets try 'wodim -scanbus'.%s\n",
+                                               geteuid() ? " Make sure you are root.":"");
+                       errmsgno(EX_BAD, "For possible transport specifiers try 'wodim dev=help'.\n");
+                       exit(err);
+               }
+       } else {
+               if (scsibus == -1 && target >= 0 && lun >= 0)
+                       scsibus = 0;
+
+               usalp = usal_smalloc();
+               usalp->debug = debug;
+               usalp->kdebug = kdebug;
+
+               usal_settarget(usalp, scsibus, target, lun);
+               if (usal__open(usalp, NULL) <= 0)
+                       comerr("Cannot open SCSI driver.\n");
+       }
+       usalp->silent = silent;
+       usalp->verbose = verbose;
+       usalp->debug = debug;
+       usalp->kdebug = kdebug;
+       usal_settimeout(usalp, deftimeout);
+
+       if (Sbufsize == 0)
+               Sbufsize = 256*1024L;
+       Sbufsize = usal_bufsize(usalp, Sbufsize);
+       if ((Sbuf = usal_getbuf(usalp, Sbufsize)) == NULL)
+               comerr("Cannot get SCSI I/O buffer.\n");
+
+#ifdef HAVE_PRIV_SET
+       is_suid = priv_ineffect(PRIV_FILE_DAC_READ) &&
+                   !priv_ineffect(PRIV_PROC_SETID);
+       /*
+        * Give up privs we do not need anymore.
+        * We no longer need:
+        *      file_dac_read,net_privaddr
+        * We still need:
+        *      sys_devices
+        */
+       priv_set(PRIV_OFF, PRIV_EFFECTIVE,
+               PRIV_FILE_DAC_READ, PRIV_NET_PRIVADDR, NULL);
+       priv_set(PRIV_OFF, PRIV_PERMITTED,
+               PRIV_FILE_DAC_READ, PRIV_NET_PRIVADDR, NULL);
+       priv_set(PRIV_OFF, PRIV_INHERITABLE,
+               PRIV_FILE_DAC_READ, PRIV_NET_PRIVADDR, PRIV_SYS_DEVICES, NULL);
+#endif
+       /*
+        * This is only for OS that do not support fine grained privs.
+        */
+       if (!is_suid)
+               is_suid = geteuid() != getuid();
+       /*
+        * We don't need root privilleges anymore.
+        */
+#ifdef HAVE_SETREUID
+       if (setreuid(-1, getuid()) < 0)
+#else
+#ifdef HAVE_SETEUID
+       if (seteuid(getuid()) < 0)
+#else
+       if (setuid(getuid()) < 0)
+#endif
+#endif
+               comerr("Panic cannot set back effective uid.\n");
+
+       /* code to use SCG */
+
+       if (scanbus) {
+               select_target(usalp, stdout);
+               exit(0);
+       }
+       do_inquiry(usalp, FALSE);
+       allow_atapi(usalp, TRUE);    /* Try to switch to 10 byte mode cmds */
+       if (is_mmc(usalp, NULL, NULL)) {
+               int     rspeed;
+               int     wspeed;
+               /*
+                * At this point we know that we have a SCSI-3/mmc compliant drive.
+                * Unfortunately ATAPI drives violate the SCSI spec in returning
+                * a response data format of '1' which from the SCSI spec would
+                * tell us not to use the "PF" bit in mode select. As ATAPI drives
+                * require the "PF" bit to be set, we 'correct' the inquiry data.
+                */
+               if (usalp->inq->data_format < 2)
+                       usalp->inq->data_format = 2;
+
+               if ((rspeed = get_curprofile(usalp)) >= 0) {
+                       if (rspeed >= 0x08 && rspeed < 0x10)
+                               is_cdrom = TRUE;
+                       if (rspeed >= 0x10 && rspeed < 0x20)
+                               is_dvd = TRUE;
+               } else {
+                       BOOL    dvd;
+
+                       mmc_check(usalp, NULL, NULL, NULL, NULL, &dvd, NULL);
+                       if (dvd == FALSE) {
+                               is_cdrom = TRUE;
+                       } else {
+                               char    xb[32];
+
+                               if (read_dvd_structure(usalp, (caddr_t)xb, 32, 0, 0, 0) >= 0) {
+                               /*
+                                * If read DVD structure is supported and works, then
+                                * we must have a DVD media in the drive. Signal to
+                                * use the DVD driver.
+                                */
+                                       is_dvd = TRUE;
+                               } else {
+                                       is_cdrom = TRUE;
+                               }
+                       }
+               }
+
+               if (speed > 0)
+                       speed *= 177;
+               if (speed > 0xFFFF || speed < 0)
+                       speed = 0xFFFF;
+               scsi_set_speed(usalp, speed, speed, ROTCTL_CLV);
+               if (scsi_get_speed(usalp, &rspeed, &wspeed) >= 0) {
+                       fprintf(stderr, "Read  speed: %5d kB/s (CD %3dx, DVD %2dx).\n",
+                               rspeed, rspeed/176, rspeed/1385);
+                       fprintf(stderr, "Write speed: %5d kB/s (CD %3dx, DVD %2dx).\n",
+                               wspeed, wspeed/176, wspeed/1385);
+               }
+       }
+       exargs.usalp       = usalp;
+       exargs.old_secsize = -1;
+/*     exargs.flags       = flags;*/
+       exargs.oerr[2]     = 0;
+
+       /*
+        * Install exit handler before we change the drive status.
+        */
+       on_comerr(exscsi, &exargs);
+       signal(SIGINT, intr);
+       signal(SIGTERM, intr);
+
+       if (dooverhead) {
+               ovtime(usalp);
+               comexit(0);
+       }
+
+       if (is_suid) {
+               if (usalp->inq->type != INQ_ROMD)
+                       comerrno(EX_BAD, "Not root. Will only work on CD-ROM in suid/priv mode\n");
+       }
+
+       if (filename || sectors || c2scan || meshpoints || fulltoc || clonemode) {
+               dorw(usalp, filename, sectors);
+       } else {
+               doit(usalp);
+       }
+       comexit(0);
+       return (0);
+}
+
+/*
+ * XXX Leider kann man vim Signalhandler keine SCSI Kommandos verschicken
+ * XXX da meistens das letzte SCSI Kommando noch laeuft.
+ * XXX Eine Loesung waere ein Abort Callback in SCSI *.
+ */
+static void
+intr(int sig)
+{
+       didintr++;
+       exsig = sig;
+/*     comexit(sig);*/
+}
+
+/* ARGSUSED */
+static void
+exscsi(int excode, void *arg)
+{
+       struct exargs   *exp = (struct exargs *)arg;
+               int     i;
+
+       /*
+        * Try to restore the old sector size.
+        */
+       if (exp != NULL && exp->exflags == 0) {
+               for (i = 0; i < 10*100; i++) {
+                       if (!exp->usalp->running)
+                               break;
+                       if (i == 10) {
+                               errmsgno(EX_BAD,
+                                       "Waiting for current SCSI command to finish.\n");
+                       }
+                       usleep(100000);
+               }
+
+               if (!exp->usalp->running) {
+                       if (exp->oerr[2] != 0) {
+                               domode(exp->usalp, exp->oerr[0], exp->oerr[1]);
+                       }
+                       if (exp->old_secsize > 0 && exp->old_secsize != 2048)
+                               select_secsize(exp->usalp, exp->old_secsize);
+               }
+               exp->exflags++; /* Make sure that it only get called once */
+       }
+}
+
+static void
+excdr(int excode, void *arg)
+{
+       exscsi(excode, arg);
+
+#ifdef needed
+       /* Do several other restores/statistics here (see cdrecord.c) */
+#endif
+}
+
+/*
+ * Return milliseconds since start time.
+ */
+static int
+prstats(void)
+{
+       int     sec;
+       int     usec;
+       int     tmsec;
+
+       if (gettimeofday(&stoptime, (struct timezone *)0) < 0)
+               comerr("Cannot get time\n");
+
+       sec = stoptime.tv_sec - starttime.tv_sec;
+       usec = stoptime.tv_usec - starttime.tv_usec;
+       tmsec = sec*1000 + usec/1000;
+#ifdef lint
+       tmsec = tmsec;  /* Bisz spaeter */
+#endif
+       if (usec < 0) {
+               sec--;
+               usec += 1000000;
+       }
+
+       fprintf(stderr, "Time total: %d.%03dsec\n", sec, usec/1000);
+       return (1000*sec + (usec / 1000));
+}
+
+/*
+ * Return milliseconds since start time, but be silent this time.
+ */
+static int
+prstats_silent(void)
+{
+       int     sec;
+       int     usec;
+       int     tmsec;
+
+       if (gettimeofday(&stoptime, (struct timezone *)0) < 0)
+               comerr("Cannot get time\n");
+
+       sec = stoptime.tv_sec - starttime.tv_sec;
+       usec = stoptime.tv_usec - starttime.tv_usec;
+       tmsec = sec*1000 + usec/1000;
+#ifdef lint
+       tmsec = tmsec;  /* Bisz spaeter */
+#endif
+       if (usec < 0) {
+               sec--;
+               usec += 1000000;
+       }
+
+       return (1000*sec + (usec / 1000));
+}
+
+static void
+dorw(SCSI *usalp, char *filename, char *sectors)
+{
+       parm_t  params;
+       char    *p = NULL;
+
+       params.start = 0;
+       params.end = -1;
+       params.sptr = -1;
+       params.askrange = FALSE;
+       params.name = NULL;
+
+       if (filename)
+               params.name = filename;
+       if (meshpoints > 0) {
+               if (params.name == NULL)
+                       params.name = "/dev/null";
+       }
+       if (sectors)
+               p = astol(sectors, &params.start);
+       if (p && *p == '-')
+               p = astol(++p, &params.end);
+       if (p && *p != '\0')
+               comerrno(EX_BAD, "Not a valid sector range '%s'\n", sectors);
+
+       if (!wait_unit_ready(usalp, 60))
+               comerrno(EX_BAD, "Device not ready.\n");
+
+#ifdef CLONE_WRITE
+       if (fulltoc) {
+               if (params.name == NULL)
+                       params.name = "/dev/null";
+               read_ftoc(usalp, &params, FALSE);
+       } else if (clonemode) {
+               if (!is_mmc(usalp, NULL, NULL))
+                       comerrno(EX_BAD, "Unsupported device for clone mode.\n");
+               noerror = TRUE;
+               if (retries == MAX_RETRY)
+                       retries = 10;
+               if (params.name == NULL)
+                       params.name = "/dev/null";
+
+               if (read_ftoc(usalp, &params, TRUE) < 0)
+                       comerrno(EX_BAD, "Read fulltoc problems.\n");
+               readcd_disk(usalp, &params);
+       } else
+#endif
+       if (c2scan) {
+               noerror = TRUE;
+               if (retries == MAX_RETRY)
+                       retries = 10;
+               if (params.name == NULL)
+                       params.name = "/dev/null";
+               readc2_disk(usalp, &params);
+       } else if (do_write)
+               write_disk(usalp, &params);
+       else
+               read_disk(usalp, &params);
+}
+
+static void
+doit(SCSI *usalp)
+{
+       int     i = 0;
+       parm_t  params;
+
+       params.start = 0;
+       params.end = -1;
+       params.sptr = -1;
+       params.askrange = TRUE;
+       params.name = "/dev/null";
+
+       for (;;) {
+               if (!wait_unit_ready(usalp, 60))
+                       comerrno(EX_BAD, "Device not ready.\n");
+
+               printf("0:read 1:veri   2:erase   3:read buffer 4:cache 5:ovtime 6:cap\n");
+               printf("7:wne  8:floppy 9:verify 10:checkcmds  11:read disk 12:write disk\n");
+               printf("13:scsireset 14:seektest 15: readda 16: reada 17: c2err\n");
+#ifdef CLONE_WRITE
+               printf("18:readom 19: lin 20: full toc\n");
+#endif
+
+               getint("Enter selection:", &i, 0, 20);
+               if (didintr)
+                       return;
+
+               switch (i) {
+
+               case 5:         ovtime(usalp);          break;
+               case 11:        read_disk(usalp, 0);    break;
+               case 12:        write_disk(usalp, 0);   break;
+               case 15:        ra(usalp);              break;
+/*             case 16:        reada_disk(usalp, 0, 0);        break;*/
+               case 17:        readc2_disk(usalp, &params);    break;
+#ifdef CLONE_WRITE
+               case 18:        readcd_disk(usalp, 0);  break;
+               case 19:        read_lin(usalp, 0);     break;
+               case 20:        read_ftoc(usalp, 0, FALSE);     break;
+#endif
+               }
+       }
+}
+
+static void
+read_disk(SCSI *usalp, parm_t *parmp)
+{
+       rparm_t rp;
+
+       read_capacity(usalp);
+       print_capacity(usalp, stderr);
+
+       rp.errors = 0;
+       rp.c2_errors = 0;
+       rp.c2_maxerrs = 0;
+       rp.c2_errsecs = 0;
+       rp.c2_badsecs = 0;
+       rp.secsize = usalp->cap->c_bsize;
+
+       read_generic(usalp, parmp, fread_data, &rp, fdata_null);
+}
+
+#ifdef CLONE_WRITE
+static void
+readcd_disk(SCSI *usalp, parm_t *parmp)
+{
+       rparm_t rp;
+       int     osecsize = 2048;
+       int     oerr = 0;
+       int     oretr = 10;
+       int     (*funcp)(SCSI *_usalp, rparm_t *_rp, caddr_t bp, long addr, int cnt);
+
+       usalp->silent++;
+       if (read_capacity(usalp) >= 0)
+               osecsize = usalp->cap->c_bsize;
+       usalp->silent--;
+       if (osecsize != 2048)
+               select_secsize(usalp, 2048);
+
+       read_capacity(usalp);
+       print_capacity(usalp, stderr);
+
+       rp.errors = 0;
+       rp.c2_errors = 0;
+       rp.c2_maxerrs = 0;
+       rp.c2_errsecs = 0;
+       rp.c2_badsecs = 0;
+       rp.secsize = 2448;
+       rp.ismmc = is_mmc(usalp, NULL, NULL);
+       funcp = fread_2448;
+
+       wait_unit_ready(usalp, 10);
+       if (fread_2448(usalp, &rp, Sbuf, 0, 0) < 0) {
+               errmsgno(EX_BAD, "read 2448 failed\n");
+               if (rp.ismmc &&
+                   fread_2448_16(usalp, &rp, Sbuf, 0, 0) >= 0) {
+                       errmsgno(EX_BAD, "read 2448_16 : OK\n");
+
+                       funcp = fread_2448_16;
+               }
+       }
+
+       oldmode(usalp, &oerr, &oretr);
+       exargs.oerr[0] = oerr;
+       exargs.oerr[1] = oretr;
+       exargs.oerr[2] = 0xFF;
+       if (parmp == NULL)              /* XXX Nur am Anfang!!! */
+               domode(usalp, -1, -1);
+       else
+               domode(usalp, nocorr?0x21:0x20, 10);
+
+       read_generic(usalp, parmp, funcp, &rp, fdata_null);
+       if (osecsize != 2048)
+               select_secsize(usalp, osecsize);
+       domode(usalp, oerr, oretr);
+}
+
+/* ARGSUSED */
+static void
+read_lin(SCSI *usalp, parm_t *parmp)
+{
+       parm_t  parm;
+       rparm_t rp;
+
+       read_capacity(usalp);
+       print_capacity(usalp, stderr);
+
+       parm.start = ULONG_C(0xF0000000);
+       parm.end =   ULONG_C(0xFF000000);
+       parm.name = "DDD";
+
+       rp.errors = 0;
+       rp.c2_errors = 0;
+       rp.c2_maxerrs = 0;
+       rp.c2_errsecs = 0;
+       rp.c2_badsecs = 0;
+       rp.secsize = 2448;
+       rp.ismmc = is_mmc(usalp, NULL, NULL);
+       domode(usalp, -1, -1);
+       read_generic(usalp, &parm, fread_lin, &rp, fdata_null);
+}
+
+static int
+read_secheader(SCSI *usalp, long addr)
+{
+       rparm_t rp;
+       int     osecsize = 2048;
+       int     ret = 0;
+
+       usalp->silent++;
+       if (read_capacity(usalp) >= 0)
+               osecsize = usalp->cap->c_bsize;
+       usalp->silent--;
+       if (osecsize != 2048)
+               select_secsize(usalp, 2048);
+
+       read_capacity(usalp);
+
+       rp.errors = 0;
+       rp.c2_errors = 0;
+       rp.c2_maxerrs = 0;
+       rp.c2_errsecs = 0;
+       rp.c2_badsecs = 0;
+       rp.secsize = 2352;
+       rp.ismmc = is_mmc(usalp, NULL, NULL);
+
+       wait_unit_ready(usalp, 10);
+
+       fillbytes(Sbuf, 2352, '\0');
+       if (fread_2352(usalp, &rp, Sbuf, addr, 1) < 0) {
+               ret = -1;
+       }
+       if (osecsize != 2048)
+               select_secsize(usalp, osecsize);
+       return (ret);
+}
+
+/* ARGSUSED */
+static int
+read_ftoc(SCSI *usalp, parm_t *parmp, BOOL do_sectype)
+{
+       FILE    *f;
+       int     i;
+       char    filename[1024];
+       struct  tocheader *tp;
+       char    *p;
+       char    xb[256];
+       int     len;
+       char    xxb[10000];
+
+
+       strcpy(filename, "toc.dat");
+       if (strcmp(parmp->name, "/dev/null") != 0) {
+
+               len = strlen(parmp->name);
+               if (len > (sizeof (filename)-5)) {
+                       len = sizeof (filename)-5;
+               }
+               snprintf(filename, sizeof (filename), "%.*s.toc", len, parmp->name);
+       }
+
+       tp = (struct tocheader *)xb;
+
+       fillbytes((caddr_t)xb, sizeof (xb), '\0');
+       if (read_toc(usalp, xb, 0, sizeof (struct tocheader), 0, FMT_FULLTOC) < 0) {
+               if (usalp->silent == 0 || usalp->verbose > 0)
+                       errmsgno(EX_BAD, "Cannot read TOC header\n");
+               return (-1);
+       }
+       len = a_to_u_2_byte(tp->len) + sizeof (struct tocheader)-2;
+       fprintf(stderr, "TOC len: %d. First Session: %d Last Session: %d.\n", len, tp->first, tp->last);
+
+       if (read_toc(usalp, xxb, 0, len, 0, FMT_FULLTOC) < 0) {
+               if (len & 1) {
+                       /*
+                        * Work around a bug in some operating systems that do not
+                        * handle odd byte DMA correctly for ATAPI drives.
+                        */
+                       wait_unit_ready(usalp, 30);
+                       read_toc(usalp, xb, 0, sizeof (struct tocheader), 0, FMT_FULLTOC);
+                       wait_unit_ready(usalp, 30);
+                       if (read_toc(usalp, xxb, 0, len+1, 0, FMT_FULLTOC) >= 0) {
+                               goto itworked;
+                       }
+               }
+               if (usalp->silent == 0)
+                       errmsgno(EX_BAD, "Cannot read full TOC\n");
+               return (-1);
+       }
+
+itworked:
+       f = fileopen(filename, "wctb");
+
+       if (f == NULL)
+               comerr("Cannot open '%s'.\n", filename);
+       filewrite(f, xxb, len);
+       if (do_sectype)
+               read_sectypes(usalp, f);
+       fflush(f);
+       fclose(f);
+
+       p = &xxb[4];
+       for (; p < &xxb[len]; p += 11) {
+               for (i = 0; i < 11; i++)
+                       fprintf(stderr, "%02X ", p[i] & 0xFF);
+               fprintf(stderr, "\n");
+       }
+       /*
+        * List all lead out start times to give information about multi
+        * session disks.
+        */
+       p = &xxb[4];
+       for (; p < &xxb[len]; p += 11) {
+               if ((p[3] & 0xFF) == 0xA2) {
+                       fprintf(stderr, "Lead out %d: %ld\n", p[0], msf_to_lba(p[8], p[9], p[10], TRUE));
+               }
+       }
+       return (0);
+}
+
+static void
+read_sectypes(SCSI *usalp, FILE *f)
+{
+       char    sect;
+
+       sect = SECT_AUDIO;
+       get_sectype(usalp, 4, &sect);
+       if (f != NULL)
+               filewrite(f, &sect, 1);
+       if (xdebug)
+               usal_prbytes("sec 0", (Uchar *)Sbuf, 16);
+
+       sect = SECT_AUDIO;
+       get_sectype(usalp, usalp->cap->c_baddr-4, &sect);
+       if (f != NULL)
+               filewrite(f, &sect, 1);
+       if (xdebug) {
+               usal_prbytes("sec E", (Uchar *)Sbuf, 16);
+               fprintf(stderr, "baddr: %ld\n", (long)usalp->cap->c_baddr);
+       }
+}
+
+static void
+get_sectype(SCSI *usalp, long addr, char *st)
+{
+       char    *synchdr = "\0\377\377\377\377\377\377\377\377\377\377\0";
+       int     sectype = SECT_AUDIO;
+       int     i;
+       long    raddr = addr;
+#define        _MAX_TRY_       20
+
+       usalp->silent++;
+       for (i = 0; i < _MAX_TRY_ && read_secheader(usalp, raddr) < 0; i++) {
+               if (addr == 0)
+                       raddr++;
+               else
+                       raddr--;
+       }
+       usalp->silent--;
+       if (i >= _MAX_TRY_) {
+               fprintf(stderr, "Sectype (%ld) is CANNOT\n", addr);
+               return;
+       } else if (i > 0) {
+               fprintf(stderr, "Sectype (%ld) needed %d retries\n", addr, i);
+       }
+#undef _MAX_TRY_
+
+       if (cmpbytes(Sbuf, synchdr, 12) < 12) {
+               if (xdebug)
+                       fprintf(stderr, "Sectype (%ld) is AUDIO\n", addr);
+               if (st)
+                       *st = SECT_AUDIO;
+               return;
+       }
+       if (xdebug)
+               fprintf(stderr, "Sectype (%ld) is DATA\n", addr);
+       if (Sbuf[15] == 0) {
+               if (xdebug)
+                       fprintf(stderr, "Sectype (%ld) is MODE 0\n", addr);
+               sectype = SECT_MODE_0;
+
+       } else if (Sbuf[15] == 1) {
+               if (xdebug)
+                       fprintf(stderr, "Sectype (%ld) is MODE 1\n", addr);
+               sectype = SECT_ROM;
+
+       } else if (Sbuf[15] == 2) {
+               if (xdebug)
+                       fprintf(stderr, "Sectype (%ld) is MODE 2\n", addr);
+
+               if ((Sbuf[16+2]  & 0x20) == 0 &&
+                   (Sbuf[16+4+2]  & 0x20) == 0) {
+                       if (xdebug)
+                               fprintf(stderr, "Sectype (%ld) is MODE 2 form 1\n", addr);
+                       sectype = SECT_MODE_2_F1;
+
+               } else if ((Sbuf[16+2]  & 0x20) != 0 &&
+                   (Sbuf[16+4+2]  & 0x20) != 0) {
+                       if (xdebug)
+                               fprintf(stderr, "Sectype (%ld) is MODE 2 form 2\n", addr);
+                       sectype = SECT_MODE_2_F2;
+               } else {
+                       if (xdebug)
+                               fprintf(stderr, "Sectype (%ld) is MODE 2 formless\n", addr);
+                       sectype = SECT_MODE_2;
+               }
+       } else {
+               fprintf(stderr, "Sectype (%ld) is UNKNOWN\n", addr);
+       }
+       if (st)
+               *st = sectype;
+       if (xdebug)
+               fprintf(stderr, "Sectype (%ld) is 0x%02X\n", addr, sectype);
+}
+
+#endif /* CLONE_WRITE */
+
+char   zeroblk[512];
+
+static void
+readc2_disk(SCSI *usalp, parm_t *parmp)
+{
+       rparm_t rp;
+       int     osecsize = 2048;
+       int     oerr = 0;
+       int     oretr = 10;
+
+       usalp->silent++;
+       if (read_capacity(usalp) >= 0)
+               osecsize = usalp->cap->c_bsize;
+       usalp->silent--;
+       if (osecsize != 2048)
+               select_secsize(usalp, 2048);
+
+       read_capacity(usalp);
+       print_capacity(usalp, stderr);
+
+       rp.errors = 0;
+       rp.c2_errors = 0;
+       rp.c2_maxerrs = 0;
+       rp.c2_errsecs = 0;
+       rp.c2_badsecs = 0;
+       rp.secsize = 2352 + 294;
+       rp.ismmc = is_mmc(usalp, NULL, NULL);
+
+       oldmode(usalp, &oerr, &oretr);
+       exargs.oerr[0] = oerr;
+       exargs.oerr[1] = oretr;
+       exargs.oerr[2] = 0xFF;
+       domode(usalp, 0x21, 10);
+
+
+       read_generic(usalp, parmp, fread_c2, &rp, fdata_c2);
+       if (osecsize != 2048)
+               select_secsize(usalp, osecsize);
+       domode(usalp, oerr, oretr);
+
+       printf("Total of %d hard read errors.\n", rp.errors);
+       printf("C2 errors total: %d bytes in %d sectors on disk\n", rp.c2_errors, rp.c2_errsecs);
+       printf("C2 errors rate: %f%% \n", (100.0*rp.c2_errors)/usalp->cap->c_baddr/2352);
+       printf("C2 errors on worst sector: %d, sectors with 100+ C2 errors: %d\n", rp.c2_maxerrs, rp.c2_badsecs);
+}
+
+/* ARGSUSED */
+static int
+fread_data(SCSI *usalp, rparm_t *rp, caddr_t bp, long addr, int cnt)
+{
+       return (read_g1(usalp, bp, addr, cnt));
+}
+
+#ifdef CLONE_WRITE
+static int
+fread_2448(SCSI *usalp, rparm_t *rp, caddr_t bp, long addr, int cnt)
+{
+       if (rp->ismmc) {
+               return (read_cd(usalp, bp, addr, cnt, rp->secsize,
+                       /* Sync + all headers + user data + EDC/ECC */
+                       (1 << 7 | 3 << 5 | 1 << 4 | 1 << 3),
+                       /* plus all subchannels RAW */
+                       1));
+       } else {
+               return (read_da(usalp, bp, addr, cnt, rp->secsize,
+                       /* Sync + all headers + user data + EDC/ECC + all subch */
+                       0x02));
+       }
+}
+
+static int
+fread_2448_16(SCSI *usalp, rparm_t *rp, caddr_t bp, long addr, int cnt)
+{
+
+       if (rp->ismmc) {
+               track_t trackdesc;
+               int     ret;
+               int     i;
+               char    *p;
+
+               trackdesc.isecsize = 2368;
+               trackdesc.secsize = 2448;
+               ret = read_cd(usalp, bp, addr, cnt, 2368,
+                       /* Sync + all headers + user data + EDC/ECC */
+                       (1 << 7 | 3 << 5 | 1 << 4 | 1 << 3),
+                       /* subchannels P/Q */
+                       2);
+               if (ret < 0)
+                       return (ret);
+
+               scatter_secs(&trackdesc, bp, cnt);
+               for (i = 0, p = bp+2352; i < cnt; i++) {
+#ifdef more_than_q_sub
+                       if ((p[15] & 0x80) != 0)
+                               printf("P");
+#endif
+                       /*
+                        * As the drives don't return P-sub, we check
+                        * whether the index equals 0.
+                        */
+                       qpto96((Uchar *)p, (Uchar *)p, p[2] == 0);
+                       p += 2448;
+               }
+               return (ret);
+       } else {
+               comerrno(EX_BAD, "Cannot fread_2448_16 on non MMC drives\n");
+
+               return (read_da(usalp, bp, addr, cnt, rp->secsize,
+                       /* Sync + all headers + user data + EDC/ECC + all subch */
+                       0x02));
+       }
+}
+
+static int
+fread_2352(SCSI *usalp, rparm_t *rp, caddr_t bp, long addr, int cnt)
+{
+       if (rp->ismmc) {
+               return (read_cd(usalp, bp, addr, cnt, rp->secsize,
+                       /* Sync + all headers + user data + EDC/ECC */
+                       (1 << 7 | 3 << 5 | 1 << 4 | 1 << 3),
+                       /* NO subchannels */
+                       0));
+       } else {
+               comerrno(EX_BAD, "Cannot fread_2352 on non MMC drives\n");
+
+               return (read_da(usalp, bp, addr, cnt, rp->secsize,
+                       /* Sync + all headers + user data + EDC/ECC + all subch */
+                       0x02));
+       }
+}
+
+static int
+fread_lin(SCSI *usalp, rparm_t *rp, caddr_t bp, long addr, int cnt)
+{
+       if (addr != ULONG_C(0xF0000000))
+               addr = ULONG_C(0xFFFFFFFF);
+
+       return (read_cd(usalp, bp, addr, cnt, rp->secsize,
+               /* Sync + all headers + user data + EDC/ECC */
+               (1 << 7 | 3 << 5 | 1 << 4 | 1 << 3),
+               /* plus all subchannels RAW */
+               1));
+}
+#endif /* CLONE_WRITE */
+
+static int
+bits(int c)
+{
+       int     n = 0;
+
+       if (c & 0x01)
+               n++;
+       if (c & 0x02)
+               n++;
+       if (c & 0x04)
+               n++;
+       if (c & 0x08)
+               n++;
+       if (c & 0x10)
+               n++;
+       if (c & 0x20)
+               n++;
+       if (c & 0x40)
+               n++;
+       if (c & 0x80)
+               n++;
+       return (n);
+}
+
+static int
+bitidx(int c)
+{
+       if (c & 0x80)
+               return (0);
+       if (c & 0x40)
+               return (1);
+       if (c & 0x20)
+               return (2);
+       if (c & 0x10)
+               return (3);
+       if (c & 0x08)
+               return (4);
+       if (c & 0x04)
+               return (5);
+       if (c & 0x02)
+               return (6);
+       if (c & 0x01)
+               return (7);
+       return (-1);
+}
+
+static int
+fread_c2(SCSI *usalp, rparm_t *rp, caddr_t bp, long addr, int cnt)
+{
+       if (rp->ismmc) {
+               return (read_cd(usalp, bp, addr, cnt, rp->secsize,
+                       /* Sync + all headers + user data + EDC/ECC + C2 */
+/*                     (1 << 7 | 3 << 5 | 1 << 4 | 1 << 3 | 2 << 1),*/
+                       (1 << 7 | 3 << 5 | 1 << 4 | 1 << 3 | 1 << 1),
+                       /* without subchannels */
+                       0));
+       } else {
+               return (read_da(usalp, bp, addr, cnt, rp->secsize,
+                       /* Sync + all headers + user data + EDC/ECC + C2 */
+                       0x04));
+       }
+}
+
+/* ARGSUSED */
+static int
+fdata_null(rparm_t *rp, caddr_t bp, long addr, int cnt)
+{
+       return (0);
+}
+
+static int
+fdata_c2(rparm_t *rp, caddr_t bp, long addr, int cnt)
+{
+       int     i;
+       int     j;
+       int     k;
+       char    *p;
+
+       p = &bp[2352];
+
+       for (i = 0; i < cnt; i++, p += (2352+294)) {
+/*             usal_prbytes("XXX ", p, 294);*/
+               if ((j = cmpbytes(p, zeroblk, 294)) < 294) {
+                       printf("C2 in sector: %3ld first at byte: %4d (0x%02X)", addr+i,
+                               j*8 + bitidx(p[j]), p[j]&0xFF);
+                       for (j = 0, k = 0; j < 294; j++)
+                               k += bits(p[j]);
+                       printf(" total: %4d errors\n", k);
+/*                     usal_prbytes("XXX ", p, 294);*/
+                       rp->c2_errors += k;
+                       if (k > rp->c2_maxerrs)
+                               rp->c2_maxerrs = k;
+                       rp->c2_errsecs++;
+                       if (k >= 100)
+                               rp->c2_badsecs += 1;
+               }
+       }
+       return (0);
+}
+
+#ifdef used
+static int
+read_scsi_g1(SCSI *usalp, caddr_t bp, long addr, int cnt)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->addr = bp;
+/*     scmd->size = cnt*512;*/
+       scmd->size = cnt*usalp->cap->c_bsize;
+       scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
+       scmd->cdb_len = SC_G1_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+       scmd->cdb.g1_cdb.cmd = 0x28;
+       scmd->cdb.g1_cdb.lun = usal_lun(usalp);
+       g1_cdbaddr(&scmd->cdb.g1_cdb, addr);
+       g1_cdblen(&scmd->cdb.g1_cdb, cnt);
+
+       usalp->cmdname = "read extended";
+
+       return (usal_cmd(usalp));
+}
+#endif
+
+#define        G0_MAXADDR      0x1FFFFFL
+
+int
+write_scsi(SCSI *usalp, caddr_t bp, long addr, int cnt)
+{
+       if (addr <= G0_MAXADDR)
+               return (write_g0(usalp, bp, addr, cnt));
+       else
+               return (write_g1(usalp, bp, addr, cnt));
+}
+
+int
+write_g0(SCSI *usalp, caddr_t bp, long addr, int cnt)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       if (usalp->cap->c_bsize <= 0)
+               raisecond("capacity_not_set", 0L);
+
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->addr = bp;
+       scmd->size = cnt*usalp->cap->c_bsize;
+       scmd->flags = SCG_DISRE_ENA;
+       scmd->cdb_len = SC_G0_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+       scmd->cdb.g0_cdb.cmd = SC_WRITE;
+       scmd->cdb.g0_cdb.lun = usal_lun(usalp);
+       g0_cdbaddr(&scmd->cdb.g0_cdb, addr);
+       scmd->cdb.g0_cdb.count = (Uchar)cnt;
+
+       usalp->cmdname = "write_g0";
+
+       return (usal_cmd(usalp));
+}
+
+int
+write_g1(SCSI *usalp, caddr_t bp, long addr, int cnt)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       if (usalp->cap->c_bsize <= 0)
+               raisecond("capacity_not_set", 0L);
+
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->addr = bp;
+       scmd->size = cnt*usalp->cap->c_bsize;
+       scmd->flags = SCG_DISRE_ENA;
+       scmd->cdb_len = SC_G1_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+       scmd->cdb.g1_cdb.cmd = SC_EWRITE;
+       scmd->cdb.g1_cdb.lun = usal_lun(usalp);
+       g1_cdbaddr(&scmd->cdb.g1_cdb, addr);
+       g1_cdblen(&scmd->cdb.g1_cdb, cnt);
+
+       usalp->cmdname = "write_g1";
+
+       return (usal_cmd(usalp));
+}
+
+#ifdef used
+static void
+Xrequest_sense(SCSI *usalp)
+{
+       char    sense_buf[32];
+       struct  usal_cmd ocmd;
+       int     sense_count;
+       char    *cmdsave;
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       cmdsave = usalp->cmdname;
+
+       movebytes(scmd, &ocmd, sizeof (*scmd));
+
+       fillbytes((caddr_t)sense_buf, sizeof (sense_buf), '\0');
+
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->addr = (caddr_t)sense_buf;
+       scmd->size = sizeof (sense_buf);
+       scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
+       scmd->cdb_len = SC_G0_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+       scmd->cdb.g1_cdb.cmd = 0x3;
+       scmd->cdb.g1_cdb.lun = usal_lun(usalp);
+       scmd->cdb.g0_cdb.count = sizeof (sense_buf);
+
+       usalp->cmdname = "request sense";
+
+       usal_cmd(usalp);
+
+       sense_count = sizeof (sense_buf) - usal_getresid(usalp);
+       movebytes(&ocmd, scmd, sizeof (*scmd));
+       scmd->sense_count = sense_count;
+       movebytes(sense_buf, (Uchar *)&scmd->sense, scmd->sense_count);
+
+       usalp->cmdname = cmdsave;
+       usal_printerr(usalp);
+       usal_printresult(usalp);        /* XXX restore key/code in future */
+}
+#endif
+
+static int
+read_retry(SCSI *usalp, caddr_t bp, long addr, long cnt, 
+                         int (*rfunc)(SCSI *usalp, rparm_t *rp, caddr_t bp, long addr, int cnt), 
+                         rparm_t *rp)
+{
+/*     int     secsize = usalp->cap->c_bsize;*/
+       int     secsize = rp->secsize;
+       int     try = 0;
+       int     err;
+       char    dummybuf[8192];
+
+       if (secsize > sizeof (dummybuf)) {
+               errmsgno(EX_BAD, "Cannot retry, sector size %d too big.\n", secsize);
+               return (-1);
+       }
+
+       errmsgno(EX_BAD, "Retrying from sector %ld.\n", addr);
+       while (cnt > 0) {
+               fprintf(stderr, ".");
+
+               do {
+                       if (didintr)
+                               comexit(exsig);         /* XXX besseres Konzept?!*/
+                       wait_unit_ready(usalp, 120);
+                       if (try >= 10) {                /* First 10 retries without seek */
+                               if ((try % 8) == 0) {
+                                       fprintf(stderr, "+");   /* Read last sector */
+                                       usalp->silent++;
+                                       (*rfunc)(usalp, rp, dummybuf, usalp->cap->c_baddr, 1);
+                                       usalp->silent--;
+                               } else if ((try % 4) == 0) {
+                                       fprintf(stderr, "-");   /* Read first sector */
+                                       usalp->silent++;
+                                       (*rfunc)(usalp, rp, dummybuf, 0, 1);
+                                       usalp->silent--;
+                               } else {
+                                       fprintf(stderr, "~");   /* Read random sector */
+                                       usalp->silent++;
+                                       (*rfunc)(usalp, rp, dummybuf, choice(usalp->cap->c_baddr), 1);
+                                       usalp->silent--;
+                               }
+                               if (didintr)
+                                       comexit(exsig);         /* XXX besseres Konzept?!*/
+                               wait_unit_ready(usalp, 120);
+                       }
+                       if (didintr)
+                               comexit(exsig);         /* XXX besseres Konzept?!*/
+
+                       fillbytes(bp, secsize, 0);
+
+                       usalp->silent++;
+                       err = (*rfunc)(usalp, rp, bp, addr, 1);
+                       usalp->silent--;
+
+                       if (err < 0) {
+                               err = usalp->scmd->ux_errno;
+/*                             fprintf(stderr, "\n");*/
+/*                             errmsgno(err, "Cannot read source disk\n");*/
+                       } else {
+                               if (usal_getresid(usalp)) {
+                                       fprintf(stderr, "\nresid: %d\n", usal_getresid(usalp));
+                                       return (-1);
+                               }
+                               break;
+                       }
+               } while (++try < retries);
+
+               if (try >= retries) {
+                       fprintf(stderr, "\n");
+                       errmsgno(err, "Error on sector %ld not corrected. Total of %d errors.\n",
+                                       addr, ++rp->errors);
+
+                       if (usalp->silent <= 1 && lverbose > 0)
+                               usal_printerr(usalp);
+
+                       add_bad(addr);
+
+                       if (!noerror)
+                               return (-1);
+                       errmsgno(EX_BAD, "-noerror set, continuing ...\n");
+               } else {
+                       if (try >= maxtry)
+                               maxtry = try;
+
+                       if (try > 1) {
+                               fprintf(stderr, "\n");
+                               errmsgno(EX_BAD,
+                               "Error on sector %ld corrected after %d tries. Total of %d errors.\n",
+                                       addr, try, rp->errors);
+                       }
+               }
+               try = 0;
+               cnt -= 1;
+               addr += 1;
+               bp += secsize;
+       }
+       return (0);
+}
+
+static void
+read_generic(SCSI *usalp, parm_t *parmp, 
+                                int (*rfunc)(SCSI *usalp, rparm_t *rp, caddr_t bp, long addr, int cnt),
+                                rparm_t *rp,
+                                int (*dfunc)(rparm_t *rp, caddr_t bp, long addr, int cnt))
+{
+       char    filename[512];
+       char    *defname = NULL;
+       FILE    *f;
+       long    addr = 0L;
+       long    old_addr = 0L;
+       long    num;
+       long    end = 0L;
+       long    start = 0L;
+       long    cnt = 0L;
+       long    next_point = 0L;
+       long    secs_per_point = 0L;
+       double  speed;
+       int     msec;
+       int     old_msec = 0;
+       int     err = 0;
+       BOOL    askrange = FALSE;
+       BOOL    isrange = FALSE;
+       int     secsize = rp->secsize;
+       int     i = 0;
+
+       if (is_suid) {
+               if (usalp->inq->type != INQ_ROMD)
+                       comerrno(EX_BAD, "Not root. Will only read from CD in suid/priv mode\n");
+       }
+
+       if (parmp == NULL || parmp->askrange)
+               askrange = TRUE;
+       if (parmp != NULL && !askrange && (parmp->start <= parmp->end))
+               isrange = TRUE;
+
+       filename[0] = '\0';
+
+       usalp->silent++;
+       if (read_capacity(usalp) >= 0)
+               end = usalp->cap->c_baddr + 1;
+       usalp->silent--;
+
+       if ((end <= 0 && isrange) || (askrange && usal_yes("Ignore disk size? ")))
+               end = 10000000; /* Hack to read empty (e.g. blank=fast) disks */
+
+       if (parmp) {
+               if (parmp->name)
+                       defname = parmp->name;
+               if (defname != NULL) {
+                       fprintf(stderr, "Copy from SCSI (%d,%d,%d) disk to file '%s'\n",
+                                       usal_scsibus(usalp), usal_target(usalp), usal_lun(usalp),
+                                       defname);
+               }
+
+               addr = start = parmp->start;
+               if (parmp->end != -1 && parmp->end < end)
+                       end = parmp->end;
+               cnt = Sbufsize / secsize;
+       }
+
+       if (defname == NULL) {
+               defname = "disk.out";
+               fprintf(stderr, "Copy from SCSI (%d,%d,%d) disk to file\n",
+                                       usal_scsibus(usalp), usal_target(usalp), usal_lun(usalp));
+               fprintf(stderr, "Enter filename [%s]: ", defname); flush();
+               (void) rols_getline(filename, sizeof (filename));
+       }
+
+       if (askrange) {
+               addr = start;
+               getlong("Enter starting sector for copy:", &addr, start, end-1);
+/*             getlong("Enter starting sector for copy:", &addr, -300, end-1);*/
+               start = addr;
+       }
+
+       if (askrange) {
+               num = end - addr;
+               getlong("Enter number of sectors to copy:", &num, 1L, num);
+               end = addr + num;
+       }
+
+       if (askrange) {
+/* XXX askcnt */
+               cnt = Sbufsize / secsize;
+               getlong("Enter number of sectors per copy:", &cnt, 1L, cnt);
+       }
+
+       if (filename[0] == '\0')
+               strncpy(filename, defname, sizeof (filename));
+       filename[sizeof (filename)-1] = '\0';
+       if (streql(filename, "-")) {
+               f = stdout;
+#ifdef NEED_O_BINARY
+               setmode(STDOUT_FILENO, O_BINARY);
+#endif
+       } else if ((f = fileopen(filename, notrunc?"wcub":"wctub")) == NULL)
+               comerr("Cannot open '%s'.\n", filename);
+
+       fprintf(stderr, "end:  %8ld\n", end);
+       if (gettimeofday(&starttime, (struct timezone *)0) < 0)
+               comerr("Cannot get start time\n");
+
+       if (meshpoints > 0) {
+               if ((end-start) < meshpoints)
+                       secs_per_point = 1;
+               else
+                       secs_per_point = (end-start) / meshpoints;
+               next_point = start + secs_per_point;
+               old_addr = start;
+       }
+
+       for (; addr < end; addr += cnt) {
+               if (didintr)
+                       comexit(exsig);         /* XXX besseres Konzept?!*/
+
+               if ((addr + cnt) > end)
+                       cnt = end - addr;
+
+               if (meshpoints > 0) {
+                       if (addr > next_point) {
+
+                               msec = prstats_silent();
+                               if ((msec - old_msec) == 0)             /* Avoid division by zero */
+                                       msec = old_msec + 1;
+                               speed = ((addr - old_addr)/(1000.0/secsize)) / (0.001*(msec - old_msec));
+                               if (do_factor) {
+                                       if (is_cdrom)
+                                               speed /= 176.400;
+                                       else if (is_dvd)
+                                               speed /= 1385.0;
+                               }
+                               fprintf(stderr, "addr: %8ld cnt: %ld", addr, cnt);
+                               printf("%8ld %8.2f\n", addr, speed);
+                               fprintf(stderr, "\r");
+                               next_point += secs_per_point;
+                               old_addr = addr;
+                               old_msec = msec;
+                               i++;
+                               if (meshpoints < 100)
+                                       flush();
+                               else if (i % (meshpoints/100) == 0)
+                                       flush();
+                       }
+               }
+               fprintf(stderr, "addr: %8ld cnt: %ld\r", addr, cnt);
+
+               usalp->silent++;
+               if ((*rfunc)(usalp, rp, Sbuf, addr, cnt) < 0) {
+                       usalp->silent--;
+                       err = usalp->scmd->ux_errno;
+                       if (quiet) {
+                               fprintf(stderr, "\n");
+                       } else if (usalp->silent == 0) {
+                               usal_printerr(usalp);
+                       }
+                       errmsgno(err, "Cannot read source disk\n");
+
+                       if (read_retry(usalp, Sbuf, addr, cnt, rfunc, rp) < 0)
+                               goto out;
+               } else {
+                       usalp->silent--;
+                       if (usal_getresid(usalp)) {
+                               fprintf(stderr, "\nresid: %d\n", usal_getresid(usalp));
+                               goto out;
+                       }
+               }
+               (*dfunc)(rp, Sbuf, addr, cnt);
+               if (filewrite(f, Sbuf, cnt * secsize) < 0) {
+                       err = geterrno();
+                       fprintf(stderr, "\n");
+                       errmsgno(err, "Cannot write '%s'\n", filename);
+                       break;
+               }
+       }
+       fprintf(stderr, "addr: %8ld", addr);
+out:
+       fprintf(stderr, "\n");
+       msec = prstats();
+       if (msec == 0)          /* Avoid division by zero */
+               msec = 1;
+#ifdef OOO
+       fprintf(stderr, "Read %.2f kB at %.1f kB/sec.\n",
+               (double)(addr - start)/(1024.0/usalp->cap->c_bsize),
+               (double)((addr - start)/(1024.0/usalp->cap->c_bsize)) / (0.001*msec));
+#else
+       fprintf(stderr, "Read %.2f kB at %.1f kB/sec.\n",
+               (double)(addr - start)/(1024.0/secsize),
+               (double)((addr - start)/(1024.0/secsize)) / (0.001*msec));
+#endif
+       print_bad();
+}
+
+static void
+write_disk(SCSI *usalp, parm_t *parmp)
+{
+       char    filename[512];
+       char    *defname = "disk.out";
+       FILE    *f;
+       long    addr = 0L;
+       long    cnt;
+       long    amt;
+       long    end;
+       int     msec;
+       int     start;
+
+       if (is_suid)
+               comerrno(EX_BAD, "Not root. Will not write in suid/priv mode\n");
+
+       filename[0] = '\0';
+       if (read_capacity(usalp) >= 0) {
+               end = usalp->cap->c_baddr + 1;
+               print_capacity(usalp, stderr);
+       }
+
+       if (end <= 1)
+               end = 10000000; /* Hack to write empty disks */
+
+       if (parmp) {
+               if (parmp->name)
+                       defname = parmp->name;
+               fprintf(stderr, "Copy from file '%s' to SCSI (%d,%d,%d) disk\n",
+                                       defname,
+                                       usal_scsibus(usalp), usal_target(usalp), usal_lun(usalp));
+
+               addr = start = parmp->start;
+               if (parmp->end != -1 && parmp->end < end)
+                       end = parmp->end;
+               cnt = Sbufsize / usalp->cap->c_bsize;
+       } else {
+               fprintf(stderr, "Copy from file to SCSI (%d,%d,%d) disk\n",
+                                       usal_scsibus(usalp), usal_target(usalp), usal_lun(usalp));
+               fprintf(stderr, "Enter filename [%s]: ", defname); flush();
+               (void) rols_getline(filename, sizeof (filename));
+               fprintf(stderr, "Notice: reading from file always starts at file offset 0.\n");
+
+               getlong("Enter starting sector for copy:", &addr, 0L, end-1);
+               start = addr;
+               cnt = end - addr;
+               getlong("Enter number of sectors to copy:", &end, 1L, end);
+               end = addr + cnt;
+
+               cnt = Sbufsize / usalp->cap->c_bsize;
+               getlong("Enter number of sectors per copy:", &cnt, 1L, cnt);
+/*             fprintf(stderr, "end:  %8ld\n", end);*/
+       }
+
+       if (filename[0] == '\0')
+               strncpy(filename, defname, sizeof (filename));
+       filename[sizeof (filename)-1] = '\0';
+       if (streql(filename, "-")) {
+               f = stdin;
+#ifdef NEED_O_BINARY
+               setmode(STDIN_FILENO, O_BINARY);
+#endif
+       } else if ((f = fileopen(filename, "rub")) == NULL)
+               comerr("Cannot open '%s'.\n", filename);
+
+       fprintf(stderr, "end:  %8ld\n", end);
+       if (gettimeofday(&starttime, (struct timezone *)0) < 0)
+               comerr("Cannot get start time\n");
+
+       for (; addr < end; addr += cnt) {
+               if (didintr)
+                       comexit(exsig);         /* XXX besseres Konzept?!*/
+
+               if ((addr + cnt) > end)
+                       cnt = end - addr;
+
+               fprintf(stderr, "addr: %8ld cnt: %ld\r", addr, cnt);
+
+               if ((amt = fileread(f, Sbuf, cnt * usalp->cap->c_bsize)) < 0)
+                       comerr("Cannot read '%s'\n", filename);
+               if (amt == 0)
+                       break;
+               if ((amt / usalp->cap->c_bsize) < cnt)
+                       cnt = amt / usalp->cap->c_bsize;
+               if (write_scsi(usalp, Sbuf, addr, cnt) < 0)
+                       comerrno(usalp->scmd->ux_errno,
+                                       "Cannot write destination disk\n");
+       }
+       fprintf(stderr, "addr: %8ld\n", addr);
+       msec = prstats();
+       if (msec == 0)          /* Avoid division by zero */
+               msec = 1;
+       fprintf(stderr, "Wrote %.2f kB at %.1f kB/sec.\n",
+               (double)(addr - start)/(1024.0/usalp->cap->c_bsize),
+               (double)((addr - start)/(1024.0/usalp->cap->c_bsize)) / (0.001*msec));
+}
+
+static int
+choice(int n)
+{
+#if    defined(HAVE_DRAND48)
+       extern  double  drand48(void);
+
+       return (drand48() * n);
+#else
+#      if      defined(HAVE_RAND)
+       extern  int     rand(void);
+
+       return (rand() % n);
+#      else
+       return (0);
+#      endif
+#endif
+}
+
+static void
+ra(SCSI *usalp)
+{
+/*     char    filename[512];*/
+       FILE    *f;
+/*     long    addr = 0L;*/
+/*     long    cnt;*/
+/*     long    end;*/
+/*     int     msec;*/
+/*     int     start;*/
+/*     int     err = 0;*/
+
+       select_secsize(usalp, 2352);
+       read_capacity(usalp);
+       print_capacity(usalp, stderr);
+       fillbytes(Sbuf, 50*2352, 0);
+       if (read_g1(usalp, Sbuf, 0, 50) < 0)
+               errmsg("read CD\n");
+       f = fileopen("DDA", "wctb");
+/*     filewrite(f, Sbuf, 50 * 2352 - usal_getresid(usalp));*/
+       filewrite(f, Sbuf, 50 * 2352);
+       fclose(f);
+}
+
+#define        g5x_cdblen(cdb, len)    ((cdb)->count[0] = ((len) >> 16L)& 0xFF,\
+                               (cdb)->count[1] = ((len) >> 8L) & 0xFF,\
+                               (cdb)->count[2] = (len) & 0xFF)
+
+int
+read_da(SCSI *usalp, caddr_t bp, long addr, int cnt, int framesize, int subcode)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       if (usalp->cap->c_bsize <= 0)
+               raisecond("capacity_not_set", 0L);
+
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->addr = bp;
+       scmd->size = cnt*framesize;
+       scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
+       scmd->cdb_len = SC_G5_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+       scmd->cdb.g5_cdb.cmd = 0xd8;
+       scmd->cdb.g5_cdb.lun = usal_lun(usalp);
+       g5_cdbaddr(&scmd->cdb.g5_cdb, addr);
+       g5_cdblen(&scmd->cdb.g5_cdb, cnt);
+       scmd->cdb.g5_cdb.res10 = subcode;
+
+       usalp->cmdname = "read_da";
+
+       return (usal_cmd(usalp));
+}
+
+int
+read_cd(SCSI *usalp, caddr_t bp, long addr, int cnt, int framesize, int data, 
+                 int subch)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->addr = bp;
+       scmd->size = cnt*framesize;
+       scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
+       scmd->cdb_len = SC_G5_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+       scmd->cdb.g5_cdb.cmd = 0xBE;
+       scmd->cdb.g5_cdb.lun = usal_lun(usalp);
+       scmd->cdb.g5_cdb.res = 0;       /* expected sector type field ALL */
+       g5_cdbaddr(&scmd->cdb.g5_cdb, addr);
+       g5x_cdblen(&scmd->cdb.g5_cdb, cnt);
+
+       scmd->cdb.g5_cdb.count[3] = data & 0xFF;
+       scmd->cdb.g5_cdb.res10 = subch & 0x07;
+
+       usalp->cmdname = "read_cd";
+
+       return (usal_cmd(usalp));
+}
+
+static void
+oldmode(SCSI *usalp, int *errp, int *retrp)
+{
+       Uchar   mode[0x100];
+       Uchar   cmode[0x100];
+       Uchar   *p;
+       int     i;
+       int     len;
+
+       fillbytes(mode, sizeof (mode), '\0');
+       fillbytes(cmode, sizeof (cmode), '\0');
+
+       if (!get_mode_params(usalp, 0x01, "CD error recovery parameter",
+                       mode, (Uchar *)0, (Uchar *)cmode, (Uchar *)0, &len)) {
+               return;
+       }
+       if (xdebug)
+               usal_prbytes("Mode Sense Data", mode, len);
+
+       mode[0] = 0;
+       mode[2] = 0; /* ??? ist manchmal 0x80 */
+       p = mode;
+       p += mode[3] + 4;
+       *p &= 0x3F;
+
+       if (xdebug)
+               usal_prbytes("Mode page 1:", p, 0x10);
+
+       i = p[2];
+       if (errp != NULL)
+               *errp = i;
+
+       i = p[3];
+       if (retrp != NULL)
+               *retrp = i;
+}
+
+static void
+domode(SCSI *usalp, int err, int retr)
+{
+       Uchar   mode[0x100];
+       Uchar   cmode[0x100];
+       Uchar   *p;
+       int     i;
+       int     len;
+
+       fillbytes(mode, sizeof (mode), '\0');
+       fillbytes(cmode, sizeof (cmode), '\0');
+
+       if (!get_mode_params(usalp, 0x01, "CD error recovery parameter",
+                       mode, (Uchar *)0, (Uchar *)cmode, (Uchar *)0, &len)) {
+               return;
+       }
+       if (xdebug || (err == -1 && retr == -1)) {
+               usal_prbytes("Mode Sense Data", mode, len);
+       }
+
+       mode[0] = 0;
+       mode[2] = 0; /* ??? ist manchmal 0x80 */
+       p = mode;
+       p += mode[3] + 4;
+       *p &= 0x3F;
+
+       if (xdebug || (err == -1 && retr == -1))
+               usal_prbytes("Mode page 1:", p, 0x10);
+
+       i = p[2];
+       if (err == -1) {
+               getint("Error handling? ", &i, 0, 255);
+               p[2] = i;
+       } else {
+               if (xdebug)
+                       fprintf(stderr, "Error handling set from %02X to %02X\n",
+               p[2], err);
+               p[2] = err;
+       }
+
+       i = p[3];
+       if (retr == -1) {
+               getint("Retry count? ", &i, 0, 255);
+               p[3] = i;
+       } else {
+               if (xdebug)
+                       fprintf(stderr, "Retry count set from %d to %d\n",
+               p[3] & 0xFF, retr);
+               p[3] = retr;
+       }
+
+       if (xdebug || (err == -1 && retr == -1))
+               usal_prbytes("Mode Select Data", mode, len);
+       mode_select(usalp, mode, len, 0, usalp->inq->data_format >= 2);
+}
+
+
+/*--------------------------------------------------------------------------*/
+static void    qpto96(Uchar *sub, Uchar *subq, int dop);
+/*EXPORT       void    qpto96          __PR((Uchar *sub, Uchar *subq, int dop));*/
+/*
+ * Q-Sub auf 96 Bytes blähen und P-Sub addieren
+ *
+ * OUT: sub, IN: subqptr
+ */
+static void
+/*EXPORT void*/
+qpto96(Uchar *sub, Uchar *subqptr, int dop)
+{
+       Uchar   tmp[16];
+       Uchar   *p;
+       int     c;
+       int     i;
+
+       if (subqptr == sub) {
+               movebytes(subqptr, tmp, 12);
+               subqptr = tmp;
+       }
+       fillbytes(sub, 96, '\0');
+
+       /* CSTYLED */
+       if (dop) for (i = 0, p = sub; i < 96; i++) {
+               *p++ |= 0x80;
+       }
+       for (i = 0, p = sub; i < 12; i++) {
+               c = subqptr[i] & 0xFF;
+/*printf("%02X\n", c);*/
+               if (c & 0x80)
+                       *p++ |= 0x40;
+               else
+                       p++;
+               if (c & 0x40)
+                       *p++ |= 0x40;
+               else
+                       p++;
+               if (c & 0x20)
+                       *p++ |= 0x40;
+               else
+                       p++;
+               if (c & 0x10)
+                       *p++ |= 0x40;
+               else
+                       p++;
+               if (c & 0x08)
+                       *p++ |= 0x40;
+               else
+                       p++;
+               if (c & 0x04)
+                       *p++ |= 0x40;
+               else
+                       p++;
+               if (c & 0x02)
+                       *p++ |= 0x40;
+               else
+                       p++;
+               if (c & 0x01)
+                       *p++ |= 0x40;
+               else
+                       p++;
+       }
+}
+
+/*--------------------------------------------------------------------------*/
+
+static void
+ovtime(SCSI *usalp)
+{
+       register int    i;
+
+       usalp->silent++;
+       (void) test_unit_ready(usalp);
+       usalp->silent--;
+       if (test_unit_ready(usalp) < 0)
+               return;
+
+       printf("Doing 1000 'TEST UNIT READY' operations.\n");
+
+       if (gettimeofday(&starttime, (struct timezone *)0) < 0)
+               comerr("Cannot get start time\n");
+
+       for (i = 1000; --i >= 0; ) {
+               (void) test_unit_ready(usalp);
+
+               if (didintr)
+                       return;
+       }
+
+       prstats();
+
+       /*
+        * ATAPI drives do not like seek_g0()
+        */
+       usalp->silent++;
+       i = seek_g0(usalp, 0L);
+       usalp->silent--;
+
+       if (i >= 0) {
+               printf("Doing 1000 'SEEK_G0 (0)' operations.\n");
+
+               if (gettimeofday(&starttime, (struct timezone *)0) < 0)
+                       comerr("Cannot get start time\n");
+
+               for (i = 1000; --i >= 0; ) {
+                       (void) seek_g0(usalp, 0L);
+
+                       if (didintr)
+                               return;
+               }
+
+               prstats();
+       }
+
+       usalp->silent++;
+       i = seek_g1(usalp, 0L);
+       usalp->silent--;
+       if (i < 0)
+               return;
+
+       printf("Doing 1000 'SEEK_G1 (0)' operations.\n");
+
+       if (gettimeofday(&starttime, (struct timezone *)0) < 0)
+               comerr("Cannot get start time\n");
+
+       for (i = 1000; --i >= 0; ) {
+               (void) seek_g1(usalp, 0L);
+
+               if (didintr)
+                       return;
+       }
+
+       prstats();
+}
+
+#define        BAD_INC         16
+long   *badsecs;
+int    nbad;
+int    maxbad;
+
+static void
+add_bad(long addr)
+{
+       if (maxbad == 0) {
+               maxbad = BAD_INC;
+               badsecs = malloc(maxbad * sizeof (long));
+               if (badsecs == NULL)
+                       comerr("No memory for bad sector list\n.");
+       }
+       if (nbad >= maxbad) {
+               maxbad += BAD_INC;
+               badsecs = realloc(badsecs, maxbad * sizeof (long));
+               if (badsecs == NULL)
+                       comerr("No memory to grow bad sector list\n.");
+       }
+       badsecs[nbad++] = addr;
+}
+
+static void
+print_bad(void)
+{
+       int     i;
+
+       if (nbad == 0)
+               return;
+
+       fprintf(stderr, "Max corected retry count was %d (limited to %d).\n", maxtry, retries);
+       fprintf(stderr, "The following %d sector(s) could not be read correctly:\n", nbad);
+       for (i = 0; i < nbad; i++)
+               fprintf(stderr, "%ld\n", badsecs[i]);
+}
diff --git a/wodim/CMakeLists.txt b/wodim/CMakeLists.txt
new file mode 100644 (file)
index 0000000..d6245c9
--- /dev/null
@@ -0,0 +1,37 @@
+PROJECT (CDRECORD C)
+INCLUDE_DIRECTORIES(../include ../libedc ${CMAKE_BINARY_DIR} ${CMAKE_BINARY_DIR}/include)
+INCLUDE(../include/AddScgBits.cmake)
+include(../include/AddSchilyBits.cmake)
+
+#AUX_SOURCE_DIRECTORY(. CDRECORD_SRCS)
+SET(CDRECORD_SRCS wodim.c audiosize.c auinfo.c  cdr_drv.c cdtext.c clone.c crc16.c cue.c  diskid.c drv_7501.c drv_jvc.c drv_mmc.c drv_philips.c drv_simul.c drv_sony.c fifo.c  isosize.c scsi_cdr_mmc4.c scsi_mmc4.c sector.c subchan.c wm_packet.c wm_session.c wm_track.c xio.c)
+SET(CDRECORD_COMMON_SRCS cd_misc.c defaults.c getnum.c misc.c modes.c movesect.c scsi_cdr.c scsi_mmc.c scsi_scan.c)
+
+INCLUDE(CheckIncludeFiles)
+
+#force libcap usage on Linux
+CHECK_INCLUDE_FILES("sys/capability.h" HAVE_SYS_CAPABILITY_H)
+IF(HAVE_SYS_CAPABILITY_H)
+       LIST(APPEND EXTRA_LIBS cap)
+ELSE(HAVE_SYS_CAPABILITY_H)
+   IF(CMAKE_SYSTEM_NAME MATCHES "Linux")
+      MESSAGE(FATAL_ERROR "Error: found a Linux system but no libcap header. Install libcap-dev.")
+   ENDIF(CMAKE_SYSTEM_NAME MATCHES "Linux")
+ENDIF(HAVE_SYS_CAPABILITY_H)
+
+LINK_DIRECTORIES(../librols ../libusal  ../libedc)
+
+ADD_DEFINITIONS(-DHAVE_LIB_EDC_ECC -DCLONE_WRITE -DDRV_DVD -DFIFO -DAUINFO -DUSE_LARGEFILES )
+
+
+ADD_EXECUTABLE (wodim ${CDRECORD_SRCS})
+ADD_LIBRARY (wodimstuff STATIC ${CDRECORD_COMMON_SRCS})
+LIST(APPEND EXTRA_LIBS wodimstuff)
+
+TARGET_LINK_LIBRARIES(wodim ${EXTRA_LIBS}  edc)
+SET_TARGET_PROPERTIES(wodim PROPERTIES SKIP_BUILD_RPATH TRUE)
+
+INSTALL(TARGETS wodim DESTINATION bin)
+INSTALL(FILES 
+   wodim.1
+DESTINATION ${MANSUBDIR}/man1)
diff --git a/wodim/audiosize.c b/wodim/audiosize.c
new file mode 100644 (file)
index 0000000..2cdad97
--- /dev/null
@@ -0,0 +1,289 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)audiosize.c     1.19 04/03/01 Copyright 1998-2004 J. Schilling */
+/*
+ *     Copyright (c) 1998-2004 J. Schilling
+ *
+ *     First .vaw implementation made by Dave Platt <dplatt@iq.nc.com>
+ *     Current .wav implementation with additional help from Heiko Eißfeld.
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <mconfig.h>
+#include <statdefs.h>
+#include <unixstd.h>
+#include <standard.h>
+#include <utypes.h>
+#include <strdefs.h>
+#include <intcvt.h>
+#include <schily.h>
+
+#include <usal/usalcmd.h>
+#include "auheader.h"
+
+typedef struct {
+       Uchar   magic[4];
+       Uchar   hdr_size[4];
+       Uchar   data_size[4];
+       Uchar   encoding[4];
+       Uchar   sample_rate[4];
+       Uchar   channels[4];
+} sun_au_t;
+
+#define        SUN_AU_MAGIC            ".snd"
+#define        SUN_AU_UNKNOWN_LEN      ((Uint)~0)
+#define        SUN_AU_ULAW8            1               /* American ISDN Telephonie */
+#define        SUN_AU_LINEAR8          2               /* Linear PCM 8 bit/channel  */
+#define        SUN_AU_LINEAR16         3               /* Linear PCM 16 bit/channel */
+#define        SUN_AU_LINEAR24         4               /* Linear PCM 24 bit/channel */
+#define        SUN_AU_LINEAR32         5               /* Linear PCM 32 bit/channel */
+#define        SUN_AU_FLOAT            6               /* 32 bit IEEE floatingpoint */
+#define        SUN_AU_DOUBLE           7               /* 64 bit IEEE floatingpoint */
+#define        SUN_AU_G721             23              /* 4 bit CCITT G.721 ADPCM  */
+#define        SUN_AU_G722             24              /* CCITT G.722 ADPCM        */
+#define        SUN_AU_G723_3           25              /* 3 bit CCITT G.723 ADPCM  */
+#define        SUN_AU_G723_5           26              /* 5 bit CCITT G.723 ADPCM  */
+#define        SUN_AU_ALAW8            27              /* International ISDN Tel.  */
+
+typedef struct {
+       Uchar   ckid[4];
+       Uchar   cksize[4];
+} chunk_t;
+
+typedef struct {
+       Uchar   wave[4];
+} riff_chunk;
+
+typedef struct {
+       Uchar   fmt_tag[2];
+       Uchar   channels[2];
+       Uchar   sample_rate[4];
+       Uchar   av_byte_rate[4];
+       Uchar   block_size[2];
+       Uchar   bits_per_sample[2];
+} fmt_chunk;
+
+#define        WAV_RIFF_MAGIC          "RIFF"          /* Magic for file format    */
+#define        WAV_WAVE_MAGIC          "WAVE"          /* Magic for Waveform Audio */
+#define        WAV_FMT_MAGIC           "fmt "          /* Start of Waveform format */
+#define        WAV_DATA_MAGIC          "data"          /* Start of data chunk      */
+#define        WAV_FORMAT_PCM          0x0001          /* Linear PCM format        */
+#define        WAV_FORMAT_ULAW         0x0101          /* American ISDN Telephonie */
+#define        WAV_FORMAT_ALAW         0x0102          /* International ISDN Tel.  */
+#define        WAV_FORMAT_ADPCM        0x0103          /* ADPCM format             */
+
+#define        le_a_to_u_short(a)      ((unsigned short) \
+                               ((((unsigned char *)a)[0]       & 0xFF) | \
+                               (((unsigned char *)a)[1] << 8   & 0xFF00)))
+
+#ifdef __STDC__
+#define        le_a_to_u_long(a)       ((unsigned long) \
+                               ((((unsigned char *)a)[0]       & 0xFF) | \
+                               (((unsigned  char *)a)[1] << 8  & 0xFF00) | \
+                               (((unsigned  char *)a)[2] << 16 & 0xFF0000) | \
+                               (((unsigned  char *)a)[3] << 24 & 0xFF000000UL)))
+#else
+#define        le_a_to_u_long(a)       ((unsigned long) \
+                               ((((unsigned char *)a)[0]       & 0xFF) | \
+                               (((unsigned  char *)a)[1] << 8  & 0xFF00) | \
+                               (((unsigned  char *)a)[2] << 16 & 0xFF0000) | \
+                               (((unsigned  char *)a)[3] << 24 & 0xFF000000)))
+#endif
+
+BOOL   is_auname(const char *name);
+off_t  ausize(int f);
+BOOL   is_wavname(const char *name);
+off_t  wavsize(int f);
+
+BOOL 
+is_auname(const char *name)
+{
+       const   char    *p;
+
+       if ((p = strrchr(name, '.')) == NULL)
+               return (FALSE);
+       return (streql(p, ".au"));
+}
+
+/*
+ * Read Sun audio header, leave file seek pointer past auheader.
+ */
+off_t 
+ausize(int f)
+{
+       sun_au_t        hdr;
+       struct stat     sb;
+       mode_t          mode;
+       off_t           size;
+       Int32_t         val;
+       long            ret = AU_BAD_HEADER;
+
+       /*
+        * First check if a bad guy tries to call ausize()
+        * with an unappropriate file descriptor.
+        * return -1 in this case.
+        */
+       if (isatty(f))
+               return (-1L);
+       if (fstat(f, &sb) < 0)
+               return (-1L);
+       mode = sb.st_mode & S_IFMT;
+       if (!S_ISREG(mode) && !S_ISBLK(mode) && !S_ISCHR(mode))
+               return (-1L);
+
+       if (read(f, &hdr, sizeof (hdr)) != sizeof (hdr))
+               goto err;
+
+       if (strncmp((char *)hdr.magic, SUN_AU_MAGIC, 4) != 0)
+               goto err;
+
+       ret = AU_BAD_CODING;
+
+       val = a_to_u_4_byte(hdr.encoding);
+       if (val != SUN_AU_LINEAR16)
+               goto err;
+
+       val = a_to_u_4_byte(hdr.channels);
+       if (val != 2)
+               goto err;
+
+       val = a_to_u_4_byte(hdr.sample_rate);
+       if (val != 44100)
+               goto err;
+
+       size = (off_t)a_to_u_4_byte(hdr.hdr_size);
+       if (size < (off_t)sizeof (hdr) || size > 512)
+               goto err;
+       lseek(f, size, SEEK_SET);
+
+       /*
+        * Most .au files don't seem to honor the data_size field,
+        * so we use the whole file size without the header.
+        */
+       size = sb.st_size - size;
+       return (size);
+
+err:
+       lseek(f, (off_t)0L, SEEK_SET);
+       return ((off_t)ret);
+}
+
+BOOL 
+is_wavname(const char *name)
+{
+       const   char    *p;
+
+       if ((p = strrchr(name, '.')) == NULL)
+               return (FALSE);
+       return (streql(p, ".wav") || streql(p, ".WAV"));
+}
+
+/*
+ * Read WAV header, leave file seek pointer past WAV header.
+ */
+off_t 
+wavsize(int f)
+{
+       chunk_t         chunk;
+       riff_chunk      riff;
+       fmt_chunk       fmt;
+       struct stat     sb;
+       off_t           cursor;
+       BOOL            gotFormat;
+       mode_t          mode;
+       off_t           size;
+       long            ret = AU_BAD_HEADER;
+
+       /*
+        * First check if a bad guy tries to call wavsize()
+        * with an unappropriate file descriptor.
+        * return -1 in this case.
+        */
+
+       if (isatty(f))
+               return (-1L);
+       if (fstat(f, &sb) < 0)
+               return (-1L);
+       mode = sb.st_mode & S_IFMT;
+       if (!S_ISREG(mode) && !S_ISBLK(mode) && !S_ISCHR(mode))
+               return (-1L);
+
+       cursor = (off_t)0;
+       gotFormat = FALSE;
+
+       for (;;) {
+               if (read(f, &chunk, sizeof (chunk)) != sizeof (chunk))
+                       goto err;
+               size = (off_t)le_a_to_u_long(chunk.cksize);
+
+               if (strncmp((char *)chunk.ckid, WAV_RIFF_MAGIC, 4) == 0) {
+                       /*
+                        * We found (first) RIFF header. Check if a WAVE
+                        * magic follows. Set up size to be able to skip
+                        * past this header.
+                        */
+                       if (read(f, &riff, sizeof (riff)) != sizeof (riff))
+                               goto err;
+                       if (strncmp((char *)riff.wave, WAV_WAVE_MAGIC, 4) != 0)
+                               goto err;
+                       size = (off_t)sizeof (riff);
+
+               } else if (strncmp((char *)chunk.ckid, WAV_FMT_MAGIC, 4) == 0) {
+                       /*
+                        * We found WAVE "fmt " header. Check size (if it is
+                        * valid for a WAVE file) and coding whether it is
+                        * useable for a CD.
+                        */
+                       if (size < (off_t)sizeof (fmt)) goto err;
+                       if (sizeof (fmt) != read(f, &fmt, sizeof (fmt))) goto err;
+                       if (le_a_to_u_short(fmt.channels) != 2 ||
+                           le_a_to_u_long(fmt.sample_rate) != 44100 ||
+                           le_a_to_u_short(fmt.bits_per_sample) != 16) {
+                               ret = AU_BAD_CODING;
+                               goto err;
+                       }
+                       gotFormat = TRUE;
+
+               } else if (strncmp((char *)chunk.ckid, WAV_DATA_MAGIC, 4) == 0) {
+                       /*
+                        * We found WAVE "data" header. This contains the
+                        * size value of the audio part.
+                        */
+                       if (!gotFormat) {
+                               ret = AU_BAD_CODING;
+                               goto err;
+                       }
+                       if ((cursor + size + sizeof (chunk)) > sb.st_size)
+                               size = sb.st_size - (cursor  + sizeof (chunk));
+                       return (size);
+               }
+               cursor += size + sizeof (chunk);
+               lseek(f, cursor, SEEK_SET);     /* Skip over current chunk */
+       }
+err:
+       lseek(f, (off_t)0L, SEEK_SET);
+       return (ret);
+}
diff --git a/wodim/auheader.h b/wodim/auheader.h
new file mode 100644 (file)
index 0000000..3bfe932
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)auheader.h      1.2 98/05/09 Copyright 1998 J. Schilling */
+/*
+ *     Copyright (c) 1998 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef        _AUHEADER_H
+#define        _AUHEADER_H
+
+#define        AU_BAD          -1
+#define        AU_BAD_HEADER   -2
+#define        AU_BAD_CODING   -3
+
+
+#endif /* _AUHEADER_H */
diff --git a/wodim/auinfo.c b/wodim/auinfo.c
new file mode 100644 (file)
index 0000000..8cf8aef
--- /dev/null
@@ -0,0 +1,525 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)auinfo.c        1.23 04/03/01 Copyright 1998-2004 J. Schilling */
+/*
+ *     Copyright (c) 1998-2004 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <mconfig.h>
+#include <stdxlib.h>
+#include <unixstd.h>
+#include <statdefs.h>
+#include <stdio.h>
+#include <standard.h>
+#include <strdefs.h>
+#include <deflts.h>
+#include <utypes.h>
+#include <schily.h>
+
+#include "cdtext.h"
+#include "wodim.h"
+
+extern int     debug;
+extern int     xdebug;
+
+BOOL                   auinfosize(char *name, track_t *trackp);
+void                   auinfo(char *name, int track, track_t *trackp);
+textptr_t      *gettextptr(int track, track_t *trackp);
+static char *savestr(char *name);
+static char *readtag(char *name);
+static char *readtstr(char *name);
+void                   setmcn(char *mcn, track_t *trackp);
+static void    isrc_illchar(char *isrc, int c);
+void                   setisrc(char *isrc, track_t *trackp);
+void                   setindex(char *tindex, track_t *trackp);
+
+#ifdef XXX
+int 
+main(int argc, char *argv[])
+{
+/*     auinfo("/etc/default/cdrecord");*/
+/*     auinfo("/mnt2/CD3/audio_01.inf");*/
+       auinfo("/mnt2/CD3/audio_01.wav");
+}
+#endif
+
+BOOL 
+auinfosize(char *name, track_t *trackp)
+{
+       const   char    *p;
+       const   char    *tlp;
+       struct stat     sb;
+       long            secs;
+       long            nsamples;
+       Llong           tracksize;
+
+       if (!is_audio(trackp))
+               return (FALSE);
+
+       if ((trackp->flags & TI_USEINFO) == 0)
+               return (FALSE);
+
+       if ((p = strrchr(name, '.')) == NULL)
+               return (FALSE);
+       if (!streql(p, ".inf") && !streql(p, ".INF"))
+               return (FALSE);
+
+       /*
+        * First check if a bad guy tries to call auinfosize()
+        * while STDIN_FILENO is a TTY.
+        */
+       if (isatty(STDIN_FILENO)) {
+               errmsgno(EX_BAD,
+                       "WARNING: Stdin is connected to a terminal.\n");
+               return (FALSE);
+       }
+
+       if (stat(name, &sb) < 0)        /* *.inf file not found         */
+               return (FALSE);
+
+       if (sb.st_size > 10000)         /* Too large for a *.inf file   */
+               return (FALSE);
+
+       if (cfg_open(name) < 0) /* Cannot open *.inf file       */
+               return (FALSE);
+
+       tlp = p = readtag("Tracklength");
+       if (p == NULL) {                /* Tracklength= Tag not found   */
+               errmsgno(EX_BAD,
+                       "WARNING: %s does not contain a 'Tracklength=' tag.\n",
+                       name);
+               cfg_close();
+               return (FALSE);
+       }
+
+       p = astol(p, &secs);
+       if (*p != '\0' && *p != ',') {
+               errmsgno(EX_BAD,
+                       "WARNING: %s: 'Tracklength=' contains illegal parameter '%s'.\n",
+                       name, tlp);
+               cfg_close();
+               return (FALSE);
+       }
+       if (*p == ',')
+               p++;
+       p = astol(p, &nsamples);
+       if (*p != '\0') {
+               errmsgno(EX_BAD,
+                       "WARNING: %s: 'Tracklength=' contains illegal parameter '%s'.\n",
+                       name, tlp);
+               cfg_close();
+               return (FALSE);
+       }
+       tracksize = (secs * 2352) + (nsamples * 4);
+       if (xdebug > 0) {
+               fprintf(stderr, "%s: Tracksize %lld bytes (%ld sectors, %ld samples)\n",
+                       name, tracksize, secs, nsamples);
+       }
+       trackp->itracksize = tracksize;
+       cfg_close();
+       return (TRUE);
+}
+
+void 
+auinfo(char *name, int track, track_t *trackp)
+{
+       char    infname[1024];
+       char    *p;
+       track_t *tp = &trackp[track];
+       textptr_t *txp;
+       long    l;
+       long    tno = -1;
+       BOOL    isdao = !is_tao(&trackp[0]);
+
+       strncpy(infname, name, sizeof (infname)-1);
+       infname[sizeof (infname)-1] = '\0';
+       p = strrchr(infname, '.');
+       if (p != 0 && &p[4] < &name[sizeof (infname)]) {
+               strcpy(&p[1], "inf");
+       }
+
+       if (cfg_open(infname) == 0) {
+
+               p = readtstr("CDINDEX_DISCID");
+               p = readtag("CDDB_DISKID");
+
+               p = readtag("MCN");
+               if (p && *p) {
+                       setmcn(p, &trackp[0]);
+                       txp = gettextptr(0, trackp); /* MCN is isrc for trk 0*/
+                       txp->tc_isrc = savestr(p);
+               }
+
+               p = readtag("ISRC");
+               if (p && *p) {
+                       setisrc(p, &trackp[track]);
+                       txp = gettextptr(track, trackp);
+                       txp->tc_isrc = savestr(p);
+               }
+
+               p = readtstr("Albumperformer");
+               if (p && *p) {
+                       txp = gettextptr(0, trackp); /* Album perf. in trk 0*/
+                       txp->tc_performer = savestr(p);
+               }
+               p = readtstr("Performer");
+               if (p && *p) {
+                       txp = gettextptr(track, trackp);
+                       txp->tc_performer = savestr(p);
+               }
+               p = readtstr("Albumtitle");
+               if (p && *p) {
+                       txp = gettextptr(0, trackp); /* Album title in trk 0*/
+                       txp->tc_title = savestr(p);
+               }
+               p = readtstr("Tracktitle");
+               if (p && *p) {
+                       txp = gettextptr(track, trackp);
+                       txp->tc_title = savestr(p);
+               }
+               p = readtstr("Songwriter");
+               if (p && *p) {
+                       txp = gettextptr(track, trackp);
+                       txp->tc_songwriter = savestr(p);
+               }
+               p = readtstr("Composer");
+               if (p && *p) {
+                       txp = gettextptr(track, trackp);
+                       txp->tc_composer = savestr(p);
+               }
+               p = readtstr("Arranger");
+               if (p && *p) {
+                       txp = gettextptr(track, trackp);
+                       txp->tc_arranger = savestr(p);
+               }
+               p = readtstr("Message");
+               if (p && *p) {
+                       txp = gettextptr(track, trackp);
+                       txp->tc_message = savestr(p);
+               }
+               p = readtstr("Diskid");
+               if (p && *p) {
+                       txp = gettextptr(0, trackp); /* Disk id is in trk 0*/
+                       txp->tc_title = savestr(p);
+               }
+               p = readtstr("Closed_info");
+               if (p && *p) {
+                       txp = gettextptr(track, trackp);
+                       txp->tc_closed_info = savestr(p);
+               }
+
+               p = readtag("Tracknumber");
+               if (p && isdao)
+                       astol(p, &tno);
+
+               p = readtag("Trackstart");
+               if (p && isdao) {
+                       l = -1L;
+                       astol(p, &l);
+                       if (track == 1 && tno == 1 && l > 0) {
+                               trackp[1].pregapsize = 150 + l;
+                               printf("Track1 Start: '%s' (%ld)\n", p, l);
+                       }
+               }
+
+               p = readtag("Tracklength");
+
+               p = readtag("Pre-emphasis");
+               if (p && *p) {
+                       if (strncmp(p, "yes", 3) == 0) {
+                               tp->flags |= TI_PREEMP;
+                               if ((tp->tracktype & TOC_MASK) == TOC_DA)
+                                       tp->sectype = SECT_AUDIO_PRE;
+
+                       } else if (strncmp(p, "no", 2) == 0) {
+                               tp->flags &= ~TI_PREEMP;
+                               if ((tp->tracktype & TOC_MASK) == TOC_DA)
+                                       tp->sectype = SECT_AUDIO_NOPRE;
+                       }
+               }
+
+               p = readtag("Channels");
+               p = readtag("Copy_permitted");
+               if (p && *p) {
+                       /*
+                        * -useinfo always wins
+                        */
+                       tp->flags &= ~(TI_COPY|TI_SCMS);
+
+                       if (strncmp(p, "yes", 3) == 0)
+                               tp->flags |= TI_COPY;
+                       else if (strncmp(p, "no", 2) == 0)
+                               tp->flags |= TI_SCMS;
+                       else if (strncmp(p, "once", 2) == 0)
+                               tp->flags &= ~(TI_COPY|TI_SCMS);
+               }
+               p = readtag("Endianess");
+               p = readtag("Index");
+               if (p && *p && isdao)
+                       setindex(p, &trackp[track]);
+
+               p = readtag("Index0");
+               if (p && isdao) {
+                       Llong ts;
+                       Llong ps;
+
+                       l = -2L;
+                       astol(p, &l);
+                       if (l == -1) {
+                               trackp[track+1].pregapsize = 0;
+                       } else if (l > 0) {
+                               ts = tp->itracksize / tp->isecsize;
+                               ps = ts - l;
+                               if (ps > 0)
+                                       trackp[track+1].pregapsize = ps;
+                       }
+               }
+       }
+
+}
+
+textptr_t *
+gettextptr(int track, track_t *trackp)
+{
+       register textptr_t *txp;
+
+       txp = (textptr_t *)trackp[track].text;
+       if (txp == NULL) {
+               txp = malloc(sizeof (textptr_t));
+               if (txp == NULL)
+                       comerr("Cannot malloc CD-Text structure.\n");
+               fillbytes(txp, sizeof (textptr_t), '\0');
+               trackp[track].text = txp;
+       }
+       return (txp);
+}
+
+static char *
+savestr(char *str)
+{
+       char    *ret;
+
+       ret = malloc(strlen(str)+1);
+       if (ret)
+               strcpy(ret, str);
+       else
+               comerr("Cannot malloc auinfo string.\n");
+       return (ret);
+}
+
+static char *
+readtag(char *name)
+{
+       register char   *p;
+
+  p = cfg_get(name);
+  if (debug)
+     printf("%s        '%s'\n", name, p);
+  return (p);
+}
+
+static char *
+readtstr(char *name)
+{
+       register char   *p;
+       register char   *p2;
+
+       p = readtag(name);
+       if (p && *p == '\'') {
+               p2 = ++p;
+               while (*p2 != '\0')
+                       p2++;
+               while (p2 > p && *p2 != '\'')
+                       p2--;
+               *p2 = '\0';
+               if (debug)
+                       printf("%s      '%s'\n", name, p);
+       }
+       return (p);
+}
+
+/*
+ * Media catalog number is a 13 digit number.
+ */
+void 
+setmcn(char *mcn, track_t *trackp)
+{
+       register char   *p;
+
+       if (strlen(mcn) != 13)
+               comerrno(EX_BAD, "MCN '%s' has illegal length.\n", mcn);
+
+       for (p = mcn; *p; p++) {
+               if (*p < '0' || *p > '9')
+                       comerrno(EX_BAD, "MCN '%s' contains illegal character '%c'.\n", mcn, *p);
+       }
+       p = malloc(14);
+       strcpy(p, mcn);
+       trackp->isrc = p;
+
+       if (debug)
+               printf("Track %d MCN: '%s'\n", (int)trackp->trackno, trackp->isrc);
+}
+
+static char    upper[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+
+static void 
+isrc_illchar(char *isrc, int c)
+{
+       errmsgno(EX_BAD, "ISRC '%s' contains illegal character '%c'.\n", isrc, c);
+}
+
+/*
+ * ISRC is 12 Byte:
+ *
+ *     Country code   'C' (alpha)        2 Bytes
+ *     Owner code     'O' (alphanumeric) 3 Bytes
+ *     Year of record 'Y' (numeric)      2 Bytes
+ *     Serial number  'S' (numeric)      5 Bytes
+ *
+ *     CC-OOO-YY-SSSSS
+ */
+void 
+setisrc(char *isrc, track_t *trackp)
+{
+       char    ibuf[13];
+       char    *ip;
+       char    *p;
+       int     i;
+       int     len;
+
+       if ((len = strlen(isrc)) != 12) {
+               for (p = isrc, i = 0; *p; p++) {
+                       if (*p == '-')
+                               i++;
+               }
+               if (((len - i) != 12) || i > 3)
+                       comerrno(EX_BAD, "ISRC '%s' has illegal length.\n", isrc);
+       }
+
+       /*
+        * The country code.
+        */
+       for (p = isrc, ip = ibuf, i = 0; i < 2; p++, i++) {
+               *ip++ = *p;
+               if (!strchr(upper, *p)) {
+/*                     goto illchar;*/
+                       /*
+                        * Flag numbers but accept them.
+                        */
+                       isrc_illchar(isrc, *p);
+                       if (*p >= '0' && *p <= '9')
+                               continue;
+                       exit(EX_BAD);
+               }
+       }
+       if (*p == '-')
+               p++;
+
+       /*
+        * The owner code.
+        */
+       for (i = 0; i < 3; p++, i++) {
+               *ip++ = *p;
+               if (strchr(upper, *p))
+                       continue;
+               if (*p >= '0' && *p <= '9')
+                       continue;
+               goto illchar;
+       }
+       if (*p == '-')
+               p++;
+
+       /*
+        * The Year and the recording number (2 + 5 numbers).
+        */
+       for (i = 0; i < 7; p++, i++) {
+               *ip++ = *p;
+               if (*p >= '0' && *p <= '9')
+                       continue;
+               if (*p == '-' && i == 2) {
+                       ip--;
+                       i--;
+                       continue;
+               }
+               goto illchar;
+       }
+       *ip = '\0';
+       p = malloc(13);
+       strcpy(p, ibuf);
+       trackp->isrc = p;
+
+       if (debug)
+               printf("Track %d ISRC: '%s'\n", (int)trackp->trackno, trackp->isrc);
+       return;
+illchar:
+       isrc_illchar(isrc, *p);
+       exit(EX_BAD);
+}
+
+void 
+setindex(char *tindex, track_t *trackp)
+{
+       char    *p;
+       int     i;
+       int     nindex;
+       long    idx;
+       long    *idxlist;
+
+       idxlist = malloc(100*sizeof (long));
+       p = tindex;
+       idxlist[0] = 0;
+       i = 0;
+       while (*p) {
+               p = astol(p, &idx);
+               if (*p != '\0' && *p != ' ' && *p != '\t' && *p != ',')
+                       goto illchar;
+               i++;
+               if (i > 99)
+                       comerrno(EX_BAD, "Too many indices for track %d\n", (int)trackp->trackno);
+               idxlist[i] = idx;
+               if (*p == ',')
+                       p++;
+               while (*p == ' ' || *p == '\t')
+                       p++;
+       }
+       nindex = i;
+
+       if (debug)
+               printf("Track %d %d Index: '%s'\n", (int)trackp->trackno, i, tindex);
+
+       if (debug) {
+               for (i = 0; i <= nindex; i++)
+                       printf("%d: %ld\n", i, idxlist[i]);
+       }
+
+       trackp->nindex = nindex;
+       trackp->tindex = idxlist;
+       return;
+illchar:
+       comerrno(EX_BAD, "Index '%s' contains illegal character '%c'.\n", tindex, *p);
+}
diff --git a/wodim/cd_misc.c b/wodim/cd_misc.c
new file mode 100644 (file)
index 0000000..b9970bb
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)cd_misc.c       1.10 01/10/29 Copyright 1997 J. Schilling */
+/*
+ *     Misc CD support routines
+ *
+ *     Copyright (c) 1997 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <mconfig.h>
+#include <standard.h>
+#include <utypes.h>    /* Includes <sys/types.h> for caddr_t */
+#include <stdio.h>
+#include <schily.h>
+
+#include "wodim.h"
+
+int    from_bcd(int b);
+int    to_bcd(int i);
+long   msf_to_lba(int m, int s, int f, BOOL force_positive);
+BOOL   lba_to_msf(long lba, msf_t *mp);
+void   sec_to_msf(long sec, msf_t *mp);
+void   print_min_atip(long li, long lo);
+
+int 
+from_bcd(int b)
+{
+       return ((b & 0x0F) + 10 * (((b)>> 4) & 0x0F));
+}
+
+int 
+to_bcd(int i)
+{
+       return (i % 10 | ((i / 10) % 10) << 4);
+}
+
+long 
+msf_to_lba(int m, int s, int f, BOOL force_positive)
+{
+       long    ret = m * 60 + s;
+
+       ret *= 75;
+       ret += f;
+       if (m < 90 || force_positive)
+               ret -= 150;
+       else
+               ret -= 450150;
+       return (ret);
+}
+
+BOOL 
+lba_to_msf(long lba, msf_t *mp)
+{
+       int     m;
+       int     s;
+       int     f;
+
+#ifdef __follow_redbook__
+       if (lba >= -150 && lba < 405000) {      /* lba <= 404849 */
+#else
+       if (lba >= -150) {
+#endif
+               m = (lba + 150) / 60 / 75;
+               s = (lba + 150 - m*60*75)  / 75;
+               f = (lba + 150 - m*60*75 - s*75);
+
+       } else if (lba >= -45150 && lba <= -151) {
+               m = (lba + 450150) / 60 / 75;
+               s = (lba + 450150 - m*60*75)  / 75;
+               f = (lba + 450150 - m*60*75 - s*75);
+
+       } else {
+               mp->msf_min   = -1;
+               mp->msf_sec   = -1;
+               mp->msf_frame = -1;
+
+               return (FALSE);
+       }
+       mp->msf_min   = m;
+       mp->msf_sec   = s;
+       mp->msf_frame = f;
+
+       if (lba > 404849)                       /* 404850 -> 404999: lead out */
+               return (FALSE);
+       return (TRUE);
+}
+
+void 
+sec_to_msf(long sec, msf_t *mp)
+{
+       int     m;
+       int     s;
+       int     f;
+
+       m = (sec) / 60 / 75;
+       s = (sec - m*60*75)  / 75;
+       f = (sec - m*60*75 - s*75);
+
+       mp->msf_min   = m;
+       mp->msf_sec   = s;
+       mp->msf_frame = f;
+}
+
+void 
+print_min_atip(long li, long lo)
+{
+       msf_t   msf;
+
+       if (li < 0) {
+               lba_to_msf(li, &msf);
+
+               printf("  ATIP start of lead in:  %ld (%02d:%02d/%02d)\n",
+                       li, msf.msf_min, msf.msf_sec, msf.msf_frame);
+       }
+       if (lo > 0) {
+               lba_to_msf(lo, &msf);
+               printf("  ATIP start of lead out: %ld (%02d:%02d/%02d)\n",
+                       lo, msf.msf_min, msf.msf_sec, msf.msf_frame);
+       }
+}
diff --git a/wodim/cdr_drv.c b/wodim/cdr_drv.c
new file mode 100644 (file)
index 0000000..a40afa3
--- /dev/null
@@ -0,0 +1,318 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)cdr_drv.c       1.36 04/03/02 Copyright 1997-2004 J. Schilling */
+/*
+ *     CDR device abstraction layer
+ *
+ *     Copyright (c) 1997-2004 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <mconfig.h>
+#include <stdio.h>
+#include <stdxlib.h>
+#include <unixstd.h>   /* Include sys/types.h to make off_t available */
+#include <standard.h>
+#include <schily.h>
+
+#include <usal/scsidefs.h>
+#include <usal/scsireg.h>
+#include <usal/scsitransp.h>
+
+#include "wodim.h"
+
+extern int     xdebug;
+
+extern cdr_t   cdr_oldcd;
+extern cdr_t   cdr_cd;
+extern cdr_t   cdr_mmc;
+extern  cdr_t   cdr_mdvd;
+extern cdr_t   cdr_mmc_sony;
+extern cdr_t   cdr_cd_dvd;
+extern cdr_t   cdr_philips_cdd521O;
+extern cdr_t   cdr_philips_dumb;
+extern cdr_t   cdr_philips_cdd521;
+extern cdr_t   cdr_philips_cdd522;
+extern cdr_t   cdr_tyuden_ew50;
+extern cdr_t   cdr_kodak_pcd600;
+extern cdr_t   cdr_pioneer_dw_s114x;
+extern cdr_t   cdr_plasmon_rf4100;
+extern cdr_t   cdr_yamaha_cdr100;
+extern cdr_t   cdr_sony_cdu924;
+extern cdr_t   cdr_ricoh_ro1060;
+extern cdr_t   cdr_ricoh_ro1420;
+extern cdr_t   cdr_teac_cdr50;
+extern cdr_t   cdr_cw7501;
+extern cdr_t   cdr_cdr_simul;
+extern cdr_t   cdr_dvd_simul;
+
+cdr_t  *drive_identify(SCSI *usalp, cdr_t *, struct scsi_inquiry *ip);
+int    drive_attach(SCSI *usalp, cdr_t *);
+int    attach_unknown(void);
+int    blank_dummy(SCSI *usalp, cdr_t *, long addr, int blanktype);
+int    format_dummy(SCSI *usalp, cdr_t *, int fmtflags);
+int    drive_getdisktype(SCSI *usalp, cdr_t *dp);
+int    cmd_ill(SCSI *usalp);
+int    cmd_dummy(SCSI *usalp, cdr_t *);
+int    no_sendcue(SCSI *usalp, cdr_t *, track_t *trackp);
+int    buf_dummy(SCSI *usalp, long *sp, long *fp);
+BOOL   set_cdrcmds(char *name, cdr_t **dpp);
+cdr_t  *get_cdrcmds(SCSI *usalp);
+
+/*
+ * List of CD-R drivers
+ */
+cdr_t  *drivers[] = {
+       &cdr_cd_dvd,
+       &cdr_mmc,
+        &cdr_mdvd,
+       &cdr_mmc_sony,
+       &cdr_cd,
+       &cdr_oldcd,
+       &cdr_philips_cdd521O,
+       &cdr_philips_dumb,
+       &cdr_philips_cdd521,
+       &cdr_philips_cdd522,
+       &cdr_tyuden_ew50,
+       &cdr_kodak_pcd600,
+       &cdr_pioneer_dw_s114x,
+       &cdr_plasmon_rf4100,
+       &cdr_yamaha_cdr100,
+       &cdr_ricoh_ro1060,
+       &cdr_ricoh_ro1420,
+       &cdr_sony_cdu924,
+       &cdr_teac_cdr50,
+       &cdr_cw7501,
+       &cdr_cdr_simul,
+       &cdr_dvd_simul,
+       (cdr_t *)NULL,
+};
+
+cdr_t *
+drive_identify(SCSI *usalp, cdr_t *dp, struct scsi_inquiry *ip)
+{
+       return (dp);
+}
+
+int 
+drive_attach(SCSI *usalp, cdr_t *dp)
+{
+       return (0);
+}
+
+int 
+attach_unknown()
+{
+       errmsgno(EX_BAD, "Unsupported drive type\n");
+       return (-1);
+}
+
+int 
+blank_dummy(SCSI *usalp, cdr_t *dp, long addr, int blanktype)
+{
+       printf("This drive or media does not support the 'BLANK media' command\n");
+       return (-1);
+}
+
+int 
+format_dummy(SCSI *usalp, cdr_t *dp, int fmtflags)
+{
+       printf("This drive or media does not support the 'FORMAT media' command\n");
+       return (-1);
+}
+
+int 
+drive_getdisktype(SCSI *usalp, cdr_t *dp)
+{
+/*     dstat_t *dsp = dp->cdr_dstat;*/
+       return (0);
+}
+
+int 
+cmd_ill(SCSI *usalp)
+{
+       errmsgno(EX_BAD, "Unspecified command not implemented for this drive.\n");
+       return (-1);
+}
+
+int 
+cmd_dummy(SCSI *usalp, cdr_t *dp)
+{
+       return (0);
+}
+
+int 
+no_sendcue(SCSI *usalp, cdr_t *dp, track_t *trackp)
+{
+       errmsgno(EX_BAD, "SAO writing not available or not implemented for this drive.\n");
+       return (-1);
+}
+
+int 
+buf_dummy(SCSI *usalp, long *sp, long *fp)
+{
+       return (-1);
+}
+
+BOOL 
+set_cdrcmds(char *name, cdr_t **dpp)
+{
+       cdr_t   **d;
+       int     n;
+
+       for (d = drivers; *d != (cdr_t *)NULL; d++) {
+               if (streql((*d)->cdr_drname, name)) {
+                       if (dpp != NULL)
+                               *dpp = *d;
+                       return (TRUE);
+               }
+       }
+       if (dpp == NULL)
+               return (FALSE);
+
+       if (!streql("help", name))
+               fprintf(stderr, "Illegal driver type '%s'.\n", name);
+
+       fprintf(stderr, "Driver types:\n");
+       for (d = drivers; *d != (cdr_t *)NULL; d++) {
+               fprintf(stderr, "%s%n",
+                       (*d)->cdr_drname, &n);
+               fprintf(stderr, "%*s%s\n",
+                       20-n, "",
+                       (*d)->cdr_drtext);
+       }
+       if (streql("help", name))
+               exit(0);
+       exit(EX_BAD);
+       return (FALSE);         /* Make lint happy */
+}
+
+cdr_t *
+get_cdrcmds(SCSI *usalp)
+{
+       cdr_t   *dp = (cdr_t *)0;
+       cdr_t   *odp = (cdr_t *)0;
+       BOOL    is_wr = FALSE;
+       BOOL    is_cd = FALSE;
+       BOOL    is_dvd = FALSE;
+       BOOL    is_dvdplus = FALSE;
+       BOOL    is_ddcd = FALSE;
+       BOOL    is_cdwr = FALSE;
+       BOOL    is_dvdwr = FALSE;
+       BOOL    is_dvdpluswr = FALSE;
+       BOOL    is_ddcdwr = FALSE;
+
+       /*
+        * First check for SCSI-3/mmc-3 drives.
+        */
+       if (get_proflist(usalp, &is_wr, &is_cd, &is_dvd,
+                                               &is_dvdplus, &is_ddcd) >= 0) {
+
+               get_wproflist(usalp, &is_cdwr, &is_dvdwr,
+                                               &is_dvdpluswr, &is_ddcdwr);
+               if (xdebug) {
+                       fprintf(stderr, 
+                       "Found MMC-3 %s CD: %s/%s DVD-: %s/%s DVD+: %s/%s DDCD: %s/%s.\n",
+                                       is_wr ? "writer": "reader",
+                                       is_cd?"r":"-",
+                                       is_cdwr?"w":"-",
+                                       is_dvd?"r":"-",
+                                       is_dvdwr?"w":"-",
+                                       is_dvdplus?"r":"-",
+                                       is_dvdpluswr?"w":"-",
+                                       is_ddcd?"r":"-",
+                                       is_ddcdwr?"w":"-");
+               }
+               if (!is_wr) {
+                       dp = &cdr_cd;
+               } else {
+                       dp = &cdr_cd_dvd;
+               }
+       } else
+       /*
+        * First check for SCSI-3/mmc drives.
+        */
+       if (is_mmc(usalp, &is_cdwr, &is_dvdwr)) {
+               if (xdebug) {
+                       fprintf(stderr, "Found MMC drive CDWR: %d DVDWR: %d.\n",
+                                                       is_cdwr, is_dvdwr);
+               }
+
+               if (is_cdwr && is_dvdwr)
+                       dp = &cdr_cd_dvd;
+               else
+                       dp = &cdr_mmc;
+
+       } else switch (usalp->dev) {
+
+       case DEV_CDROM:         dp = &cdr_oldcd;                break;
+       case DEV_MMC_CDROM:     dp = &cdr_cd;                   break;
+       case DEV_MMC_CDR:       dp = &cdr_mmc;                  break;
+       case DEV_MMC_CDRW:      dp = &cdr_mmc;                  break;
+       case DEV_MMC_DVD_WR:    dp = &cdr_cd_dvd;               break;
+
+       case DEV_CDD_521_OLD:   dp = &cdr_philips_cdd521O;      break;
+       case DEV_CDD_521:       dp = &cdr_philips_cdd521;       break;
+       case DEV_CDD_522:
+       case DEV_CDD_2000:
+       case DEV_CDD_2600:      dp = &cdr_philips_cdd522;       break;
+       case DEV_TYUDEN_EW50:   dp = &cdr_tyuden_ew50;          break;
+       case DEV_PCD_600:       dp = &cdr_kodak_pcd600;         break;
+       case DEV_YAMAHA_CDR_100:dp = &cdr_yamaha_cdr100;        break;
+       case DEV_MATSUSHITA_7501:dp = &cdr_cw7501;              break;
+       case DEV_MATSUSHITA_7502:
+       case DEV_YAMAHA_CDR_400:dp = &cdr_mmc;                  break;
+       case DEV_PLASMON_RF_4100:dp = &cdr_plasmon_rf4100;      break;
+       case DEV_SONY_CDU_924:  dp = &cdr_sony_cdu924;          break;
+       case DEV_RICOH_RO_1060C:dp = &cdr_ricoh_ro1060;         break;
+       case DEV_RICOH_RO_1420C:dp = &cdr_ricoh_ro1420;         break;
+       case DEV_TEAC_CD_R50S:  dp = &cdr_teac_cdr50;           break;
+
+       case DEV_PIONEER_DW_S114X: dp = &cdr_pioneer_dw_s114x;  break;
+
+       default:                dp = &cdr_mmc;
+       }
+       odp = dp;
+
+       if (xdebug) {
+               fprintf(stderr, "Using driver '%s' for identify.\n",
+                       dp != NULL ?
+                       dp->cdr_drname :
+                       "<no driver>");
+       }
+
+       if (dp != (cdr_t *)0)
+               dp = dp->cdr_identify(usalp, dp, usalp->inq);
+
+       if (xdebug && dp != odp) {
+               fprintf(stderr, "Identify set driver to '%s'.\n",
+                       dp != NULL ?
+                       dp->cdr_drname :
+                       "<no driver>");
+       }
+
+       return (dp);
+}
diff --git a/wodim/cdtext.c b/wodim/cdtext.c
new file mode 100644 (file)
index 0000000..40df2a5
--- /dev/null
@@ -0,0 +1,546 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)cdtext.c        1.10 04/03/01 Copyright 1999-2004 J. Schilling */
+/*
+ *     Generic CD-Text support functions
+ *
+ *     Copyright (c) 1999-2004 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <mconfig.h>
+#include <stdio.h>
+#include <stdxlib.h>
+#include <unixstd.h>   /* Include sys/types.h to make off_t available */
+#include <standard.h>
+#include <utypes.h>
+#include <strdefs.h>
+#include <schily.h>
+
+#include <usal/scsitransp.h>   /* For write_leadin() */
+
+#include "cdtext.h"
+#include "wodim.h"
+#include "crc16.h"
+
+#define        PTI_TITLE       0x80    /* Album name and Track titles */
+#define        PTI_PERFORMER   0x81    /* Singer/player/conductor/orchestra */
+#define        PTI_SONGWRITER  0x82    /* Name of the songwriter */
+#define        PTI_COMPOSER    0x83    /* Name of the composer */
+#define        PTI_ARRANGER    0x84    /* Name of the arranger */
+#define        PTI_MESSAGE     0x85    /* Message from content provider or artist */
+#define        PTI_DISK_ID     0x86    /* Disk identification information */
+#define        PTI_GENRE       0x87    /* Genre identification / information */
+#define        PTI_TOC         0x88    /* TOC information */
+#define        PTI_TOC2        0x89    /* Second TOC */
+#define        PTI_RES_8A      0x8A    /* Reserved 8A */
+#define        PTI_RES_8B      0x8B    /* Reserved 8B */
+#define        PTI_RES_8C      0x8C    /* Reserved 8C */
+#define        PTI_CLOSED_INFO 0x8D    /* For internal use by content provider */
+#define        PTI_ISRC        0x8E    /* UPC/EAN code of album and ISRC for tracks */
+#define        PTI_SIZE        0x8F    /* Size information of the block */
+
+extern int     xdebug;
+
+typedef struct textpack {
+       Uchar   pack_type;      /* Pack Type indicator  */
+       char    track_no;       /* Track Number (0..99) */
+       char    seq_number;     /* Sequence Number      */
+       char    block_number;   /* Block # / Char pos   */
+       char    text[12];       /* CD-Text Data field   */
+       char    crc[2];         /* CRC 16               */
+} txtpack_t;
+
+#define        EXT_DATA 0x80           /* Extended data indicator in track_no */
+#define        DBCC     0x80           /* Double byte char indicator in block */
+
+/*
+ *     CD-Text size example:
+ *
+ *     0  1  2  3  00 01 02 03 04 05 06 07 08 09 10 11 CRC16
+ *
+ *     8F 00 2B 00 01 01 0D 03 0C 0C 00 00 00 00 01 00 7B 3D
+ *     8F 01 2C 00 00 00 00 00 00 00 12 03 2D 00 00 00 DA B7
+ *     8F 02 2D 00 00 00 00 00 09 00 00 00 00 00 00 00 6A 24
+ *
+ *     charcode 1
+ *     first tr 1
+ *     last tr  13
+ *     Copyr    3
+ *     Pack Count 80= 12, 81 = 12, 86 = 1, 8e = 18, 8f = 3
+ *     last seq   0 = 2d
+ *     languages  0 = 9
+ */
+
+typedef struct textsizes {
+       char    charcode;
+       char    first_track;
+       char    last_track;
+       char    copyr_flags;
+       char    pack_count[16];
+       char    last_seqnum[8];
+       char    language_codes[8];
+} txtsize_t;
+
+typedef struct textargs {
+       txtpack_t       *tp;
+       char            *p;
+       txtsize_t       *tsize;
+       int             seqno;
+} txtarg_t;
+
+
+Uchar  *textsub;
+int    textlen;
+
+BOOL                   checktextfile(char *fname);
+static void    setuptextdata(Uchar *bp, int len);
+static BOOL    cdtext_crc_ok(struct textpack *p);
+void                   packtext(int tracks, track_t *trackp);
+static BOOL    anytext(int pack_type, int tracks, track_t *trackp);
+static void    fillup_pack(txtarg_t *ap);
+static void    fillpacks(txtarg_t *ap, char *from, int len, int track_no, int pack_type);
+int                    write_cdtext(SCSI *usalp, cdr_t *dp, long startsec);
+static void    eight2six(Uchar *in, Uchar *out);
+static void    six2eight(Uchar *in, Uchar *out);
+
+
+BOOL checktextfile(char *fname)
+{
+       FILE    *f;
+       Uchar   hbuf[4];
+       Uchar   *bp;
+       struct textpack *tp;
+       int     len;
+       int     crc;
+       int     n;
+       int     j;
+       off_t   fs;
+
+       if ((f = fileopen(fname, "rb")) == NULL) {
+               errmsg("Cannot open '%s'.\n", fname);
+               return (FALSE);
+       }
+       fs = filesize(f);
+       j = fs % sizeof (struct textpack);
+       if (j == 4) {
+               n = fileread(f, hbuf, 4);
+               if (n != 4) {
+                       if (n < 0)
+                               errmsg("Cannot read '%s'.\n", fname);
+                       else
+                               errmsgno(EX_BAD, "File '%s' is too small for CD-Text.\n", fname);
+                       return (FALSE);
+               }
+               len = hbuf[0] * 256 + hbuf[1];
+               len -= 2;
+               n = fs - 4;
+               if (n != len) {
+                       errmsgno(EX_BAD, "Inconsistent CD-Text file '%s' length should be %d but is %lld\n",
+                               fname, len+4, (Llong)fs);
+                       return (FALSE);
+               }
+       } else if (j != 0) {
+               errmsgno(EX_BAD, "Inconsistent CD-Text file '%s' not a multiple of pack length\n",
+                       fname);
+               return (FALSE);
+       } else {
+               len = fs;
+       }
+       printf("Text len: %d\n", len);
+       bp = malloc(len);
+       if (bp == NULL) {
+               errmsg("Cannot malloc CD-Text read buffer.\n");
+               return (FALSE);
+       }
+       n = fileread(f, bp, len);
+
+       tp = (struct textpack *)bp;
+       for (n = 0; n < len; n += sizeof (struct textpack), tp++) {
+               if (tp->pack_type < 0x80 || tp->pack_type > 0x8F) {
+                       errmsgno(EX_BAD, "Illegal pack type 0x%02X pack #%ld in CD-Text file '%s'.\n",
+                               tp->pack_type, (long)(n/sizeof (struct textpack)), fname);
+                       return (FALSE);
+               }
+               crc = (tp->crc[0] & 0xFF) << 8 | (tp->crc[1] & 0xFF);
+               crc ^= 0xFFFF;
+               if (crc != calcCRC((Uchar *)tp, sizeof (*tp)-2)) {
+                       if (cdtext_crc_ok(tp)) {
+                               errmsgno(EX_BAD,
+                               "Corrected CRC ERROR in pack #%ld (offset %d-%ld) in CD-Text file '%s'.\n",
+                               (long)(n/sizeof (struct textpack)),
+                               n+j, (long)(n+j+sizeof (struct textpack)),
+                               fname);
+                       } else {
+                       errmsgno(EX_BAD, "CRC ERROR in pack #%ld (offset %d-%ld) in CD-Text file '%s'.\n",
+                               (long)(n/sizeof (struct textpack)),
+                               n+j, (long)(n+j+sizeof (struct textpack)),
+                               fname);
+                       return (FALSE);
+                       }
+               }
+       }
+       setuptextdata(bp, len);
+       free(bp);
+
+       return (TRUE);
+}
+
+static void setuptextdata(Uchar *bp, int len)
+{
+       int     n;
+       int     i;
+       int     j;
+       Uchar   *p;
+
+       if (xdebug) {
+               printf("%ld packs %% 4 = %ld\n",
+                       (long)(len/sizeof (struct textpack)),
+                       (long)(len/sizeof (struct textpack)) % 4);
+       }
+       i = (len/sizeof (struct textpack)) % 4;
+       if (i == 0) {
+               n = len;
+       } else if (i == 2) {
+               n = 2 * len;
+       } else {
+               n = 4 * len;
+       }
+       n = (n * 4) / 3;
+       p = malloc(n);
+       if (p == NULL) {
+               errmsg("Cannot malloc CD-Text write buffer.\n");
+       }
+       for (i = 0, j = 0; j < n; ) {
+               eight2six(&bp[i%len], &p[j]);
+               i += 3;
+               j += 4;
+       }
+       textsub = p;
+       textlen = n;
+
+#ifdef DEBUG
+       {
+       Uchar   sbuf[10000];
+       struct textpack *tp;
+       FILE            *f;
+       int             crc;
+
+       tp = (struct textpack *)bp;
+       p = sbuf;
+       for (n = 0; n < len; n += sizeof (struct textpack), tp++) {
+               crc = (tp->crc[0] & 0xFF) << 8 | (tp->crc[1] & 0xFF);
+               crc ^= 0xFFFF;
+
+               printf("Pack:%3d ", n/ sizeof (struct textpack));
+               printf("Pack type: %02X ", tp->pack_type & 0xFF);
+               printf("Track #: %2d ", tp->track_no & 0xFF);
+               printf("Sequence #:%3d ", tp->seq_number & 0xFF);
+               printf("Block #:%3d ", tp->block_number & 0xFF);
+               printf("CRC: %04X (%04X) ", crc, calcCRC((Uchar *)tp, sizeof (*tp)-2));
+               printf("Text: '%.12s'\n", tp->text);
+               movebytes(tp->text, p, 12);
+               p += 12;
+       }
+       printf("len total: %d\n", n);
+       f = fileopen("cdtext.out", "wctb");
+       if (f) {
+               filewrite(f, sbuf, p - sbuf);
+               fflush(f);
+               fclose(f);
+       }
+       }
+#endif
+}
+
+static BOOL cdtext_crc_ok(struct textpack *p)
+{
+       int             crc;
+       struct textpack new;
+
+       movebytes(p, &new, sizeof (struct textpack));
+       new.crc[0] ^= 0xFF;
+       new.crc[1] ^= 0xFF;
+       crc = calcCRC((Uchar *)&new, sizeof (struct textpack));
+       crc = flip_crc_error_corr((Uchar *)&new, sizeof (struct textpack), crc);
+       new.crc[0] ^= 0xFF;
+       new.crc[1] ^= 0xFF;
+       if (crc == 0)
+               movebytes(&new, p, 18);
+
+       return (crc == 0);
+}
+
+
+void packtext(int tracks, track_t *trackp)
+{
+       int     type;
+       int     i;
+       struct textpack *tp;
+       struct textsizes tsize;
+       txtarg_t targ;
+       char    sbuf[256*18];
+
+       fillbytes(sbuf, sizeof (sbuf), 0);
+       fillbytes(&tsize, sizeof (tsize), 0);
+
+       tsize.charcode          = CC_8859_1;            /* ISO-8859-1       */
+       tsize.first_track       = trackp[1].trackno;
+       tsize.last_track        = trackp[1].trackno + tracks - 1;
+#ifdef __FOUND_ON_COMMERCIAL_CD__
+       tsize.copyr_flags       = 3;                    /* for titles/names */
+#else
+       tsize.copyr_flags       = 0;                    /* no Copyr. limitat. */
+#endif
+       tsize.pack_count[0x0F]  = 3;                    /* 3 size packs     */
+       tsize.last_seqnum[0]    = 0;                    /* Start value only */
+       tsize.language_codes[0] = LANG_ENGLISH;         /* English          */
+
+       tp = (struct textpack *)sbuf;
+
+       targ.tp = tp;
+       targ.p = NULL;
+       targ.tsize = &tsize;
+       targ.seqno = 0;
+
+       for (type = 0; type <= 0x0E; type++) {
+               register int    maxtrk;
+               register char   *s;
+
+               if (!anytext(type, tracks, trackp))
+                       continue;
+               maxtrk = tsize.last_track;
+               if (type == 6) {
+                       maxtrk = 0;
+               }
+               for (i = 0; i <= maxtrk; i++) {
+                       s = trackp[i].text;
+                       if (s)
+                               s = ((textptr_t *)s)->textcodes[type];
+                       if (s)
+                               fillpacks(&targ, s, strlen(s)+1, i, 0x80| type);
+                       else
+                               fillpacks(&targ, "", 1, i, 0x80| type);
+
+               }
+               fillup_pack(&targ);
+       }
+
+       /*
+        * targ.seqno overshoots by one and we add 3 size packs...
+        */
+       tsize.last_seqnum[0] = targ.seqno + 2;
+
+       for (i = 0; i < 3; i++) {
+               fillpacks(&targ, &((char *)(&tsize))[i*12], 12, i, 0x8f);
+       }
+
+       setuptextdata((Uchar *)sbuf, targ.seqno*18);
+
+#ifdef DEBUG
+       {       FILE    *f;
+
+       f = fileopen("cdtext.new", "wctb");
+       if (f) {
+               filewrite(f, sbuf, targ.seqno*18);
+               fflush(f);
+               fclose(f);
+       }
+       }
+#endif
+}
+
+static BOOL anytext(int pack_type, int tracks, track_t *trackp)
+{
+       register int    i;
+       register char   *p;
+
+       for (i = 0; i <= tracks; i++) {
+               if (trackp[i].text == NULL)
+                       continue;
+               p = ((textptr_t *)(trackp[i].text))->textcodes[pack_type];
+               if (p != NULL && *p != '\0')
+                       return (TRUE);
+       }
+       return (FALSE);
+}
+
+static void fillup_pack(register txtarg_t *ap)
+{
+       if (ap->p) {
+               fillbytes(ap->p, &ap->tp->text[12] - ap->p, '\0');
+               fillcrc((Uchar *)ap->tp, sizeof (*ap->tp));
+               ap->p  = 0;
+               ap->tp++;
+       }
+}
+
+static void fillpacks(register txtarg_t *ap, register char *from, int len, 
+                                        int track_no, int pack_type)
+{
+       register int            charpos;
+       register char           *p;
+       register txtpack_t      *tp;
+
+       tp = ap->tp;
+       p  = ap->p;
+       charpos = 0;
+       do {
+               if (p == 0) {
+                       p = tp->text;
+                       tp->pack_type = pack_type;
+                       if (pack_type != 0x8f)
+                               ap->tsize->pack_count[pack_type & 0x0F]++;
+                       tp->track_no = track_no;
+                       tp->seq_number = ap->seqno++;
+                       if (charpos < 15)
+                               tp->block_number = charpos;
+                       else
+                               tp->block_number = 15;
+               }
+               for (; --len >= 0 && p < &tp->text[12]; charpos++) {
+                       *p++ = *from++;
+               }
+               len++;  /* Overshoot compensation */
+
+               if (p >= &tp->text[12]) {
+                       fillcrc((Uchar *)tp, sizeof (*tp));
+                       p = 0;
+                       tp++;
+               }
+       } while (len > 0);
+
+       ap->tp = tp;
+       ap->p = p;
+}
+
+int write_cdtext(SCSI *usalp, cdr_t *dp, long startsec)
+{
+       char    *bp = (char *)textsub;
+       int     buflen = textlen;
+       long    amount;
+       long    bytes = 0;
+       long    end = -150;
+       int     secspt = textlen / 96;
+       int     bytespt = textlen;
+       long    maxdma = usalp->maxbuf;
+       int     idx;
+       int     secs;
+       int     nbytes;
+
+/*maxdma = 4320;*/
+       if (maxdma >= (2*textlen)) {
+               /*
+                * Try to make each CD-Text transfer use as much data
+                * as possible.
+                */
+               bp = usalp->bufptr;
+               for (idx = 0; (idx + textlen) <= maxdma; idx += textlen)
+                       movebytes(textsub, &bp[idx], textlen);
+               buflen = idx;
+               secspt = buflen / 96;
+               bytespt = buflen;
+/*printf("textlen: %d buflen: %d secspt: %d\n", textlen, buflen, secspt);*/
+       } else if (maxdma < buflen) {
+               /*
+                * We have more CD-Text data than we may transfer at once.
+                */
+               secspt = maxdma / 96;
+               bytespt = secspt * 96;
+       }
+       while (startsec < end) {
+               if ((end - startsec) < secspt) {
+                       secspt = end - startsec;
+                       bytespt = secspt * 96;
+               }
+               idx = 0;
+               secs = secspt;
+               nbytes = bytespt;
+               do {                    /* loop over CD-Text data buffer */
+
+                       if ((idx + nbytes) > buflen) {
+                               nbytes = buflen - idx;
+                               secs = nbytes / 96;
+                       }
+/*printf("idx: %d nbytes: %d secs: %d startsec: %ld\n",*/
+/*idx, nbytes, secs, startsec);*/
+                       amount = write_secs(usalp, dp,
+                               (char *)&bp[idx], startsec, nbytes, secs, FALSE);
+                       if (amount < 0) {
+                               printf("write CD-Text data: error after %ld bytes\n",
+                                               bytes);
+                               return (-1);
+                       }
+                       bytes += amount;
+                       idx += amount;
+                       startsec += secs;
+               } while (idx < buflen && startsec < end);
+       }
+       return (0);
+}
+
+
+/*
+ * 3 input bytes (8 bit based) are converted into 4 output bytes (6 bit based).
+ */
+static void eight2six(register Uchar *in, register Uchar *out)
+{
+       register int    c;
+
+       c = in[0];
+       out[0]  = (c >> 2) & 0x3F;
+       out[1]  = (c & 0x03) << 4;
+
+       c = in[1];
+       out[1] |= (c & 0xF0) >> 4;
+       out[2]  = (c & 0x0F) << 2;
+
+       c = in[2];
+       out[2] |= (c & 0xC0) >> 6;
+       out[3]  = c & 0x3F;
+}
+
+/*
+ * 4 input bytes (6 bit based) are converted into 3 output bytes (8 bit based).
+ */
+static void six2eight(register Uchar *in, register Uchar *out)
+{
+       register int    c;
+
+       c = in[0] & 0x3F;
+       out[0]  = c << 2;
+
+       c = in[1] & 0x3F;
+       out[0] |= c >> 4;
+       out[1]  = c << 4;
+
+       c = in[2] & 0x3F;
+       out[1] |= c >> 2;
+       out[2]  = c << 6;
+
+       c = in[3] & 0x3F;
+       out[2] |= c;
+}
diff --git a/wodim/cdtext.h b/wodim/cdtext.h
new file mode 100644 (file)
index 0000000..89808c6
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)cdtext.h        1.5 04/03/02 Copyright 1999-2004 J. Schilling */
+/*
+ *     Generic CD-Text support definitions
+ *
+ *     Copyright (c) 1999-2004 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef        CDTEXT_H
+#define        CDTEXT_H
+
+/*
+ * Strings for the CD-Text Pack Type indicators 0x80...0x8F
+ * We cannot use a plain structure here because we like to loop
+ * over all members.
+ */
+typedef struct textcodes {
+       char    *textcodes[16];
+} textptr_t;
+
+#define        tc_title        textcodes[0x00]
+#define        tc_performer    textcodes[0x01]
+#define        tc_songwriter   textcodes[0x02]
+#define        tc_composer     textcodes[0x03]
+#define        tc_arranger     textcodes[0x04]
+#define        tc_message      textcodes[0x05]
+#define        tc_diskid       textcodes[0x06]
+#define        tc_genre        textcodes[0x07]
+#define        tc_toc          textcodes[0x08]
+#define        tc_toc2         textcodes[0x09]
+
+#define        tc_closed_info  textcodes[0x0d]
+#define        tc_isrc         textcodes[0x0e]
+
+/*
+ *     binaere Felder sind
+ *     Disc ID                 (Wirklich ???)
+ *     Genre ID
+ *     TOC
+ *     Second TOC
+ *     Size information
+ */
+
+/*
+ * Genre codes from Enhanced CD Specification page 21
+ */
+#define        GENRE_UNUSED            0       /* not used                         */
+#define        GENRE_UNDEFINED         1       /* not defined                      */
+#define        GENRE_ADULT_CONTEMP     2       /* Adult Contemporary               */
+#define        GENRE_ALT_ROCK          3       /* Alternative Rock                 */
+#define        GENRE_CHILDRENS         4       /* Childrens Music                  */
+#define        GENRE_CLASSIC           5       /* Classical                        */
+#define        GENRE_CHRIST_CONTEMP    6       /* Contemporary Christian           */
+#define        GENRE_COUNTRY           7       /* Country                          */
+#define        GENRE_DANCE             8       /* Dance                            */
+#define        GENRE_EASY_LISTENING    9       /* Easy Listening                   */
+#define        GENRE_EROTIC            10      /* Erotic                           */
+#define        GENRE_FOLK              11      /* Folk                             */
+#define        GENRE_GOSPEL            12      /* Gospel                           */
+#define        GENRE_HIPHOP            13      /* Hip Hop                          */
+#define        GENRE_JAZZ              14      /* Jazz                             */
+#define        GENRE_LATIN             15      /* Latin                            */
+#define        GENRE_MUSICAL           16      /* Musical                          */
+#define        GENRE_NEWAGE            17      /* New Age                          */
+#define        GENRE_OPERA             18      /* Opera                            */
+#define        GENRE_OPERETTA          19      /* Operetta                         */
+#define        GENRE_POP               20      /* Pop Music                        */
+#define        GENRE_RAP               21      /* RAP                              */
+#define        GENRE_REGGAE            22      /* Reggae                           */
+#define        GENRE_ROCK              23      /* Rock Music                       */
+#define        GENRE_RYTHMANDBLUES     24      /* Rhythm & Blues                   */
+#define        GENRE_SOUNDEFFECTS      25      /* Sound Effects                    */
+#define        GENRE_SPOKEN_WORD       26      /* Spoken Word                      */
+#define        GENRE_WORLD_MUSIC       28      /* World Music                      */
+#define        GENRE_RESERVED          29      /* Reserved is 29..32767            */
+#define        GENRE_RIAA              32768   /* Registration by RIAA 32768..65535 */
+
+/*
+ * Character codings used in CD-Text data.
+ * Korean and Mandarin Chinese to be defined in sept 1996
+ */
+#define        CC_8859_1       0x00            /* ISO 8859-1                   */
+#define        CC_ASCII        0x01            /* ISO 646, ASCII (7 bit)       */
+#define        CC_RESERVED_02  0x02            /* Reserved codes 0x02..0x7f    */
+#define        CC_KANJI        0x80            /* Music Shift-JIS Kanji        */
+#define        CC_KOREAN       0x81            /* Korean                       */
+#define        CC_CHINESE      0x82            /* Mandarin Chinese             */
+#define        CC_RESERVED_83  0x83            /* Reserved codes 0x83..0xFF    */
+
+
+/*
+ * The language code is encoded as specified in ANNEX 1 to part 5 of EBU
+ * Tech 32 58 -E (1991).
+ *
+ * The current language codes are guessed
+ */
+#define        LANG_CZECH       6              /* 0x06                         */
+#define        LANG_DANISH      7              /* 0x07                         */
+#define        LANG_GERMAN      8              /* 0x08                         */
+#define        LANG_ENGLISH     9              /* 0x09                         */
+#define        LANG_SPANISH    10              /* 0x0A                         */
+#define        LANG_FRENCH     15              /* 0x0F                         */
+#define        LANG_ITALIAN    21              /* 0x15                         */
+#define        LANG_HUNGARIAN  27              /* 0x1B                         */
+#define        LANG_DUTCH      29              /* 0x1D                         */
+#define        LANG_NORWEGIAN  30              /* 0x1E                         */
+#define        LANG_POLISH     32              /* 0x20                         */
+#define        LANG_PORTUGUESE 33              /* 0x21                         */
+#define        LANG_SLOVENE    38              /* 0x26                         */
+#define        LANG_FINNISH    39              /* 0x27                         */
+#define        LANG_SWEDISH    40              /* 0x28                         */
+#define        LANG_RUSSIAN    86              /* 0x56                         */
+#define        LANG_KOREAN     101             /* 0x65                         */
+#define        LANG_JAPANESE   105             /* 0x69                         */
+#define        LANG_GREEK      112             /* 0x70                         */
+#define        LANG_CHINESE    117             /* 0x75                         */
+
+#endif
diff --git a/wodim/clone.c b/wodim/clone.c
new file mode 100644 (file)
index 0000000..da8fb91
--- /dev/null
@@ -0,0 +1,270 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)clone.c 1.7 04/03/02 Copyright 2001-2004 J. Schilling */
+/*
+ *     Clone Subchannel processing
+ *
+ *     Copyright (c) 2001-2004 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <mconfig.h>
+#include <stdio.h>
+#include <fctldefs.h>
+#include <strdefs.h>
+#include <unixstd.h>
+#include <standard.h>
+#include <btorder.h>
+#include <utypes.h>
+#include <schily.h>
+
+#include <usal/usalcmd.h>
+#include <usal/scsitransp.h>
+
+#include "wodim.h"
+#include "crc16.h"
+
+#include <usal/scsireg.h>
+#include "scsimmc.h"
+
+/*#define      SAO_RAW*/
+
+void   clone_toc(track_t *trackp);
+void   clone_tracktype(track_t *trackp);
+
+extern int     lverbose;
+extern int     xdebug;
+
+extern Uchar   _subq[110][12];
+extern int     _nsubh;
+
+
+static int     ctrl_first;
+static int     ctrl_last;
+static int     sectype_first;
+static int     sectype_last;
+static int     disktype;
+static long    loutstart;
+
+/*
+ * Read Clone TOC description from full toc file.
+ */
+void clone_toc(track_t *trackp)
+{
+       char    filename[1024];
+       msf_t   m;
+       msf_t   mr;
+       struct  tocheader *tp;
+       struct  ftrackdesc *fp;
+       int     f;
+       char    buf[2048];
+       int     amt;
+       int     len;
+       int     i;
+       int     j;
+       int     ctrladr;
+       Uint    first = 100;
+       Uint    last = 0;
+
+       len = strlen(trackp[1].filename);
+       if (len > (sizeof (filename)-5)) {
+               len = sizeof (filename)-5;
+       }
+       snprintf(filename, sizeof (filename), "%.*s.toc", len, trackp[1].filename);
+
+       f = open(filename, O_RDONLY|O_BINARY);
+       if (f < 0)
+               comerr("Cannot open '%s'.\n", filename);
+       amt = read(f, buf, sizeof (buf));
+
+       if (amt == sizeof (buf))
+               comerrno(EX_BAD, "TOC too large.\n");
+       close(f);
+       tp = (struct tocheader *)buf;
+       len = a_to_u_2_byte(tp->len) + sizeof (struct tocheader)-2;
+
+       if (xdebug) {
+               printf("Read %d bytes TOC len: %d first session: %d last session: %d\n",
+                       amt, len, tp->first, tp->last);
+       }
+
+       fp = (struct ftrackdesc *)&buf[4];
+
+       for (i = 4, j = 0; i < len; i += 11) {
+               fp = (struct ftrackdesc *)&buf[i];
+               if (xdebug)
+                       usal_prbytes("FT", (Uchar *)&buf[i], 11);
+               if (fp->sess_number != 1)
+                       comerrno(EX_BAD, "Can only copy session # 1.\n");
+
+               if (fp->adr == 1) {
+                       if (fp->point < first) {
+                               first = fp->point;
+                               ctrl_first = fp->control;
+                       }
+                       if (fp->point <= 99 && fp->point > last) {
+                               last = fp->point;
+                               ctrl_last = fp->control;
+                       }
+               }
+               if (fp->adr != 1) {
+                       switch (fp->point) {
+
+                       case 0xB0:
+                       case 0xC0:
+                       case 0xC1:
+                               break;
+                       default:
+                               continue;
+                       }
+               }
+               m.msf_min    = fp->amin;
+               m.msf_sec    = fp->asec;
+               m.msf_frame  = fp->aframe;
+
+               mr.msf_min   = fp->pmin;
+               mr.msf_sec   = fp->psec;
+               mr.msf_frame = fp->pframe;
+
+               if (fp->point == 0xA0) {
+                       disktype = mr.msf_sec;
+                       mr.msf_sec = from_bcd(mr.msf_sec);              /* convert to BCD */
+               }
+
+               if (fp->point == 0xA2)
+                       loutstart = msf_to_lba(fp->pmin, fp->psec, fp->pframe, TRUE);
+               ctrladr = fp->control << 4;
+               ctrladr |= fp->adr;
+
+               filltpoint(_subq[j], ctrladr, fp->point, &mr);
+               fillttime(_subq[j], &m);
+               _subq[j][6] = fp->res7;
+               if (fp->point == 0xC0 || fp->point == 0xC1) {
+                       _subq[j][3] = m.msf_min;
+                       _subq[j][4] = m.msf_sec;
+                       _subq[j][5] = m.msf_frame;
+               }
+               if (fp->point == 0xC1) {
+                       _subq[j][7] = mr.msf_min;
+                       _subq[j][8] = mr.msf_sec;
+                       _subq[j][9] = mr.msf_frame;
+               }
+               if (xdebug)
+                       usal_prbytes("TOC  ", _subq[j], 12);
+               j++;
+       }
+       _nsubh = j;
+       if (xdebug) {
+               printf("nsubheader %d lout: %ld track 1 secs: %ld\n", j, loutstart, trackp[1].tracksecs);
+               printf("first %u last %u ctrl first: %X ctrl last %X\n", first, last, ctrl_first, ctrl_last);
+       }
+       if (trackp->tracks != 1)
+               comerrno(EX_BAD, "Clone writing currently supports only one file argument.\n");
+       if (loutstart > trackp[1].tracksecs)
+               comerrno(EX_BAD, "Clone writing TOC length %ld does not match track length %ld\n",
+                       loutstart, trackp[1].tracksecs);
+
+       if (amt > len) {
+               sectype_first = buf[len];
+               sectype_last = buf[len+1];
+               if (xdebug) {
+                       printf("sectype first: %X sectype last %X\n",
+                               sectype_first, sectype_last);
+               }
+       }
+}
+
+
+/*
+ * Set tracktypes for track 0 (lead-in) & track AA (lead-out)
+ *
+ * Control 0 = audio
+ * Control 1 = audio preemp
+ * Control 2 = audio copy
+ * Control 3 = audio copy preemp
+ * Control 4 = data
+ * Control 5 = packet data
+ */
+void clone_tracktype(track_t *trackp)
+{
+       int     tracks = trackp->tracks;
+       int     sectype;
+
+       sectype = SECT_ROM;
+       if ((ctrl_first & TM_DATA) == 0) {
+               sectype = SECT_AUDIO;
+
+               if ((ctrl_first & TM_PREEM) != 0) {
+                       trackp[0].flags |= TI_PREEMP;
+               } else {
+                       trackp[0].flags &= ~TI_PREEMP;
+                       sectype |= ST_PREEMPMASK;
+               }
+               if ((ctrl_first & TM_ALLOW_COPY) != 0) {
+                       trackp[0].flags |= TI_COPY;
+               } else {
+                       trackp[0].flags &= ~TI_COPY;
+               }
+/* XXX ???     flags |= TI_SCMS; */
+       } else {
+               if ((ctrl_first & TM_INCREMENTAL) != 0) {
+                       trackp[0].flags |= TI_PACKET;
+               } else {
+                       trackp[0].flags &= ~TI_PACKET;
+               }
+               if (sectype_first != 0)
+                       sectype = sectype_first;
+       }
+       trackp[0].sectype = sectype;
+
+       sectype = SECT_ROM;
+
+       if ((ctrl_last & TM_DATA) == 0) {
+               sectype = SECT_AUDIO;
+
+               if ((ctrl_last & TM_PREEM) != 0) {
+                       trackp[tracks+1].flags |= TI_PREEMP;
+               } else {
+                       trackp[tracks+1].flags &= ~TI_PREEMP;
+                       sectype |= ST_PREEMPMASK;
+               }
+               if ((ctrl_last & TM_ALLOW_COPY) != 0) {
+                       trackp[tracks+1].flags |= TI_COPY;
+               } else {
+                       trackp[tracks+1].flags &= ~TI_COPY;
+               }
+/* XXX ???     flags |= TI_SCMS; */
+       } else {
+               if ((ctrl_first & TM_INCREMENTAL) != 0) {
+                       trackp[0].flags |= TI_PACKET;
+               } else {
+                       trackp[0].flags &= ~TI_PACKET;
+                       if (sectype_last != 0)
+                               sectype = sectype_last;
+               }
+       }
+       trackp[tracks+1].sectype = sectype;
+}
diff --git a/wodim/crc16.c b/wodim/crc16.c
new file mode 100644 (file)
index 0000000..8eecf04
--- /dev/null
@@ -0,0 +1,160 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)crc16.c 1.6 04/03/02 Copyright 1998-2004 J. Schilling */
+/*
+ *     Q-subchannel CRC subroutines
+ *
+ *     Polynom is: p(x) = x ** 16 + x ** 12 + x ** 5 + 1
+ *     If computed over 12 bytes, the result must be zero.
+ *     On the disk the CRC bits are inverted.
+ *
+ *     Copyright (c) 1998-2003 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <mconfig.h>
+#include <standard.h>
+#include <utypes.h>
+#include "crc16.h"
+
+static UInt16_t        updcrc(Uint p_crc, UInt8_t *cp, Uint cnt);
+UInt16_t       calcCRC(Uchar *buf, Uint bsize);
+UInt16_t       fillcrc(Uchar *buf, Uint bsize);
+UInt16_t       flip_crc_error_corr(Uchar *b, Uint bsize, Uint p_crc);
+
+
+       /* number of bits in CRC: don't change it. */
+#define        BPW     16
+
+       /* this the number of bits per char: don't change it. */
+#define        BPB     8
+
+static UInt16_t crctab[1<<BPB] = {
+    0x0000,  0x1021,  0x2042,  0x3063,  0x4084,  0x50a5,  0x60c6,  0x70e7,
+    0x8108,  0x9129,  0xa14a,  0xb16b,  0xc18c,  0xd1ad,  0xe1ce,  0xf1ef,
+    0x1231,  0x0210,  0x3273,  0x2252,  0x52b5,  0x4294,  0x72f7,  0x62d6,
+    0x9339,  0x8318,  0xb37b,  0xa35a,  0xd3bd,  0xc39c,  0xf3ff,  0xe3de,
+    0x2462,  0x3443,  0x0420,  0x1401,  0x64e6,  0x74c7,  0x44a4,  0x5485,
+    0xa56a,  0xb54b,  0x8528,  0x9509,  0xe5ee,  0xf5cf,  0xc5ac,  0xd58d,
+    0x3653,  0x2672,  0x1611,  0x0630,  0x76d7,  0x66f6,  0x5695,  0x46b4,
+    0xb75b,  0xa77a,  0x9719,  0x8738,  0xf7df,  0xe7fe,  0xd79d,  0xc7bc,
+    0x48c4,  0x58e5,  0x6886,  0x78a7,  0x0840,  0x1861,  0x2802,  0x3823,
+    0xc9cc,  0xd9ed,  0xe98e,  0xf9af,  0x8948,  0x9969,  0xa90a,  0xb92b,
+    0x5af5,  0x4ad4,  0x7ab7,  0x6a96,  0x1a71,  0x0a50,  0x3a33,  0x2a12,
+    0xdbfd,  0xcbdc,  0xfbbf,  0xeb9e,  0x9b79,  0x8b58,  0xbb3b,  0xab1a,
+    0x6ca6,  0x7c87,  0x4ce4,  0x5cc5,  0x2c22,  0x3c03,  0x0c60,  0x1c41,
+    0xedae,  0xfd8f,  0xcdec,  0xddcd,  0xad2a,  0xbd0b,  0x8d68,  0x9d49,
+    0x7e97,  0x6eb6,  0x5ed5,  0x4ef4,  0x3e13,  0x2e32,  0x1e51,  0x0e70,
+    0xff9f,  0xefbe,  0xdfdd,  0xcffc,  0xbf1b,  0xaf3a,  0x9f59,  0x8f78,
+    0x9188,  0x81a9,  0xb1ca,  0xa1eb,  0xd10c,  0xc12d,  0xf14e,  0xe16f,
+    0x1080,  0x00a1,  0x30c2,  0x20e3,  0x5004,  0x4025,  0x7046,  0x6067,
+    0x83b9,  0x9398,  0xa3fb,  0xb3da,  0xc33d,  0xd31c,  0xe37f,  0xf35e,
+    0x02b1,  0x1290,  0x22f3,  0x32d2,  0x4235,  0x5214,  0x6277,  0x7256,
+    0xb5ea,  0xa5cb,  0x95a8,  0x8589,  0xf56e,  0xe54f,  0xd52c,  0xc50d,
+    0x34e2,  0x24c3,  0x14a0,  0x0481,  0x7466,  0x6447,  0x5424,  0x4405,
+    0xa7db,  0xb7fa,  0x8799,  0x97b8,  0xe75f,  0xf77e,  0xc71d,  0xd73c,
+    0x26d3,  0x36f2,  0x0691,  0x16b0,  0x6657,  0x7676,  0x4615,  0x5634,
+    0xd94c,  0xc96d,  0xf90e,  0xe92f,  0x99c8,  0x89e9,  0xb98a,  0xa9ab,
+    0x5844,  0x4865,  0x7806,  0x6827,  0x18c0,  0x08e1,  0x3882,  0x28a3,
+    0xcb7d,  0xdb5c,  0xeb3f,  0xfb1e,  0x8bf9,  0x9bd8,  0xabbb,  0xbb9a,
+    0x4a75,  0x5a54,  0x6a37,  0x7a16,  0x0af1,  0x1ad0,  0x2ab3,  0x3a92,
+    0xfd2e,  0xed0f,  0xdd6c,  0xcd4d,  0xbdaa,  0xad8b,  0x9de8,  0x8dc9,
+    0x7c26,  0x6c07,  0x5c64,  0x4c45,  0x3ca2,  0x2c83,  0x1ce0,  0x0cc1,
+    0xef1f,  0xff3e,  0xcf5d,  0xdf7c,  0xaf9b,  0xbfba,  0x8fd9,  0x9ff8,
+    0x6e17,  0x7e36,  0x4e55,  0x5e74,  0x2e93,  0x3eb2,  0x0ed1,  0x1ef0,
+};
+
+#define        SUBSIZE 96      /* 12 bytes with 8 bits */
+
+static UInt16_t 
+updcrc(Uint p_crc, register UInt8_t *cp, register Uint cnt)
+{
+       register UInt16_t       crc = p_crc;
+
+       while (cnt-- > 0) {
+               crc = (crc<<BPB) ^ crctab[(crc>>(BPW-BPB)) ^ (*cp++)];
+       }
+       return (crc);
+}
+
+/*static UInt16_t*/
+UInt16_t 
+calcCRC(Uchar *buf, Uint bsize)
+{
+       return (updcrc(0x0000, (UInt8_t *)buf, bsize));
+}
+
+/*
+ * CRC für Q-Sub füllen
+ */
+UInt16_t 
+fillcrc(Uchar *buf, Uint bsize)
+{
+       UInt16_t        crc = calcCRC(buf, bsize-2);
+
+       /*
+        * Invert CRC bits for RED Book compliance.
+        */
+       crc = crc ^ 0xFFFF;
+
+       buf[bsize-2] = (crc >> 8) & 0xFF;
+       buf[bsize-1] = crc & 0xFF;
+       return (crc);
+}
+
+static UInt8_t fliptab[BPB] = {
+       0x01,
+       0x02,
+       0x04,
+       0x08,
+       0x10,
+       0x20,
+       0x40,
+       0x80,
+};
+
+UInt16_t 
+flip_crc_error_corr(Uchar *b, Uint bsize, Uint p_crc)
+{
+       register UInt16_t       crc = p_crc;
+       register Uint           btsize = bsize * BPB;
+
+       if (crc != 0) {
+               int     i;
+
+               for (i = 0; i < btsize; i++) {
+                       UInt8_t c;
+
+                       c = fliptab[i % BPB];
+                       b[i / BPB] ^= c;
+                       if ((crc = calcCRC(b, bsize)) == 0) {
+                               return (crc);
+                       }
+                       b[i / BPB] ^= c;
+               }
+       }
+       return (crc & 0xffff);
+}
diff --git a/wodim/crc16.h b/wodim/crc16.h
new file mode 100644 (file)
index 0000000..c8f425c
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)crc16.h 1.3 02/03/04 Copyright 1998-2002 J. Schilling */
+/*
+ *     Q-subchannel CRC definitions
+ *
+ *     Copyright (c) 1998-2002 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef        _CRC16_H
+#define        _CRC16_H
+
+extern UInt16_t        calcCRC(Uchar *buf, Uint bsize);
+extern UInt16_t        fillcrc(Uchar *buf, Uint bsize);
+extern UInt16_t        flip_crc_error_corr(Uchar *b, Uint bsize, Uint p_crc);
+
+#endif
diff --git a/wodim/cue.c b/wodim/cue.c
new file mode 100644 (file)
index 0000000..0eb88b3
--- /dev/null
@@ -0,0 +1,1198 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)cue.c   1.20 04/03/02 Copyright 2001-2004 J. Schilling */
+/*
+ *     Cue sheet parser
+ *
+ *     Copyright (c) 2001-2004 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <mconfig.h>
+#include <stdio.h>
+#include <stdxlib.h>
+#include <unixstd.h>
+#include <standard.h>
+#include <fctldefs.h>
+#include <statdefs.h>
+#include <vadefs.h>
+#include <schily.h>
+#include <strdefs.h>
+#include <utypes.h>
+#include <ctype.h>
+#include <errno.h>
+
+#include "xio.h"
+#include "cdtext.h"
+#include "wodim.h"
+#include "auheader.h"
+#include "libport.h"
+
+typedef struct state {
+       char    *filename;
+       void    *xfp;
+       Llong   trackoff;
+       Llong   filesize;
+       int     filetype;
+       int     tracktype;
+       int     sectype;
+       int     dbtype;
+       int     secsize;
+       int     dataoff;
+       int     state;
+       int     track;
+       int     index;
+       long    index0;
+       long    index1;         /* Current index 1 value        */
+       long    secoff;         /* Old index 1 value            */
+       long    pregapsize;
+       long    postgapsize;
+       int     flags;
+} state_t;
+
+static char    linebuf[4096];
+static char    *fname;
+static char    *linep;
+static char    *wordendp;
+static char    wordendc;
+static int     olinelen;
+static int     linelen;
+static int     lineno;
+
+static char    worddelim[] = "=:,/";
+static char    nulldelim[] = "";
+
+#define        STATE_NONE      0
+#define        STATE_POSTGAP   1
+#define        STATE_TRACK     2
+#define        STATE_FLAGS     3
+#define        STATE_INDEX0    4
+#define        STATE_INDEX1    5
+
+typedef struct keyw {
+       char    *k_name;
+       int     k_type;
+} keyw_t;
+
+/*
+ *     Keywords (first word on line):
+ *             CATALOG         - global        CATALOG         <MCN>
+ *             CDTEXTFILE      - global        CDTEXTFILE      <fname>
+ *             FILE            - track static  FILE            <fame> <type>
+ *             FLAGS           - track static  FLAGS           <flag> ...
+ *             INDEX           - track static  INDEX           <#> <mm:ss:ff>
+ *             ISRC            - track static  ISRC            <ISRC>
+ *             PERFORMER       - global/static PERFORMER       <string>
+ *             POSTGAP         - track locak   POSTGAP         <mm:ss:ff>
+ *             PREGAP          - track static  PREGAP          <mm:ss:ff>
+ *             REM             - anywhere      REM             <comment>
+ *             SONGWRITER      - global/static SONGWRITER      <string>
+ *             TITLE           - global/static TITLE           <string>
+ *             TRACK           - track static  TRACK           <#> <datatype>
+ *
+ *     Order of keywords:
+ *             CATALOG
+ *             CDTEXTFILE
+ *             PERFORMER | SONGWRITER | TITLE          Doc says past FILE...
+ *             FILE                                    Must be past CATALOG
+ *             ------- Repeat the following:           mehrere FILE Commands?
+ *             TRACK
+ *             FLAGS | ISRC | PERFORMER | PREGAP | SONGWRITER | TITLE
+ *             INDEX
+ *             POSTGAP
+ */
+
+#define        K_G             0x10000         /* Global                       */
+#define        K_T             0x20000         /* Track static                 */
+#define        K_A             (K_T | K_G)     /* Global & Track static                */
+
+#define        K_MCN           (0 | K_G)       /* Media catalog number         */
+#define        K_TEXTFILE      (1 | K_G)       /* CD-Text binary file          */
+#define        K_FILE          (2 | K_T)       /* Input data file              */
+#define        K_FLAGS         (3 | K_T)       /* Flags for ctrl nibble        */
+#define        K_INDEX         (4 | K_T)       /* Index marker for track       */
+#define        K_ISRC          (5 | K_T)       /* ISRC string for track        */
+#define        K_PERFORMER     (6 | K_A)       /* CD-Text Performer            */
+#define        K_POSTGAP       (7 | K_T)       /* Post gap for track (autogen) */
+#define        K_PREGAP        (8 | K_T)       /* Pre gap for track (autogen)  */
+#define        K_REM           (9 | K_A)       /* Remark (Comment)             */
+#define        K_SONGWRITER    (10| K_A)       /* CD-Text Songwriter           */
+#define        K_TITLE         (11| K_A)       /* CD-Text Title                */
+#define        K_TRACK         (12| K_T)       /* Track marker                 */
+
+
+static keyw_t  keywords[] = {
+       { "CATALOG",    K_MCN },
+       { "CDTEXTFILE", K_TEXTFILE },
+       { "FILE",       K_FILE },
+       { "FLAGS",      K_FLAGS },
+       { "INDEX",      K_INDEX },
+       { "ISRC",       K_ISRC },
+       { "PERFORMER",  K_PERFORMER },
+       { "POSTGAP",    K_POSTGAP },
+       { "PREGAP",     K_PREGAP },
+       { "REM",        K_REM },
+       { "SONGWRITER", K_SONGWRITER },
+       { "TITLE",      K_TITLE },
+       { "TRACK",      K_TRACK },
+       { NULL,         0 },
+};
+
+
+/*
+ *     Filetypes - argument to FILE Keyword (one only):
+ *
+ *             BINARY          - Intel binary file (least significant byte first)
+ *             MOTOTOLA        - Motorola binary file (most significant byte first)
+ *             AIFF            - Audio AIFF file
+ *             AU              - Sun Audio file
+ *             WAVE            - Audio WAVE file
+ *             MP3             - Audio MP3 file
+ */
+#define        K_BINARY        100
+#define        K_MOTOROLA      101
+#define        K_AIFF          102
+#define        K_AU            103
+#define        K_WAVE          104
+#define        K_MP3           105
+#define        K_OGG           106
+
+static keyw_t  filetypes[] = {
+       { "BINARY",     K_BINARY },
+       { "MOTOROLA",   K_MOTOROLA },
+       { "AIFF",       K_AIFF },
+       { "AU",         K_AU },
+       { "WAVE",       K_WAVE },
+       { "MP3",        K_MP3 },
+       { "OGG",        K_OGG },
+       { NULL,         0 },
+};
+
+/*
+ *     Flags - argument to FLAGS Keyword (more than one allowed):
+ *             DCP             - Digital copy permitted
+ *             4CH             - Four channel audio
+ *             PRE             - Pre-emphasis enabled (audio tracks only)
+ *             SCMS            - Serial copy management system (not supported by all recorders)
+ */
+#define        K_DCP           1000
+#define        K_4CH           1001
+#define        K_PRE           1002
+#define        K_SCMS          1003
+
+static keyw_t  flags[] = {
+       { "DCP",        K_DCP },
+       { "4CH",        K_4CH },
+       { "PRE",        K_PRE },
+       { "SCMS",       K_SCMS },
+       { NULL,         0 },
+};
+
+/*
+ *     Datatypes - argument to TRACK Keyword (one only):
+ *             AUDIO           - Audio/Music (2352)
+ *             CDG             - Karaoke CD+G (2448)
+ *             MODE1/2048      - CDROM Mode1 Data (cooked)
+ *             MODE1/2352      - CDROM Mode1 Data (raw)
+ *             MODE2/2336      - CDROM-XA Mode2 Data
+ *             MODE2/2352      - CDROM-XA Mode2 Data
+ *             CDI/2336        - CDI Mode2 Data
+ *             CDI/2352        - CDI Mode2 Data
+ */
+#define        K_AUDIO         10000
+#define        K_CDG           10001
+#define        K_MODE1         10002
+#define        K_MODE2         10003
+#define        K_CDI           10004
+
+static keyw_t  dtypes[] = {
+       { "AUDIO",      K_AUDIO },
+       { "CDG",        K_CDG },
+       { "MODE1",      K_MODE1 },
+       { "MODE2",      K_MODE2 },
+       { "CDI",        K_CDI },
+       { NULL,         0 },
+};
+
+
+int    parsecue(char *cuefname, track_t trackp[]);
+void   fparsecue(FILE *f, track_t trackp[]);
+static void    parse_mcn(track_t trackp[], state_t *sp);
+static void    parse_textfile(track_t trackp[], state_t *sp);
+static void    parse_file(track_t trackp[], state_t *sp);
+static void    parse_flags(track_t trackp[], state_t *sp);
+static void    parse_index(track_t trackp[], state_t *sp);
+static void    parse_isrc(track_t trackp[], state_t *sp);
+static void    parse_performer(track_t trackp[], state_t *sp);
+static void    parse_postgap(track_t trackp[], state_t *sp);
+static void    parse_pregap(track_t trackp[], state_t *sp);
+static void    parse_songwriter(track_t trackp[], state_t *sp);
+static void    parse_title(track_t trackp[], state_t *sp);
+static void    parse_track(track_t trackp[], state_t *sp);
+static void    parse_offset(long *lp);
+static void    newtrack(track_t trackp[], state_t *sp);
+
+static keyw_t  *lookup(char *word, keyw_t table[]);
+static void    wdebug(void);
+static FILE    *cueopen(char *name);
+static char    *cuename(void);
+static char    *nextline(FILE *f);
+static void    ungetline(void);
+static char    *skipwhite(const char *s);
+static char    *peekword(void);
+static char    *lineend(void);
+static char    *markword(char *delim);
+static char    *getnextitem(char *delim);
+static char    *neednextitem(char *delim);
+static char    *nextword(void);
+static char    *needword(void);
+static char    *curword(void);
+static char    *nextitem(void);
+static char    *needitem(void);
+static void    checkextra(void);
+static void    cueabort(const char *fmt, ...);
+
+#ifdef CUE_MAIN
+int    debug;
+int    xdebug = 1;
+
+int write_secs(void);
+int write_secs() { return (-1); }
+
+int 
+main(int argc, char *argv[])
+{
+       int     i;
+       track_t track[MAX_TRACK+2];     /* Max tracks + track 0 + track AA */
+
+       save_args(argc, argv);
+
+       fillbytes(track, sizeof (track), '\0');
+       for (i = 0; i < MAX_TRACK+2; i++)
+               track[i].track = track[i].trackno = i;
+       track[0].tracktype = TOC_MASK;
+
+
+       parsecue(argv[1], track);
+       return (0);
+}
+#else
+extern int     xdebug;
+#endif
+
+int 
+parsecue(char *cuefname, track_t trackp[])
+{
+       FILE    *f = cueopen(cuefname);
+
+       fparsecue(f, trackp);
+       return (0);
+}
+
+void 
+fparsecue(FILE *f, track_t trackp[])
+{
+       char    *word;
+       struct keyw *kp;
+       BOOL    isglobal = TRUE;
+       state_t state;
+
+       state.filename  = NULL;
+       state.xfp       = NULL;
+       state.trackoff  = 0;
+       state.filesize  = 0;
+       state.filetype  = 0;
+       state.tracktype = 0;
+       state.sectype   = 0;
+       state.dbtype    = 0;
+       state.secsize   = 0;
+       state.dataoff   = 0;
+       state.state     = STATE_NONE;
+       state.track     = 0;
+       state.index     = -1;
+       state.index0    = -1;
+       state.index1    = -1;
+       state.secoff    = 0;
+       state.pregapsize = -1;
+       state.postgapsize = -1;
+       state.flags     = 0;
+
+       if (xdebug > 1)
+               printf("---> Entering CUE Parser...\n");
+       do {
+               if (nextline(f) == NULL) {
+                       /*
+                        * EOF on CUE File
+                        * Do post processing here
+                        */
+                       if (state.state < STATE_INDEX1)
+                               cueabort("Incomplete CUE file");
+                       if (state.xfp)
+                               xclose(state.xfp);
+                       if (xdebug > 1) {
+                               printf("---> CUE Parser got EOF, found %d tracks.\n",
+                                                               state.track);
+                       }
+                       return;
+               }
+               word = nextitem();
+               if (*word == '\0')      /* empty line */
+                       continue;
+
+               if (xdebug > 1)
+                       printf("\nKEY: '%s'     %s\n", word, peekword());
+               kp = lookup(word, keywords);
+               if (kp == NULL)
+                       cueabort("Unknown CUE keyword '%s'", word);
+
+               if ((kp->k_type & K_G) == 0) {
+                       if (isglobal)
+                               isglobal = FALSE;
+               }
+               if ((kp->k_type & K_T) == 0) {
+                       if (!isglobal)
+                               cueabort("Badly placed CUE keyword '%s'", word);
+               }
+/*             printf("%s-", isglobal ? "G" : "T");*/
+/*             wdebug();*/
+
+               switch (kp->k_type) {
+
+               case K_MCN:        parse_mcn(trackp, &state);           break;
+               case K_TEXTFILE:   parse_textfile(trackp, &state);      break;
+               case K_FILE:       parse_file(trackp, &state);          break;
+               case K_FLAGS:      parse_flags(trackp, &state);         break;
+               case K_INDEX:      parse_index(trackp, &state);         break;
+               case K_ISRC:       parse_isrc(trackp, &state);          break;
+               case K_PERFORMER:  parse_performer(trackp, &state);     break;
+               case K_POSTGAP:    parse_postgap(trackp, &state);       break;
+               case K_PREGAP:     parse_pregap(trackp, &state);        break;
+               case K_REM:                                             break;
+               case K_SONGWRITER: parse_songwriter(trackp, &state);    break;
+               case K_TITLE:      parse_title(trackp, &state);         break;
+               case K_TRACK:      parse_track(trackp, &state);         break;
+
+               default:
+                       cueabort("Panic: unknown CUE command '%s'", word);
+               }
+       } while (1);
+}
+
+static void 
+parse_mcn(track_t trackp[], state_t *sp)
+{
+       char    *word;
+       textptr_t *txp;
+
+       if (sp->track != 0)
+               cueabort("CATALOG keyword must be before first TRACK");
+
+       word = needitem();
+       setmcn(word, &trackp[0]);
+       txp = gettextptr(0, trackp); /* MCN is isrc for trk 0 */
+       txp->tc_isrc = strdup(word);
+
+       checkextra();
+}
+
+static void 
+parse_textfile(track_t trackp[], state_t *sp)
+{
+       char    *word;
+
+       if (sp->track != 0)
+               cueabort("CDTEXTFILE keyword must be before first TRACK");
+
+       word = needitem();
+
+       if (trackp[MAX_TRACK+1].flags & TI_TEXT) {
+               if (!checktextfile(word)) {
+                       comerrno(EX_BAD,
+                               "Cannot use '%s' as CD-Text file.\n",
+                               word);
+               }
+               trackp[0].flags |= TI_TEXT;
+       } else {
+               errmsgno(EX_BAD, "Ignoring CDTEXTFILE '%s'.\n", word);
+               errmsgno(EX_BAD, "If you like to write CD-Text, call wodim -text.\n");
+       }
+
+       checkextra();
+}
+
+static void 
+parse_file(track_t trackp[], state_t *sp)
+{
+       char    cname[1024];
+       char    newname[1024];
+       struct keyw *kp;
+       char    *word;
+       char    *filetype;
+       struct stat     st;
+#ifdef hint
+       Llong           lsize;
+#endif
+
+       if (sp->filename != NULL)
+               cueabort("Only one FILE allowed");
+
+       word = needitem();
+       if (sp->xfp)
+               xclose(sp->xfp);
+       sp->xfp = xopen(word, O_RDONLY|O_BINARY, 0);
+       if (sp->xfp == NULL && geterrno() == ENOENT) {
+               char    *p;
+
+               if (strchr(word, '/') == 0 &&
+                   strchr(cuename(), '/') != 0) {
+                       snprintf(cname, sizeof (cname),
+                               "%s", cuename());
+                       p = strrchr(cname, '/');
+                       if (p)
+                               *p = '\0';
+                       snprintf(newname, sizeof (newname),
+                               "%s/%s", cname, word);
+                       word = newname;
+                       sp->xfp = xopen(word, O_RDONLY|O_BINARY, 0);
+               }
+       }
+       if (sp->xfp == NULL)
+               comerr("Cannot open FILE '%s'.\n", word);
+
+       sp->filename     = strdup(word);
+       sp->trackoff     = 0;
+       sp->filesize     = 0;
+       sp->flags       &= ~TI_SWAB;    /* Reset what we might set for FILE */
+
+       filetype = needitem();
+       kp = lookup(filetype, filetypes);
+       if (kp == NULL)
+               cueabort("Unknown filetype '%s'", filetype);
+
+       switch (kp->k_type) {
+
+       case K_BINARY:
+       case K_MOTOROLA:
+                       if (fstat(xfileno(sp->xfp), &st) >= 0 &&
+                           S_ISREG(st.st_mode)) {
+                               sp->filesize = st.st_size;
+                       } else {
+                               cueabort("Unknown file size for FILE '%s'",
+                                                               sp->filename);
+                       }
+                       break;
+       case K_AIFF:
+                       cueabort("Unsupported filetype '%s'", kp->k_name);
+                       break;
+       case K_AU:
+                       sp->filesize = ausize(xfileno(sp->xfp));
+                       break;
+       case K_WAVE:
+                       sp->filesize = wavsize(xfileno(sp->xfp));
+                       sp->flags |= TI_SWAB;
+                       break;
+       case K_MP3:
+       case K_OGG:
+                       cueabort("Unsupported filetype '%s'", kp->k_name);
+                       break;
+
+       default:        cueabort("Panic: unknown filetype '%s'", filetype);
+       }
+
+       if (sp->filesize == AU_BAD_CODING) {
+               cueabort("Inappropriate audio coding in '%s'",
+                                                       sp->filename);
+       }
+       if (xdebug > 0)
+               printf("Track %d File '%s' Filesize %lld\n",
+                       sp->track, sp->filename, sp->filesize);
+
+       sp->filetype = kp->k_type;
+
+       checkextra();
+
+
+#ifdef hint
+               trackp->itracksize = lsize;
+               if (trackp->itracksize != lsize)
+                       comerrno(EX_BAD, "This OS cannot handle large audio images.\n");
+#endif
+}
+
+static void 
+parse_flags(track_t trackp[], state_t *sp)
+{
+       struct keyw *kp;
+       char    *word;
+
+       if ((sp->state < STATE_TRACK) ||
+           (sp->state >= STATE_INDEX0))
+               cueabort("Badly placed FLAGS keyword");
+       sp->state = STATE_FLAGS;
+
+       do {
+               word = needitem();
+               kp = lookup(word, flags);
+               if (kp == NULL)
+                       cueabort("Unknown flag '%s'", word);
+
+               switch (kp->k_type) {
+
+               case K_DCP:     sp->flags |= TI_COPY;   break;
+               case K_4CH:     sp->flags |= TI_QUADRO; break;
+               case K_PRE:     sp->flags |= TI_PREEMP; break;
+               case K_SCMS:    sp->flags |= TI_SCMS;   break;
+               default:        cueabort("Panic: unknown FLAG '%s'", word);
+               }
+
+       } while (peekword() < lineend());
+
+       if (xdebug > 0)
+               printf("Track %d flags 0x%08X\n", sp->track, sp->flags);
+}
+
+static void 
+parse_index(track_t trackp[], state_t *sp)
+{
+       char    *word;
+       long    l;
+       int     track = sp->track;
+
+       if (sp->state < STATE_TRACK)
+               cueabort("Badly placed INDEX keyword");
+
+
+       word = needitem();
+       if (*astolb(word, &l, 10) != '\0')
+               cueabort("Not a number '%s'", word);
+       if (l < 0 || l > 99)
+               cueabort("Illegal index '%s'", word);
+
+       if ((sp->index < l) &&
+           (((sp->index + 1) == l) || l == 1))
+               sp->index = l;
+       else
+               cueabort("Badly placed INDEX %ld number", l);
+
+       if (l > 0)
+               sp->state = STATE_INDEX1;
+       else
+               sp->state = STATE_INDEX0;
+
+       parse_offset(&l);
+
+       if (xdebug > 1)
+               printf("Track %d Index %d %ld\n", sp->track, sp->index, l);
+
+       if (sp->index == 0)
+               sp->index0 = l;
+       if (sp->index == 1) {
+               sp->index1 = l;
+               trackp[track].nindex = 1;
+               newtrack(trackp, sp);
+
+               if (xdebug > 1) {
+                       printf("Track %d pregapsize %ld\n",
+                               sp->track, trackp[track].pregapsize);
+               }
+       }
+       if (sp->index == 2) {
+               trackp[track].tindex = malloc(100*sizeof (long));
+               trackp[track].tindex[1] = 0;
+               trackp[track].tindex[2] = l - sp->index1;
+               trackp[track].nindex = 2;
+       }
+       if (sp->index > 2) {
+               trackp[track].tindex[sp->index] = l - sp->index1;
+               trackp[track].nindex = sp->index;
+       }
+
+       checkextra();
+}
+
+static void 
+parse_isrc(track_t trackp[], state_t *sp)
+{
+       char    *word;
+       textptr_t *txp;
+       int     track = sp->track;
+
+       if (track == 0)
+               cueabort("ISRC keyword must be past first TRACK");
+
+       if ((sp->state < STATE_TRACK) ||
+           (sp->state >= STATE_INDEX0))
+               cueabort("Badly placed ISRC keyword");
+       sp->state = STATE_FLAGS;
+
+       word = needitem();
+       setisrc(word, &trackp[track]);
+       txp = gettextptr(track, trackp);
+       txp->tc_isrc = strdup(word);
+
+       checkextra();
+}
+
+static void 
+parse_performer(track_t trackp[], state_t *sp)
+{
+       char    *word;
+       textptr_t *txp;
+
+       word = needitem();
+       txp = gettextptr(sp->track, trackp);
+       txp->tc_performer = strdup(word);
+
+       checkextra();
+}
+
+static void 
+parse_postgap(track_t trackp[], state_t *sp)
+{
+       long    l;
+
+       if (sp->state < STATE_INDEX1)
+               cueabort("Badly placed POSTGAP keyword");
+       sp->state = STATE_POSTGAP;
+
+       parse_offset(&l);
+       sp->postgapsize = l;
+
+       checkextra();
+}
+
+static void 
+parse_pregap(track_t trackp[], state_t *sp)
+{
+       long    l;
+
+       if ((sp->state < STATE_TRACK) ||
+           (sp->state >= STATE_INDEX0))
+               cueabort("Badly placed PREGAP keyword");
+       sp->state = STATE_FLAGS;
+
+       parse_offset(&l);
+       sp->pregapsize = l;
+
+       checkextra();
+}
+
+static void 
+parse_songwriter(track_t trackp[], state_t *sp)
+{
+       char    *word;
+       textptr_t *txp;
+
+       word = needitem();
+       txp = gettextptr(sp->track, trackp);
+       txp->tc_songwriter = strdup(word);
+
+       checkextra();
+}
+
+static void 
+parse_title(track_t trackp[], state_t *sp)
+{
+       char    *word;
+       textptr_t *txp;
+
+       word = needitem();
+       txp = gettextptr(sp->track, trackp);
+       txp->tc_title = strdup(word);
+
+       checkextra();
+}
+
+static void 
+parse_track(track_t trackp[], state_t *sp)
+{
+       struct keyw *kp;
+       char    *word;
+       long    l;
+       long    secsize = -1;
+
+       if ((sp->state >= STATE_TRACK) &&
+           (sp->state < STATE_INDEX1))
+               cueabort("Badly placed TRACK keyword");
+       sp->state = STATE_TRACK;
+       sp->index = -1;
+
+       word = needitem();
+       if (*astolb(word, &l, 10) != '\0')
+               cueabort("Not a number '%s'", word);
+       if (l <= 0 || l > 99)
+               cueabort("Illegal TRACK number '%s'", word);
+
+       if ((sp->track < l) &&
+           (((sp->track + 1) == l) || sp->track == 0))
+               sp->track = l;
+       else
+               cueabort("Badly placed TRACK %ld number", l);
+
+       word = needword();
+       kp = lookup(word, dtypes);
+       if (kp == NULL)
+               cueabort("Unknown filetype '%s'", word);
+
+       if (wordendc == '/') {
+               word = needitem();
+               if (*astol(++word, &secsize) != '\0')
+                       cueabort("Not a number '%s'", word);
+       }
+
+       /*
+        * Reset all flags that may be set in TRACK & FLAGS lines
+        */
+       sp->flags &= ~(TI_AUDIO|TI_COPY|TI_QUADRO|TI_PREEMP|TI_SCMS);
+
+       if (kp->k_type == K_AUDIO)
+               sp->flags |= TI_AUDIO;
+
+       switch (kp->k_type) {
+
+       case K_CDG:
+               if (secsize < 0)
+                       secsize = 2448;
+       case K_AUDIO:
+               if (secsize < 0)
+                       secsize = 2352;
+
+               sp->tracktype = TOC_DA;
+               sp->sectype = SECT_AUDIO;
+               sp->dbtype = DB_RAW;
+               sp->secsize = secsize;
+               sp->dataoff = 0;
+               if (secsize != 2352)
+                       cueabort("Unsupported sector size %ld for audio", secsize);
+               break;
+
+       case K_MODE1:
+               if (secsize < 0)
+                       secsize = 2048;
+
+               sp->tracktype = TOC_ROM;
+               sp->sectype = SECT_ROM;
+               sp->dbtype = DB_ROM_MODE1;
+               sp->secsize = secsize;
+               sp->dataoff = 16;
+               /*
+                * XXX Sector Size == 2352 ???
+                * XXX It seems that there exist bin/cue pairs with this value
+                */
+               if (secsize != 2048)
+                       cueabort("Unsupported sector size %ld for data", secsize);
+               break;
+
+       case K_MODE2:
+       case K_CDI:
+               sp->tracktype = TOC_ROM;
+               sp->sectype = SECT_MODE_2;
+               sp->dbtype = DB_ROM_MODE2;
+               sp->secsize = secsize;
+               sp->dataoff = 16;
+               if (secsize == 2352) {
+                       sp->tracktype = TOC_XA2;
+                       sp->sectype = SECT_MODE_2_MIX;
+                       sp->sectype |= ST_MODE_RAW;
+                       sp->dbtype = DB_RAW;
+                       sp->dataoff = 0;
+               } else if (secsize != 2336)
+                       cueabort("Unsupported sector size %ld for mode2", secsize);
+               if (kp->k_type == K_CDI)
+                       sp->tracktype = TOC_CDI;
+               break;
+
+       default:        cueabort("Panic: unknown datatype '%s'", word);
+       }
+
+       if (sp->flags & TI_PREEMP)
+               sp->sectype |= ST_PREEMPMASK;
+       sp->secsize = secsize;
+
+       if (xdebug > 1) {
+               printf("Track %d Tracktype %s/%d\n",
+                       sp->track, kp->k_name, sp->secsize);
+       }
+
+       checkextra();
+}
+
+static void 
+parse_offset(long *lp)
+{
+       char    *word;
+       char    *p;
+       long    m = -1;
+       long    s = -1;
+       long    f = -1;
+
+       word = needitem();
+
+       if (strchr(word, ':') == NULL) {
+               if (*astol(word, lp) != '\0')
+                       cueabort("Not a number '%s'", word);
+               return;
+       }
+       if (*(p = astolb(word, &m, 10)) != ':')
+               cueabort("Not a number '%s'", word);
+       if (m < 0 || m >= 160)
+               cueabort("Illegal minute value in '%s'", word);
+       p++;
+       if (*(p = astolb(p, &s, 10)) != ':')
+               cueabort("Not a number '%s'", p);
+       if (s < 0 || s >= 60)
+               cueabort("Illegal second value in '%s'", word);
+       p++;
+       if (*(p = astolb(p, &f, 10)) != '\0')
+               cueabort("Not a number '%s'", p);
+       if (f < 0 || f >= 75)
+               cueabort("Illegal frame value in '%s'", word);
+
+       m = m * 60 + s;
+       m = m * 75 + f;
+       *lp = m;
+}
+
+/*--------------------------------------------------------------------------*/
+static void 
+newtrack(track_t trackp[], state_t *sp)
+{
+       register int    i;
+       register int    track = sp->track;
+               Llong   tracksize;
+
+       if (xdebug > 1)
+               printf("-->Newtrack %d\n", track);
+       if (track > 1) {
+               tracksize = (sp->index1 - sp->secoff) * trackp[track-1].secsize;
+
+               if (xdebug > 1)
+                       printf("    trackoff %lld filesize %lld index1 %ld size %ld/%lld\n",
+                               sp->trackoff, sp->filesize, sp->index1,
+                               sp->index1 - sp->secoff,
+                               tracksize);
+
+               trackp[track-1].itracksize = tracksize;
+               trackp[track-1].tracksize = tracksize;
+               trackp[track-1].tracksecs = sp->index1 - sp->secoff;
+
+               sp->trackoff += tracksize;
+               sp->secoff = sp->index1;
+       }
+       /*
+        * Make 'tracks' immediately usable in track structure.
+        */
+       for (i = 0; i < MAX_TRACK+2; i++)
+               trackp[i].tracks = track;
+
+       trackp[track].filename = sp->filename;
+       trackp[track].xfp = xopen(sp->filename, O_RDONLY|O_BINARY, 0);
+       trackp[track].trackstart = 0L;
+/*
+SEtzen wenn tracksecs bekannt sind
+d.h. mit Index0 oder Index 1 vom nächsten track
+
+       trackp[track].itracksize = tracksize;
+       trackp[track].tracksize = tracksize;
+       trackp[track].tracksecs = -1L;
+*/
+       tracksize = sp->filesize - sp->trackoff;
+
+       trackp[track].itracksize = tracksize;
+       trackp[track].tracksize = tracksize;
+       trackp[track].tracksecs = (tracksize + sp->secsize - 1) / sp->secsize;
+
+       if (xdebug > 1)
+               printf("    Remaining Filesize %lld (%lld secs)\n",
+                       (sp->filesize-sp->trackoff),
+                       (sp->filesize-sp->trackoff +sp->secsize - 1) / sp->secsize);
+
+       if (sp->pregapsize >= 0) {
+/*             trackp[track].flags &= ~TI_PREGAP;*/
+               sp->flags &= ~TI_PREGAP;
+               trackp[track].pregapsize = sp->pregapsize;
+       } else {
+/*             trackp[track].flags |= TI_PREGAP;*/
+               if (track > 1)
+                       sp->flags |= TI_PREGAP;
+               if (track == 1)
+                       trackp[track].pregapsize = sp->index1 + 150;
+               else if (sp->index0 < 0)
+                       trackp[track].pregapsize = -1;
+               else
+                       trackp[track].pregapsize = sp->index1 - sp->index0;
+       }
+/*     trackp[track].padsecs = xxx*/
+
+       trackp[track].isecsize = sp->secsize;
+       trackp[track].secsize = sp->secsize;
+       trackp[track].flags = sp->flags | trackp[0].flags;
+
+       trackp[track].secspt = 0;       /* transfer size is set up in set_trsizes() */
+/*     trackp[track].pktsize = pktsize; */
+       trackp[track].pktsize = 0;
+       trackp[track].trackno = sp->track;
+       trackp[track].sectype = sp->sectype;
+
+       trackp[track].dataoff = sp->dataoff;
+       trackp[track].tracktype = sp->tracktype;
+       trackp[track].dbtype = sp->dbtype;
+
+       if (track == 1) {
+               trackp[0].tracktype &= ~TOC_MASK;
+               trackp[0].tracktype |= sp->tracktype;
+
+               if (xdebug > 1) {
+                       printf("Track %d Tracktype %X\n",
+                                       0, trackp[0].tracktype);
+               }
+       }
+       if (xdebug > 1) {
+               printf("Track %d Tracktype %X\n",
+                               track, trackp[track].tracktype);
+       }
+       trackp[track].nindex = 1;
+       trackp[track].tindex = 0;
+
+       if (xdebug > 1) {
+               printf("Track %d flags 0x%08X\n", 0, trackp[0].flags);
+               printf("Track %d flags 0x%08X\n", track, trackp[track].flags);
+       }
+}
+
+/*--------------------------------------------------------------------------*/
+static keyw_t *
+lookup(char *word, keyw_t table[])
+{
+       register keyw_t *kp = table;
+
+       while (kp->k_name) {
+               if (streql(kp->k_name, word))
+                       return (kp);
+               kp++;
+       }
+       return (NULL);
+}
+
+/*--------------------------------------------------------------------------*/
+/*
+ * Parser low level functions start here...
+ */
+
+static void 
+wdebug()
+{
+/*             printf("WORD: '%s' rest '%s'\n", word, peekword());*/
+               printf("WORD: '%s' rest '%s'\n", linep, peekword());
+               printf("linep %lX peekword %lX end %lX\n",
+                       (long)linep, (long)peekword(), (long)&linebuf[linelen]);
+}
+
+static FILE *
+cueopen(char *name)
+{
+       FILE    *f;
+
+       f = fileopen(name, "r");
+       if (f == NULL)
+               comerr("Cannot open '%s'.\n", name);
+
+       fname = name;
+       return (f);
+}
+
+static char *
+cuename()
+{
+       return (fname);
+}
+
+static char *
+nextline(FILE *f)
+{
+       register int    len;
+
+       do {
+               fillbytes(linebuf, sizeof (linebuf), '\0');
+               len = rols_fgetline(f, linebuf, sizeof (linebuf));
+               if (len < 0)
+                       return (NULL);
+               if (len > 0 && linebuf[len-1] == '\r') {
+                       linebuf[len-1] = '\0';
+                       len--;
+               }
+               linelen = len;
+               lineno++;
+       } while (linebuf[0] == '#');
+
+       olinelen = linelen;
+       linep = linebuf;
+       wordendp = linep;
+       wordendc = *linep;
+
+       return (linep);
+}
+
+static void 
+ungetline()
+{
+       linelen = olinelen;
+       linep = linebuf;
+       *wordendp = wordendc;
+       wordendp = linep;
+       wordendc = *linep;
+}
+
+static char *
+skipwhite(const char *s)
+{
+       register const Uchar    *p = (const Uchar *)s;
+
+       while (*p) {
+               if (!isspace(*p))
+                       break;
+               p++;
+       }
+       return ((char *)p);
+}
+
+static char *
+peekword()
+{
+       return (&wordendp[1]);
+}
+
+static char *
+lineend()
+{
+       return (&linebuf[linelen]);
+}
+
+static char *
+markword(char *delim)
+{
+       register        BOOL    quoted = FALSE;
+       register        Uchar   c;
+       register        Uchar   *s;
+       register        Uchar   *from;
+       register        Uchar   *to;
+
+       for (s = (Uchar *)linep; (c = *s) != '\0'; s++) {
+               if (c == '"') {
+                       quoted = !quoted;
+/*                     strcpy((char *)s, (char *)&s[1]);*/
+                       for (to = s, from = &s[1]; *from; ) {
+                               c = *from++;
+                               if (c == '\\' && quoted && (*from == '\\' || *from == '"'))
+                                       c = *from++;
+                               *to++ = c;
+                       }
+                       *to = '\0';
+                       c = *s;
+linelen--;
+               }
+               if (!quoted && isspace(c))
+                       break;
+               if (!quoted && strchr(delim, c) && s > (Uchar *)linep)
+                       break;
+       }
+       wordendp = (char *)s;
+       wordendc = (char)*s;
+       *s = '\0';
+
+       return (linep);
+}
+
+static char *
+getnextitem(char *delim)
+{
+       *wordendp = wordendc;
+
+       linep = skipwhite(wordendp);
+       return (markword(delim));
+}
+
+static char *
+neednextitem(char *delim)
+{
+       char    *olinep = linep;
+       char    *nlinep;
+
+       nlinep = getnextitem(delim);
+
+       if ((olinep == nlinep) || (*nlinep == '\0'))
+               cueabort("Missing text");
+
+       return (nlinep);
+}
+
+static char *
+nextword()
+{
+       return (getnextitem(worddelim));
+}
+
+static char *
+needword()
+{
+       return (neednextitem(worddelim));
+}
+
+static char *
+curword()
+{
+       return (linep);
+}
+
+static char *
+nextitem()
+{
+       return (getnextitem(nulldelim));
+}
+
+static char *
+needitem()
+{
+       return (neednextitem(nulldelim));
+}
+
+static void 
+checkextra()
+{
+       if (peekword() < lineend())
+               cueabort("Extra text '%s'", peekword());
+}
+
+/* VARARGS1 */
+static void cueabort(const char *fmt, ...)
+{
+       va_list args;
+  va_start(args, fmt);
+  vfprintf(stderr, fmt, args);
+       va_end(args);
+  fprintf(stderr, " on line %d in '%s'.\n", lineno, fname);
+  exit(EXIT_FAILURE);
+}
diff --git a/wodim/defaults.c b/wodim/defaults.c
new file mode 100644 (file)
index 0000000..a09da6c
--- /dev/null
@@ -0,0 +1,139 @@
+/* 
+ * Copyright 2006 Eduard Bloch 
+ *
+ * This code emulates the interface of the original defaults.c file. However,
+ * it improves its behaviour and deals with corner cases: prepended and
+ * trailing spaces on variable and value, no requirement for using TABs
+ * anymore. No requirements to insert dummy values like -1 or "".
+ *
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <mconfig.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <deflts.h>
+#include <ctype.h>
+#include <string.h>
+
+#define CFGPATH "/etc/wodim.conf"
+/* The better way would be exporting the meta functions to getnum.h or so */
+extern int     getnum(char *arg, long *valp);
+
+void 
+cdr_defaults(char **p_dev_name, int *p_speed, long *p_fifosize, 
+                                       char **p_drv_opts)
+{
+       char *t; /* tmp */
+       int wc=0;
+       char loc[256], sSpeed[11], sFs[11], sOpts[81];
+       char *devcand=NULL;
+
+  cfg_open(CFGPATH);
+
+       if(p_dev_name && *p_dev_name)
+               devcand=*p_dev_name;
+       else if(NULL!=(t=getenv("CDR_DEVICE")))
+               devcand=t;
+       else if(NULL!=(t=cfg_get("CDR_DEVICE")))
+               devcand=strdup(t); /* needs to use it as a key later, same stat. memory */
+
+       if(devcand && NULL != (t=cfg_get(devcand))) {
+               /* extract them now, may be used later */
+               wc=sscanf(t, "%255s %10s %10s %80s", loc, sSpeed, sFs, sOpts);
+       }
+
+       if(p_dev_name) {
+               if(wc>0)
+                       *p_dev_name = strdup(loc);
+               else if(devcand) /* small mem. leak possible, does not matter, checks for that would require more code size than we loose */
+                       *p_dev_name=strdup(devcand);
+       }
+       if(p_speed) { /* sth. to write back */
+               char *bad;
+               int cfg_speed=-1;
+
+               /* that value may be used twice */
+               if(NULL!=(t=cfg_get("CDR_SPEED"))) {
+                       cfg_speed=strtol(t,&bad,10);
+                       if(*bad || cfg_speed<-1) {
+                               fprintf(stderr, "Bad default CDR_SPEED setting (%s).\n", t);
+                               exit(EXIT_FAILURE);
+                       }
+               }
+
+               if(*p_speed>0) { 
+                       /* ok, already set by the program arguments */
+               }
+               else if(NULL!=(t=getenv("CDR_SPEED"))) {
+                       *p_speed=strtol(t,&bad,10);
+                       if(*bad || *p_speed<-1) {
+                               fprintf(stderr, "Bad CDR_SPEED environment (%s).\n", t);
+                               exit(EXIT_FAILURE);
+                       }
+               }
+               else if(wc>1 && *sSpeed) {
+                       *p_speed=strtol(sSpeed, &bad, 10);
+                       if(*bad || *p_speed<-1) {
+                               fprintf(stderr, "Bad speed (%s) in the config, drive description.\n", sSpeed);
+                               exit(EXIT_FAILURE);
+                       }
+                       if(*p_speed==-1) 
+                               /* that's autodetect, use the config default as last ressort */
+                               *p_speed=cfg_speed;
+               }
+               else 
+                       *p_speed=cfg_speed;
+       }
+       if(p_fifosize) { /* sth. to write back */
+               if(*p_fifosize>0) { 
+                       /* ok, already set by the user */
+               }
+               else if(NULL!=(t=getenv("CDR_FIFOSIZE"))) {
+                       if(getnum(t, p_fifosize)!=1 || *p_fifosize<-1) {
+                               fprintf(stderr, "Bad CDR_FIFOSIZE environment (%s).\n", t);
+                               exit(EXIT_FAILURE);
+                       }
+               }
+               else if(wc>2 && *sFs && strcmp("-1", sFs)) {
+                       if(getnum(sFs, p_fifosize)!=1 || *p_fifosize<-1) {
+                               fprintf(stderr, "Bad fifo size (%s) in the config, device description.\n", sFs);
+                               exit(EXIT_FAILURE);
+                       }
+               }
+               else if(NULL!=(t=cfg_get("CDR_FIFOSIZE"))) {
+                       if(getnum(t, p_fifosize)!=1 || *p_fifosize<-1) {
+                               fprintf(stderr, "Bad speed default setting (%s).\n", t);
+                               exit(EXIT_FAILURE);
+                       }
+               }
+               if(NULL!=(t=cfg_get("CDR_MAXFIFOSIZE"))) {
+                       long max;
+                       if(getnum(t, &max)!=1 || *p_fifosize<-1) {
+                               fprintf(stderr, "Bad CDR_MAXFIFOSIZE setting (%s).\n", t);
+                               exit(EXIT_FAILURE);
+                       }
+                       if(*p_fifosize>max)
+                               *p_fifosize=max;
+               }
+       }
+
+       if(p_drv_opts && !*p_drv_opts && wc>3 && strcmp(sOpts, "\"\""))
+               *p_drv_opts=strdup(sOpts);
+
+  cfg_close();
+
+}
diff --git a/wodim/defaults.h b/wodim/defaults.h
new file mode 100644 (file)
index 0000000..3a5c8f8
--- /dev/null
@@ -0,0 +1,14 @@
+/* 
+ * Copyright 2006 Eduard Bloch 
+ *
+ * This code emulates the interface of the original defaults.c file. However,
+ * it improves its behaviour and deals with corner cases: prepended and
+ * trailing spaces on variable and value, no requirement for using TABs
+ * anymore. No requirements to insert dummy values like -1 or "".
+ *
+ */
+#ifndef _DEFAULTS_H_
+#define _DEFAULTS_H_
+extern int     getnum(char *arg, long *valp);
+void cdr_defaults(char **p_dev_name, int *p_speed, long *p_fifosize, char **p_drv_opts);
+#endif
diff --git a/wodim/diskid.c b/wodim/diskid.c
new file mode 100644 (file)
index 0000000..70675a3
--- /dev/null
@@ -0,0 +1,522 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)diskid.c        1.37 04/03/02 Copyright 1998-2004 J. Schilling */
+/*
+ *     Disk Idientification Method
+ *
+ *     Copyright (c) 1998-2004 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <mconfig.h>
+
+#include <stdio.h>
+#include <standard.h>
+#include <utypes.h>
+
+#include "wodim.h"
+
+void   pr_manufacturer(msf_t *mp, BOOL rw, BOOL audio);
+static struct disk_man *man_ptr(msf_t *mp);
+int    manufacturer_id(msf_t *mp);
+long   disk_rcap(msf_t *mp, long maxblock, BOOL rw, BOOL audio);
+
+struct disk_man {
+       msf_t   mi_msf;
+       char    mi_num;
+       char    *mi_name;
+};
+
+/*
+ * Illegal (old) Manufacturer.
+ */
+static char    m_ill[]   = "Unknown old Manufacturer code";
+static char    m_illrw[] = "Illegal Manufacturer code";
+
+/*
+ * Permanent codes.
+ */
+static char    m_kingpro[]     = "King Pro Mediatek Inc.";
+static char    m_custpo[]      = "Customer Pressing Oosterhout";
+static char    m_taeil[]       = "Taeil Media Co.,Ltd.";
+static char    m_doremi[]      = "Doremi Media Co., Ltd.";
+static char    m_xcitec[]      = "Xcitec Inc.";
+static char    m_leaddata[]    = "Lead Data Inc.";
+static char    m_fuji[]        = "FUJI Photo Film Co., Ltd.";
+static char    m_hitachi[]     = "Hitachi Maxell, Ltd.";
+static char    m_kodakjp[]     = "Kodak Japan Limited";
+static char    m_mitsui[]      = "Mitsui Chemicals, Inc.";
+static char    m_pioneer[]     = "Pioneer Video Corporation";
+static char    m_plasmon[]     = "Plasmon Data systems Ltd.";
+static char    m_princo[]      = "Princo Corporation";
+static char    m_ricoh[]       = "Ricoh Company Limited";
+static char    m_skc[]         = "SKC Co., Ltd.";
+static char    m_tyuden[]      = "Taiyo Yuden Company Limited";
+static char    m_tdk[]         = "TDK Corporation";
+static char    m_mitsubishi[]  = "Mitsubishi Chemical Corporation";
+static char    m_auvistar[]    = "Auvistar Industry Co.,Ltd.";
+static char    m_gigastore[]   = "GIGASTORAGE CORPORATION";
+static char    m_fornet[]      = "FORNET INTERNATIONAL PTE LTD.";
+static char    m_cmc[]         = "CMC Magnetics Corporation";
+static char    m_odm[]         = "Optical Disc Manufacturing Equipment";
+static char    m_ritek[]       = "Ritek Co.";
+
+/*
+ * Tentative codes.
+ */
+static char    m_bestdisk[]    = "Bestdisc Technology Corporation";
+static char    m_wealth_fair[] = "WEALTH FAIR INVESTMENT LIMITED";
+static char    m_general_mag[] = "General Magnetics Ld";
+static char    m_mpo[]         = "MPO";
+static char    m_jvc[]         = "VICTOR COMPANY OF JAPAN, LIMITED";
+static char    m_vivistar[]    = "VIVASTAR AG";
+static char    m_taroko[]      = "TAROKO INTERNATIONAL CO.,LTD.";
+static char    m_unidisc[]     = "UNIDISC TECHNOLOGY CO.,LTD";
+static char    m_hokodig[]     = "Hong Kong Digital Technology Co., Ltd.";
+static char    m_viva[]        = "VIVA MAGNETICS LIMITED";
+static char    m_hile[]        = "Hile Optical Disc Technology Corp.";
+static char    m_friendly[]    = "Friendly CD-Tek Co.";
+static char    m_soundsound[]  = "Sound Sound Multi-Media Development Limited";
+static char    m_kdg[]         = "kdg mediatech AG";
+static char    m_seantram[]    = "Seantram Technology Inc.";
+static char    m_eximpo[]      = "EXIMPO";
+static char    m_delphi[]      = "DELPHI TECHNOLOGY INC.";
+static char    m_harmonic[]    = "Harmonic Hall Optical Disc Ltd.";
+static char    m_guannyinn[]   = "Guann Yinn Co.,Ltd.";
+static char    m_optime[]      = "Opti.Me.S. S.p.A.";
+static char    m_nacar[]       = "Nacar Media srl";
+static char    m_optrom[]      = "OPTROM.INC.";
+static char    m_audiodis[]    = "AUDIO DISTRIBUTORS CO., LTD.";
+static char    m_acer[]        = "Acer Media Technology, Inc.";
+static char    m_woongjin[]    = "Woongjin Media corp";
+static char    m_infodisk[]    = "INFODISC Technology Co., Ltd.";
+static char    m_unitech[]     = "UNITECH JAPAN INC.";
+static char    m_ams[]         = "AMS Technology Inc.";
+static char    m_vanguard[]    = "Vanguard Disc Inc.";
+static char    m_grandadv[]    = "Grand Advance Technology Ltd.";
+static char    m_digitalstor[] = "DIGITAL STORAGE TECHNOLOGY CO.,LTD";
+static char    m_matsushita[]  = "Matsushita Electric Industrial Co.,Ltd.";
+static char    m_albrechts[]   = "CDA Datenträger Albrechts GmbH.";
+static char    m_xalbrechts[]  = "??? CDA Datenträger Albrechts GmbH.";
+
+static char    m_prodisc[]     = "Prodisc Technology Inc.";
+static char    m_postech[]     = "POSTECH Corporation";
+#ifdef used
+static char    m_ncolumbia[]   = "NIPPON COLUMBIA CO.,LTD.";
+#endif
+static char    m_odc[]         = "OPTICAL DISC CORPRATION";
+static char    m_sony[]        = "SONY Corporation";
+static char    m_cis[]         = "CIS Technology Inc.";
+static char    m_csitaly[]     = "Computer Support Italy s.r.l.";
+static char    m_mmmm[]        = "Multi Media Masters & Machinary SA";
+
+/*
+ * Guessed codes.
+ */
+/*static       char    m_seantram[]    = "Seantram Technology Inc.";*/
+static char    m_advanced[]    = "Advanced Digital Media";
+static char    m_moser[]       = "Moser Baer India Limited";
+static char    m_nanya[]       = "NAN-YA Plastics Corporation";
+static char    m_shenzen[]     = "SHENZEN SG&GAST DIGITAL OPTICAL DISCS";
+
+static struct disk_man notable =
+       {{00, 00, 00},  -1, "unknown (not in table)" };
+
+/*
+ * Old (illegal) code table. It lists single specific codes (97:xx:yy).
+ */
+static struct disk_man odman[] = {
+       /*
+        * Illegal (old) codes.
+        */
+       {{97, 25, 00}, 80, "ILLEGAL OLD CODE: TDK ???" },
+       {{97, 25, 15},  0, m_ill },
+       {{97, 27, 00}, 81, "ILLEGAL OLD CODE: Old Ritek Co.???" },
+       {{97, 27, 25},  0, m_ill },
+       {{97, 30, 00},  0, m_ill },
+       {{97, 33, 00}, 82, "ILLEGAL OLD CODE: Old CDA Datenträger Albrechts GmbH." },
+       {{97, 35, 44},  0, m_ill },
+       {{97, 39, 00},  0, m_ill },
+       {{97, 45, 36}, 83, "ILLEGAL OLD CODE: Old Kodak Photo CD" },
+       {{97, 47, 00},  0, m_ill },
+       {{97, 47, 30},  0, m_ill },
+       {{97, 48, 14},  0, m_ill },
+       {{97, 48, 33},  0, m_ill },
+       {{97, 49, 00},  0, m_ill },
+       {{97, 54, 00},  0, m_ill },
+       {{97, 55, 06},  0, m_ill },
+       {{97, 57, 00},  0, m_ill },
+       /*
+        * List end marker
+        */
+       {{00, 00, 00}, 0, NULL },
+};
+
+#define        noman   (sizeof (oman)/sizeof (oman[0]))
+
+/*
+ * Actual code table. It lists code ranges (97:xx:y0 - 97:xx:y9).
+ *
+ * Note that dp->mi_msf.msf_frame needs to be always rounded down
+ * to 0 even for media that has e.g. 97:27/01 in the official table.
+ */
+static struct disk_man dman[] = {
+       /*
+        * Permanent codes.
+        */
+
+       {{97, 22, 10}, 53, m_seantram },
+       {{97, 15, 00}, 26, m_tdk },
+       {{97, 49, 30}, 47, m_optime },
+       {{97, 28, 00}, 47, m_optime },
+       {{97, 28, 40}, 36, m_kingpro },
+       {{97, 23, 60}, 49, m_custpo },
+       {{97, 29, 00}, 37, m_taeil },
+       {{97, 26, 10}, 19, m_postech },
+       {{97, 47, 40}, 19, m_postech },
+       {{97, 24, 10}, 24, m_sony },
+/*     {{97, 46, 10}, 24, m_sony },*/
+       {{97, 23, 10}, 33, m_doremi },
+       {{97, 25, 60}, 30, m_xcitec },
+       {{97, 45, 60}, 30, m_xcitec },
+       {{97, 26, 50}, 10, m_leaddata },
+       {{97, 48, 60}, 10, m_leaddata },
+       {{97, 26, 40},  6, m_fuji },
+       {{97, 46, 40},  6, m_fuji },
+       {{97, 25, 20},  8, m_hitachi },
+       {{97, 47, 10},  8, m_hitachi },
+       {{97, 27, 40},  9, m_kodakjp },
+       {{97, 48, 10},  9, m_kodakjp },
+       {{97, 27, 50}, 12, m_mitsui },
+       {{97, 48, 50}, 12, m_mitsui },
+       {{97, 27, 30}, 17, m_pioneer },
+       {{97, 48, 30}, 17, m_pioneer },
+       {{97, 27, 10}, 18, m_plasmon },
+       {{97, 48, 20}, 18, m_plasmon },
+       {{97, 27, 20}, 20, m_princo },
+       {{97, 47, 20}, 20, m_princo },
+       {{97, 27, 60}, 21, m_ricoh },
+       {{97, 48, 00}, 21, m_ricoh },
+       {{97, 26, 20}, 23, m_skc },
+       {{97, 24, 00}, 25, m_tyuden },
+       {{97, 46, 00}, 25, m_tyuden },
+       {{97, 32, 00}, 26, m_tdk },
+       {{97, 49, 00}, 26, m_tdk },
+       {{97, 34, 20}, 11, m_mitsubishi },
+       {{97, 50, 20}, 11, m_mitsubishi },
+       {{97, 28, 30},  1, m_auvistar },
+       {{97, 46, 50},  1, m_auvistar },
+       {{97, 28, 10},  7, m_gigastore },
+       {{97, 49, 10},  7, m_gigastore },
+       {{97, 26, 00},  5, m_fornet },
+       {{97, 45, 00},  5, m_fornet },
+       {{97, 26, 60},  3, m_cmc },
+       {{97, 46, 60},  3, m_cmc },
+       {{97, 21, 40}, 16, m_odm },
+       {{97, 31, 00}, 22, m_ritek },
+       {{97, 47, 50}, 22, m_ritek },
+       {{97, 28, 20}, 13, m_mmmm },
+       {{97, 46, 20}, 13, m_mmmm },
+       {{97, 32, 10}, 27, m_prodisc },
+
+       /*
+        * Tentative codes.
+        */
+       {{97, 21, 30}, 67, m_bestdisk },
+       {{97, 18, 10}, 66, m_wealth_fair },
+       {{97, 29, 50}, 65, m_general_mag },
+       {{97, 25, 00}, 64, m_mpo },             /* in reality 25/01    */
+       {{97, 49, 40}, 63, m_jvc },
+       {{97, 23, 40}, 63, m_jvc },
+       {{97, 25, 40}, 62, m_vivistar },
+       {{97, 18, 60}, 61, m_taroko },
+       {{97, 29, 20}, 60, m_unidisc },
+       {{97, 46, 10}, 59, m_hokodig },         /* XXX was m_sony */
+       {{97, 22, 50}, 59, m_hokodig },
+       {{97, 29, 40}, 58, m_viva },
+       {{97, 29, 30}, 57, m_hile },
+       {{97, 51, 50}, 57, m_hile },
+       {{97, 28, 60}, 56, m_friendly },
+       {{97, 21, 50}, 55, m_soundsound },
+       {{97, 24, 40}, 54, m_kdg },
+       {{97, 22, 30}, 52, m_eximpo },
+       {{97, 28, 50}, 51, m_delphi },
+       {{97, 29, 00}, 50, m_harmonic },
+       {{97, 15, 10}, 22, m_ritek },
+       {{97, 45, 50}, 48, m_guannyinn },
+       {{97, 24, 50}, 48, m_guannyinn },
+       {{97, 23, 20}, 46, m_nacar },
+       {{97, 23, 50}, 45, m_optrom },
+       {{97, 23, 30}, 44, m_audiodis },
+       {{97, 22, 60}, 43, m_acer },
+       {{97, 45, 20}, 43, m_acer },
+       {{97, 15, 20}, 11, m_mitsubishi },
+       {{97, 22, 00}, 39, m_woongjin },
+       {{97, 25, 30}, 40, m_infodisk },
+       {{97, 51, 20}, 40, m_infodisk },
+       {{97, 24, 30}, 41, m_unitech },
+       {{97, 25, 50}, 42, m_ams },
+       {{97, 29, 10}, 38, m_vanguard },
+       {{97, 50, 10}, 38, m_vanguard },
+       {{97, 16, 30}, 35, m_grandadv },
+       {{97, 31, 30}, 35, m_grandadv },
+       {{97, 51, 10}, 35, m_grandadv },
+       {{97, 49, 20}, 36, m_kingpro },
+       {{97, 27, 00}, 34, m_digitalstor },     /* in reality 27/01    */
+       {{97, 48, 40}, 34, m_digitalstor },     /* XXX was m_ncolumbia */
+       {{97, 23, 00}, 31, m_matsushita },
+       {{97, 49, 60}, 31, m_matsushita },
+       {{97, 30, 10}, 32, m_albrechts },       /* XXX was m_ncolumbia */
+       {{97, 50, 30}, 32, m_albrechts },
+       {{97, 47, 60}, 27, m_prodisc },
+/*     {{97, 30, 10}, 14, m_ncolumbia },*/
+/*     {{97, 48, 40}, 14, m_ncolumbia },*/
+       {{97, 26, 30}, 15, m_odc },
+       {{97, 22, 40},  2, m_cis },
+       {{97, 45, 40},  2, m_cis },
+       {{97, 24, 20},  4, m_csitaly },
+       {{97, 46, 30},  4, m_csitaly },
+
+       /*
+        * Guessed codes.
+        */
+       {{97, 20, 10}, 32, m_xalbrechts },                      /* XXX guess */
+/*     {{97, 23, 40}, 32, m_xalbrechts },*/                    /* Really is JVC */
+
+       /*
+        * New guessed codes (2002 ff.).
+        * Id code >= 68 referres to a new manufacturer.
+        */
+#define        I_GUESS 105
+       {{97, 22, 20}, 68, m_advanced },
+       {{97, 42, 20}, 68, m_advanced },
+       {{97, 24, 60}, 50, m_harmonic },
+       {{97, 17, 00}, 69, m_moser },
+       {{97, 15, 30}, 70, m_nanya },
+       {{97, 16, 20}, 71, m_shenzen },
+       {{97, 45, 10}, 41, m_unitech },
+
+       /*
+        * List end marker
+        */
+       {{00, 00, 00},  0, NULL },
+};
+
+#define        ndman   (sizeof (dman)/sizeof (dman[0]))
+
+static struct disk_man *
+man_ptr(msf_t *mp)
+{
+       struct disk_man * dp;
+       int     frame;
+       int     type;
+
+       type = mp->msf_frame % 10;
+       frame = mp->msf_frame - type;
+
+       dp = odman;
+       while (dp->mi_msf.msf_min != 0) {
+               if (mp->msf_min == dp->mi_msf.msf_min &&
+                               mp->msf_sec == dp->mi_msf.msf_sec &&
+                               mp->msf_frame == dp->mi_msf.msf_frame) {
+                       return (dp);
+               }
+               dp++;
+       }
+       dp = dman;
+       while (dp->mi_msf.msf_min != 0) {
+               if (mp->msf_min == dp->mi_msf.msf_min &&
+                               mp->msf_sec == dp->mi_msf.msf_sec &&
+                               frame == dp->mi_msf.msf_frame) {
+                       /*
+                        * Note that dp->mi_msf.msf_frame is always rounded
+                        * down to 0 even for media that has 97:27/01 in the
+                        * official table.
+                        */
+                       return (dp);
+               }
+               dp++;
+       }
+       return (NULL);
+}
+
+void pr_manufacturer(msf_t *mp, BOOL rw, BOOL audio)
+{
+       struct disk_man * dp;
+       struct disk_man xdman;
+       int     type;
+       char    *tname;
+
+/*     printf("pr_manufacturer rw: %d audio: %d\n", rw, audio);*/
+
+       type = mp->msf_frame % 10;
+       if (type < 5) {
+               tname = "Long strategy type (Cyanine, AZO or similar)";
+       } else {
+               tname = "Short strategy type (Phthalocyanine or similar)";
+       }
+       if (rw) {
+               tname = "Phase change";
+       }
+
+       dp = man_ptr(mp);
+       if (dp != NULL) {
+               if (dp->mi_num == 0 || dp->mi_num >= 80) {
+                       if (!rw) {
+                               tname = "unknown dye (old id code)";
+                       } else {
+                               xdman = *dp;
+                               dp = &xdman;
+                               dp->mi_num = 0;
+                               dp->mi_name = m_illrw;
+                       }
+               }
+       } else {
+               tname = "unknown dye (reserved id code)";
+               dp = &notable;
+       }
+       printf("Disk type:    %s\n", tname);
+       printf("Manuf. index: %d\n", dp->mi_num);
+       printf("Manufacturer: %s\n", dp->mi_name);
+
+       if (mp->msf_min != 97)  /* This may be garbage ATIP from a DVD */
+               return;
+
+       if (dp >= &dman[I_GUESS] && dp < &dman[ndman]) {
+               printf("Manufacturer is guessed because of the orange forum embargo.\n");
+               printf("The orange forum likes to get money for recent information.\n");
+               printf("The information for this media may not be correct.\n");
+       }
+       if (dp == &notable) {
+               printf("Manufacturer is unknown because of the orange forum embargo.\n");
+               printf("As the orange forum likes to get money for recent information,\n");
+               printf("it may be that this media does not use illegal manufacturer coding.\n");
+       }
+}
+
+int manufacturer_id(msf_t *mp)
+{
+       struct disk_man * dp;
+
+       dp = man_ptr(mp);
+       if (dp != NULL)
+               return (dp->mi_num);
+       return (-1);
+}
+
+struct disk_rcap {
+       msf_t   ci_msf;                         /* Lead in start time       */
+       long    ci_cap;                         /* Lead out start time      */
+       long    ci_rcap;                        /* Abs max lead out start   */
+};
+
+static struct disk_rcap rcap[] = {
+
+#ifdef __redbook_only__
+       {{97, 35, 44}, 359849, 404700 },        /*! Unknown 99 min (89:58/00)*/
+#endif
+       {{97, 35, 44}, 359849, 449700 },        /*! Unknown 99 min (99:58/00) */
+       {{97, 31, 00}, 359849, 368923 },        /*! Arita CD-R 80           */
+       {{97, 26, 50}, 359849, 369096 },        /*! Lead Data CD-R 80       */
+       {{97, 26, 12}, 359849, 368000 },        /*X POSTECH 80 Min          */
+       {{97, 25, 00}, 359849, 374002 },        /* TDK 80 Minuten           */
+       {{97, 20, 14}, 359700, 376386 },        /*! Albrechts DataFile Plus */
+       {{97, 35, 44}, 359100, 368791 },        /*! NoName BC-1 700 Mb/80 Min */
+
+       {{97, 26, 60}, 337350, 349030 },        /* Koch grün CD-R74PRO      */
+       {{97, 26, 50}, 337050, 351205 },        /* Saba                     */
+       {{97, 26, 00}, 337050, 351411 },        /*!DGN (FORNET)             */
+       {{97, 22, 40}, 336631, 349971 },        /* Targa grün CD-R74        */
+       {{97, 26, 50}, 336631, 351727 },        /*! Sunstar (Lead Data)     */
+       {{97, 26, 55}, 336631, 350474 },        /*! NoName ZAP (Lead Data)  */
+
+       {{97, 27, 28}, 336601, 346489 },        /*! BTC CD-R (Princo)       */
+       {{97, 27, 30}, 336601, 351646 },        /*! Pioneer blau CDM-W74S   */
+       {{97, 27, 31}, 336601, 351379 },        /* Pioneer blau CDM-W74S    */
+       {{97, 27, 33}, 336601, 347029 },        /*! Pioneer braun CDM-V74S  */
+       {{97, 26, 40}, 336225, 346210 },        /* Fuji Silver Disk         */
+       {{97, 28, 10}, 336225, 348757 },        /*!GigaStorage Cursor CD-R  */
+       {{97, 31, 00}, 336225, 345460 },        /* Arita grün               */
+       {{97, 25, 28}, 336075, 352879 },        /* Maxell gold CD-R74G      */
+       {{97, 24, 01}, 336075, 346856 },        /*!Philips Premium Silver   */
+       {{97, 24, 00}, 336075, 346741 },        /* Philips grün CD-R74      */
+
+       {{97, 22, 41}, 335206, 349385 },        /* Octek grün               */
+       {{97, 34, 20}, 335100, 342460 },        /* Verbatim DataLifePlus    */
+       {{97, 33, 00}, 335100, 344634 },        /*!ITS Singapore (braun/grün) */
+       {{97, 32, 19}, 335100, 343921 },        /*!Prodisc silber/silber    */
+       {{97, 25, 21}, 335100, 346013 },        /* Maxell grün CD-R74XL     */
+       {{97, 27, 00}, 335100, 353448 },        /* TDK grün CD-RXG74        */
+       {{97, 27, 31}, 335100, 351862 },        /*!Maxell CD-R74MU (Musik)  */
+       {{97, 27, 33}, 335100, 351336 },        /* Pioneer RDD-74A          */
+
+       {{97, 26, 60}, 334259, 349036 },        /* BASF grün                */
+       {{97, 28, 21}, 333976, 348217 },        /*! Noname-B (MMMM)         */
+       {{97, 28, 20}, 333976, 346485 },        /* Koch  grün  CD-R74 PRO   */
+       {{97, 32, 00}, 333975, 345736 },        /* Imation 3M               */
+       {{97, 32, 00}, 333975, 348835 },        /* TDK Reflex X     CD-R74  */
+       {{97, 30, 18}, 333899, 344857 },        /* HiSpace  grün            */
+       {{97, 27, 66}, 333750, 352726 },        /*!Philips Megalife (Musik) */
+       {{97, 28, 43}, 333750, 345344 },        /*!MMore CD-R               */
+       {{97, 27, 65}, 333750, 348343 },        /* Ricoh gold               */
+
+       {{97, 27, 00}, 333750, 336246 },        /* BestMedia grün   CD-R74  */
+       {{97, 27, 28}, 333491, 347473 },        /* Fuji grün (alt)          */
+       {{97, 24, 48}, 333491, 343519 },        /* BASF (alt)               */
+       {{97, 27, 55}, 333235, 343270 },        /* Teac gold CD-R74         */
+       {{97, 27, 45}, 333226, 343358 },        /* Kodak gold               */
+       {{97, 28, 20}, 333226, 346483 },        /* SAST grün                */
+       {{97, 27, 45}, 333226, 343357 },        /* Mitsumi gold             */
+       {{97, 28, 25}, 333226, 346481 },        /* Cedar Grün               */
+       {{97, 23, 00}, 333226, 346206 },        /* Fuji grün (alt)          */
+       {{97, 33, 00}, 333225, 349623 },        /* DataFile Albrechts       */
+       {{97, 24, 24}, 333198, 342536 },        /*!SUN CD Recordable        */
+
+       {{97, 27, 19}, 332850, 348442 },        /* Plasmon gold PCD-R74     */
+       {{97, 32, 00}, 96600,  106502 },        /* TDK 80mm (for music only) */
+
+       /*
+        * List end marker
+        */
+       {{00, 00, 00}, 0L, 0L },
+};
+
+long 
+disk_rcap(msf_t *mp, long maxblock, BOOL rw, BOOL audio)
+{
+       struct disk_rcap * dp;
+
+       dp = rcap;
+       while (dp->ci_msf.msf_min != 0) {
+               if (mp->msf_min == dp->ci_msf.msf_min &&
+                               mp->msf_sec == dp->ci_msf.msf_sec &&
+                               mp->msf_frame == dp->ci_msf.msf_frame &&
+                               maxblock == dp->ci_cap)
+                       return (dp->ci_rcap);
+               dp++;
+       }
+       return (0L);
+}
diff --git a/wodim/drv_7501.c b/wodim/drv_7501.c
new file mode 100644 (file)
index 0000000..5083750
--- /dev/null
@@ -0,0 +1,1030 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)drv_7501.c      1.16 05/05/16 Copyright 2003-2005 J. Schilling */
+/*
+ *     Device driver for the Masushita CW-7501
+ *
+ *     Copyright (c) 2003-2005 J. Schilling
+ *
+ * Mode Pages:
+ *     0x01    error recovery          Seite 100
+ *     0x02    disconnect/reconnect    Seite 107
+ *     0x0D    CD-ROM device parameter Seite 110
+ *     0x0E    CD-ROM Audio control    Seite 112
+ *     0x20    Speed & Tray position   Seite 115
+ *     0x21    Media catalog number    Seite 124
+ *     0x22    ISRC                    Seite 125
+ *     0x23    Dummy/Write Information Seite 126
+ *     0x24    CD-R disk information   Seite 127
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef        DEBUG
+#define        DEBUG
+#endif
+#include <mconfig.h>
+
+#include <stdio.h>
+#include <standard.h>
+#include <stdxlib.h>
+#include <unixstd.h>
+#include <errno.h>
+#include <strdefs.h>
+#include <timedefs.h>
+
+#include <utypes.h>
+#include <btorder.h>
+#include <intcvt.h>
+#include <schily.h>
+
+#include <usal/usalcmd.h>
+#include <usal/scsidefs.h>
+#include <usal/scsireg.h>
+#include <usal/scsitransp.h>
+
+#include <libport.h>
+
+#include "wodim.h"
+
+extern int     silent;
+extern int     debug;
+extern int     verbose;
+extern int     lverbose;
+extern int     xdebug;
+
+#if defined(_BIT_FIELDS_LTOH)  /* Intel byteorder */
+
+struct cw7501_mode_page_20 {   /* Speed control */
+               MP_P_CODE;              /* parsave & pagecode */
+       Uchar   p_len;                  /* 0x02 = 2 Bytes */
+       Uchar   speed;
+       Ucbit   res             : 7;
+       Ucbit   traypos         : 1;
+};
+
+#else                          /* Motorola byteorder */
+
+struct cw7501_mode_page_20 {   /* Speed control */
+               MP_P_CODE;              /* parsave & pagecode */
+       Uchar   p_len;                  /* 0x02 = 2 Bytes */
+       Uchar   speed;
+       Ucbit   traypos         : 1;
+       Ucbit   res             : 7;
+};
+#endif
+
+#if defined(_BIT_FIELDS_LTOH)  /* Intel byteorder */
+
+struct cw7501_mode_page_21 {   /* MCN */
+               MP_P_CODE;              /* parsave & pagecode */
+       Uchar   p_len;                  /* 0x12 = 20 Bytes */
+       Ucbit   control         : 4;
+       Ucbit   addr            : 4;
+       Uchar   res_3;
+       Uchar   res_4;
+       Uchar   mcn[15];
+};
+
+#else                          /* Motorola byteorder */
+
+struct cw7501_mode_page_21 {   /* MCN */
+               MP_P_CODE;              /* parsave & pagecode */
+       Uchar   p_len;                  /* 0x12 = 20 Bytes */
+       Ucbit   addr            : 4;
+       Ucbit   control         : 4;
+       Uchar   res_3;
+       Uchar   res_4;
+       Uchar   mcn[15];
+};
+#endif
+
+
+#if defined(_BIT_FIELDS_LTOH)  /* Intel byteorder */
+
+struct cw7501_mode_page_22 {   /* ISRC */
+               MP_P_CODE;              /* parsave & pagecode */
+       Uchar   p_len;                  /* 0x12 = 20 Bytes */
+       Ucbit   control         : 4;
+       Ucbit   addr            : 4;
+       Uchar   trackno;
+       Uchar   res_4;
+       Uchar   isrc[15];
+};
+
+#else                          /* Motorola byteorder */
+
+struct cw7501_mode_page_22 {   /* ISRC */
+               MP_P_CODE;              /* parsave & pagecode */
+       Uchar   p_len;                  /* 0x12 = 20 Bytes */
+       Ucbit   addr            : 4;
+       Ucbit   control         : 4;
+       Uchar   trackno;
+       Uchar   res_4;
+       Uchar   isrc[15];
+};
+#endif
+
+#if defined(_BIT_FIELDS_LTOH)  /* Intel byteorder */
+
+struct cw7501_mode_page_23 {   /* Dummy / Write information */
+               MP_P_CODE;              /* parsave & pagecode */
+       Uchar   p_len;                  /* 0x02 = 2 Bytes */
+       Uchar   res;
+       Ucbit   autopg          : 1;
+       Ucbit   dummy           : 1;
+       Ucbit   res3_72         : 6;
+};
+
+#else                          /* Motorola byteorder */
+
+struct cw7501_mode_page_23 {   /* Dummy / Write information */
+               MP_P_CODE;              /* parsave & pagecode */
+       Uchar   p_len;                  /* 0x02 = 2 Bytes */
+       Uchar   res;
+       Ucbit   res3_72         : 6;
+       Ucbit   dummy           : 1;
+       Ucbit   autopg          : 1;
+};
+#endif
+
+struct cw7501_mode_page_24 {   /* CD-R Disk information */
+               MP_P_CODE;              /* parsave & pagecode */
+       Uchar   p_len;                  /* 0x0A = 12 Bytes */
+       Uchar   disktype;
+       Uchar   res;
+       Uchar   appl_code[4];
+       Uchar   disk_id[4];
+};
+
+struct cw7501_mode_data {
+       struct scsi_mode_header header;
+       union cdd_pagex {
+               struct cw7501_mode_page_20      page20;
+               struct cw7501_mode_page_21      page21;
+               struct cw7501_mode_page_22      page22;
+               struct cw7501_mode_page_23      page23;
+               struct cw7501_mode_page_24      page24;
+       } pagex;
+};
+
+/*
+ * Mode for read track information
+ */
+#define        TI_TRACKINFO_R  0
+#define        TI_NWA          1
+#define        TI_PMA          2
+#define        TI_TRACKINFO    3
+
+struct cw7501_nwa {
+       Uchar   nwa_length[2];
+       Uchar   nwa_res;
+       Uchar   nwa_trackno;
+       Uchar   nwa_nwa[4];
+       Uchar   nwa_freeblocks[4];
+};
+
+struct cw7501_cue {
+       Uchar   cs_ctladr;              /* CTL/ADR for this track       */
+       Uchar   cs_tno;                 /* This track number            */
+       Uchar   cs_index;               /* Index within this track      */
+       Uchar   cs_dataform;            /* Data form                    */
+                                       /* Bit 0..3 Physical Format     */
+                                       /* Bit 4 Alt Copy (SCMS)        */
+                                       /* Bit 5 SubC Audio + RAW96 sub */
+       Uchar   cs_extension;           /* Reserved or MCN/ISRC         */
+       Uchar   cs_min;                 /* Absolute time minutes        */
+       Uchar   cs_sec;                 /* Absolute time seconds        */
+       Uchar   cs_frame;               /* Absolute time frames         */
+};
+
+
+static int     cw7501_attach(SCSI *usalp, cdr_t *dp);
+static int     cw7501_init(SCSI *usalp, cdr_t *dp);
+static int     cw7501_getdisktype(SCSI *usalp, cdr_t *dp);
+static int     cw7501_speed_select(SCSI *usalp, cdr_t *dp, int *speedp);
+static int     cw7501_next_wr_addr(SCSI *usalp, track_t *trackp, long *ap);
+static int     cw7501_write(SCSI *usalp, caddr_t bp, long sectaddr, long size, 
+                                                                        int blocks, BOOL islast);
+static int     cw7501_write_leadin(SCSI *usalp, cdr_t *dp, track_t *trackp);
+static int     cw7501_open_track(SCSI *usalp, cdr_t *dp, track_t *trackp);
+static int     cw7501_close_track(SCSI *usalp, cdr_t *dp, track_t *trackp);
+static int     cw7501_open_session(SCSI *usalp, cdr_t *dp, track_t *trackp);
+static int     cw7501_gen_cue(track_t *trackp, void *vcuep, BOOL needgap);
+static void    fillcue(struct cw7501_cue *cp, int ca, int tno, int idx, 
+                                                         int dataform, int scms, msf_t *mp);
+static int     cw7501_send_cue(SCSI *usalp, cdr_t *dp, track_t *trackp);
+static int     cw7501_fixate(SCSI *usalp, cdr_t *dp, track_t *trackp);
+static int     cw7501_rezero(SCSI *usalp, int reset, int dwreset);
+static int     cw7501_read_trackinfo(SCSI *usalp, Uchar *bp, int count, 
+                                                                                                int track, int mode);
+static int     cw7501_write_dao(SCSI *usalp, Uchar *bp, int len, int disktype);
+static int     cw7501_reserve_track(SCSI *usalp, unsigned long);
+static int     cw7501_set_mode(SCSI *usalp, int phys_form, int control,
+                                               int subc, int alt, int trackno, int tindex,
+                                               int packet_size, int write_mode);
+static int     cw7501_finalize(SCSI *usalp, int pad, int fixed);
+
+
+cdr_t  cdr_cw7501 = {
+       0, 0,
+       /*
+        * Prinzipiell geht auch: CDR_PACKET & CDR_SRAW96R
+        */
+       CDR_TAO|CDR_SAO|CDR_TRAYLOAD,
+       CDR_CDRW_NONE,
+       2, 2,
+       "cw_7501",
+       "driver for Matsushita/Panasonic CW-7501",
+       0,
+       (dstat_t *)0,
+       drive_identify,
+       cw7501_attach,
+       cw7501_init,
+       cw7501_getdisktype,
+       scsi_load,
+       scsi_unload,
+       buf_dummy,                              /* RD buffer cap not supp. */
+       cmd_dummy,                                      /* recovery_needed */
+       (int(*)(SCSI *, cdr_t *, int))cmd_dummy,        /* recover      */
+       cw7501_speed_select,
+       select_secsize,
+       cw7501_next_wr_addr,
+       cw7501_reserve_track,
+       cw7501_write,
+       cw7501_gen_cue,
+       cw7501_send_cue,
+       cw7501_write_leadin,
+       cw7501_open_track,
+       cw7501_close_track,
+       cw7501_open_session,
+       cmd_dummy,                              /* close seession       */
+       cmd_dummy,                                      /* abort        */
+       read_session_offset,
+       cw7501_fixate,
+       cmd_dummy,                                      /* stats        */
+       blank_dummy,
+       format_dummy,
+       (int(*)(SCSI *, caddr_t, int, int))NULL,        /* no OPC       */
+       cmd_dummy,                                      /* opt1         */
+       cmd_dummy,                                      /* opt2         */
+};
+
+static const char *sd_cw7501_error_str[] = {
+       "\100\201diagnostic failure on ROM",                    /* 40 81 */
+       "\100\202diagnostic failure on CPU internal RAM",       /* 40 82 */
+       "\100\203diagnostic failure on BUFFER RAM",             /* 40 83 */
+       "\100\204diagnostic failure on internal SCSI controller",       /* 40 84 */
+       "\100\205diagnostic failure on system mechanism",       /* 40 85 */
+
+       "\210\000Illegal Que Sheet (DAO parameter)",            /* 88 00 */
+       "\211\000Inappropriate command",                        /* 89 00 */
+
+       "\250\000Audio Play operation Not in Progress",         /* A8 00 */
+       "\251\000Buffer Overrun",                               /* A9 00 */
+
+       "\300\000Unrecordable Disk",                            /* C0 00 */
+       "\301\000Illegal Track Status",                         /* C1 00 */
+       "\302\000Reserved track Status",                        /* C2 00 */
+       "\304\000Illegal Reserve Length for Reserve Track Command",     /* C4 00 */
+       "\304\001Illegal Data Form for Reserve Track Command",  /* C4 01 */
+       "\304\002Unable to Reserve Track, Because Track Mode has been Changed", /* C4 02 */
+
+       "\305\000Buffer error during recording",                /* C5 00 */
+       "\307\000Disk Style mismatch",                          /* C7 00 */
+       "\312\000Power Calibration error",                      /* CA 00 */
+       "\313\000Write error (Fatal Error/Time out)",           /* CB 00 */
+       "\314\000Not enough space (Leadin/Leadout space)",      /* CC 00 */
+       "\315\000No track present to finalize",                 /* CD 00 */
+       "\317\000Unable to recover damaged disk",               /* CF 00 */
+
+       "\320\000PMA area full (1000 blocks)",                  /* D0 00 */
+       "\321\000PCA area full (100 counts)",                   /* D1 00 */
+       "\322\000Recovery failed",                              /* D2 00 */
+       "\323\000Recovery needed",                              /* D3 00 */
+       NULL
+};
+
+static int 
+cw7501_attach(SCSI *usalp, cdr_t *dp)
+{
+       usal_setnonstderrs(usalp, sd_cw7501_error_str);
+       return (0);
+}
+
+static int 
+cw7501_init(SCSI *usalp, cdr_t *dp)
+{
+       return (cw7501_speed_select(usalp, dp, NULL));
+}
+
+static int 
+cw7501_getdisktype(SCSI *usalp, cdr_t *dp)
+{
+       Ulong   maxb = 0;
+       Uchar   buf[256];
+       int     ret;
+       dstat_t *dsp = dp->cdr_dstat;
+
+       if (xdebug > 0) {
+               usalp->silent++;
+               fillbytes((caddr_t)buf, sizeof (buf), '\0');
+               ret = cw7501_read_trackinfo(usalp, buf, 32, 0, 0);
+               if (ret >= 0)
+               usal_prbytes("TI EXIST-R   (0): ", buf, 32 -usal_getresid(usalp));
+
+               fillbytes((caddr_t)buf, sizeof (buf), '\0');
+               ret = cw7501_read_trackinfo(usalp, buf, 32, 0, 1);
+               if (ret >= 0)
+               usal_prbytes("TI NWA       (1): ", buf, 32 -usal_getresid(usalp));
+
+               fillbytes((caddr_t)buf, sizeof (buf), '\0');
+               ret = cw7501_read_trackinfo(usalp, buf, 32, 0, 2);
+               if (ret >= 0)
+               usal_prbytes("TI PMA       (2): ", buf, 32 -usal_getresid(usalp));
+
+               fillbytes((caddr_t)buf, sizeof (buf), '\0');
+               ret = cw7501_read_trackinfo(usalp, buf, 32, 0, 3);
+               if (ret >= 0)
+               usal_prbytes("TI EXIST-ROM (3): ", buf, 32 -usal_getresid(usalp));
+               usalp->silent--;
+       }
+
+       fillbytes((caddr_t)buf, sizeof (buf), '\0');
+
+       usalp->silent++;
+       ret = cw7501_read_trackinfo(usalp, buf, 12, 0, TI_NWA);
+       if (ret < 0 &&
+                       (dsp->ds_cdrflags & (RF_WRITE|RF_BLANK)) == RF_WRITE) {
+
+               /*
+                * Try to clear the dummy bit to reset the virtual
+                * drive status. Not all drives support it even though
+                * it is mentioned in the MMC standard.
+                */
+               if (lverbose)
+                       printf("Trying to clear drive status.\n");
+               cw7501_rezero(usalp, 0, 1);
+               wait_unit_ready(usalp, 60);
+               ret = cw7501_read_trackinfo(usalp, buf, 12, 0, TI_NWA);
+       }
+       usalp->silent--;
+
+       if (ret >= 0) {
+               maxb = a_to_u_4_byte(&buf[8]);
+               if (maxb != 0)
+                       maxb -= 150;
+       }
+       dsp->ds_maxblocks = maxb;
+
+       return (drive_getdisktype(usalp, dp));
+}
+
+
+static int 
+cw7501_speed_select(SCSI *usalp, cdr_t *dp, int *speedp)
+{
+       struct  scsi_mode_page_header   *mp;
+       char                            mode[256];
+       int                             len = 20;
+       int                             page = 0x20;
+       struct cw7501_mode_page_20      *xp20;
+       struct cw7501_mode_data         md;
+       int                             count;
+       int                             speed = 1;
+       BOOL                            dummy = (dp->cdr_cmdflags & F_DUMMY) != 0;
+
+       if (speedp) {
+               speed = *speedp;
+       } else {
+               fillbytes((caddr_t)mode, sizeof (mode), '\0');
+
+               if (!get_mode_params(usalp, page, "Speed information",
+                       (Uchar *)mode, (Uchar *)0, (Uchar *)0, (Uchar *)0, &len)) {
+                       return (-1);
+               }
+               if (len == 0)
+                       return (-1);
+
+               mp = (struct scsi_mode_page_header *)
+                       (mode + sizeof (struct scsi_mode_header) +
+                       ((struct scsi_mode_header *)mode)->blockdesc_len);
+
+               xp20  = (struct cw7501_mode_page_20 *)mp;
+               speed = xp20->speed;
+       }
+
+       fillbytes((caddr_t)&md, sizeof (md), '\0');
+
+       count  = sizeof (struct scsi_mode_header) +
+               sizeof (struct cw7501_mode_page_20);
+
+       md.pagex.page20.p_code = 0x20;
+       md.pagex.page20.p_len =  0x02;
+       md.pagex.page20.speed = speed;
+
+       if (mode_select(usalp, (Uchar *)&md, count, 0, usalp->inq->data_format >= 2) < 0)
+               return (-1);
+
+       fillbytes((caddr_t)&md, sizeof (md), '\0');
+
+       count  = sizeof (struct scsi_mode_header) +
+               sizeof (struct cw7501_mode_page_23);
+
+       md.pagex.page23.p_code = 0x23;
+       md.pagex.page23.p_len =  0x02;
+       md.pagex.page23.dummy = dummy?1:0;
+
+       return (mode_select(usalp, (Uchar *)&md, count, 0, usalp->inq->data_format >= 2));
+}
+
+static int 
+cw7501_next_wr_addr(SCSI *usalp, track_t *trackp, long *ap)
+{
+       struct cw7501_nwa       *nwa;
+       Uchar   buf[256];
+       long    next_addr;
+       int     result = -1;
+
+
+       /*
+        * Reading info for current track may require doing the read_track_info
+        * with either the track number (if the track is currently being written)
+        * or with 0 (if the track hasn't been started yet and is invisible
+        */
+       nwa = (struct cw7501_nwa *)buf;
+
+       if (trackp != 0 && trackp->track > 0 && is_packet(trackp)) {
+               fillbytes((caddr_t)buf, sizeof (buf), '\0');
+
+               usalp->silent++;
+               result = cw7501_read_trackinfo(usalp, buf, sizeof (*nwa),
+                                                       trackp->trackno,
+                                                       TI_NWA);
+               usalp->silent--;
+       }
+
+       if (result < 0) {
+               if (cw7501_read_trackinfo(usalp, buf, sizeof (*nwa),
+                                                       0, TI_NWA) < 0)
+                       return (-1);
+       }
+       if (usalp->verbose)
+               usal_prbytes("track info:", buf,
+                               12-usal_getresid(usalp));
+       next_addr = a_to_4_byte(&nwa->nwa_nwa);
+       /*
+        * XXX Für TAO definitiv notwendig.
+        * XXX ABhängig von Auto-Pregap?
+        */
+       /* XXX */ next_addr += 150;
+       if (ap)
+               *ap = next_addr;
+       return (0);
+}
+
+static int 
+cw7501_write(SCSI *usalp, 
+             caddr_t bp     /* address of buffer */, 
+             long sectaddr  /* disk address (sector) to put */, 
+             long size      /* number of bytes to transfer */, 
+             int blocks     /* sector count */, 
+             BOOL islast    /* last write for track */)
+{
+       if (lverbose > 1 && islast)
+               printf("\nWriting last record for this track.\n");
+
+       return (write_xg0(usalp, bp, 0, size, blocks));
+}
+
+static int 
+cw7501_write_leadin(SCSI *usalp, cdr_t *dp, track_t *trackp)
+{
+       Uint    i;
+       long    startsec = 0L;
+
+       if (wm_base(dp->cdr_dstat->ds_wrmode) == WM_SAO) {
+               if (debug || lverbose) {
+                       printf("Sending CUE sheet...\n");
+                       flush();
+               }
+               if ((*dp->cdr_send_cue)(usalp, dp, trackp) < 0) {
+                       errmsgno(EX_BAD, "Cannot send CUE sheet.\n");
+                       return (-1);
+               }
+
+               /*
+                * Next writable address function does not work in DAO
+                * mode for this writer, so we just assume -150.
+                */
+               startsec = -150;
+               if (debug)
+                       printf("SAO startsec: %ld\n", startsec);
+
+               if (trackp[0].flags & TI_TEXT) {
+                       errmsgno(EX_BAD, "CD-Text unsupported in CW-7501 - ignoring.\n");
+               } else for (i = 1; i <= trackp->tracks; i++) {
+                       trackp[i].trackstart += startsec +150;
+               }
+       }
+       return (0);
+}
+
+static Uchar   db2phys[] = {
+       0x00,                   /*  0 2352 bytes of raw data                    */
+       0xFF,                   /*  1 2368 bytes (raw data + P/Q Subchannel)    */
+       0xFF,                   /*  2 2448 bytes (raw data + P-W Subchannel)    */
+       0xFF,                   /*  3 2448 bytes (raw data + P-W raw Subchannel)*/
+       0xFF,                   /*  4 -    Reserved                             */
+       0xFF,                   /*  5 -    Reserved                             */
+       0xFF,                   /*  6 -    Reserved                             */
+       0xFF,                   /*  7 -    Vendor specific                      */
+       0x02,                   /*  8 2048 bytes Mode 1 (ISO/IEC 10149)         */
+       0x03,                   /*  9 2336 bytes Mode 2 (ISO/IEC 10149)         */
+       0xFF,                   /* 10 2048 bytes Mode 2 (CD-ROM XA form 1)      */
+       0x04,                   /* 11 2056 bytes Mode 2 (CD-ROM XA form 1)      */
+       0xFF,                   /* 12 2324 bytes Mode 2 (CD-ROM XA form 2)      */
+       0x08,                   /* 13 2332 bytes Mode 2 (CD-ROM XA 1/2+subhdr)  */
+       0xFF,                   /* 14 -    Reserved                             */
+       0xFF,                   /* 15 -    Vendor specific                      */
+};
+
+static int 
+cw7501_open_track(SCSI *usalp, cdr_t *dp, track_t *trackp)
+{
+       struct  scsi_mode_page_header   *mp;
+       Uchar                           mode[256];
+       int                             len = 0;
+       int                             page = 0x23;
+       struct cw7501_mode_page_23      *xp23;
+
+       if (!is_tao(trackp) && !is_packet(trackp)) {
+               if (trackp->pregapsize > 0 && (trackp->flags & TI_PREGAP) == 0) {
+                       if (lverbose) {
+                               printf("Writing pregap for track %d at %ld\n",
+                                       (int)trackp->trackno,
+                                       trackp->trackstart-trackp->pregapsize);
+                       }
+                       /*
+                        * XXX Do we need to check isecsize too?
+                        */
+                       pad_track(usalp, dp, trackp,
+                               trackp->trackstart-trackp->pregapsize,
+                               (Llong)trackp->pregapsize*trackp->secsize,
+                                       FALSE, 0);
+               }
+               return (0);
+       }
+
+       if (select_secsize(usalp, trackp->secsize) < 0)
+               return (-1);
+
+       if (!get_mode_params(usalp, page, "Dummy/autopg information",
+                       (Uchar *)mode, (Uchar *)0, (Uchar *)0, (Uchar *)0, &len)) {
+               return (-1);
+       }
+       if (len == 0)
+               return (-1);
+
+       mp = (struct scsi_mode_page_header *)
+               (mode + sizeof (struct scsi_mode_header) +
+               ((struct scsi_mode_header *)mode)->blockdesc_len);
+
+       xp23  = (struct cw7501_mode_page_23 *)mp;
+       xp23->autopg = 1;
+       if (!set_mode_params(usalp, "Dummy/autopg page", mode, len, 0, trackp->secsize))
+               return (-1);
+
+       /*
+        * Set write modes for next track.
+        */
+       if (cw7501_set_mode(usalp, db2phys[trackp->dbtype & 0x0F],
+                       st2mode[trackp->sectype&ST_MASK] | (is_copy(trackp) ? TM_ALLOW_COPY : 0),
+                       0, is_scms(trackp) ? 1 : 0,
+                       trackp->trackno, 1, 0,
+                       /* write mode TAO */ 0x01) < 0)
+               return (-1);
+
+       return (0);
+}
+
+
+static int 
+cw7501_close_track(SCSI *usalp, cdr_t *dp, track_t *trackp)
+{
+       if (!is_tao(trackp) && !is_packet(trackp)) {
+               return (0);
+       }
+       return (scsi_flush_cache(usalp, FALSE));
+}
+
+static int 
+cw7501_open_session(SCSI *usalp, cdr_t *dp, track_t *trackp)
+{
+       struct cw7501_mode_data         md;
+       int                             count;
+
+       if (select_secsize(usalp, 2048) < 0)
+               return (-1);
+
+       /*
+        * Disable Auto Pregap when writing in SAO mode.
+        */
+       if (!is_tao(trackp) && !is_packet(trackp)) {
+               struct  scsi_mode_page_header   *mp;
+               Uchar                           mode[256];
+               int                             len = 0;
+               int                             page = 0x23;
+               struct cw7501_mode_page_23      *xp23;
+
+               if (!get_mode_params(usalp, page, "Dummy/autopg information",
+                               (Uchar *)mode, (Uchar *)0, (Uchar *)0, (Uchar *)0, &len)) {
+                       return (-1);
+               }
+               if (len == 0)
+                       return (-1);
+
+               mp = (struct scsi_mode_page_header *)
+                       (mode + sizeof (struct scsi_mode_header) +
+                       ((struct scsi_mode_header *)mode)->blockdesc_len);
+
+               xp23  = (struct cw7501_mode_page_23 *)mp;
+               xp23->autopg = 0;
+               if (!set_mode_params(usalp, "Dummy/autopg page", mode, len, 0, trackp->secsize))
+                       return (-1);
+
+               return (0);
+       }
+
+       /*
+        * Set Disk Type and Disk ID.
+        */
+       fillbytes((caddr_t)&md, sizeof (md), '\0');
+
+       count  = sizeof (struct scsi_mode_header) +
+               sizeof (struct cw7501_mode_page_24);
+
+       md.pagex.page24.p_code = 0x24;
+       md.pagex.page24.p_len =  0x0A;
+       md.pagex.page24.disktype = toc2sess[track_base(trackp)->tracktype & TOC_MASK];
+       i_to_4_byte(&md.pagex.page24.disk_id, 0x12345);
+
+       return (mode_select(usalp, (Uchar *)&md, count, 0, usalp->inq->data_format >= 2));
+}
+
+static int 
+cw7501_fixate(SCSI *usalp, cdr_t *dp, track_t *trackp)
+{
+       if (!is_tao(trackp) && !is_packet(trackp)) {
+               return (scsi_flush_cache(usalp, FALSE));
+       }
+       /*
+        * 0x00 Finalize Disk (not appendable)
+        * 0x01 Finalize Session (allow next session)
+        * 0x10 Finalize track (variable packet writing) - Must fluch cache before
+        */
+       return (cw7501_finalize(usalp, 0, (track_base(trackp)->tracktype & TOCF_MULTI) ? 0x01 : 0x00));
+}
+
+/*--------------------------------------------------------------------------*/
+
+static int 
+cw7501_gen_cue(track_t *trackp, void *vcuep, BOOL needgap)
+{
+       int     tracks = trackp->tracks;
+       int     i;
+       struct cw7501_cue       **cuep = vcuep;
+       struct cw7501_cue       *cue;
+       struct cw7501_cue       *cp;
+       int     ncue = 0;
+       int     icue = 0;
+       int     pgsize;
+       msf_t   m;
+       int     ctl;
+       int     df;
+       int     scms;
+
+       cue = malloc(1);
+
+       for (i = 0; i <= tracks; i++) {
+               ctl = (st2mode[trackp[i].sectype & ST_MASK]) << 4;
+               if (is_copy(&trackp[i]))
+                       ctl |= TM_ALLOW_COPY << 4;
+               df = db2phys[trackp[i].dbtype & 0x0F];
+
+               if (trackp[i].isrc) {   /* MCN or ISRC */
+                       ncue += 2;
+                       cue = realloc(cue, ncue * sizeof (*cue));
+                       cp = &cue[icue++];
+                       if (i == 0) {
+                               cp->cs_ctladr = 0x02;
+                               movebytes(&trackp[i].isrc[0], &cp->cs_tno, 7);
+                               cp = &cue[icue++];
+                               cp->cs_ctladr = 0x02;
+                               movebytes(&trackp[i].isrc[7], &cp->cs_tno, 7);
+                       } else {
+                               cp->cs_ctladr = 0x03;
+                               cp->cs_tno = i;
+                               movebytes(&trackp[i].isrc[0], &cp->cs_index, 6);
+                               cp = &cue[icue++];
+                               cp->cs_ctladr = 0x03;
+                               cp->cs_tno = i;
+                               movebytes(&trackp[i].isrc[6], &cp->cs_index, 6);
+                       }
+               }
+               if (i == 0) {   /* Lead in */
+                       lba_to_msf(-150, &m);
+                       cue = realloc(cue, ++ncue * sizeof (*cue));
+                       cp = &cue[icue++];
+                       fillcue(cp, ctl|0x01, i, 0, df, 0, &m);
+               } else {
+                       scms = 0;
+
+                       if (is_scms(&trackp[i]))
+                               scms = 0x80;
+                       pgsize = trackp[i].pregapsize;
+                       if (pgsize == 0 && needgap)
+                               pgsize++;
+                       lba_to_msf(trackp[i].trackstart-pgsize, &m);
+                       cue = realloc(cue, ++ncue * sizeof (*cue));
+                       cp = &cue[icue++];
+                       fillcue(cp, ctl|0x01, i, 0, df, scms, &m);
+
+                       if (trackp[i].nindex == 1) {
+                               lba_to_msf(trackp[i].trackstart, &m);
+                               cue = realloc(cue, ++ncue * sizeof (*cue));
+                               cp = &cue[icue++];
+                               fillcue(cp, ctl|0x01, i, 1, df, scms, &m);
+                       } else {
+                               int     idx;
+                               long    *idxlist;
+
+                               ncue += trackp[i].nindex;
+                               idxlist = trackp[i].tindex;
+                               cue = realloc(cue, ncue * sizeof (*cue));
+
+                               for (idx = 1; idx <= trackp[i].nindex; idx++) {
+                                       lba_to_msf(trackp[i].trackstart + idxlist[idx], &m);
+                                       cp = &cue[icue++];
+                                       fillcue(cp, ctl|0x01, i, idx, df, scms, &m);
+                               }
+                       }
+               }
+       }
+       /* Lead out */
+       ctl = (st2mode[trackp[tracks+1].sectype & ST_MASK]) << 4;
+       df = db2phys[trackp[tracks+1].dbtype & 0x0F];
+       lba_to_msf(trackp[tracks+1].trackstart, &m);
+       cue = realloc(cue, ++ncue * sizeof (*cue));
+       cp = &cue[icue++];
+       fillcue(cp, ctl|0x01, 0xAA, 1, df, 0, &m);
+
+       if (lverbose > 1) {
+               for (i = 0; i < ncue; i++) {
+                       usal_prbytes("", (Uchar *)&cue[i], 8);
+               }
+       }
+       if (cuep)
+               *cuep = cue;
+       else
+               free(cue);
+       return (ncue);
+}
+
+static void 
+fillcue(struct cw7501_cue *cp  /* The target cue entry */, 
+        int ca                                 /* Control/adr for this entry */, 
+        int tno                                        /* Track number for this entry */, 
+        int idx                                        /* Index for this entry */, 
+        int dataform                   /* Data format for this entry */, 
+        int scms                                       /* Serial copy management */, 
+        msf_t *mp                              /* MSF value for this entry */)
+{
+       cp->cs_ctladr = ca;
+       if (tno <= 99)
+               cp->cs_tno = to_bcd(tno);
+       else
+               cp->cs_tno = tno;
+       cp->cs_index = to_bcd(idx);
+       if (scms != 0)
+               dataform |= 0x10;
+       cp->cs_dataform = dataform;
+       cp->cs_extension = 0;
+       cp->cs_min = to_bcd(mp->msf_min);
+       cp->cs_sec = to_bcd(mp->msf_sec);
+       cp->cs_frame = to_bcd(mp->msf_frame);
+}
+
+static int 
+cw7501_send_cue(SCSI *usalp, cdr_t *dp, track_t *trackp)
+{
+       struct cw7501_cue *cp;
+       int             ncue;
+       int             ret;
+       Uint            i;
+       struct timeval starttime;
+       struct timeval stoptime;
+       int             disktype;
+
+       disktype = toc2sess[track_base(trackp)->tracktype & TOC_MASK];
+
+       for (i = 1; i <= trackp->tracks; i++) {
+               if (trackp[i].tracksize < (tsize_t)0) {
+                       errmsgno(EX_BAD, "Track %d has unknown length.\n", i);
+                       return (-1);
+               }
+       }
+       ncue = (*dp->cdr_gen_cue)(trackp, &cp, FALSE);
+
+       starttime.tv_sec = 0;
+       starttime.tv_usec = 0;
+       stoptime = starttime;
+       gettimeofday(&starttime, (struct timezone *)0);
+
+       usalp->silent++;
+       ret = cw7501_write_dao(usalp, (Uchar *)cp, ncue*8, disktype);
+       usalp->silent--;
+       free(cp);
+       if (ret < 0) {
+               errmsgno(EX_BAD, "CUE sheet not accepted. Retrying with minimum pregapsize = 1.\n");
+               ncue = (*dp->cdr_gen_cue)(trackp, &cp, TRUE);
+               ret  = cw7501_write_dao(usalp, (Uchar *)cp, ncue*8, disktype);
+               free(cp);
+       }
+       if (ret >= 0 && lverbose) {
+               gettimeofday(&stoptime, (struct timezone *)0);
+               prtimediff("Write Lead-in time: ", &starttime, &stoptime);
+       }
+       return (ret);
+}
+
+/*--------------------------------------------------------------------------*/
+static int 
+cw7501_rezero(SCSI *usalp, int reset, int dwreset)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->addr = (caddr_t)0;
+       scmd->size = 0;
+       scmd->flags = SCG_DISRE_ENA;
+       scmd->cdb_len = SC_G0_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+       scmd->cdb.g0_cdb.cmd = SC_REZERO_UNIT;
+       scmd->cdb.g0_cdb.lun = usal_lun(usalp);
+       scmd->cdb.cmd_cdb[5] |= reset ? 0x80 : 0;
+       scmd->cdb.cmd_cdb[5] |= dwreset ? 0x40 : 0;
+
+       usalp->cmdname = "cw7501 rezero";
+
+       return (usal_cmd(usalp));
+}
+
+
+static int
+cw7501_read_trackinfo(SCSI *usalp, Uchar *bp, int count, int track, int mode)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t) scmd, sizeof (*scmd), '\0');
+       scmd->addr = (caddr_t)bp;
+       scmd->size = count;
+       scmd->flags = SCG_RECV_DATA | SCG_DISRE_ENA;
+       scmd->cdb_len = SC_G1_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+       scmd->cdb.g1_cdb.cmd = 0xE9;
+       scmd->cdb.g1_cdb.lun = usal_lun(usalp);
+       scmd->cdb.cmd_cdb[6] = track;
+       g1_cdblen(&scmd->cdb.g1_cdb, count);
+       scmd->cdb.cmd_cdb[9] = (mode & 3) << 6;
+
+       usalp->cmdname = "cw7501 read_track_information";
+
+       if (usal_cmd(usalp) < 0)
+               return (-1);
+
+       return (0);
+}
+
+static int 
+cw7501_write_dao(SCSI *usalp, Uchar *bp, int len, int disktype)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->addr = (caddr_t)bp;
+       scmd->size = len;
+       scmd->flags = SCG_DISRE_ENA;
+       scmd->cdb_len = SC_G1_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+       scmd->cdb.g1_cdb.cmd = 0xE6;
+       scmd->cdb.g1_cdb.lun = usal_lun(usalp);
+       scmd->cdb.cmd_cdb[2] = disktype;
+       g1_cdblen(&scmd->cdb.g1_cdb, len);
+
+       usalp->cmdname = "cw7501 write_dao";
+
+       if (usal_cmd(usalp) < 0)
+               return (-1);
+       return (0);
+}
+
+/*
+ * XXX CW-7501 also needs "control", so we need to make a different
+ * XXX driver interface.
+ */
+static int 
+cw7501_reserve_track(SCSI *usalp, unsigned long len)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->flags = SCG_DISRE_ENA;
+       scmd->cdb_len = SC_G1_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+       scmd->cdb.g1_cdb.cmd = 0xE7;
+       scmd->cdb.g1_cdb.lun = usal_lun(usalp);
+/*     scmd->cdb.cmd_cdb[2] = control & 0x0F;*/
+       i_to_4_byte(&scmd->cdb.cmd_cdb[5], len);
+
+       usalp->cmdname = "cw7501 reserve_track";
+
+       comerrno(EX_BAD, "Control (as in set mode) missing.\n");
+
+       if (usal_cmd(usalp) < 0)
+               return (-1);
+       return (0);
+}
+
+static int 
+cw7501_set_mode(SCSI *usalp, int phys_form, int control, int subc, 
+                                               int alt, int trackno, int tindex, int packet_size, 
+                                               int write_mode)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->flags = SCG_DISRE_ENA;
+       scmd->cdb_len = SC_G1_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+       scmd->cdb.g1_cdb.cmd = 0xE2;
+       scmd->cdb.g1_cdb.lun = usal_lun(usalp);
+       scmd->cdb.cmd_cdb[2] = phys_form & 0x0F;
+       scmd->cdb.cmd_cdb[3] = (control & 0x0F) << 4;
+       scmd->cdb.cmd_cdb[3] |= subc ? 2 : 0;
+       scmd->cdb.cmd_cdb[3] |= alt ? 1 : 0;
+       scmd->cdb.cmd_cdb[4] = trackno;
+       scmd->cdb.cmd_cdb[5] = tindex;
+       i_to_3_byte(&scmd->cdb.cmd_cdb[6], packet_size);
+       scmd->cdb.cmd_cdb[9] = (write_mode & 0x03) << 6;
+
+       usalp->cmdname = "cw7501 set_mode";
+
+       if (usal_cmd(usalp) < 0)
+               return (-1);
+       return (0);
+}
+
+static int 
+cw7501_finalize(SCSI *usalp, int pad, int fixed)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->flags = SCG_DISRE_ENA;
+       scmd->cdb_len = SC_G1_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+       scmd->timeout = 8 * 60;         /* Needs up to 4 minutes */
+       scmd->cdb.g1_cdb.cmd = 0xE3;
+       scmd->cdb.g1_cdb.lun = usal_lun(usalp);
+       scmd->cdb.cmd_cdb[1] = pad ? 1 : 0;
+       scmd->cdb.cmd_cdb[8] = fixed & 0x03;
+
+       usalp->cmdname = "cw7501 finalize";
+
+       if (usal_cmd(usalp) < 0)
+               return (-1);
+       return (0);
+}
diff --git a/wodim/drv_jvc.c b/wodim/drv_jvc.c
new file mode 100644 (file)
index 0000000..ee2bcc2
--- /dev/null
@@ -0,0 +1,1433 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/** @(#)drv_jvc.c      1.82 05/05/16 Copyright 1997-2005 J. Schilling */
+/*
+ *     CDR device implementation for
+ *     JVC/TEAC
+ *
+ *     Copyright (c) 1997-2005 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/*#define      XXDEBUG*/
+/*#define      XXBUFFER*/
+
+#include <mconfig.h>
+
+#include <stdio.h>
+#include <standard.h>
+#include <fctldefs.h>
+#include <errno.h>
+#include <strdefs.h>
+#include <unixstd.h>
+#ifdef XXDEBUG
+#include <stdxlib.h>
+#endif
+
+#include <utypes.h>
+#include <btorder.h>
+#include <intcvt.h>
+#include <schily.h>
+
+#include <usal/usalcmd.h>
+#include <usal/scsidefs.h>
+#include <usal/scsireg.h>
+#include <usal/scsitransp.h>
+
+#include "wodim.h"
+
+/* just a hack */
+long   lba_addr;
+BOOL   last_done;
+
+/*
+ * macros for building MSF values from LBA
+ */
+#define        LBA_MIN(x)      ((x)/(60*75))
+#define        LBA_SEC(x)      (((x)%(60*75))/75)
+#define        LBA_FRM(x)      ((x)%75)
+#define        MSF_CONV(a)     ((((a)%(unsigned)100)/10)*16 + ((a)%(unsigned)10))
+
+extern int     lverbose;
+
+#if defined(_BIT_FIELDS_LTOH)  /* Intel byteorder */
+struct teac_mode_page_21 {             /* teac dummy selection */
+               MP_P_CODE;              /* parsave & pagecode */
+       Uchar   p_len;                  /* 0x01 = 1 Byte */
+       Ucbit   dummy           : 2;
+       Ucbit   res             : 6;
+};
+#else
+struct teac_mode_page_21 {             /* teac dummy selection */
+               MP_P_CODE;              /* parsave & pagecode */
+       Uchar   p_len;                  /* 0x01 = 1 Byte */
+       Ucbit   res             : 6;
+       Ucbit   dummy           : 2;
+};
+#endif
+
+struct teac_mode_page_31 {             /* teac speed selection */
+               MP_P_CODE;              /* parsave & pagecode */
+       Uchar   p_len;                  /* 0x02 = 2 Byte */
+       Uchar   speed;
+       Uchar   res;
+};
+
+struct cdd_52x_mode_data {
+       struct scsi_mode_header header;
+       union cdd_pagex {
+               struct teac_mode_page_21        teac_page21;
+               struct teac_mode_page_31        teac_page31;
+       } pagex;
+};
+
+#if defined(_BIT_FIELDS_LTOH)  /* Intel byteorder */
+
+struct pgm_subcode {           /* subcode for progam area */
+       Uchar   subcode;
+       Ucbit   addr            : 4;
+       Ucbit   control         : 4;
+       Uchar   track;
+       Uchar   index;
+};
+
+#else
+
+struct pgm_subcode {           /* subcode for progam area */
+       Uchar   subcode;
+       Ucbit   control         : 4;
+       Ucbit   addr            : 4;
+       Uchar   track;
+       Uchar   index;
+};
+
+#endif
+
+#define        set_pgm_subcode(sp, t, c, a, tr, idx)           (\
+                       (sp)->subcode = (t),             \
+                       (sp)->control = (c),             \
+                       (sp)->addr = (a),                \
+                       (sp)->track = MSF_CONV(tr),      \
+                       (sp)->index = (idx))
+
+#define        SC_P            1       /* Subcode defines pre-gap (Pause)      */
+#define        SC_TR           0       /* Subcode defines track data           */
+
+#if defined(_BIT_FIELDS_LTOH)  /* Intel byteorder */
+
+typedef struct lin_subcode {   /* subcode for lead in area */
+       Ucbit   addr            : 4;
+       Ucbit   control         : 4;
+       Uchar   track;
+       Uchar   msf[3];
+} lsc_t;
+
+#else
+
+typedef struct lin_subcode {   /* subcode for lead in area */
+       Ucbit   control         : 4;
+       Ucbit   addr            : 4;
+       Uchar   track;
+       Uchar   msf[3];
+} lsc_t;
+
+#endif
+
+#define        set_toc_subcode(sp, c, a, tr, bno)                              (\
+                       ((lsc_t *)sp)->control = (c),                    \
+                       ((lsc_t *)sp)->addr = (a),                       \
+                       ((lsc_t *)sp)->track = MSF_CONV(tr),             \
+                       ((lsc_t *)sp)->msf[0] = MSF_CONV(LBA_MIN(bno)),  \
+                       ((lsc_t *)sp)->msf[1] = MSF_CONV(LBA_SEC(bno)),  \
+                       ((lsc_t *)sp)->msf[2] = MSF_CONV(LBA_FRM(bno)),  \
+                       &((lsc_t *)sp)->msf[3])
+
+#define        set_lin_subcode(sp, c, a, pt, min, sec, frm)                    (\
+                       ((lsc_t *)sp)->control = (c),                    \
+                       ((lsc_t *)sp)->addr = (a),                       \
+                       ((lsc_t *)sp)->track = (pt),                     \
+                       ((lsc_t *)sp)->msf[0] = (min),                   \
+                       ((lsc_t *)sp)->msf[1] = (sec),                   \
+                       ((lsc_t *)sp)->msf[2] = (frm),                   \
+                       &((lsc_t *)sp)->msf[3])
+
+#if defined(_BIT_FIELDS_LTOH)  /* Intel byteorder */
+
+struct upc_subcode {           /* subcode for upc/bar code */
+       Uchar   res;
+       Ucbit   addr            : 4;
+       Ucbit   control         : 4;
+       Uchar   upc[13];
+};
+
+#else
+
+struct upc_subcode {           /* subcode for upc/bar code */
+       Uchar   res;
+       Ucbit   control         : 4;
+       Ucbit   addr            : 4;
+       Uchar   upc[13];
+};
+
+#endif
+
+#if defined(_BIT_FIELDS_LTOH)  /* Intel byteorder */
+
+struct isrc_subcode {          /* subcode for ISRC code */
+       Uchar   res;
+       Ucbit   addr            : 4;
+       Ucbit   control         : 4;
+       Uchar   isrc[12];
+       Uchar   res14;
+};
+
+#else
+
+struct isrc_subcode {          /* subcode for ISRC code */
+       Uchar   res;
+       Ucbit   control         : 4;
+       Ucbit   addr            : 4;
+       Uchar   isrc[12];
+       Uchar   res14;
+};
+
+#endif
+
+
+static int     teac_attach(SCSI *usalp, cdr_t *dp);
+static int     teac_init(SCSI *usalp, cdr_t *dp);
+static int     teac_getdisktype(SCSI *usalp, cdr_t *dp);
+static int     speed_select_teac(SCSI *usalp, cdr_t *dp, int *speedp);
+static int     select_secsize_teac(SCSI *usalp, track_t *trackp);
+static int     next_wr_addr_jvc(SCSI *usalp, track_t *, long *ap);
+static int     write_teac_xg1(SCSI *usalp, caddr_t, long, long, int, BOOL);
+static int     cdr_write_teac(SCSI *usalp, caddr_t bp, long sectaddr, long size, 
+                                                                               int blocks, BOOL islast);
+static int     open_track_jvc(SCSI *usalp, cdr_t *dp, track_t *trackp);
+static int     teac_fixation(SCSI *usalp, cdr_t *dp, track_t *trackp);
+static int     close_track_teac(SCSI *usalp, cdr_t *dp, track_t *trackp);
+static int     teac_open_session(SCSI *usalp, cdr_t *dp, track_t *trackp);
+static int     initsub_teac(SCSI *usalp, int toctype, int multi);
+static int     teac_doopc(SCSI *usalp);
+static int     teac_opc(SCSI *usalp, caddr_t, int cnt, int doopc);
+static int     opt_power_judge(SCSI *usalp, int judge);
+static int     clear_subcode(SCSI *usalp);
+static int     set_limits(SCSI *usalp, long lba, long length);
+static int     set_subcode(SCSI *usalp, Uchar *subcode_data, int length);
+static int     read_disk_info_teac(SCSI *usalp, Uchar *data, int length, 
+                                                                                         int type);
+static int     teac_freeze(SCSI *usalp, int bp_flag);
+static int     teac_wr_pma(SCSI *usalp);
+static int     teac_rd_pma(SCSI *usalp);
+static int     next_wr_addr_teac(SCSI *usalp, long start_lba, long last_lba);
+static int     blank_jvc(SCSI *usalp, cdr_t *dp, long addr, int blanktype);
+static int     buf_cap_teac(SCSI *usalp, long *sp, long *fp);
+static long    read_peak_buffer_cap_teac(SCSI *usalp);
+static int     buffer_inquiry_teac(SCSI *usalp, int fmt);
+#ifdef XXBUFFER
+static void    check_buffer_teac(SCSI *usalp);
+#endif
+#ifdef XXDEBUG
+static void    xxtest_teac(SCSI *usalp);
+#endif
+
+
+cdr_t  cdr_teac_cdr50 = {
+       0, 0,
+/*     CDR_TAO|CDR_SAO|CDR_SWABAUDIO|CDR_NO_LOLIMIT,*/
+       CDR_TAO|CDR_SWABAUDIO|CDR_NO_LOLIMIT,
+       CDR_CDRW_ALL,
+       2, 4,
+       "teac_cdr50",
+       "driver for Teac CD-R50S, Teac CD-R55S, JVC XR-W2010, Pinnacle RCD-5020",
+       0,
+       (dstat_t *)0,
+       drive_identify,
+       teac_attach,
+       teac_init,
+       teac_getdisktype,
+       scsi_load,
+       scsi_unload,
+       buf_cap_teac,
+       cmd_dummy,                                      /* recovery_needed */
+       (int(*)(SCSI *, cdr_t *, int))cmd_dummy,        /* recover      */
+       speed_select_teac,
+       select_secsize,
+       next_wr_addr_jvc,
+       (int(*)(SCSI *, Ulong))cmd_ill, /* reserve_track        */
+       cdr_write_teac,
+       (int(*)(track_t *, void *, BOOL))cmd_dummy,     /* gen_cue */
+       no_sendcue,
+       (int(*)(SCSI *, cdr_t *, track_t *))cmd_dummy, /* leadin */
+       open_track_jvc,
+       close_track_teac,
+       teac_open_session,
+       cmd_dummy,
+       cmd_dummy,                                      /* abort        */
+       read_session_offset_philips,
+       teac_fixation,
+       cmd_dummy,                                      /* stats        */
+/*     blank_dummy,*/
+       blank_jvc,
+       format_dummy,
+       teac_opc,
+       cmd_dummy,                                      /* opt1         */
+       cmd_dummy,                                      /* opt2         */
+};
+
+static int 
+teac_init(SCSI *usalp, cdr_t *dp)
+{
+       return (speed_select_teac(usalp, dp, NULL));
+}
+
+static int 
+teac_getdisktype(SCSI *usalp, cdr_t *dp)
+{
+       dstat_t *dsp = dp->cdr_dstat;
+       struct scsi_mode_data md;
+       int     count = sizeof (struct scsi_mode_header) +
+                       sizeof (struct scsi_mode_blockdesc);
+       int     len;
+       int     page = 0;
+       long    l;
+
+       fillbytes((caddr_t)&md, sizeof (md), '\0');
+
+       (void) test_unit_ready(usalp);
+       if (mode_sense(usalp, (Uchar *)&md, count, page, 0) < 0) {      /* Page n current */
+               return (-1);
+       } else {
+               len = ((struct scsi_mode_header *)&md)->sense_data_len + 1;
+       }
+       if (((struct scsi_mode_header *)&md)->blockdesc_len < 8)
+               return (-1);
+
+       l = a_to_u_3_byte(md.blockdesc.nlblock);
+       dsp->ds_maxblocks = l;
+       return (drive_getdisktype(usalp, dp));
+}
+
+static int 
+speed_select_teac(SCSI *usalp, cdr_t *dp, int *speedp)
+{
+       struct cdd_52x_mode_data md;
+       int     count;
+       int     status;
+       int     speed = 1;
+       BOOL    dummy = (dp->cdr_cmdflags & F_DUMMY) != 0;
+
+       if (speedp)
+               speed = *speedp;
+
+       fillbytes((caddr_t)&md, sizeof (md), '\0');
+
+       count  = sizeof (struct scsi_mode_header) +
+               sizeof (struct teac_mode_page_21);
+
+       md.pagex.teac_page21.p_code = 0x21;
+       md.pagex.teac_page21.p_len =  0x01;
+       md.pagex.teac_page21.dummy = dummy?3:0;
+
+       status = mode_select(usalp, (Uchar *)&md, count, 0, usalp->inq->data_format >= 2);
+       if (status < 0)
+               return (status);
+
+       if (speedp == 0)
+               return (0);
+
+       fillbytes((caddr_t)&md, sizeof (md), '\0');
+
+       count  = sizeof (struct scsi_mode_header) +
+               sizeof (struct teac_mode_page_31);
+
+       speed >>= 1;
+       md.pagex.teac_page31.p_code = 0x31;
+       md.pagex.teac_page31.p_len =  0x02;
+       md.pagex.teac_page31.speed = speed;
+
+       return (mode_select(usalp, (Uchar *)&md, count, 0, usalp->inq->data_format >= 2));
+}
+
+static int 
+select_secsize_teac(SCSI *usalp, track_t *trackp)
+{
+       struct scsi_mode_data md;
+       int     count = sizeof (struct scsi_mode_header) +
+                       sizeof (struct scsi_mode_blockdesc);
+       int     len;
+       int     page = 0;
+
+       fillbytes((caddr_t)&md, sizeof (md), '\0');
+
+       (void) test_unit_ready(usalp);
+       if (mode_sense(usalp, (Uchar *)&md, count, page, 0) < 0) {      /* Page n current */
+               return (-1);
+       } else {
+               len = ((struct scsi_mode_header *)&md)->sense_data_len + 1;
+       }
+       if (((struct scsi_mode_header *)&md)->blockdesc_len < 8)
+               return (-1);
+
+       md.header.sense_data_len = 0;
+       md.header.blockdesc_len = 8;
+
+       md.blockdesc.density = 1;
+       if (trackp->secsize == 2352)
+               md.blockdesc.density = 4;
+       i_to_3_byte(md.blockdesc.lblen, trackp->secsize);
+
+       return (mode_select(usalp, (Uchar *)&md, count, 0, usalp->inq->data_format >= 2));
+}
+
+static int 
+next_wr_addr_jvc(SCSI *usalp, track_t *trackp, long *ap)
+{
+       if (trackp != 0 && trackp->track > 0) {
+               *ap = lba_addr;
+       } else {
+               long    nwa;
+
+               if (read_B0(usalp, TRUE, &nwa, NULL) < 0)
+                       return (-1);
+
+               *ap = nwa + 150;
+       }
+       return (0);
+}
+
+static int 
+write_teac_xg1(SCSI *usalp, 
+               caddr_t bp       /* address of buffer */, 
+               long sectaddr    /* disk address (sector) to put */, 
+               long size        /* number of bytes to transfer */,
+               int blocks       /* sector count */, 
+               BOOL extwr       /* is an extended write */)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->addr = bp;
+       scmd->size = size;
+       scmd->flags = SCG_DISRE_ENA|SCG_CMD_RETRY;
+/*     scmd->flags = SCG_DISRE_ENA;*/
+       scmd->cdb_len = SC_G1_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+       scmd->cdb.g1_cdb.cmd = SC_EWRITE;
+       scmd->cdb.g1_cdb.lun = usal_lun(usalp);
+       g1_cdbaddr(&scmd->cdb.g1_cdb, sectaddr);
+       g1_cdblen(&scmd->cdb.g1_cdb, blocks);
+       scmd->cdb.g1_cdb.vu_97 = extwr;
+
+       usalp->cmdname = "write_teac_g1";
+
+       if (usal_cmd(usalp) < 0)
+               return (-1);
+       return (size - usal_getresid(usalp));
+}
+
+static int 
+cdr_write_teac(SCSI *usalp, 
+               caddr_t bp       /* address of buffer */,
+               long sectaddr    /* disk address (sector) to put */,
+               long size        /* number of bytes to transfer */,
+               int blocks       /* sector count */,
+               BOOL islast      /* last write for track */)
+{
+       int     ret;
+
+       if (islast)
+               last_done = TRUE;
+
+       ret = write_teac_xg1(usalp, bp, sectaddr, size, blocks, !islast);
+       if (ret < 0)
+               return (ret);
+
+       lba_addr = sectaddr + blocks;
+#ifdef XXBUFFER
+       check_buffer_teac(usalp);
+#endif
+       return (ret);
+}
+
+static int 
+open_track_jvc(SCSI *usalp, cdr_t *dp, track_t *trackp)
+{
+       int     status;
+       long    blocks;
+       long    pregapsize;
+       struct  pgm_subcode     sc;
+
+       last_done = FALSE;
+
+       if (select_secsize_teac(usalp, trackp) < 0)
+               return (-1);
+
+       status = clear_subcode(usalp);
+/*next_wr_addr_teac(usalp);*/
+       if (status < 0)
+               return (status);
+
+if (trackp->pregapsize != 0) {
+       if (lverbose > 1) {
+               printf("set_limits(%ld, %ld)-> %ld\n",
+               lba_addr, trackp->pregapsize, lba_addr + trackp->pregapsize);
+       }
+
+       status = set_limits(usalp, lba_addr, trackp->pregapsize);
+       if (status < 0)
+               return (status);
+
+       /*
+        * Set pre-gap (pause - index 0)
+        */
+       set_pgm_subcode(&sc, SC_P,
+                       st2mode[trackp->sectype&ST_MASK], ADR_POS, trackp->trackno, 0);
+
+       if (lverbose > 1)
+               usal_prbytes("Subcode:", (Uchar *)&sc, sizeof (sc));
+
+       status = set_subcode(usalp, (Uchar *)&sc, sizeof (sc));
+       if (status < 0)
+               return (status);
+
+       pregapsize = trackp->pregapsize;
+       if (!is_audio(trackp)) {
+               lba_addr += 5;  /* link & run in blocks */
+               pregapsize -= 5;
+       }
+       if (lverbose > 1) {
+               printf("pad_track(%ld, %ld)-> %ld\n",
+                       lba_addr, pregapsize, lba_addr + pregapsize);
+       }
+       /*
+        * XXX Do we need to check isecsize too?
+        */
+       if (pad_track(usalp, dp, trackp,
+                       lba_addr, (Llong)pregapsize*trackp->secsize,
+                       FALSE, (Llong *)0) < 0)
+               return (-1);
+}
+
+       blocks = trackp->tracksize/trackp->secsize +
+                   (trackp->tracksize%trackp->secsize?1:0);
+       blocks += trackp->padsecs;
+       if (blocks < 300)
+               blocks = 300;
+       if (!is_audio(trackp))
+               blocks += 2;
+if (!is_last(trackp) && trackp[1].pregapsize == 0)
+               blocks -= 150;
+
+       /*
+        * set the limits for the new subcode - seems to apply to all
+        * of the data track.
+        * Unknown tracksize is handled in open_session.
+        * We definitely need to know the tracksize in this driver.
+        */
+       if (lverbose > 1) {
+               printf("set_limits(%ld, %ld)-> %ld\n",
+                       lba_addr, blocks, lba_addr + blocks);
+       }
+       status = set_limits(usalp, lba_addr, blocks);
+       if (status < 0)
+               return (status);
+
+       /*
+        * Set track start (index 1)
+        */
+       set_pgm_subcode(&sc, SC_TR,
+                       st2mode[trackp->sectype&ST_MASK], ADR_POS, trackp->trackno, 1);
+
+       if (lverbose > 1)
+               usal_prbytes("Subcode:", (Uchar *)&sc, sizeof (sc));
+
+       status = set_subcode(usalp, (Uchar *)&sc, sizeof (sc));
+       if (status < 0)
+               return (status);
+
+if (!is_last(trackp) && trackp[1].pregapsize == 0) {
+       blocks += lba_addr;
+       pregapsize = 150;
+
+       if (lverbose > 1) {
+               printf("set_limits(%ld, %ld)-> %ld\n",
+               blocks, pregapsize, blocks + pregapsize);
+       }
+
+       status = set_limits(usalp, blocks, pregapsize);
+       if (status < 0)
+               return (status);
+
+       /*
+        * Set pre-gap (pause - index 0)
+        */
+       trackp++;
+       set_pgm_subcode(&sc, SC_P,
+                       st2mode[trackp->sectype&ST_MASK], ADR_POS, trackp->trackno, 0);
+
+       if (lverbose > 1)
+               usal_prbytes("Subcode:", (Uchar *)&sc, sizeof (sc));
+
+       status = set_subcode(usalp, (Uchar *)&sc, sizeof (sc));
+       if (status < 0)
+               return (status);
+}
+       return (status);
+}
+
+static char    sector[3000];
+
+static int 
+close_track_teac(SCSI *usalp, cdr_t *dp, track_t *trackp)
+{
+       int     ret = 0;
+
+       if (!last_done) {
+               printf("WARNING: adding dummy block to close track.\n");
+               /*
+                * need read sector size
+                * XXX do we really need this ?
+                * XXX if we need this can we set blocks to 0 ?
+                */
+               ret =  write_teac_xg1(usalp, sector, lba_addr, 2352, 1, FALSE);
+               lba_addr++;
+       }
+       if (!is_audio(trackp))
+               lba_addr += 2;
+       teac_wr_pma(usalp);
+       return (ret);
+}
+
+
+
+static const char *sd_teac50_error_str[] = {
+       "\100\200diagnostic failure on component parts",        /* 40 80 */
+       "\100\201diagnostic failure on memories",               /* 40 81 */
+       "\100\202diagnostic failure on cd-rom ecc circuit",     /* 40 82 */
+       "\100\203diagnostic failure on gate array",             /* 40 83 */
+       "\100\204diagnostic failure on internal SCSI controller",       /* 40 84 */
+       "\100\205diagnostic failure on servo processor",        /* 40 85 */
+       "\100\206diagnostic failure on program rom",            /* 40 86 */
+       "\100\220thermal sensor failure",                       /* 40 90 */
+       "\200\000controller prom error",                        /* 80 00 */     /* JVC */
+       "\201\000no disk present - couldn't get focus",         /* 81 00 */     /* JVC */
+       "\202\000no cartridge present",                         /* 82 00 */     /* JVC */
+       "\203\000unable to spin up",                            /* 83 00 */     /* JVC */
+       "\204\000addr exceeded the last valid block addr",      /* 84 00 */     /* JVC */
+       "\205\000sync error",                                   /* 85 00 */     /* JVC */
+       "\206\000address can't find or not data track",         /* 86 00 */     /* JVC */
+       "\207\000missing track",                                /* 87 00 */     /* JVC */
+       "\213\000cartridge could not be ejected",               /* 8B 00 */     /* JVC */
+       "\215\000audio not playing",                            /* 8D 00 */     /* JVC */
+       "\216\000read toc error",                               /* 8E 00 */     /* JVC */
+       "\217\000a blank disk is detected by read toc",         /* 8F 00 */
+       "\220\000pma less disk - not a recordable disk",        /* 90 00 */
+       "\223\000mount error",                                  /* 93 00 */     /* JVC */
+       "\224\000toc less disk",                                /* 94 00 */
+       "\225\000disc information less disk",                   /* 95 00 */     /* JVC */
+       "\226\000disc information read error",                  /* 96 00 */     /* JVC */
+       "\227\000linear velocity measurement error",            /* 97 00 */     /* JVC */
+       "\230\000drive sequence stop",                          /* 98 00 */     /* JVC */
+       "\231\000actuator velocity control error",              /* 99 00 */     /* JVC */
+       "\232\000slider velocity control error",                /* 9A 00 */     /* JVC */
+       "\233\000opc initialize error",                         /* 9B 00 */
+       "\233\001power calibration not executed",               /* 9B 01 */
+       "\234\000opc execution eror",                           /* 9C 00 */
+       "\234\001alpc error - opc execution",                   /* 9C 01 */
+       "\234\002opc execution timeout",                        /* 9C 02 */
+       "\245\000disk application code does not match host application code",   /* A5 00 */
+       "\255\000completed preview write",                      /* AD 00 */
+       "\256\000invalid B0 value",                             /* AE 00 */     /* JVC */
+       "\257\000pca area full",                                /* AF 00 */
+       "\260\000efm isn't detected",                           /* B0 00 */     /* JVC */
+       "\263\000no logical sector",                            /* B3 00 */     /* JVC */
+       "\264\000full pma area",                                /* B4 00 */
+       "\265\000read address is atip area - blank",            /* B5 00 */
+       "\266\000write address is efm area - aleady written",   /* B6 00 */
+       "\271\000abnormal spinning - servo irq",                /* B9 00 */     /* JVC */
+       "\272\000no write data - buffer empty",                 /* BA 00 */
+       "\273\000write emergency occurred",                     /* BB 00 */
+       "\274\000read timeout",                                 /* BC 00 */     /* JVC */
+       "\277\000abnormal spin - nmi",                          /* BF 00 */     /* JVC */
+       "\301\0004th run-in block detected",                    /* C1 00 */
+       "\302\0003rd run-in block detected",                    /* C2 00 */
+       "\303\0002nd run-in block detected",                    /* C3 00 */
+       "\304\0001st run-in block detected",                    /* C4 00 */
+       "\305\000link block detected",                          /* C5 00 */
+       "\306\0001st run-out block detected",                   /* C6 00 */
+       "\307\0002nd run-out block detected",                   /* C7 00 */
+       "\314\000write request means mixed data mode",          /* CC 00 */
+       "\315\000unable to ensure reliable writing with the inserted disk - unsupported disk",   /* CD 00 */
+       "\316\000unable to ensure reliable writing as the inserted disk does not support speed", /* CE 00 */
+       "\317\000unable to ensure reliable writing as the inserted disk has no char id code",    /* CF 00 */
+       NULL
+};
+
+static int 
+teac_attach(SCSI *usalp, cdr_t *dp)
+{
+       usal_setnonstderrs(usalp, sd_teac50_error_str);
+#ifdef XXDEBUG
+       xxtest_teac(usalp);
+       exit(0);
+#endif
+       return (0);
+}
+
+static int 
+teac_fixation(SCSI *usalp, cdr_t *dp, track_t *trackp)
+{
+       long    lba;
+       int     status;
+       Uchar   *sp;
+       Uint    i;
+extern char    *buf;
+
+       if (trackp->tracks < 1) {
+               /*
+                * We come here if wodim isonly called with the -fix option.
+                * As long as we cannot read and interpret the PMA, we must
+                * abort here.
+                */
+               teac_rd_pma(usalp);
+/*             errmsgno(EX_BAD, "Cannot fixate zero track disk.\n");*/
+               errmsgno(EX_BAD, "Cannot fixate without track list (not yet implemented).\n");
+               return (-1);
+       }
+       sp = (Uchar *)buf;
+
+       sleep(1);
+
+       status = clear_subcode(usalp);
+       sleep(1);
+       if (status < 0)
+               return (status);
+
+       sp[0] = 0;              /* reserved */
+       sp[1] = 0;              /* reserved */
+       sp[2] = 0;              /* Q TNO */
+
+       sp = &sp[3];            /* point past header */
+
+       /*
+        * Set up TOC entries for all tracks
+        */
+       for (i = 1; i <= trackp->tracks; i++) {
+               lba = trackp[i].trackstart+150; /* MSF=00:02:00 is LBA=0 */
+
+               sp = set_toc_subcode(sp,
+                               /* ctrl/adr for this track */
+                               st2mode[trackp[i].sectype&ST_MASK], ADR_POS,
+                                       trackp[i].trackno, lba);
+       }
+
+       /*
+        * Set first track on disk
+        *
+        * XXX We set the track type for the lead-in to the track type
+        * XXX of the first track. The TEAC manual states that we should use
+        * XXX audio if the disk contains both, audio and data tracks.
+        */
+       sp = set_lin_subcode(sp,
+               /* ctrl/adr for first track */
+               st2mode[trackp[1].sectype&ST_MASK], ADR_POS,
+               0xA0,                           /* Point A0 */
+               trackp[1].trackno,              /* first track # */
+               toc2sess[track_base(trackp)->tracktype & TOC_MASK],     /* disk type */
+               0);                             /* reserved */
+
+       /*
+        * Set last track on disk
+        */
+       sp = set_lin_subcode(sp,
+               /* ctrl/adr for first track */
+               st2mode[trackp[1].sectype&ST_MASK], ADR_POS,
+               0xA1,                           /* Point A1 */
+               MSF_CONV(trackp[trackp->tracks].trackno), /* last track # */
+               0,                              /* reserved */
+               0);                             /* reserved */
+
+       /*
+        * Set start of lead out area in MSF
+        * MSF=00:02:00 is LBA=0
+        */
+       lba = lba_addr + 150;
+       if (lverbose > 1)
+       printf("lba: %ld lba_addr: %ld\n", lba, lba_addr);
+
+       if (lverbose > 1)
+       printf("Lead out start: (%02d:%02d/%02d)\n",
+                       minutes(lba*2352),
+                       seconds(lba*2352),
+                       frames(lba*2352));
+
+       sp = set_lin_subcode(sp,
+               /* ctrl/adr for first track */
+               st2mode[trackp[1].sectype&ST_MASK], ADR_POS,
+               0xA2,                           /* Point A2 */
+               MSF_CONV(LBA_MIN(lba)),
+               MSF_CONV(LBA_SEC(lba)),
+               MSF_CONV(LBA_FRM(lba)));
+
+       status = sp - ((Uchar *)buf);
+       if (lverbose > 1) {
+               printf("Subcode len: %d\n", status);
+               usal_prbytes("Subcode:", (Uchar *)buf, status);
+       }
+       status = set_subcode(usalp, (Uchar *)buf, status);
+       sleep(1);
+       if (status < 0)
+               return (status);
+
+       /*
+        * now write the toc
+        */
+       status = teac_freeze(usalp, (track_base(trackp)->tracktype & TOCF_MULTI) == 0);
+       return (status);
+
+}
+
+static int 
+teac_open_session(SCSI *usalp, cdr_t *dp, track_t *trackp)
+{
+       Uint    i;
+
+       for (i = 1; i <= trackp->tracks; i++) {
+               if (trackp[i].tracksize < (tsize_t)0) {
+                       /*
+                        * XXX How about setting the subcode range to infinity.
+                        * XXX and correct it in clode track before writing
+                        * XXX the PMA?
+                        */
+                       errmsgno(EX_BAD, "Track %d has unknown length.\n", i);
+                       return (-1);
+               }
+       }
+       return (initsub_teac(usalp, track_base(trackp)->tracktype & TOC_MASK,
+                               track_base(trackp)->tracktype & TOCF_MULTI));
+}
+
+static int 
+initsub_teac(SCSI *usalp, int toctype, int multi)
+{
+       int     status;
+
+       usalp->silent++;
+       if (read_B0(usalp, TRUE, &lba_addr, NULL) < 0)
+               lba_addr = -150;
+       usalp->silent--;
+
+       status = clear_subcode(usalp);
+       if (status < 0)
+               return (status);
+
+       return (0);
+}
+
+static int 
+teac_doopc(SCSI *usalp)
+{
+       int     status;
+
+       if (lverbose) {
+               fprintf(stdout, "Judging disk...");
+               flush();
+       }
+       status = opt_power_judge(usalp, 1);
+       if (status < 0) {
+               printf("\n");
+               return (status);
+       }
+       if (lverbose) {
+               fprintf(stdout, "done.\nCalibrating laser...");
+               flush();
+       }
+
+       status = opt_power_judge(usalp, 0);
+       if (lverbose) {
+               fprintf(stdout, "done.\n");
+       }
+       /*
+        * Check for error codes 0xCD ... 0xCF
+        */
+       usalp->silent++;
+       if (next_wr_addr_teac(usalp, -1, -1) < 0) {
+               if (usalp->verbose == 0 && usal_sense_key(usalp) != SC_ILLEGAL_REQUEST)
+                       usal_printerr(usalp);
+       }
+       usalp->silent--;
+       return (status);
+}
+
+static int 
+teac_opc(SCSI *usalp, caddr_t bp, int cnt, int doopc)
+{
+       int     status;
+       int     count = 0;
+
+       do {
+               status = teac_doopc(usalp);
+       } while (++count <= 1 && status < 0);
+
+       return (status);
+}
+
+/*--------------------------------------------------------------------------*/
+#define        SC_SET_LIMITS           0xb3            /* teac 12 byte command */
+#define        SC_SET_SUBCODE          0xc2            /* teac 10 byte command */
+#define        SC_READ_PMA             0xc4            /* teac 10 byte command */
+#define        SC_READ_DISK_INFO       0xc7            /* teac 10 byte command */
+#define        SC_BUFFER_INQUIRY       0xe0            /* teac 12 byte command */
+
+#define        SC_WRITE_PMA            0xe1            /* teac 12 byte command */
+#define        SC_FREEZE               0xe3            /* teac 12 byte command */
+#define        SC_OPC_EXECUTE          0xec            /* teac 12 byte command */
+#define        SC_CLEAR_SUBCODE        0xe4            /* teac 12 byte command */
+#define        SC_NEXT_WR_ADDRESS      0xe6            /* teac 12 byte command */
+
+#define        SC_READ_PEAK_BUF_CAP    0xef            /* teac 12 byte command */
+
+/*
+ * Optimum power calibration for Teac Drives.
+ */
+static int 
+opt_power_judge(SCSI *usalp, int judge)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->addr = (caddr_t)0;
+       scmd->size = 0;
+       scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
+       scmd->cdb_len = SC_G5_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+       scmd->timeout = 60;
+
+       scmd->cdb.g5_cdb.cmd = SC_OPC_EXECUTE;
+       scmd->cdb.g5_cdb.lun = usal_lun(usalp);
+       scmd->cdb.g5_cdb.reladr = judge; /* Judge the Disc */
+
+       usalp->cmdname = "opt_power_judge";
+
+       return (usal_cmd(usalp));
+}
+
+/*
+ * Clear subcodes for Teac Drives.
+ */
+static int 
+clear_subcode(SCSI *usalp)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->addr = (caddr_t)0;
+       scmd->size = 0;
+       scmd->flags = SCG_DISRE_ENA;
+       scmd->cdb_len = SC_G5_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+
+       scmd->cdb.g5_cdb.cmd = SC_CLEAR_SUBCODE;
+       scmd->cdb.g5_cdb.lun = usal_lun(usalp);
+       scmd->cdb.g5_cdb.addr[3] = 0x80;
+
+       usalp->cmdname = "clear subcode";
+
+       return (usal_cmd(usalp));
+}
+
+/*
+ * Set limits for command linking for Teac Drives.
+ */
+static int 
+set_limits(SCSI *usalp, long lba, long length)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->addr = (caddr_t)0;
+       scmd->size = 0;
+       scmd->flags = SCG_DISRE_ENA;
+       scmd->cdb_len = SC_G5_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+
+       scmd->cdb.g5_cdb.cmd = SC_SET_LIMITS;
+       scmd->cdb.g5_cdb.lun = usal_lun(usalp);
+       i_to_4_byte(&scmd->cdb.g5_cdb.addr[0], lba);
+       i_to_4_byte(&scmd->cdb.g5_cdb.count[0], length);
+
+       usalp->cmdname = "set limits";
+
+       return (usal_cmd(usalp));
+}
+
+/*
+ * Set subcode for Teac Drives.
+ */
+static int 
+set_subcode(SCSI *usalp, Uchar *subcode_data, int length)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->addr = (caddr_t)subcode_data;
+       scmd->size = length;
+       scmd->flags = SCG_DISRE_ENA;
+       scmd->cdb_len = SC_G1_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+
+       scmd->cdb.g1_cdb.cmd = SC_SET_SUBCODE;
+       scmd->cdb.g1_cdb.lun = usal_lun(usalp);
+       g1_cdblen(&scmd->cdb.g1_cdb, length);
+
+       usalp->cmdname = "set subcode";
+
+       return (usal_cmd(usalp));
+}
+
+static int 
+read_disk_info_teac(SCSI *usalp, Uchar *data, int length, int type)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->addr = (caddr_t)data;
+       scmd->size = length;
+       scmd->flags = SCG_RECV_DATA |SCG_DISRE_ENA;
+       scmd->cdb_len = SC_G1_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+
+       scmd->cdb.g1_cdb.cmd = SC_READ_DISK_INFO;
+       scmd->cdb.g1_cdb.lun = usal_lun(usalp);
+
+       scmd->cdb.g1_cdb.reladr = type & 1;
+       scmd->cdb.g1_cdb.res    = (type & 2) >> 1;
+
+       usalp->cmdname = "read disk info teac";
+
+       return (usal_cmd(usalp));
+}
+
+/*
+ * Perform the freeze command for Teac Drives.
+ */
+static int 
+teac_freeze(SCSI *usalp, int bp_flag)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->addr = (caddr_t)0;
+       scmd->size = 0;
+       scmd->flags = SCG_DISRE_ENA;
+       scmd->cdb_len = SC_G5_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+       scmd->timeout = 8 * 60;         /* Needs up to 4 minutes */
+
+       scmd->cdb.g5_cdb.cmd = SC_FREEZE;
+       scmd->cdb.g5_cdb.lun = usal_lun(usalp);
+       scmd->cdb.g5_cdb.addr[3] = bp_flag ? 0x80 : 0;
+
+       usalp->cmdname = "teac_freeze";
+
+       return (usal_cmd(usalp));
+}
+
+static int 
+teac_wr_pma(SCSI *usalp)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->addr = (caddr_t)0;
+       scmd->size = 0;
+       scmd->flags = SCG_DISRE_ENA;
+       scmd->cdb_len = SC_G5_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+
+       scmd->cdb.g5_cdb.cmd = SC_WRITE_PMA;
+       scmd->cdb.g5_cdb.lun = usal_lun(usalp);
+
+       usalp->cmdname = "teac_write_pma";
+
+       return (usal_cmd(usalp));
+}
+
+/*
+ * Read PMA for Teac Drives.
+ */
+static int 
+teac_rd_pma(SCSI *usalp)
+{
+       unsigned char   xx[256];
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)xx, sizeof (xx), '\0');
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->addr = (caddr_t)xx;
+       scmd->size = sizeof (xx);
+       scmd->flags = SCG_RECV_DATA |SCG_DISRE_ENA;
+       scmd->cdb_len = SC_G1_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+
+       scmd->cdb.g1_cdb.cmd = SC_READ_PMA;
+       scmd->cdb.g1_cdb.lun = usal_lun(usalp);
+
+       g1_cdblen(&scmd->cdb.g1_cdb, sizeof (xx));
+
+       usalp->cmdname = "teac_read_pma";
+
+/*     return (usal_cmd(usalp));*/
+       if (usal_cmd(usalp) < 0)
+               return (-1);
+
+       if (usalp->verbose) {
+               usal_prbytes("PMA Data", xx, sizeof (xx) - usal_getresid(usalp));
+       }
+       if (lverbose) {
+               unsigned i;
+               Uchar   *p;
+
+               usal_prbytes("PMA Header: ", xx, 4);
+               i = xx[2];
+               p = &xx[4];
+               for (; i <= xx[3]; i++) {
+                       usal_prbytes("PMA: ", p, 10);
+                       p += 10;
+               }
+       }
+       return (0);
+}
+
+/*
+ * Next writable address for Teac Drives.
+ */
+static int 
+next_wr_addr_teac(SCSI *usalp, long start_lba, long last_lba)
+{
+       unsigned char   xx[256];
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)xx, sizeof (xx), '\0');
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->addr = (caddr_t)xx;
+       scmd->size = sizeof (xx);
+       scmd->flags = SCG_RECV_DATA |SCG_DISRE_ENA;
+       scmd->cdb_len = SC_G5_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+
+       scmd->cdb.g5_cdb.cmd = SC_NEXT_WR_ADDRESS;
+       scmd->cdb.g5_cdb.lun = usal_lun(usalp);
+
+       i_to_4_byte(&scmd->cdb.g5_cdb.addr[0], start_lba);
+       i_to_4_byte(&scmd->cdb.g5_cdb.count[0], last_lba);
+
+       if (usalp->verbose)
+               printf("start lba: %ld last lba: %ld\n",
+                                       start_lba, last_lba);
+
+       usalp->cmdname = "next writable address";
+
+/*     return (usal_cmd(usalp));*/
+       if (usal_cmd(usalp) < 0)
+               return (-1);
+
+       if (usalp->verbose) {
+               usal_prbytes("WRa Data", xx, sizeof (xx) - usal_getresid(usalp));
+               printf("NWA: %ld\n", a_to_4_byte(xx));
+       }
+       return (0);
+}
+
+static int 
+blank_jvc(SCSI *usalp, cdr_t *dp, long addr, int blanktype)
+{
+       extern  char    *blank_types[];
+
+       if (lverbose) {
+               printf("Blanking %s\n", blank_types[blanktype & 0x07]);
+               flush();
+       }
+
+       return (scsi_blank(usalp, addr, blanktype, FALSE));
+}
+
+static int 
+buf_cap_teac(SCSI *usalp, long *sp, long *fp)
+{
+       Ulong   freespace;
+       Ulong   bufsize;
+       long    ret;
+       int     per;
+
+       ret = read_peak_buffer_cap_teac(usalp);
+       if (ret < 0)
+               return (-1);
+       bufsize = ret;
+       freespace = 0;
+       if (sp)
+               *sp = bufsize;
+       if (fp)
+               *fp = freespace;
+
+       if (usalp->verbose || (sp == 0 && fp == 0))
+               printf("BFree: %ld K BSize: %ld K\n", freespace >> 10, bufsize >> 10);
+
+       if (bufsize == 0)
+               return (0);
+       per = (100 * (bufsize - freespace)) / bufsize;
+       if (per < 0)
+               return (0);
+       if (per > 100)
+               return (100);
+       return (per);
+}
+
+static long 
+read_peak_buffer_cap_teac(SCSI *usalp)
+{
+       Uchar   xx[4];
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)xx, sizeof (xx), '\0');
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->addr = (caddr_t)xx;
+       scmd->size = sizeof (xx);
+       scmd->flags = SCG_RECV_DATA |SCG_DISRE_ENA;
+       scmd->cdb_len = SC_G5_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+
+       scmd->cdb.g5_cdb.cmd = SC_READ_PEAK_BUF_CAP;
+       scmd->cdb.g5_cdb.lun = usal_lun(usalp);
+
+       usalp->cmdname = "read peak buffer capacity";
+
+#define        BDEBUG
+#ifndef        BDEBUG
+       return (usal_cmd(usalp));
+#else
+       if (usal_cmd(usalp) < 0)
+               return (-1);
+
+       if (usalp->verbose) {
+               usal_prbytes("WRa Data", xx, sizeof (xx) - usal_getresid(usalp));
+               printf("Buffer cap: %ld\n", a_to_u_3_byte(&xx[1]));
+       }
+       return (a_to_u_3_byte(&xx[1]));
+/*     return (0);*/
+#endif
+}
+
+#define        BI_ONE_BYTE     0xC0
+#define        BI_448_BYTE     0x40
+#define        BI_APP_CODE     0x10
+
+static int 
+buffer_inquiry_teac(SCSI *usalp, int fmt)
+{
+       Uchar   xx[448];
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)xx, sizeof (xx), '\0');
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->addr = (caddr_t)xx;
+       scmd->size = sizeof (xx);
+       scmd->size = 448;
+       scmd->flags = SCG_RECV_DATA |SCG_DISRE_ENA;
+       scmd->cdb_len = SC_G5_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+
+       scmd->cdb.g5_cdb.cmd = SC_BUFFER_INQUIRY;
+       scmd->cdb.g5_cdb.lun = usal_lun(usalp);
+
+       if (fmt > 0) {
+               scmd->cdb.g5_cdb.addr[3] = fmt;
+               if (fmt == BI_ONE_BYTE)
+                       scmd->size = 1;
+       } else {
+               scmd->cdb.g5_cdb.addr[3] = BI_448_BYTE;
+/*             scmd->cdb.g5_cdb.addr[3] = BI_APP_CODE;*/
+       }
+
+       usalp->cmdname = "buffer inquiry";
+
+#define        BDEBUG
+#ifndef        BDEBUG
+       return (usal_cmd(usalp));
+#else
+       if (usal_cmd(usalp) < 0)
+               return (-1);
+
+       if (usalp->verbose) {
+/*             usal_prbytes("WRa Data", xx, sizeof (xx) - usal_getresid(usalp));*/
+/*             usal_prbytes("WRa Data", xx, 1);*/
+
+               if (fmt > 0) printf("fmt: %X ", fmt);
+               usal_prbytes("WRa Data", xx, 9);
+               printf("%d\n", xx[8] - xx[1]);
+/*             printf("Buffer cap: %ld\n", a_to_u_3_byte(&xx[1]));*/
+       }
+       return (0);
+#endif
+}
+
+#ifdef XXBUFFER
+static void 
+check_buffer_teac(SCSI *usalp)
+{
+       printf("-------\n");
+       buffer_inquiry_teac(usalp, 0);
+#ifdef SL
+       usleep(40000);
+       buffer_inquiry_teac(usalp, 0);
+#endif
+       read_peak_buffer_cap_teac(usalp);
+}
+#endif
+/*--------------------------------------------------------------------------*/
+#ifdef XXDEBUG
+#include "scsimmc.h"
+
+static int     g7_teac(SCSI *usalp);
+static int     g6_teac(SCSI *usalp);
+
+static int 
+g7_teac(SCSI *usalp)
+{
+       Uchar   xx[2048];
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)xx, sizeof (xx), '\0');
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->addr = (caddr_t)xx;
+       scmd->size = sizeof (xx);
+       scmd->flags = SCG_RECV_DATA |SCG_DISRE_ENA;
+       scmd->cdb_len = SC_G5_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+
+       scmd->cdb.g5_cdb.cmd = 0xDf;
+/*     scmd->cdb.g5_cdb.cmd = 0xE5;*/
+       scmd->cdb.g5_cdb.lun = usal_lun(usalp);
+
+/*     scmd->cdb.g5_cdb.addr[3] = BI_ONE_BYTE;*/
+/*     scmd->size = 1;*/
+
+/*     scmd->cdb.g5_cdb.addr[3] = BI_448_BYTE;*/
+/*     scmd->cdb.g5_cdb.addr[3] = BI_APP_CODE;*/
+
+       usalp->cmdname = "g7 teac";
+
+/*     return (usal_cmd(usalp));*/
+       if (usal_cmd(usalp) < 0)
+               return (-1);
+
+/*     if (usalp->verbose) {*/
+               usal_prbytes("WRa Data", xx, sizeof (xx) - usal_getresid(usalp));
+/*             usal_prbytes("WRa Data", xx, 1);*/
+/*             usal_prbytes("WRa Data", xx, 9);*/
+/*printf("%d\n", xx[8] - xx[1]);*/
+/*             printf("Buffer cap: %ld\n", a_to_u_3_byte(&xx[1]));*/
+/*     }*/
+       return (0);
+}
+
+static int 
+g6_teac(SCSI *usalp)
+{
+       Uchar   xx[2048];
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)xx, sizeof (xx), '\0');
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->addr = (caddr_t)xx;
+       scmd->size = sizeof (xx);
+       scmd->flags = SCG_RECV_DATA |SCG_DISRE_ENA;
+       scmd->cdb_len = SC_G1_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+
+       scmd->cdb.g1_cdb.cmd = 0xC1;
+       scmd->cdb.g1_cdb.cmd = 0xC3;
+       scmd->cdb.g1_cdb.cmd = 0xC6;
+       scmd->cdb.g1_cdb.cmd = 0xC7;    /* Read TOC */
+       scmd->cdb.g1_cdb.cmd = 0xCe;
+       scmd->cdb.g1_cdb.cmd = 0xCF;
+       scmd->cdb.g1_cdb.cmd = 0xC7;    /* Read TOC */
+       scmd->cdb.g1_cdb.lun = usal_lun(usalp);
+
+       usalp->cmdname = "g6 teac";
+
+/*     return (usal_cmd(usalp));*/
+       if (usal_cmd(usalp) < 0)
+               return (-1);
+
+/*     if (usalp->verbose) {*/
+               usal_prbytes("WRa Data", xx, sizeof (xx) - usal_getresid(usalp));
+/*             usal_prbytes("WRa Data", xx, 1);*/
+/*             usal_prbytes("WRa Data", xx, 9);*/
+/*printf("%d\n", xx[8] - xx[1]);*/
+/*             printf("Buffer cap: %ld\n", a_to_u_3_byte(&xx[1]));*/
+/*     }*/
+       return (0);
+}
+
+static void 
+xxtest_teac(SCSI *usalp)
+{
+       read_peak_buffer_cap_teac(usalp);
+
+/*#define      XDI*/
+#ifdef XDI
+       {
+               Uchar cbuf[512];
+
+/*             read_disk_info_teac(usalp, data, length, type)*/
+/*             read_disk_info_teac(usalp, cbuf, 512, 2);*/
+/*             read_disk_info_teac(usalp, cbuf, 512, 2);*/
+               read_disk_info_teac(usalp, cbuf, 512, 3);
+               usal_prbytes("DI Data", cbuf, sizeof (cbuf) - usal_getresid(usalp));
+       }
+#endif /* XDI */
+
+       buffer_inquiry_teac(usalp, -1);
+
+/*#define      XBU*/
+#ifdef XBU
+       {
+               int i;
+
+               for (i = 0; i < 63; i++) {
+                       usalp->silent++;
+                       buffer_inquiry_teac(usalp, i<<2);
+                       usalp->silent--;
+               }
+       }
+#endif /* XBU */
+
+/*     printf("LLLL\n");*/
+/*     g7_teac(usalp);*/
+/*     g6_teac(usalp);*/
+}
+#endif /* XXDEBUG */
diff --git a/wodim/drv_mmc.c b/wodim/drv_mmc.c
new file mode 100644 (file)
index 0000000..b075889
--- /dev/null
@@ -0,0 +1,4362 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)drv_mmc.c       1.163 06/01/12 Copyright 1997-2006 J. Schilling */
+/*
+ *     CDR device implementation for
+ *     SCSI-3/mmc conforming drives
+ *     e.g. Yamaha CDR-400, Ricoh MP6200
+ *
+ *     Copyright (c) 1997-2006 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*#define      DEBUG*/
+#define        PRINT_ATIP
+#include <mconfig.h>
+
+#include <stdio.h>
+#include <standard.h>
+#include <fctldefs.h>
+#include <errno.h>
+#include <strdefs.h>
+#include <stdxlib.h>
+#include <unixstd.h>
+#include <timedefs.h>
+
+#include <utypes.h>
+#include <btorder.h>
+#include <intcvt.h>
+#include <schily.h>
+
+#include <usal/usalcmd.h>
+#include <usal/scsidefs.h>
+#include <usal/scsireg.h>
+#include <usal/scsitransp.h>
+
+#include "scsimmc.h"
+#include "mmcvendor.h"
+#include "wodim.h"
+#include "scsi_scan.h"
+
+extern char    *driveropts;
+
+extern int     debug;
+extern int     lverbose;
+extern int     xdebug;
+
+static int     curspeed = 1;
+
+static char    clv_to_speed[16] = {
+/*             0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 */
+               0, 2, 4, 6, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+static char    hs_clv_to_speed[16] = {
+/*             0  1  2  3  4  5  6  7   8  9 10 11 12 13 14 15 */
+               0, 2, 4, 6, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+static char    us_clv_to_speed[16] = {
+/*             0  1  2  3  4  5   6  7  8   9   10  11 12 13 14 15 */
+               0, 2, 4, 8, 0, 0, 16, 0, 24, 32, 40, 48, 0, 0, 0, 0
+};
+
+#ifdef __needed__
+static int     mmc_load(SCSI *usalp, cdr_t *dp);
+static int     mmc_unload(SCSI *usalp, cdr_t *dp);
+#endif
+void                           mmc_opthelp(cdr_t *dp, int excode);
+char                           *hasdrvopt(char *optstr, char *optname);
+static cdr_t   *identify_mmc(SCSI *usalp, cdr_t *, struct scsi_inquiry *);
+static int     attach_mmc(SCSI *usalp, cdr_t *);
+static   int   attach_mdvd(SCSI *usalp, cdr_t *);
+int                            check_writemodes_mmc(SCSI *usalp, cdr_t *dp);
+int                            check_writemodes_mdvd(SCSI *usalp, cdr_t *dp);
+static int     deflt_writemodes_mmc(SCSI *usalp, BOOL reset_dummy);
+static   int   deflt_writemodes_mdvd(SCSI *usalp, BOOL reset_dummy);
+static int     get_diskinfo(SCSI *usalp, struct disk_info *dip);
+static void    di_to_dstat(struct disk_info *dip, dstat_t *dsp);
+static int     get_atip(SCSI *usalp, struct atipinfo *atp);
+#ifdef PRINT_ATIP
+static int     get_pma(SCSI *usalp);
+#endif
+static int     init_mmc(SCSI *usalp, cdr_t *dp);
+static int     getdisktype_mmc(SCSI *usalp, cdr_t *dp);
+static  int   getdisktype_mdvd(SCSI *usalp, cdr_t *dp);
+static int     speed_select_mmc(SCSI *usalp, cdr_t *dp, int *speedp);
+static  int   speed_select_mdvd(SCSI *usalp, cdr_t *dp, int *speedp);
+static int     mmc_set_speed(SCSI *usalp, int readspeed, int writespeed, 
+                                                                         int rotctl);
+static int     next_wr_addr_mmc(SCSI *usalp, track_t *trackp, long *ap);
+static  int   next_wr_addr_mdvd(SCSI *usalp, track_t *trackp, long *ap);
+static int     write_leadin_mmc(SCSI *usalp, cdr_t *dp, track_t *trackp);
+static int     open_track_mmc(SCSI *usalp, cdr_t *dp, track_t *trackp);
+static  int   open_track_mdvd(SCSI *usalp, cdr_t *dp, track_t *trackp);
+static int     close_track_mmc(SCSI *usalp, cdr_t *dp, track_t *trackp);
+static  int   close_track_mdvd(SCSI *usalp, cdr_t *dp, track_t *trackp); 
+static int     open_session_mmc(SCSI *usalp, cdr_t *dp, track_t *trackp);
+static  int   open_session_mdvd(SCSI *usalp, cdr_t *dp, track_t *trackp);
+static int     waitfix_mmc(SCSI *usalp, int secs);
+static int     fixate_mmc(SCSI *usalp, cdr_t *dp, track_t *trackp);
+static  int   fixate_mdvd(SCSI *usalp, cdr_t *dp, track_t *trackp);
+static int     blank_mmc(SCSI *usalp, cdr_t *dp, long addr, int blanktype);
+static int     format_mdvd(SCSI *usalp, cdr_t *dp, int formattype);
+static int     send_opc_mmc(SCSI *usalp, caddr_t, int cnt, int doopc);
+static int     opt1_mmc(SCSI *usalp, cdr_t *dp);
+static int     opt1_mdvd(SCSI *usalp, cdr_t *dp);
+static int     opt2_mmc(SCSI *usalp, cdr_t *dp);
+static int     scsi_sony_write(SCSI *usalp, caddr_t bp, long sectaddr, long size, 
+                                                                                int blocks, BOOL islast);
+static int     gen_cue_mmc(track_t *trackp, void *vcuep, BOOL needgap);
+static void    fillcue(struct mmc_cue *cp, int ca, int tno, int idx, int dataform,
+                                                        int scms, msf_t *mp);
+static int     send_cue_mmc(SCSI *usalp, cdr_t *dp, track_t *trackp);
+static         int     stats_mmc(SCSI *usalp, cdr_t *dp);
+static         BOOL    mmc_isplextor(SCSI *usalp);
+static         BOOL    mmc_isyamaha(SCSI *usalp);
+static         void    do_varirec_plextor(SCSI *usalp);
+static         int     do_gigarec_plextor(SCSI *usalp);
+static         int     drivemode_plextor(SCSI *usalp, caddr_t bp, int cnt, int modecode, 
+                                                                                       void *modeval);
+static         int     drivemode2_plextor(SCSI *usalp, caddr_t bp, int cnt, int modecode, 
+                                                                                        void *modeval);
+static         int     check_varirec_plextor(SCSI *usalp);
+static         int     check_gigarec_plextor(SCSI *usalp);
+static         int     varirec_plextor(SCSI *usalp, BOOL on, int val);
+static         int     gigarec_plextor(SCSI *usalp, int val);
+static         Int32_t gigarec_mult(int code, Int32_t  val);
+static         int     check_ss_hide_plextor(SCSI *usalp);
+static         int     check_speed_rd_plextor(SCSI *usalp);
+static         int     check_powerrec_plextor(SCSI *usalp);
+static         int     ss_hide_plextor(SCSI *usalp, BOOL do_ss, BOOL do_hide);
+static         int     speed_rd_plextor(SCSI *usalp, BOOL do_speedrd);
+static         int     powerrec_plextor(SCSI *usalp, BOOL do_powerrec);
+static         int     get_speeds_plextor(SCSI *usalp, int *selp, int *maxp, int *lastp);
+static         int     bpc_plextor(SCSI *usalp, int mode, int *bpp);
+static         int     set_audiomaster_yamaha(SCSI *usalp, cdr_t *dp, BOOL keep_mode);
+
+struct         ricoh_mode_page_30 * get_justlink_ricoh(SCSI *usalp, Uchar *mode);
+static         int     force_speed_yamaha(SCSI *usalp, int readspeed, int writespeed);
+static         BOOL    get_tattoo_yamaha(SCSI *usalp, BOOL print, Int32_t *irp, 
+                                                                               Int32_t *orp);
+static         int     do_tattoo_yamaha(SCSI *usalp, FILE *f);
+static         int     yamaha_write_buffer(SCSI *usalp, int mode, int bufferid, long offset,
+                                                                                 long parlen, void *buffer, long buflen);
+static int     dvd_dual_layer_split(SCSI *usalp, cdr_t *dp, long tsize);
+
+extern int     reserve_track(SCSI *usalp, Ulong size); /* FIXME */
+extern int     scsi_format(SCSI *usalp, caddr_t addr, int size, BOOL background); /* FIXME */
+
+#ifdef __needed__
+static int 
+mmc_load(SCSI *usalp, cdr_t *dp)
+{
+       return (scsi_load_unload(usalp, 1));
+}
+
+static int 
+mmc_unload(SCSI *usalp, cdr_t *dp)
+{
+       return (scsi_load_unload(usalp, 0));
+}
+#endif
+
+/*
+ * MMC CD-writer
+ */
+cdr_t  cdr_mmc = {
+       0, 0,
+       CDR_SWABAUDIO,
+       CDR_CDRW_ALL,
+       372, 372,
+       "mmc_cdr",
+       "generic SCSI-3/mmc   CD-R/CD-RW driver",
+       0,
+       (dstat_t *)0,
+       identify_mmc,
+       attach_mmc,
+       init_mmc,
+       getdisktype_mmc,
+       scsi_load,
+       scsi_unload,
+       read_buff_cap,
+       cmd_dummy,                                      /* check_recovery */
+       (int(*)(SCSI *, cdr_t *, int))cmd_dummy,        /* recover      */
+       speed_select_mmc,
+       select_secsize,
+       next_wr_addr_mmc,
+       (int(*)(SCSI *, Ulong))cmd_ill, /* reserve_track        */
+       scsi_cdr_write,
+       gen_cue_mmc,
+       send_cue_mmc,
+       write_leadin_mmc,
+       open_track_mmc,
+       close_track_mmc,
+       open_session_mmc,
+       cmd_dummy,
+       cmd_dummy,                                      /* abort        */
+       read_session_offset,
+       fixate_mmc,
+       stats_mmc,
+       blank_mmc,
+       format_dummy,
+       send_opc_mmc,
+       opt1_mmc,
+       opt2_mmc,
+};
+
+cdr_t   cdr_mdvd = {
+       0, 0,
+       CDR_SWABAUDIO,
+       CDR_CDRW_ALL,
+       370,370,
+       "mmc_mdvd",
+       "generic SCSI-3/mmc DVD-R(W) driver",
+       0,
+       (dstat_t *)0,
+       identify_mmc,
+       attach_mdvd,
+       init_mmc,
+       getdisktype_mdvd,
+       scsi_load,
+       scsi_unload,
+       read_buff_cap,
+       cmd_dummy,                                       /* check_recovery */
+       (int(*)__PR((SCSI *, cdr_t *, int)))cmd_dummy,   /* recover     */
+       speed_select_mdvd,
+       select_secsize,
+       next_wr_addr_mdvd,
+       (int(*)(SCSI *, Ulong))cmd_ill,   /* reserve_track        */
+       scsi_cdr_write,
+       (int(*)__PR((track_t *, void *, BOOL)))cmd_dummy, /* gen_cue */
+       (int(*)__PR((SCSI *usalp, cdr_t *, track_t *)))cmd_dummy, /* send_cue */
+       write_leadin_mmc,
+       open_track_mdvd,
+       close_track_mdvd,
+       open_session_mdvd,
+       cmd_dummy,
+       cmd_dummy,                                      /* abort        */
+       read_session_offset,
+       fixate_mdvd,
+       stats_mmc,
+       blank_mmc,
+       format_mdvd,
+       send_opc_mmc,
+       opt1_mdvd,
+       opt2_mmc,
+       dvd_dual_layer_split,
+};
+
+/*
+ * Sony MMC CD-writer
+ */
+cdr_t  cdr_mmc_sony = {
+       0, 0,
+       CDR_SWABAUDIO,
+       CDR_CDRW_ALL,
+       372, 372,
+       "mmc_cdr_sony",
+       "generic SCSI-3/mmc   CD-R/CD-RW driver (Sony 928 variant)",
+       0,
+       (dstat_t *)0,
+       identify_mmc,
+       attach_mmc,
+       init_mmc,
+       getdisktype_mmc,
+       scsi_load,
+       scsi_unload,
+       read_buff_cap,
+       cmd_dummy,                                      /* check_recovery */
+       (int(*)(SCSI *, cdr_t *, int))cmd_dummy,        /* recover      */
+       speed_select_mmc,
+       select_secsize,
+       next_wr_addr_mmc,
+       (int(*)(SCSI *, Ulong))cmd_ill, /* reserve_track        */
+       scsi_sony_write,
+       gen_cue_mmc,
+       send_cue_mmc,
+       write_leadin_mmc,
+       open_track_mmc,
+       close_track_mmc,
+       open_session_mmc,
+       cmd_dummy,
+       cmd_dummy,                                      /* abort        */
+       read_session_offset,
+       fixate_mmc,
+       cmd_dummy,                              /* stats                */
+       blank_mmc,
+       format_dummy,
+       send_opc_mmc,
+       opt1_mmc,
+       opt2_mmc,
+};
+
+/*
+ * SCSI-3/mmc conformant CD-ROM drive
+ */
+cdr_t  cdr_cd = {
+       0, 0,
+       CDR_ISREADER|CDR_SWABAUDIO,
+       CDR_CDRW_NONE,
+       372, 372,
+       "mmc_cd",
+       "generic SCSI-3/mmc   CD-ROM driver",
+       0,
+       (dstat_t *)0,
+       identify_mmc,
+       attach_mmc,
+       cmd_dummy,
+       drive_getdisktype,
+       scsi_load,
+       scsi_unload,
+       read_buff_cap,
+       cmd_dummy,                                      /* check_recovery */
+       (int(*)(SCSI *, cdr_t *, int))cmd_dummy,        /* recover      */
+       speed_select_mmc,
+       select_secsize,
+       (int(*)(SCSI *usalp, track_t *, long *))cmd_ill,        /* next_wr_addr         */
+       (int(*)(SCSI *, Ulong))cmd_ill, /* reserve_track        */
+       scsi_cdr_write,
+       (int(*)(track_t *, void *, BOOL))cmd_dummy,     /* gen_cue */
+       no_sendcue,
+       (int(*)(SCSI *, cdr_t *, track_t *))cmd_dummy, /* leadin */
+       open_track_mmc,
+       close_track_mmc,
+       (int(*)(SCSI *usalp, cdr_t *, track_t *))cmd_dummy,
+       cmd_dummy,
+       cmd_dummy,                                      /* abort        */
+       read_session_offset,
+       (int(*)(SCSI *usalp, cdr_t *, track_t *))cmd_dummy,     /* fixation */
+       cmd_dummy,                                      /* stats        */
+       blank_dummy,
+       format_dummy,
+       (int(*)(SCSI *, caddr_t, int, int))NULL,        /* no OPC       */
+       cmd_dummy,                                      /* opt1         */
+       cmd_dummy,                                      /* opt2         */
+};
+
+/*
+ * Old pre SCSI-3/mmc CD drive
+ */
+cdr_t  cdr_oldcd = {
+       0, 0,
+       CDR_ISREADER,
+       CDR_CDRW_NONE,
+       372, 372,
+       "scsi2_cd",
+       "generic SCSI-2       CD-ROM driver",
+       0,
+       (dstat_t *)0,
+       identify_mmc,
+       drive_attach,
+       cmd_dummy,
+       drive_getdisktype,
+       scsi_load,
+       scsi_unload,
+       buf_dummy,
+       cmd_dummy,                                      /* check_recovery */
+       (int(*)(SCSI *, cdr_t *, int))cmd_dummy,        /* recover      */
+       speed_select_mmc,
+       select_secsize,
+       (int(*)(SCSI *usal, track_t *, long *))cmd_ill, /* next_wr_addr         */
+       (int(*)(SCSI *, Ulong))cmd_ill, /* reserve_track        */
+       scsi_cdr_write,
+       (int(*)(track_t *, void *, BOOL))cmd_dummy,     /* gen_cue */
+       no_sendcue,
+       (int(*)(SCSI *, cdr_t *, track_t *))cmd_dummy, /* leadin */
+       open_track_mmc,
+       close_track_mmc,
+       (int(*)(SCSI *usalp, cdr_t *, track_t *))cmd_dummy,
+       cmd_dummy,
+       cmd_dummy,                                      /* abort        */
+       read_session_offset_philips,
+       (int(*)(SCSI *usalp, cdr_t *, track_t *))cmd_dummy,     /* fixation */
+       cmd_dummy,                                      /* stats        */
+       blank_dummy,
+       format_dummy,
+       (int(*)(SCSI *, caddr_t, int, int))NULL,        /* no OPC       */
+       cmd_dummy,                                      /* opt1         */
+       cmd_dummy,                                      /* opt2         */
+};
+
+/*
+ * SCSI-3/mmc conformant CD or DVD writer
+ * Checks the current medium and then returns either cdr_mmc or cdr_dvd
+ */
+cdr_t  cdr_cd_dvd = {
+       0, 0,
+       CDR_SWABAUDIO,
+       CDR_CDRW_ALL,
+       372, 372,
+       "mmc_cd_dvd",
+       "generic SCSI-3/mmc   CD/DVD driver (checks media)",
+       0,
+       (dstat_t *)0,
+       identify_mmc,
+       attach_mmc,
+       cmd_dummy,
+       drive_getdisktype,
+       scsi_load,
+       scsi_unload,
+       read_buff_cap,
+       cmd_dummy,                                      /* check_recovery */
+       (int(*)(SCSI *, cdr_t *, int))cmd_dummy,        /* recover      */
+       speed_select_mmc,
+       select_secsize,
+       (int(*)(SCSI *usalp, track_t *, long *))cmd_ill,        /* next_wr_addr         */
+       (int(*)(SCSI *, Ulong))cmd_ill, /* reserve_track        */
+       scsi_cdr_write,
+       (int(*)(track_t *, void *, BOOL))cmd_dummy,     /* gen_cue */
+       no_sendcue,
+       (int(*)(SCSI *, cdr_t *, track_t *))cmd_dummy, /* leadin */
+       open_track_mmc,
+       close_track_mmc,
+       (int(*)(SCSI *usalp, cdr_t *, track_t *))cmd_dummy,
+       cmd_dummy,
+       cmd_dummy,                                      /* abort        */
+       read_session_offset,
+       (int(*)(SCSI *usalp, cdr_t *, track_t *))cmd_dummy,     /* fixation */
+       cmd_dummy,                                      /* stats        */
+       blank_dummy,
+       format_dummy,
+       (int(*)(SCSI *, caddr_t, int, int))NULL,        /* no OPC       */
+       cmd_dummy,                                      /* opt1         */
+       cmd_dummy,                                      /* opt2         */
+};
+
+void 
+mmc_opthelp(cdr_t *dp, int excode)
+{
+       BOOL    haveopts = FALSE;
+
+       fprintf(stderr, "Driver options:\n");
+       if (dp->cdr_flags & CDR_BURNFREE) {
+               fprintf(stderr, "burnfree       Prepare writer to use BURN-Free technology\n");
+               fprintf(stderr, "noburnfree     Disable using BURN-Free technology\n");
+               haveopts = TRUE;
+       }
+       if (dp->cdr_flags & CDR_VARIREC) {
+               fprintf(stderr, "varirec=val    Set VariRec Laserpower to -2, -1, 0, 1, 2\n");
+               fprintf(stderr, "               Only works for audio and if speed is set to 4\n");
+               haveopts = TRUE;
+       }
+       if (dp->cdr_flags & CDR_GIGAREC) {
+               fprintf(stderr, "gigarec=val    Set GigaRec capacity ratio to 0.6, 0.7, 0.8, 1.0, 1.2, 1.3, 1.4\n");
+               haveopts = TRUE;
+       }
+       if (dp->cdr_flags & CDR_AUDIOMASTER) {
+               fprintf(stderr, "audiomaster    Turn Audio Master feature on (SAO CD-R Audio/Data only)\n");
+               haveopts = TRUE;
+       }
+       if (dp->cdr_flags & CDR_FORCESPEED) {
+               fprintf(stderr, "forcespeed     Tell the drive to force speed even for low quality media\n");
+               haveopts = TRUE;
+       }
+       if (dp->cdr_flags & CDR_SPEEDREAD) {
+               fprintf(stderr, "speedread      Tell the drive to read as fast as possible\n");
+               fprintf(stderr, "nospeedread    Disable to read as fast as possible\n");
+               haveopts = TRUE;
+       }
+       if (dp->cdr_flags & CDR_DISKTATTOO) {
+               fprintf(stderr, "tattooinfo     Print image size info for DiskT@2 feature\n");
+               fprintf(stderr, "tattoofile=name        Use 'name' as DiskT@2 image file\n");
+               haveopts = TRUE;
+       }
+       if (dp->cdr_flags & CDR_SINGLESESS) {
+               fprintf(stderr, "singlesession  Tell the drive to behave as single session only drive\n");
+               fprintf(stderr, "nosinglesession        Disable single session only mode\n");
+               haveopts = TRUE;
+       }
+       if (dp->cdr_flags & CDR_HIDE_CDR) {
+               fprintf(stderr, "hidecdr                Tell the drive to hide CD-R media\n");
+               fprintf(stderr, "nohidecdr      Disable hiding CD-R media\n");
+               haveopts = TRUE;
+       }
+       if (!haveopts) {
+               fprintf(stderr, "None supported for this drive.\n");
+       }
+       exit(excode);
+}
+
+char *
+hasdrvopt(char *optstr, char *optname)
+{
+       char    *ep;
+       char    *np;
+       char    *ret = NULL;
+       int     optnamelen;
+       int     optlen;
+       BOOL    not = FALSE;
+
+       if (optstr == NULL)
+               return (ret);
+
+       optnamelen = strlen(optname);
+
+       while (*optstr) {
+               not = FALSE;                    /* Reset before every token */
+               if ((ep = strchr(optstr, ',')) != NULL) {
+                       optlen = ep - optstr;
+                       np = &ep[1];
+               } else {
+                       optlen = strlen(optstr);
+                       np = &optstr[optlen];
+               }
+               if ((ep = strchr(optstr, '=')) != NULL) {
+                       if (ep < np)
+                               optlen = ep - optstr;
+               }
+               if (optstr[0] == '!') {
+                       optstr++;
+                       optlen--;
+                       not = TRUE;
+               }
+               if (strncmp(optstr, "no", 2) == 0) {
+                       optstr += 2;
+                       optlen -= 2;
+                       not = TRUE;
+               }
+               if (strncmp(optstr, optname, optlen) == 0) {
+                       ret = &optstr[optlen];
+                       break;
+               }
+               optstr = np;
+       }
+       if (ret != NULL) {
+               if (*ret == ',' || *ret == '\0') {
+                       if (not)
+                               return ("0");
+                       return ("1");
+               }
+               if (*ret == '=') {
+                       if (not)
+                               return (NULL);
+                       return (++ret);
+               }
+       }
+       return (ret);
+}
+
+static cdr_t *
+identify_mmc(SCSI *usalp, cdr_t *dp, struct scsi_inquiry *ip)
+{
+       BOOL    cdrr     = FALSE;       /* Read CD-R    */
+       BOOL    cdwr     = FALSE;       /* Write CD-R   */
+       BOOL    cdrrw    = FALSE;       /* Read CD-RW   */
+       BOOL    cdwrw    = FALSE;       /* Write CD-RW  */
+       BOOL    dvdwr    = FALSE;       /* DVD writer   */
+       BOOL    is_dvd   = FALSE;       /* use DVD driver*/
+       Uchar   mode[0x100];
+       struct  cd_mode_page_2A *mp;
+       int     profile;
+
+       if (ip->type != INQ_WORM && ip->type != INQ_ROMD)
+               return ((cdr_t *)0);
+
+       allow_atapi(usalp, TRUE); /* Try to switch to 10 byte mode cmds */
+
+       usalp->silent++;
+       mp = mmc_cap(usalp, mode);      /* Get MMC capabilities */
+       usalp->silent--;
+       if (mp == NULL)
+               return (&cdr_oldcd);    /* Pre SCSI-3/mmc drive         */
+
+       /*
+        * At this point we know that we have a SCSI-3/mmc compliant drive.
+        * Unfortunately ATAPI drives violate the SCSI spec in returning
+        * a response data format of '1' which from the SCSI spec would
+        * tell us not to use the "PF" bit in mode select. As ATAPI drives
+        * require the "PF" bit to be set, we 'correct' the inquiry data.
+        *
+        * XXX xxx_identify() should not have any side_effects ??
+        */
+       if (ip->data_format < 2)
+               ip->data_format = 2;
+
+       /*
+        * First handle exceptions....
+        */
+       if (strncmp(ip->vendor_info, "SONY", 4) == 0 &&
+           strncmp(ip->prod_ident, "CD-R   CDU928E", 14) == 0) {
+               return (&cdr_mmc_sony);
+       }
+
+       /*
+        * Now try to do it the MMC-3 way....
+        */
+       profile = get_curprofile(usalp);
+       if (xdebug)
+               printf("Current profile: 0x%04X\n", profile);
+       if (profile == 0) {
+               if (xdebug)
+                       print_profiles(usalp);
+               /*
+                * If the current profile is 0x0000, then the
+                * drive does not know about the media. First
+                * close the tray and then try to issue the
+                * get_curprofile() command again.
+                */
+               usalp->silent++;
+               load_media(usalp, dp, FALSE);
+               usalp->silent--;
+               profile = get_curprofile(usalp);
+               scsi_prevent_removal(usalp, 0);
+               if (xdebug)
+                       printf("Current profile: 0x%04X\n", profile);
+       }
+       if (profile >= 0) {
+               if (lverbose)
+                       print_profiles(usalp);
+               if (profile == 0 || (profile >= 0x10 && profile <= 0x15) || profile > 0x19) {
+                   /*
+                    * 10h DVD-ROM
+                    * 11h DVD-R
+                    * 12h DVD-RAM
+                    * 13h DVD-RW (Restricted overwrite)
+                    * 14h DVD-RW (Sequential recording)
+                    * 1Ah DVD+RW
+                    * 1Bh DVD+R
+                    * 2Bh DVD+R DL
+                    * 
+                    */
+                   if (profile == 0x11 || profile == 0x13 || profile == 0x14 || profile == 0x1A || profile == 0x1B || profile == 0x2B) {
+                       is_dvd = TRUE;
+                       dp = &cdr_mdvd;
+                   } else {
+                       is_dvd = FALSE;
+                       dp = &cdr_cd;
+
+                       if (profile == 0) {             /* No Medium */
+                               BOOL    is_cdr = FALSE;
+
+                               /*
+                                * Check for CD-writer
+                                */
+                               get_wproflist(usalp, &is_cdr, NULL,
+                                                       NULL, NULL);
+                               if (is_cdr)
+                                       return (&cdr_mmc);
+                               /*
+                                * Other MMC-3 drive without media
+                                */
+                               return (dp);
+                       } if (profile == 0x12) {        /* DVD-RAM */
+                               errmsgno(EX_BAD,
+                               "Found unsupported DVD-RAM media.\n");
+                               return (dp);
+                       }
+                   }
+               }
+       } else {
+               if (xdebug)
+                       printf("Drive is pre MMC-3\n");
+       }
+
+       mmc_getval(mp, &cdrr, &cdwr, &cdrrw, &cdwrw, NULL, &dvdwr);
+
+       if (!cdwr && !cdwrw) {  /* SCSI-3/mmc CD drive          */
+               /*
+                * If the drive does not support to write CD's, we select the
+                * CD-ROM driver here. If we have DVD-R/DVD-RW support compiled
+                * in, we may later decide to switch to the DVD driver.
+                */
+               dp = &cdr_cd;
+       } else {
+               /*
+                * We need to set the driver to cdr_mmc because we may come
+                * here with driver set to cdr_cd_dvd which is not a driver
+                * that may be used for actual CD/DVD writing.
+                */
+               dp = &cdr_mmc;
+       }
+
+/*#define      DVD_DEBUG*/
+#ifdef DVD_DEBUG
+       if (1) {        /* Always check for DVD media in debug mode */
+#else
+       if ((cdwr || cdwrw) && dvdwr) {
+#endif
+               char    xb[32];
+
+#ifndef        DVD_DEBUG
+               usalp->silent++;
+#else
+               fprintf(stderr, "identify_dvd: checking for DVD media\n");
+#endif
+               if (read_dvd_structure(usalp, (caddr_t)xb, 32, 0, 0, 0) >= 0) {
+                       /*
+                        * If read DVD structure is supported and works, then
+                        * we must have a DVD media in the drive. Signal to
+                        * use the DVD driver.
+                        */
+                       is_dvd = TRUE;
+               } else {
+                       if (usal_sense_key(usalp) == SC_NOT_READY) {
+                               /*
+                                * If the SCSI sense key is NOT READY, then the
+                                * drive does not know about the media. First
+                                * close the tray and then try to issue the
+                                * read_dvd_structure() command again.
+                                */
+                               load_media(usalp, dp, FALSE);
+                               if (read_dvd_structure(usalp, (caddr_t)xb, 32, 0, 0, 0) >= 0) {
+                                       is_dvd = TRUE;
+                               }
+                               scsi_prevent_removal(usalp, 0);
+                       }
+               }
+#ifndef        DVD_DEBUG
+               usalp->silent--;
+#else
+               fprintf(stderr, "identify_dvd: is_dvd: %d\n", is_dvd);
+#endif
+       }
+       if (is_dvd) {
+     if(lverbose>2) 
+        fprintf(stderr, "Found DVD media: using cdr_mdvd.\n");  
+     dp = &cdr_mdvd; 
+       }
+       dp->profile = profile;
+       dp->is_dvd = is_dvd;
+       return (dp);
+}
+
+static int 
+attach_mmc(SCSI *usalp, cdr_t *dp)
+{
+       int     ret;
+       Uchar   mode[0x100];
+       struct  cd_mode_page_2A *mp;
+       struct  ricoh_mode_page_30 *rp = NULL;
+
+       allow_atapi(usalp, TRUE); /* Try to switch to 10 byte mode cmds */
+
+       usalp->silent++;
+       mp = mmc_cap(usalp, NULL); /* Get MMC capabilities in allocated mp */
+       usalp->silent--;
+       if (mp == NULL)
+               return (-1);    /* Pre SCSI-3/mmc drive         */
+
+       dp->cdr_cdcap = mp;     /* Store MMC cap pointer        */
+
+       dp->cdr_dstat->ds_dr_max_rspeed = a_to_u_2_byte(mp->max_read_speed)/176;
+       if (dp->cdr_dstat->ds_dr_max_rspeed == 0)
+               dp->cdr_dstat->ds_dr_max_rspeed = 372;
+       dp->cdr_dstat->ds_dr_cur_rspeed = a_to_u_2_byte(mp->cur_read_speed)/176;
+       if (dp->cdr_dstat->ds_dr_cur_rspeed == 0)
+               dp->cdr_dstat->ds_dr_cur_rspeed = 372;
+
+       dp->cdr_dstat->ds_dr_max_wspeed = a_to_u_2_byte(mp->max_write_speed)/176;
+       if (mp->p_len >= 28)
+               dp->cdr_dstat->ds_dr_cur_wspeed = a_to_u_2_byte(mp->v3_cur_write_speed)/176;
+       else
+               dp->cdr_dstat->ds_dr_cur_wspeed = a_to_u_2_byte(mp->cur_write_speed)/176;
+
+       if (dp->cdr_speedmax > dp->cdr_dstat->ds_dr_max_wspeed)
+               dp->cdr_speedmax = dp->cdr_dstat->ds_dr_max_wspeed;
+
+       if (dp->cdr_speeddef > dp->cdr_speedmax)
+               dp->cdr_speeddef = dp->cdr_speedmax;
+
+       rp = get_justlink_ricoh(usalp, mode);
+
+       if (mp->p_len >= 28)
+               dp->cdr_flags |= CDR_MMC3;
+       if (mp->p_len >= 24)
+               dp->cdr_flags |= CDR_MMC2;
+       dp->cdr_flags |= CDR_MMC;
+
+       if (mp->loading_type == LT_TRAY)
+               dp->cdr_flags |= CDR_TRAYLOAD;
+       else if (mp->loading_type == LT_CADDY)
+               dp->cdr_flags |= CDR_CADDYLOAD;
+
+       if (mp->BUF != 0) {
+               dp->cdr_flags |= CDR_BURNFREE;
+       } else if (rp) {
+               if ((dp->cdr_cmdflags & F_DUMMY) && rp->TWBFS && rp->BUEFS)
+                       dp->cdr_flags |= CDR_BURNFREE;
+
+               if (rp->BUEFS)
+                       dp->cdr_flags |= CDR_BURNFREE;
+       }
+
+       if (mmc_isplextor(usalp)) {
+               if (check_varirec_plextor(usalp) >= 0)
+                       dp->cdr_flags |= CDR_VARIREC;
+
+               if (check_gigarec_plextor(usalp) >= 0)
+                       dp->cdr_flags |= CDR_GIGAREC;
+
+               if (check_ss_hide_plextor(usalp) >= 0)
+                       dp->cdr_flags |= CDR_SINGLESESS|CDR_HIDE_CDR;
+
+               if (check_powerrec_plextor(usalp) >= 0)
+                       dp->cdr_flags |= CDR_FORCESPEED;
+
+               if (check_speed_rd_plextor(usalp) >= 0)
+                       dp->cdr_flags |= CDR_SPEEDREAD;
+       }
+       if (mmc_isyamaha(usalp)) {
+               if (set_audiomaster_yamaha(usalp, dp, FALSE) >= 0)
+                       dp->cdr_flags |= CDR_AUDIOMASTER;
+
+               /*
+                * Starting with CRW 2200 / CRW 3200
+                */
+               if ((mp->p_len+2) >= (unsigned)28)
+                       dp->cdr_flags |= CDR_FORCESPEED;
+
+               if (get_tattoo_yamaha(usalp, FALSE, 0, 0))
+                       dp->cdr_flags |= CDR_DISKTATTOO;
+       }
+
+       if (rp && rp->AWSCS)
+               dp->cdr_flags |= CDR_FORCESPEED;
+
+#ifdef FUTURE_ROTCTL
+       if (mp->p_len >= 28) {
+               int     val;
+
+               val = dp->cdr_dstat->ds_dr_cur_wspeed;
+               if (val == 0)
+                       val = 372;
+
+               usalp->verbose++;
+               if (scsi_set_speed(usalp, -1, val, ROTCTL_CAV) < 0) {
+                       fprintf(stderr, "XXX\n");
+               }
+               usalp->verbose--;
+       }
+#endif
+
+       check_writemodes_mmc(usalp, dp);
+
+       /* Enable Burnfree by default, it can be disabled later */
+       if ((dp->cdr_flags & CDR_BURNFREE) != 0)
+               dp->cdr_dstat->ds_cdrflags |= RF_BURNFREE;
+
+       if (driveropts != NULL) {
+               char    *p;
+
+               if (strcmp(driveropts, "help") == 0) {
+                       mmc_opthelp(dp, 0);
+               }
+
+               p = hasdrvopt(driveropts, "varirec");
+               if (p != NULL && (dp->cdr_flags & CDR_VARIREC) != 0) {
+                       dp->cdr_dstat->ds_cdrflags |= RF_VARIREC;
+               }
+
+               p = hasdrvopt(driveropts, "gigarec");
+               if (p != NULL && (dp->cdr_flags & CDR_GIGAREC) != 0) {
+                       dp->cdr_dstat->ds_cdrflags |= RF_GIGAREC;
+               }
+
+               p = hasdrvopt(driveropts, "audiomaster");
+               if (p != NULL && *p == '1' && (dp->cdr_flags & CDR_AUDIOMASTER) != 0) {
+                       dp->cdr_dstat->ds_cdrflags |= RF_AUDIOMASTER;
+                       dp->cdr_dstat->ds_cdrflags &= ~RF_BURNFREE;
+               }
+               p = hasdrvopt(driveropts, "forcespeed");
+               if (p != NULL && *p == '1' && (dp->cdr_flags & CDR_FORCESPEED) != 0) {
+                       dp->cdr_dstat->ds_cdrflags |= RF_FORCESPEED;
+               }
+               p = hasdrvopt(driveropts, "tattooinfo");
+               if (p != NULL && *p == '1' && (dp->cdr_flags & CDR_DISKTATTOO) != 0) {
+                       get_tattoo_yamaha(usalp, TRUE, 0, 0);
+               }
+               p = hasdrvopt(driveropts, "tattoofile");
+               if (p != NULL && (dp->cdr_flags & CDR_DISKTATTOO) != 0) {
+                       FILE    *f;
+
+                       if ((f = fileopen(p, "rb")) == NULL)
+                               comerr("Cannot open '%s'.\n", p);
+
+                       if (do_tattoo_yamaha(usalp, f) < 0)
+                               errmsgno(EX_BAD, "Cannot do DiskT@2.\n");
+                       fclose(f);
+               }
+               p = hasdrvopt(driveropts, "singlesession");
+               if (p != NULL && (dp->cdr_flags & CDR_SINGLESESS) != 0) {
+                       if (*p == '1') {
+                               dp->cdr_dstat->ds_cdrflags |= RF_SINGLESESS;
+                       } else if (*p == '0') {
+                               dp->cdr_dstat->ds_cdrflags &= ~RF_SINGLESESS;
+                       }
+               }
+               p = hasdrvopt(driveropts, "hidecdr");
+               if (p != NULL && (dp->cdr_flags & CDR_HIDE_CDR) != 0) {
+                       if (*p == '1') {
+                               dp->cdr_dstat->ds_cdrflags |= RF_HIDE_CDR;
+                       } else if (*p == '0') {
+                               dp->cdr_dstat->ds_cdrflags &= ~RF_HIDE_CDR;
+                       }
+               }
+               p = hasdrvopt(driveropts, "speedread");
+               if (p != NULL && (dp->cdr_flags & CDR_SPEEDREAD) != 0) {
+                       if (*p == '1') {
+                               dp->cdr_dstat->ds_cdrflags |= RF_SPEEDREAD;
+                       } else if (*p == '0') {
+                               dp->cdr_dstat->ds_cdrflags &= ~RF_SPEEDREAD;
+                       }
+               }
+       }
+
+       if ((ret = get_supported_cdrw_media_types(usalp)) < 0) {
+               dp->cdr_cdrw_support = CDR_CDRW_ALL;
+               return (0);
+       }
+       dp->cdr_cdrw_support = ret;
+       if (lverbose > 1)
+               printf("Supported CD-RW media types: %02X\n", dp->cdr_cdrw_support);
+
+       return (0);
+}
+
+static int 
+attach_mdvd(SCSI *usalp, cdr_t *dp)
+{
+       struct  cd_mode_page_2A *mp;
+
+
+       allow_atapi(usalp, TRUE);/* Try to switch to 10 byte mode cmds */
+
+       usalp->silent++;
+       mp = mmc_cap(usalp, NULL);/* Get MMC capabilities in allocated mp */
+       usalp->silent--;
+       if (mp == NULL)
+               return (-1);    /* Pre SCSI-3/mmc drive         */
+
+       dp->cdr_cdcap = mp;     /* Store MMC cap pointer        */
+
+       dp->cdr_dstat->ds_dr_max_rspeed = a_to_u_2_byte(mp->max_read_speed)/1385;
+       if (dp->cdr_dstat->ds_dr_max_rspeed == 0)
+               dp->cdr_dstat->ds_dr_max_rspeed = 1385;
+       dp->cdr_dstat->ds_dr_cur_rspeed = a_to_u_2_byte(mp->cur_read_speed)/1385;
+       if (dp->cdr_dstat->ds_dr_cur_rspeed == 0)
+               dp->cdr_dstat->ds_dr_cur_rspeed = 1385;
+
+       dp->cdr_dstat->ds_dr_max_wspeed = a_to_u_2_byte(mp->max_write_speed)/1385;
+       if (mp->p_len >= 28)
+               dp->cdr_dstat->ds_dr_cur_wspeed = a_to_u_2_byte(mp->v3_cur_write_speed)/1385;
+       else
+               dp->cdr_dstat->ds_dr_cur_wspeed = a_to_u_2_byte(mp->cur_write_speed)/1385;
+
+       if (dp->cdr_speedmax > dp->cdr_dstat->ds_dr_max_wspeed)
+               dp->cdr_speedmax = dp->cdr_dstat->ds_dr_max_wspeed;
+
+       if (dp->cdr_speeddef > dp->cdr_speedmax)
+               dp->cdr_speeddef = dp->cdr_speedmax;
+
+
+        if (mp->loading_type == LT_TRAY)
+                dp->cdr_flags |= CDR_TRAYLOAD;
+        else if (mp->loading_type == LT_CADDY)
+                dp->cdr_flags |= CDR_CADDYLOAD;
+
+        if (mp->BUF != 0)
+                dp->cdr_flags |= CDR_BURNFREE;
+
+        check_writemodes_mdvd(usalp, dp);
+
+        if (driveropts != NULL) {
+                if (strcmp(driveropts, "help") == 0) {
+                        mmc_opthelp(dp, 0);
+                }
+        }
+
+        return (0);
+}
+
+int 
+check_writemodes_mmc(SCSI *usalp, cdr_t *dp)
+{
+       Uchar   mode[0x100];
+       int     len;
+       struct  cd_mode_page_05 *mp;
+
+       if (xdebug)
+               printf("Checking possible write modes: ");
+
+       /*
+        * Reset mp->test_write (-dummy) here.
+        */
+       deflt_writemodes_mmc(usalp, TRUE);
+
+       fillbytes((caddr_t)mode, sizeof (mode), '\0');
+
+       usalp->silent++;
+       if (!get_mode_params(usalp, 0x05, "CD write parameter",
+                       mode, (Uchar *)0, (Uchar *)0, (Uchar *)0, &len)) {
+               usalp->silent--;
+               return (-1);
+       }
+       if (len == 0) {
+               usalp->silent--;
+               return (-1);
+       }
+
+       mp = (struct cd_mode_page_05 *)
+               (mode + sizeof (struct scsi_mode_header) +
+               ((struct scsi_mode_header *)mode)->blockdesc_len);
+#ifdef DEBUG
+       usal_prbytes("CD write parameter:", (Uchar *)mode, len);
+#endif
+
+       /*
+        * mp->test_write has already been reset in deflt_writemodes_mmc()
+        * Do not reset mp->test_write (-dummy) here. It should be set
+        * only at one place and only one time.
+        */
+
+       mp->write_type = WT_TAO;
+       mp->track_mode = TM_DATA;
+       mp->dbtype = DB_ROM_MODE1;
+
+       if (set_mode_params(usalp, "CD write parameter", mode, len, 0, -1)) {
+               dp->cdr_flags |= CDR_TAO;
+               if (xdebug)
+                       printf("TAO ");
+       } else
+               dp->cdr_flags &= ~CDR_TAO;
+
+       mp->write_type = WT_PACKET;
+       mp->track_mode |= TM_INCREMENTAL;
+/*     mp->fp = (trackp->pktsize > 0) ? 1 : 0;*/
+/*     i_to_4_byte(mp->packet_size, trackp->pktsize);*/
+       mp->fp = 0;
+       i_to_4_byte(mp->packet_size, 0);
+
+       if (set_mode_params(usalp, "CD write parameter", mode, len, 0, -1)) {
+               dp->cdr_flags |= CDR_PACKET;
+               if (xdebug)
+                       printf("PACKET ");
+       } else
+               dp->cdr_flags &= ~CDR_PACKET;
+       mp->fp = 0;
+       i_to_4_byte(mp->packet_size, 0);
+       mp->track_mode = TM_DATA;
+       mp->write_type = WT_SAO;
+
+       if (set_mode_params(usalp, "CD write parameter", mode, len, 0, -1)) {
+               dp->cdr_flags |= CDR_SAO;
+               if (xdebug)
+                       printf("SAO ");
+       } else
+               dp->cdr_flags &= ~CDR_SAO;
+
+       if (dp->cdr_flags & CDR_SAO) {
+               mp->dbtype = DB_RAW_PQ;
+
+#ifdef __needed__
+               if (set_mode_params(usalp, "CD write parameter", mode, len, 0, -1)) {
+                       dp->cdr_flags |= CDR_SRAW16;
+                       if (xdebug)
+                               printf("SAO/R16 ");
+               }
+#endif
+
+               mp->dbtype = DB_RAW_PW;
+
+               if (set_mode_params(usalp, "CD write parameter", mode, len, 0, -1)) {
+                       dp->cdr_flags |= CDR_SRAW96P;
+                       if (xdebug)
+                               printf("SAO/R96P ");
+               }
+
+               mp->dbtype = DB_RAW_PW_R;
+
+               if (set_mode_params(usalp, "CD write parameter", mode, len, 0, -1)) {
+                       dp->cdr_flags |= CDR_SRAW96R;
+                       if (xdebug)
+                               printf("SAO/R96R ");
+               }
+       }
+
+       mp->write_type = WT_RAW;
+       mp->dbtype = DB_RAW_PQ;
+
+       if (set_mode_params(usalp, "CD write parameter", mode, len, 0, -1)) {
+               dp->cdr_flags |= CDR_RAW;
+               dp->cdr_flags |= CDR_RAW16;
+               if (xdebug)
+                       printf("RAW/R16 ");
+       }
+
+       mp->dbtype = DB_RAW_PW;
+
+       if (set_mode_params(usalp, "CD write parameter", mode, len, 0, -1)) {
+               dp->cdr_flags |= CDR_RAW;
+               dp->cdr_flags |= CDR_RAW96P;
+               if (xdebug)
+                       printf("RAW/R96P ");
+       }
+
+       mp->dbtype = DB_RAW_PW_R;
+
+       if (set_mode_params(usalp, "CD write parameter", mode, len, 0, -1)) {
+               dp->cdr_flags |= CDR_RAW;
+               dp->cdr_flags |= CDR_RAW96R;
+               if (xdebug)
+                       printf("RAW/R96R ");
+       }
+
+       if (xdebug)
+               printf("\n");
+
+       /*
+        * Reset mp->test_write (-dummy) here.
+        */
+       deflt_writemodes_mmc(usalp, TRUE);
+       usalp->silent--;
+
+       return (0);
+}
+
+int 
+check_writemodes_mdvd(SCSI *usalp, cdr_t *dp)
+{
+       Uchar   mode[0x100];
+       int     len;
+       struct  cd_mode_page_05 *mp;
+
+       if (xdebug)
+               printf("Checking possible write modes: ");
+
+       deflt_writemodes_mdvd(usalp, FALSE);
+
+       fillbytes((caddr_t)mode, sizeof(mode), '\0');
+
+       usalp->silent++;
+       if (!get_mode_params(usalp, 0x05, "DVD write parameter",
+                       mode, (Uchar *)0, (Uchar *)0, (Uchar *)0, &len)) {
+               usalp->silent--;
+               return (-1);
+       }
+       if (len == 0) {
+               usalp->silent--;
+               return (-1);
+       }
+
+       mp = (struct cd_mode_page_05 *)
+               (mode + sizeof(struct scsi_mode_header) +
+               ((struct scsi_mode_header *)mode)->blockdesc_len);
+
+       mp->test_write = 0;
+
+       /*We only check for PACKET and SAO since these are the only supported modes for DVD */
+       /*XXX these checks are irrelevant because they are not medium sensitive. ie the device returns 
+         error only when it does not support a given mode for ALL mediums. It should check using 
+         GET CONFIGURATION command.*/
+
+       mp->write_type = WT_PACKET;
+       mp->fp = 0;
+       i_to_4_byte(mp->packet_size, 0);
+
+       if (set_mode_params(usalp, "DVD write parameter", mode, len, 0, -1)) {
+               dp->cdr_flags |= CDR_PACKET;
+               if (xdebug)
+                 printf("PACKET ");
+       } else
+         dp->cdr_flags &= ~CDR_PACKET;
+       mp->fp = 0;
+       i_to_4_byte(mp->packet_size, 0);
+       mp->track_mode = TM_DATA; 
+
+
+       mp->write_type = WT_SAO;
+
+       if (set_mode_params(usalp, "CD write parameter", mode, len, 0, -1)) {
+               dp->cdr_flags |= CDR_SAO;
+               if (xdebug)
+                       printf("SAO ");
+       } else
+               dp->cdr_flags &= ~CDR_SAO;
+
+
+       if (xdebug)
+               printf("\n");
+
+       deflt_writemodes_mdvd(usalp, TRUE);
+       usalp->silent--;
+       return (0);
+}
+
+static int 
+deflt_writemodes_mmc(SCSI *usalp, BOOL reset_dummy)
+{
+       Uchar   mode[0x100];
+       int     len;
+       struct  cd_mode_page_05 *mp;
+
+       fillbytes((caddr_t)mode, sizeof (mode), '\0');
+
+       usalp->silent++;
+       if (!get_mode_params(usalp, 0x05, "CD write parameter",
+                       mode, (Uchar *)0, (Uchar *)0, (Uchar *)0, &len)) {
+               usalp->silent--;
+               return (-1);
+       }
+       if (len == 0) {
+               usalp->silent--;
+               return (-1);
+       }
+
+       mp = (struct cd_mode_page_05 *)
+               (mode + sizeof (struct scsi_mode_header) +
+               ((struct scsi_mode_header *)mode)->blockdesc_len);
+#ifdef DEBUG
+       usal_prbytes("CD write parameter:", (Uchar *)mode, len);
+       fprintf(stderr, "Audio pause len: %d\n", a_to_2_byte(mp->audio_pause_len));
+#endif
+
+       /*
+        * This is the only place where we reset mp->test_write (-dummy)
+        */
+       if (reset_dummy)
+               mp->test_write = 0;
+
+       /*
+        * Set default values:
+        * Write type = 01 (track at once)
+        * Track mode = 04 (CD-ROM)
+        * Data block type = 08 (CD-ROM)
+        * Session format = 00 (CD-ROM)
+        *
+        * XXX Note:    the same code appears in check_writemodes_mmc() and
+        * XXX          in speed_select_mmc().
+        */
+       mp->write_type = WT_TAO;
+       mp->track_mode = TM_DATA;
+       mp->dbtype = DB_ROM_MODE1;
+       mp->session_format = SES_DA_ROM; /* Matsushita has illegal def. value */
+
+       i_to_2_byte(mp->audio_pause_len, 150);  /* LG has illegal def. value */
+
+#ifdef DEBUG
+       usal_prbytes("CD write parameter:", (Uchar *)mode, len);
+#endif
+       if (!set_mode_params(usalp, "CD write parameter", mode, len, 0, -1)) {
+
+               mp->write_type  = WT_SAO;
+               mp->LS_V        = 0;
+               mp->copy        = 0;
+               mp->fp          = 0;
+               mp->multi_session  = MS_NONE;
+               mp->host_appl_code = 0;
+
+               if (!set_mode_params(usalp, "CD write parameter", mode, len, 0, -1)) {
+                       usalp->silent--;
+                       return (-1);
+               }
+       }
+       usalp->silent--;
+       return (0);
+}
+
+static int 
+deflt_writemodes_mdvd(SCSI *usalp, BOOL reset_dummy)
+{
+       Uchar   mode[0x100];
+       int     len;
+       struct  cd_mode_page_05 *mp;
+
+       fillbytes((caddr_t)mode, sizeof(mode), '\0');
+
+       usalp->silent++;
+       if (!get_mode_params(usalp, 0x05, "DVD write parameter",
+                       mode, (Uchar *)0, (Uchar *)0, (Uchar *)0, &len)) {
+               usalp->silent--;
+               return (-1);
+       }
+       if (len == 0) {
+               usalp->silent--;
+               return (-1);
+       }
+
+       mp = (struct cd_mode_page_05 *)
+               (mode + sizeof(struct scsi_mode_header) +
+               ((struct scsi_mode_header *)mode)->blockdesc_len);
+
+       mp->test_write = 0;
+       /*
+        * This is the only place where we reset mp->test_write (-dummy) for DVD
+        */
+       if (reset_dummy)
+               mp->test_write = 0;
+
+       /*
+        * Set default values:
+        * Write type = 02 (session at once)
+        *
+        * XXX Note:    the same code appears in check_writemodes_mmc() and
+        * XXX          in speed_select_mmc().
+        */
+       mp->write_type = WT_SAO;
+       mp->track_mode = TM_DATA; 
+       mp->dbtype = DB_ROM_MODE1;
+       mp->session_format = SES_DA_ROM;
+
+
+       if (set_mode_params(usalp, "DVD write parameter", mode, len, 0, -1) < 0) {
+               usalp->silent--;
+               return (-1);
+       }
+       usalp->silent--;
+       return (0);
+}
+
+#ifdef PRINT_ATIP
+static void    print_di(struct disk_info *dip);
+static void    atip_printspeed(char *fmt, int speedindex, char speedtab[]);
+static void    print_atip(SCSI *usalp, struct atipinfo *atp);
+#endif /* PRINT_ATIP */
+
+static int 
+get_diskinfo(SCSI *usalp, struct disk_info *dip)
+{
+       int     len;
+       int     ret;
+
+       fillbytes((caddr_t)dip, sizeof (*dip), '\0');
+
+       /*
+        * Used to be 2 instead of 4 (now). But some Y2k ATAPI drives as used
+        * by IOMEGA create a DMA overrun if we try to transfer only 2 bytes.
+        */
+/*     if (read_disk_info(usalp, (caddr_t)dip, 2) < 0)*/
+       if (read_disk_info(usalp, (caddr_t)dip, 4) < 0)
+               return (-1);
+       len = a_to_u_2_byte(dip->data_len);
+       len += 2;
+       ret = read_disk_info(usalp, (caddr_t)dip, len);
+
+#ifdef DEBUG
+       usal_prbytes("Disk info:", (Uchar *)dip,
+                               len-usal_getresid(usalp));
+#endif
+       return (ret);
+}
+
+static void 
+di_to_dstat(struct disk_info *dip, dstat_t *dsp)
+{
+       dsp->ds_diskid = a_to_u_4_byte(dip->disk_id);
+       if (dip->did_v)
+               dsp->ds_flags |= DSF_DID_V;
+       dsp->ds_disktype = dip->disk_type;
+       dsp->ds_diskstat = dip->disk_status;
+       dsp->ds_sessstat = dip->sess_status;
+       if (dip->erasable)
+               dsp->ds_flags |= DSF_ERA;
+
+       dsp->ds_trfirst    = dip->first_track;
+       dsp->ds_trlast     = dip->last_track_ls;
+       dsp->ds_trfirst_ls = dip->first_track_ls;
+
+       dsp->ds_maxblocks = msf_to_lba(dip->last_lead_out[1],
+                                       dip->last_lead_out[2],
+                                       dip->last_lead_out[3], TRUE);
+       /*
+        * Check for 0xFF:0xFF/0xFF which is an indicator for a complete disk
+        */
+       if (dsp->ds_maxblocks == 1166730)
+               dsp->ds_maxblocks = -1L;
+
+       dsp->ds_first_leadin = msf_to_lba(dip->last_lead_in[1],
+                                       dip->last_lead_in[2],
+                                       dip->last_lead_in[3], FALSE);
+       if (dsp->ds_first_leadin > 0)
+               dsp->ds_first_leadin = 0;
+
+       if (dsp->ds_last_leadout == 0 && dsp->ds_maxblocks >= 0)
+               dsp->ds_last_leadout = dsp->ds_maxblocks;
+       dsp->ds_trfirst=dip->first_track; 
+       dsp->ds_trlast=dip->last_track_ls;
+       dsp->ds_trfirst_ls=dip->first_track_ls;
+}
+
+static int 
+get_atip(SCSI *usalp, struct atipinfo *atp)
+{
+       int     len;
+       int     ret;
+
+       fillbytes((caddr_t)atp, sizeof (*atp), '\0');
+
+       /*
+        * Used to be 2 instead of sizeof (struct tocheader), but all
+        * other places in the code use sizeof (struct tocheader) too and
+        * some Y2k ATAPI drives as used by IOMEGA create a DMA overrun if we
+        * try to transfer only 2 bytes.
+        */
+       if (read_toc(usalp, (caddr_t)atp, 0, sizeof (struct tocheader), 0, FMT_ATIP) < 0)
+               return (-1);
+       len = a_to_u_2_byte(atp->hd.len);
+       len += 2;
+       ret = read_toc(usalp, (caddr_t)atp, 0, len, 0, FMT_ATIP);
+
+#ifdef DEBUG
+       usal_prbytes("ATIP info:", (Uchar *)atp,
+                               len-usal_getresid(usalp));
+#endif
+       /*
+        * Yamaha sometimes returns zeroed ATIP info for disks without ATIP
+        */
+       if (atp->desc.lead_in[1] == 0 &&
+                       atp->desc.lead_in[2] == 0 &&
+                       atp->desc.lead_in[3] == 0 &&
+                       atp->desc.lead_out[1] == 0 &&
+                       atp->desc.lead_out[2] == 0 &&
+                       atp->desc.lead_out[3] == 0)
+               return (-1);
+
+       if (atp->desc.lead_in[1] >= 0x90 && debug) {
+               /*
+                * Only makes sense with buggy Ricoh firmware.
+                */
+               errmsgno(EX_BAD, "Converting ATIP from BCD\n");
+               atp->desc.lead_in[1] = from_bcd(atp->desc.lead_in[1]);
+               atp->desc.lead_in[2] = from_bcd(atp->desc.lead_in[2]);
+               atp->desc.lead_in[3] = from_bcd(atp->desc.lead_in[3]);
+
+               atp->desc.lead_out[1] = from_bcd(atp->desc.lead_out[1]);
+               atp->desc.lead_out[2] = from_bcd(atp->desc.lead_out[2]);
+               atp->desc.lead_out[3] = from_bcd(atp->desc.lead_out[3]);
+       }
+
+       return (ret);
+}
+
+#ifdef PRINT_ATIP
+
+static int 
+get_pma(SCSI *usalp)
+{
+       int     len;
+       int     ret;
+       char    atp[1024];
+
+       fillbytes((caddr_t)atp, sizeof (*atp), '\0');
+
+       /*
+        * Used to be 2 instead of sizeof (struct tocheader), but all
+        * other places in the code use sizeof (struct tocheader) too and
+        * some Y2k ATAPI drives as used by IOMEGA create a DMA overrun if we
+        * try to transfer only 2 bytes.
+        */
+/*     if (read_toc(usalp, (caddr_t)atp, 0, 2, 1, FMT_PMA) < 0)*/
+/*     if (read_toc(usalp, (caddr_t)atp, 0, 2, 0, FMT_PMA) < 0)*/
+       if (read_toc(usalp, (caddr_t)atp, 0, sizeof (struct tocheader), 0, FMT_PMA) < 0)
+               return (-1);
+/*     len = a_to_u_2_byte(atp->hd.len);*/
+       len = a_to_u_2_byte(atp);
+       len += 2;
+/*     ret = read_toc(usalp, (caddr_t)atp, 0, len, 1, FMT_PMA);*/
+       ret = read_toc(usalp, (caddr_t)atp, 0, len, 0, FMT_PMA);
+
+#ifdef DEBUG
+       usal_prbytes("PMA:", (Uchar *)atp,
+                               len-usal_getresid(usalp));
+#endif
+       ret = read_toc(usalp, (caddr_t)atp, 0, len, 1, FMT_PMA);
+
+#ifdef DEBUG
+       usal_prbytes("PMA:", (Uchar *)atp,
+                               len-usal_getresid(usalp));
+#endif
+       return (ret);
+}
+
+#endif /* PRINT_ATIP */
+
+static int 
+init_mmc(SCSI *usalp, cdr_t *dp)
+{
+       return (speed_select_mmc(usalp, dp, NULL));
+}
+
+static int 
+getdisktype_mdvd(SCSI *usalp, cdr_t *dp)
+{
+       int ret = 0;
+       dstat_t *dsp = dp->cdr_dstat;
+
+       struct track_info track_info;
+    if(lverbose)
+        printf("HINT: use dvd+rw-mediainfo from dvd+rw-tools for information extraction.\n");
+       /* if(getdisktype_mmc(usalp, dp)<0)
+               return -1;
+               */
+
+       /* read rzone info to get the space left on disk */
+       /*ds_trlast is the last rzone on disk, can be invisible */
+       if(read_rzone_info(usalp, (caddr_t)&track_info, sizeof(track_info))>=0)
+               dsp->ds_maxblocks=a_to_u_4_byte(track_info.free_blocks)+a_to_4_byte(track_info.next_writable_addr);
+
+       dsp->ds_disktype&= ~DT_CD;
+       dsp->ds_disktype|= DT_DVD;
+
+       return (ret);
+
+}
+
+static int 
+getdisktype_mmc(SCSI *usalp, cdr_t *dp)
+{
+extern char    *buf;
+       dstat_t *dsp = dp->cdr_dstat;
+       struct disk_info *dip;
+       Uchar   mode[0x100];
+       msf_t   msf;
+       BOOL    did_atip = FALSE;
+       BOOL    did_dummy = FALSE;
+       int     rplus;
+
+       msf.msf_min = msf.msf_sec = msf.msf_frame = 0;
+
+       /*
+        * It seems that there are drives that do not support to
+        * read ATIP (e.g. HP 7100)
+        * Also if a NON CD-R media is inserted, this will never work.
+        * For this reason, make a failure non-fatal.
+        */
+       usalp->silent++;
+       if (get_atip(usalp, (struct atipinfo *)mode) >= 0) {
+               struct atipinfo *atp = (struct atipinfo *)mode;
+
+               msf.msf_min =           mode[8];
+               msf.msf_sec =           mode[9];
+               msf.msf_frame =         mode[10];
+               if (atp->desc.erasable) {
+                       dsp->ds_flags |= DSF_ERA;
+                       if (atp->desc.sub_type == 1)
+                               dsp->ds_flags |= DSF_HIGHSP_ERA;
+                       else if (atp->desc.sub_type == 2)
+                               dsp->ds_flags |= DSF_ULTRASP_ERA;
+                       else if (atp->desc.sub_type == 3)
+                               dsp->ds_flags |= DSF_ULTRASP_ERA | DSF_ULTRASPP_ERA;
+               }
+               if (atp->desc.a1_v) {
+                       if (atp->desc.clv_low != 0)
+                               dsp->ds_at_min_speed = clv_to_speed[atp->desc.clv_low];
+                       if (atp->desc.clv_high != 0)
+                               dsp->ds_at_max_speed = clv_to_speed[atp->desc.clv_high];
+
+                       if (atp->desc.erasable && atp->desc.sub_type == 1) {
+                               if (atp->desc.clv_high != 0)
+                                       dsp->ds_at_max_speed = hs_clv_to_speed[atp->desc.clv_high];
+                       }
+               }
+               if (atp->desc.a2_v && atp->desc.erasable && (atp->desc.sub_type == 2 || atp->desc.sub_type == 3)) {
+                       Uint    vlow;
+                       Uint    vhigh;
+
+                       vlow = (atp->desc.a2[0] >> 4) & 0x07;
+                       vhigh = atp->desc.a2[0] & 0x0F;
+                       if (vlow != 0)
+                               dsp->ds_at_min_speed = us_clv_to_speed[vlow];
+                       if (vhigh != 0)
+                               dsp->ds_at_max_speed = us_clv_to_speed[vhigh];
+               }
+               did_atip = TRUE;
+       }
+       usalp->silent--;
+
+#ifdef PRINT_ATIP
+       if ((dp->cdr_dstat->ds_cdrflags & RF_PRATIP) != 0 && did_atip) {
+               print_atip(usalp, (struct atipinfo *)mode);
+               pr_manufacturer(&msf,
+                       ((struct atipinfo *)mode)->desc.erasable,
+                       ((struct atipinfo *)mode)->desc.uru);
+       }
+#endif
+again:
+       dip = (struct disk_info *)buf;
+       if (get_diskinfo(usalp, dip) < 0)
+               return (-1);
+
+       /*
+        * Check for non writable disk first.
+        */
+       
+       /* DVD+RW does not need to be blanked */
+       rplus = dsp->ds_cdrflags;
+       if (dp->profile == 0x1A) rplus = RF_BLANK;
+       
+       if (dip->disk_status == DS_COMPLETE &&
+                       (rplus & dsp->ds_cdrflags & (RF_WRITE|RF_BLANK)) == RF_WRITE) {
+               if (!did_dummy) {
+                       int     xspeed = 0xFFFF;
+                       int     oflags = dp->cdr_cmdflags;
+
+                       /*
+                        * Try to clear the dummy bit to reset the virtual
+                        * drive status. Not all drives support it even though
+                        * it is mentioned in the MMC standard.
+                        */
+                       if (lverbose)
+                               printf("Trying to clear drive status.\n");
+
+                       dp->cdr_cmdflags &= ~F_DUMMY;
+                       speed_select_mmc(usalp, dp, &xspeed);
+                       dp->cdr_cmdflags = oflags;
+                       did_dummy = TRUE;
+                       goto again;
+               }
+               /*
+                * Trying to clear drive status did not work...
+                */
+               reload_media(usalp, dp);
+       }
+       if (get_diskinfo(usalp, dip) < 0)
+               return (-1);
+       di_to_dstat(dip, dsp);
+       if (!did_atip && dsp->ds_first_leadin < 0)
+               lba_to_msf(dsp->ds_first_leadin, &msf);
+
+       if ((dp->cdr_dstat->ds_cdrflags & RF_PRATIP) != 0 && !did_atip) {
+               print_min_atip(dsp->ds_first_leadin, dsp->ds_last_leadout);
+               if (dsp->ds_first_leadin < 0)
+                               pr_manufacturer(&msf,
+                               dip->erasable,
+                               dip->uru);
+       }
+       dsp->ds_maxrblocks = disk_rcap(&msf, dsp->ds_maxblocks,
+                               dip->erasable,
+                               dip->uru);
+
+
+#ifdef PRINT_ATIP
+#ifdef DEBUG
+       if (get_atip(usalp, (struct atipinfo *)mode) < 0)
+               return (-1);
+       /*
+        * Get pma gibt Ã„rger mit CW-7502
+        * Wenn Die Disk leer ist, dann stuerzt alles ab.
+        * Firmware 4.02 kann nicht get_pma
+        */
+       if (dip->disk_status != DS_EMPTY) {
+/*             get_pma();*/
+       }
+       printf("ATIP lead in:  %ld (%02d:%02d/%02d)\n",
+               msf_to_lba(mode[8], mode[9], mode[10], FALSE),
+               mode[8], mode[9], mode[10]);
+       printf("ATIP lead out: %ld (%02d:%02d/%02d)\n",
+               msf_to_lba(mode[12], mode[13], mode[14], TRUE),
+               mode[12], mode[13], mode[14]);
+       print_di(dip);
+       print_atip(usalp, (struct atipinfo *)mode);
+#endif
+#endif /* PRINT_ATIP */
+       return (drive_getdisktype(usalp, dp));
+}
+
+#ifdef PRINT_ATIP
+
+#define        DOES(what, flag)        printf("  Does %s%s\n", flag?"":"not ", what);
+#define        IS(what, flag)          printf("  Is %s%s\n", flag?"":"not ", what);
+#define        VAL(what, val)          printf("  %s: %d\n", what, val[0]*256 + val[1]);
+#define        SVAL(what, val)         printf("  %s: %s\n", what, val);
+
+static void 
+print_di(struct disk_info *dip)
+{
+       static  char *ds_name[] = { "empty", "incomplete/appendable", "complete", "illegal" };
+       static  char *ss_name[] = { "empty", "incomplete/appendable", "illegal", "complete", };
+
+       IS("erasable", dip->erasable);
+       printf("disk status: %s\n", ds_name[dip->disk_status]);
+       printf("session status: %s\n", ss_name[dip->sess_status]);
+       printf("first track: %d number of sessions: %d first track in last sess: %d last track in last sess: %d\n",
+               dip->first_track,
+               dip->numsess,
+               dip->first_track_ls,
+               dip->last_track_ls);
+       IS("unrestricted", dip->uru);
+       printf("Disk type: ");
+       switch (dip->disk_type) {
+
+       case SES_DA_ROM:        printf("CD-DA or CD-ROM");      break;
+       case SES_CDI:           printf("CDI");                  break;
+       case SES_XA:            printf("CD-ROM XA");            break;
+       case SES_UNDEF:         printf("undefined");            break;
+       default:                printf("reserved");             break;
+       }
+       printf("\n");
+       if (dip->did_v)
+               printf("Disk id: 0x%lX\n", a_to_u_4_byte(dip->disk_id));
+
+       printf("last start of lead in: %ld\n",
+               msf_to_lba(dip->last_lead_in[1],
+               dip->last_lead_in[2],
+               dip->last_lead_in[3], FALSE));
+       printf("last start of lead out: %ld\n",
+               msf_to_lba(dip->last_lead_out[1],
+               dip->last_lead_out[2],
+               dip->last_lead_out[3], TRUE));
+
+       if (dip->dbc_v)
+               printf("Disk bar code: 0x%lX%lX\n",
+                       a_to_u_4_byte(dip->disk_barcode),
+                       a_to_u_4_byte(&dip->disk_barcode[4]));
+
+       if (dip->num_opc_entries > 0) {
+               printf("OPC table:\n");
+       }
+}
+
+char   *cdr_subtypes[] = {
+       "Normal Rewritable (CLV) media",
+       "High speed Rewritable (CAV) media",
+       "Medium Type A, low Beta category (A-)",
+       "Medium Type A, high Beta category (A+)",
+       "Medium Type B, low Beta category (B-)",
+       "Medium Type B, high Beta category (B+)",
+       "Medium Type C, low Beta category (C-)",
+       "Medium Type C, high Beta category (C+)",
+};
+
+char   *cdrw_subtypes[] = {
+       "Normal Rewritable (CLV) media",
+       "High speed Rewritable (CAV) media",
+       "Ultra High speed Rewritable media",
+       "Ultra High speed+ Rewritable media",
+       "Medium Type B, low Beta category (B-)",
+       "Medium Type B, high Beta category (B+)",
+       "Medium Type C, low Beta category (C-)",
+       "Medium Type C, high Beta category (C+)",
+};
+
+static void 
+atip_printspeed(char *fmt, int speedindex, char speedtab[])
+{
+       printf("%s:", fmt);
+       if (speedtab[speedindex] == 0) {
+               printf(" %2d (reserved val %2d)",
+                       speedtab[speedindex], speedindex);
+       } else {
+               printf(" %2d", speedtab[speedindex]);
+       }
+}
+
+static void 
+print_atip(SCSI *usalp, struct atipinfo *atp)
+{
+       char    *sub_type;
+       char    *speedvtab = clv_to_speed;
+
+       if (usalp->verbose)
+               usal_prbytes("ATIP info: ", (Uchar *)atp, sizeof (*atp));
+
+       printf("ATIP info from disk:\n");
+       printf("  Indicated writing power: %d\n", atp->desc.ind_wr_power);
+       if (atp->desc.erasable || atp->desc.ref_speed)
+               printf("  Reference speed: %d\n", clv_to_speed[atp->desc.ref_speed]);
+       IS("unrestricted", atp->desc.uru);
+/*     printf("  Disk application code: %d\n", atp->desc.res5_05);*/
+       IS("erasable", atp->desc.erasable);
+       if (atp->desc.erasable)
+               sub_type = cdrw_subtypes[atp->desc.sub_type];
+       else
+               sub_type = cdr_subtypes[atp->desc.sub_type];
+       if (atp->desc.sub_type)
+               printf("  Disk sub type: %s (%d)\n", sub_type, atp->desc.sub_type);
+       printf("  ATIP start of lead in:  %ld (%02d:%02d/%02d)\n",
+               msf_to_lba(atp->desc.lead_in[1],
+               atp->desc.lead_in[2],
+               atp->desc.lead_in[3], FALSE),
+               atp->desc.lead_in[1],
+               atp->desc.lead_in[2],
+               atp->desc.lead_in[3]);
+       printf("  ATIP start of lead out: %ld (%02d:%02d/%02d)\n",
+               msf_to_lba(atp->desc.lead_out[1],
+               atp->desc.lead_out[2],
+               atp->desc.lead_out[3], TRUE),
+               atp->desc.lead_out[1],
+               atp->desc.lead_out[2],
+               atp->desc.lead_out[3]);
+       if (atp->desc.a1_v) {
+               if (atp->desc.erasable && atp->desc.sub_type == 1) {
+                       speedvtab = hs_clv_to_speed;
+               }
+               if (atp->desc.a2_v && (atp->desc.sub_type == 2 || atp->desc.sub_type == 3)) {
+                       speedvtab = us_clv_to_speed;
+               }
+               if (atp->desc.clv_low != 0 || atp->desc.clv_high != 0) {
+                       atip_printspeed("  1T speed low",
+                               atp->desc.clv_low, speedvtab);
+                       atip_printspeed(" 1T speed high",
+                               atp->desc.clv_high, speedvtab);
+                       printf("\n");
+               }
+       }
+       if (atp->desc.a2_v) {
+               Uint    vlow;
+               Uint    vhigh;
+
+               vlow = (atp->desc.a2[0] >> 4) & 0x07;
+               vhigh = atp->desc.a2[0] & 0x0F;
+
+               if (vlow != 0 || vhigh != 0) {
+                       atip_printspeed("  2T speed low",
+                                       vlow, speedvtab);
+                       atip_printspeed(" 2T speed high",
+                                       vhigh, speedvtab);
+                       printf("\n");
+               }
+       }
+       if (atp->desc.a1_v) {
+               printf("  power mult factor: %d %d\n", atp->desc.power_mult, atp->desc.tgt_y_pow);
+               if (atp->desc.erasable)
+                       printf("  recommended erase/write power: %d\n", atp->desc.rerase_pwr_ratio);
+       }
+       if (atp->desc.a1_v) {
+               printf("  A1 values: %02X %02X %02X\n",
+                               (&atp->desc.res15)[1],
+                               (&atp->desc.res15)[2],
+                               (&atp->desc.res15)[3]);
+       }
+       if (atp->desc.a2_v) {
+               printf("  A2 values: %02X %02X %02X\n",
+                               atp->desc.a2[0],
+                               atp->desc.a2[1],
+                               atp->desc.a2[2]);
+       }
+       if (atp->desc.a3_v) {
+               printf("  A3 values: %02X %02X %02X\n",
+                               atp->desc.a3[0],
+                               atp->desc.a3[1],
+                               atp->desc.a3[2]);
+       }
+}
+#endif /* PRINT_ATIP */
+
+static int 
+speed_select_mmc(SCSI *usalp, cdr_t *dp, int *speedp)
+{
+       Uchar   mode[0x100];
+       Uchar   moder[0x100];
+       int     len;
+       struct  cd_mode_page_05 *mp;
+       struct  ricoh_mode_page_30 *rp = NULL;
+       int     val;
+       BOOL    forcespeed = FALSE;
+       BOOL    dummy = (dp->cdr_cmdflags & F_DUMMY) != 0;
+
+       if (speedp)
+               curspeed = *speedp;
+
+       /*
+        * Do not reset mp->test_write (-dummy) here.
+        */
+       deflt_writemodes_mmc(usalp, FALSE);
+
+       fillbytes((caddr_t)mode, sizeof (mode), '\0');
+
+       if (!get_mode_params(usalp, 0x05, "CD write parameter",
+                       mode, (Uchar *)0, (Uchar *)0, (Uchar *)0, &len))
+               return (-1);
+       if (len == 0)
+               return (-1);
+
+       mp = (struct cd_mode_page_05 *)
+               (mode + sizeof (struct scsi_mode_header) +
+               ((struct scsi_mode_header *)mode)->blockdesc_len);
+#ifdef DEBUG
+       usal_prbytes("CD write parameter:", (Uchar *)mode, len);
+#endif
+
+    if(dummy) {
+        mp->test_write = 1;
+        /* but it does not work on DVD+RW and -RAM, also bail out on other
+         * types that have not been tested yet */
+        int profile=get_curprofile(usalp);
+        switch(profile) {
+            case(0x12):
+            case(0x1a):
+            case(0x2a):
+            case(0x43):
+            case(0x52):
+                {
+                    fprintf(stderr, 
+                            "Dummy mode not possible with %s.\n",
+                            mmc_obtain_profile_name(profile) );
+                    exit(EXIT_FAILURE);
+                }
+        }
+    }
+    else
+        mp->test_write = 0;
+
+#ifdef DEBUG
+       usal_prbytes("CD write parameter:", (Uchar *)mode, len);
+#endif
+       if (!set_mode_params(usalp, "CD write parameter", mode, len, 0, -1))
+               return (-1);
+
+       /*
+        * Neither set nor get speed.
+        */
+       if (speedp == 0)
+               return (0);
+
+
+       rp = get_justlink_ricoh(usalp, moder);
+       if (mmc_isyamaha(usalp)) {
+               forcespeed = FALSE;
+       } else if (mmc_isplextor(usalp) && (dp->cdr_flags & CDR_FORCESPEED) != 0) {
+               int     pwr;
+
+               pwr = check_powerrec_plextor(usalp);
+               if (pwr >= 0)
+                       forcespeed = (pwr == 0);
+       } else if ((dp->cdr_flags & CDR_FORCESPEED) != 0) {
+               forcespeed = rp && rp->AWSCD != 0;
+       }
+
+       if (lverbose && (dp->cdr_flags & CDR_FORCESPEED) != 0)
+               printf("Forcespeed is %s.\n", forcespeed?"ON":"OFF");
+
+       if (!forcespeed && (dp->cdr_dstat->ds_cdrflags & RF_FORCESPEED) != 0) {
+               printf("Turning forcespeed on\n");
+               forcespeed = TRUE;
+       }
+       if (forcespeed && (dp->cdr_dstat->ds_cdrflags & RF_FORCESPEED) == 0) {
+               printf("Turning forcespeed off\n");
+               forcespeed = FALSE;
+       }
+       if (mmc_isplextor(usalp) && (dp->cdr_flags & CDR_FORCESPEED) != 0) {
+               powerrec_plextor(usalp, !forcespeed);
+       }
+       if (!mmc_isyamaha(usalp) && (dp->cdr_flags & CDR_FORCESPEED) != 0) {
+
+               if (rp) {
+                       rp->AWSCD = forcespeed?1:0;
+                       set_mode_params(usalp, "Ricoh Vendor Page", moder, moder[0]+1, 0, -1);
+                       rp = get_justlink_ricoh(usalp, moder);
+               }
+       }
+
+       /*
+        * 44100 * 2 * 2 =  176400 bytes/s
+        *
+        * The right formula would be:
+        * tmp = (((long)curspeed) * 1764) / 10;
+        *
+        * But the standard is rounding the wrong way.
+        * Furtunately rounding down is guaranteed.
+        */
+       val = curspeed*177;
+       if (val > 0xFFFF)
+               val = 0xFFFF;
+       if (mmc_isyamaha(usalp) && forcespeed) {
+               if (force_speed_yamaha(usalp, -1, val) < 0)
+                       return (-1);
+       } else if (mmc_set_speed(usalp, -1, val, ROTCTL_CLV) < 0) {
+               return (-1);
+       }
+
+       if (scsi_get_speed(usalp, 0, &val) >= 0) {
+               if (val > 0) {
+                       fprintf(stderr, "Speed set to %d KB/s\n", val); 
+                       curspeed = val / 176;
+                       *speedp = curspeed;
+               }
+       }
+       return (0);
+}
+
+/*
+ * Some drives do not round up when writespeed is e.g. 1 and
+ * the minimum write speed of the drive is higher. Try to increment
+ * the write speed unti it gets accepted by the drive.
+ */
+static int 
+mmc_set_speed(SCSI *usalp, int readspeed, int writespeed, int rotctl)
+{
+       int     rs;
+       int     ws;
+       int     ret = -1;
+       int     c;
+       int     k;
+
+       if (scsi_get_speed(usalp, &rs, &ws) >= 0) {
+               if (readspeed < 0)
+                       readspeed = rs;
+               if (writespeed < 0)
+                       writespeed = ws;
+       }
+       if (writespeed < 0 || writespeed > 0xFFFF)
+               return (ret);
+
+       usalp->silent++;
+       while (writespeed <= 0xFFFF) {
+               ret = scsi_set_speed(usalp, readspeed, writespeed, rotctl);
+               if (ret >= 0)
+                       break;
+               c = usal_sense_code(usalp);
+               k = usal_sense_key(usalp);
+               /*
+                * Abort quickly if it does not make sense to repeat.
+                * 0x24 == Invalid field in cdb
+                * 0x24 means illegal speed.
+                */
+               if ((k != SC_ILLEGAL_REQUEST) || (c != 0x24)) {
+                       if (usalp->silent <= 1)
+                               usal_printerr(usalp);
+                       usalp->silent--;
+                       return (-1);
+               }
+               writespeed += 177;
+       }
+       if (ret < 0 && usalp->silent <= 1)
+               usal_printerr(usalp);
+       usalp->silent--;
+
+       return (ret);
+}
+
+static int 
+speed_select_mdvd(SCSI *usalp, cdr_t *dp, int *speedp)
+{
+  int retcode;
+  char perf_desc[28];
+  int write_speed = *speedp * 1385;
+   
+  /* For the moment we just divide the CD speed by 7*/
+
+  if(speedp!=NULL)
+     (*speedp)=(*speedp)*8;
+  
+  memset(perf_desc, 0, sizeof(perf_desc));
+
+  /* Write Rotation Control = ROTCTL_CLV 
+   * | Restore Logical Unit Defaults = 0 
+   * | Exact = 0 
+   * | Random Access = 0) 
+   */
+  perf_desc[0]= ROTCTL_CLV << 3 | 0 << 2 | 0 << 1 | 0; 
+  /* Start LBA to 0 */
+  perf_desc[4] = 0;
+  perf_desc[5] = 0;
+  perf_desc[6] = 0;
+  perf_desc[7] = 0;
+  /* End LBA set to 0 (setting to 0xffffffff failed on my LG burner
+   */
+  perf_desc[8] = 0;
+  perf_desc[9] = 0;
+  perf_desc[10] = 0;
+  perf_desc[11] = 0;
+  /* Read Speed = 0xFFFF */
+  perf_desc[12] = 0;
+  perf_desc[13] = 0;
+  perf_desc[14] = 0xFF;
+  perf_desc[15] = 0xFF;
+  /* Read Time = 1s */
+  perf_desc[18] = 1000 >> 8;
+  perf_desc[19] = 1000 & 0xFF;   
+  /* Write Speed */
+  perf_desc[20] = write_speed >> 24;
+  perf_desc[21] = write_speed >> 16 & 0xFF;
+  perf_desc[22] = write_speed >> 8 & 0xFF;
+  perf_desc[23] = write_speed & 0xFF;
+  /* Write Time = 1s */
+  perf_desc[26] = 1000 >> 8;
+  perf_desc[27] = 1000 & 0xFF;  
+  
+  /* retcode = scsi_set_streaming(usalp, NULL, 0); */
+  retcode = scsi_set_streaming(usalp, perf_desc, sizeof(perf_desc));
+  if (retcode == -1) return retcode;
+  retcode = speed_select_mmc(usalp, dp, speedp);
+  if(speedp!=NULL)
+     (*speedp)=(*speedp)/7;
+   return retcode;
+}
+
+static int 
+next_wr_addr_mmc(SCSI *usalp, track_t *trackp, long *ap)
+{
+       struct  track_info      track_info;
+       long    next_addr;
+       int     result = -1;
+
+
+       /*
+        * Reading info for current track may require doing the read_track_info
+        * with either the track number (if the track is currently being written)
+        * or with 0xFF (if the track hasn't been started yet and is invisible
+        */
+
+       if (trackp != 0 && trackp->track > 0 && is_packet(trackp)) {
+               usalp->silent++;
+               result = read_track_info(usalp, (caddr_t)&track_info, TI_TYPE_TRACK,
+                                                       trackp->trackno,
+                                                       sizeof (track_info));
+               usalp->silent--;
+       }
+
+       if (result < 0) {
+               if (read_track_info(usalp, (caddr_t)&track_info, TI_TYPE_TRACK, 0xFF,
+                                               sizeof (track_info)) < 0) {
+                       errmsgno(EX_BAD, "Cannot get next writable address for 'invisible' track.\n");
+                       errmsgno(EX_BAD, "This means that we are checking recorded media.\n");
+                       errmsgno(EX_BAD, "This media cannot be written in streaming mode anymore.\n");
+                       errmsgno(EX_BAD, "If you like to write to 'preformatted' RW media, try to blank the media first.\n");
+                       return (-1);
+               }
+       }
+       if (usalp->verbose)
+               usal_prbytes("track info:", (Uchar *)&track_info,
+                               sizeof (track_info)-usal_getresid(usalp));
+       next_addr = a_to_4_byte(track_info.next_writable_addr);
+       if (ap)
+               *ap = next_addr;
+       return (0);
+}
+
+static int 
+write_leadin_mmc(SCSI *usalp, cdr_t *dp, track_t *trackp)
+{
+       Uint    i;
+       long    startsec = 0L;
+
+/*     if (flags & F_SAO) {*/
+       if (wm_base(dp->cdr_dstat->ds_wrmode) == WM_SAO) {
+               if (debug || lverbose) {
+                       printf("Sending CUE sheet...\n");
+                       flush();
+               }
+               if ((*dp->cdr_send_cue)(usalp, dp, trackp) < 0) {
+                       errmsgno(EX_BAD, "Cannot send CUE sheet.\n");
+                       return (-1);
+               }
+
+               (*dp->cdr_next_wr_address)(usalp, &trackp[0], &startsec);
+               if (trackp[0].flags & TI_TEXT) {
+                       startsec = dp->cdr_dstat->ds_first_leadin;
+                       printf("SAO startsec: %ld\n", startsec);
+               } else if (startsec <= 0 && startsec != -150) {
+                       if(lverbose>2)
+                               fprintf(stderr, "WARNING: Drive returns wrong startsec (%ld) using -150\n",
+                                       startsec);
+                       startsec = -150;
+               }
+               if (debug)
+                       printf("SAO startsec: %ld\n", startsec);
+
+               if (trackp[0].flags & TI_TEXT) {
+                       if (startsec > 0) {
+                               errmsgno(EX_BAD, "CD-Text must be in first session.\n");
+                               return (-1);
+                       }
+                       if (debug || lverbose)
+                               printf("Writing lead-in...\n");
+                       if (write_cdtext(usalp, dp, startsec) < 0)
+                               return (-1);
+
+                       dp->cdr_dstat->ds_cdrflags |= RF_LEADIN;
+               } else for (i = 1; i <= trackp->tracks; i++) {
+                       trackp[i].trackstart += startsec +150;
+               }
+#ifdef XXX
+               if (debug || lverbose)
+                       printf("Writing lead-in...\n");
+
+               pad_track(usalp, dp, &trackp[1], -150, (Llong)0,
+                                       FALSE, 0);
+#endif
+       }
+/*     if (flags & F_RAW) {*/
+    if (wm_base(dp->cdr_dstat->ds_wrmode) == WM_RAW) {
+        /*
+                * In RAW write mode, we now write the lead in (TOC).
+                */
+               (*dp->cdr_next_wr_address)(usalp, &trackp[0], &startsec);
+               if (startsec > -4500) {
+                       /*
+                        * There must be at least 1 minute lead-in.
+                        */
+                       errmsgno(EX_BAD, "WARNING: Drive returns wrong startsec (%ld) using %ld from ATIP\n",
+                                       startsec, (long)dp->cdr_dstat->ds_first_leadin);
+                       startsec = dp->cdr_dstat->ds_first_leadin;
+               }
+               if (startsec > -4500) {
+                       errmsgno(EX_BAD, "Illegal startsec (%ld)\n", startsec);
+                       return (-1);
+               }
+               if (debug || lverbose)
+                       printf("Writing lead-in at sector %ld\n", startsec);
+               if (write_leadin(usalp, dp, trackp, startsec) < 0)
+                       return (-1);
+               dp->cdr_dstat->ds_cdrflags |= RF_LEADIN;
+       }
+       return (0);
+}
+
+int    st2mode[] = {
+       0,              /* 0                    */
+       TM_DATA,        /* 1 ST_ROM_MODE1       */
+       TM_DATA,        /* 2 ST_ROM_MODE2       */
+       0,              /* 3                    */
+       0,              /* 4 ST_AUDIO_NOPRE     */
+       TM_PREEM,       /* 5 ST_AUDIO_PRE       */
+       0,              /* 6                    */
+       0,              /* 7                    */
+};
+
+static int 
+next_wr_addr_mdvd(SCSI *usalp, track_t *trackp, long *ap)
+{
+       int     track=0;
+       struct  track_info      track_info;
+       long    next_addr;
+       int     result = -1;
+       struct  disk_info disk_info;
+       if (trackp){
+           track = trackp->trackno;
+       }
+
+       if (trackp != 0 && track > 0 && is_packet(trackp)) {
+               usalp->silent++;
+               result = read_track_info(usalp, (caddr_t)&track_info, TI_TYPE_SESS, track, sizeof(track_info));
+               usalp->silent--;
+               if (scsi_in_progress(usalp)){
+                 return -1;
+               }
+               
+       }
+
+       if (result < 0) {
+         /* Get the last rzone*/
+               if(read_disk_info(usalp,(caddr_t)&disk_info,8)<0)
+                 return (-1);
+            
+               /* if (read_track_info(usalp, (caddr_t)&track_info, TI_TYPE_SESS, 0xFF, sizeof(track_info)) < 0) */
+                   if (read_rzone_info(usalp, (caddr_t)&track_info, sizeof(track_info)) < 0)
+                       return (-1);
+       }
+       if (usalp->verbose)
+               usal_prbytes("track info:", (Uchar *)&track_info,
+                               sizeof(track_info)-usal_getresid(usalp));
+       next_addr = a_to_4_byte(track_info.next_writable_addr);
+       if (ap)
+               *ap = next_addr;
+       return (0);
+}
+
+static int 
+open_track_mmc(SCSI *usalp, cdr_t *dp, track_t *trackp)
+{
+       Uchar   mode[0x100];
+       int     len;
+       struct  cd_mode_page_05 *mp;
+
+       if (!is_tao(trackp) && !is_packet(trackp)) {
+               if (trackp->pregapsize > 0 && (trackp->flags & TI_PREGAP) == 0) {
+                       if (lverbose) {
+                               printf("Writing pregap for track %d at %ld\n",
+                                       (int)trackp->trackno,
+                                       trackp->trackstart-trackp->pregapsize);
+                       }
+                       /*
+                        * XXX Do we need to check isecsize too?
+                        */
+                       pad_track(usalp, dp, trackp,
+                               trackp->trackstart-trackp->pregapsize,
+                               (Llong)trackp->pregapsize*trackp->secsize,
+                                       FALSE, 0);
+               }
+               return (0);
+       }
+
+       fillbytes((caddr_t)mode, sizeof (mode), '\0');
+
+       if (!get_mode_params(usalp, 0x05, "CD write parameter",
+                       mode, (Uchar *)0, (Uchar *)0, (Uchar *)0, &len))
+               return (-1);
+       if (len == 0)
+               return (-1);
+
+       mp = (struct cd_mode_page_05 *)
+               (mode + sizeof (struct scsi_mode_header) +
+               ((struct scsi_mode_header *)mode)->blockdesc_len);
+
+
+/*     mp->track_mode = ???;*/
+       mp->track_mode = st2mode[trackp->sectype & ST_MASK];
+/*     mp->copy = ???;*/
+       mp->dbtype = trackp->dbtype;
+
+/*i_to_short(mp->audio_pause_len, 300);*/
+/*i_to_short(mp->audio_pause_len, 150);*/
+/*i_to_short(mp->audio_pause_len, 0);*/
+
+       if (is_packet(trackp)) {
+               mp->write_type = WT_PACKET;
+               mp->track_mode |= TM_INCREMENTAL;
+               mp->fp = (trackp->pktsize > 0) ? 1 : 0;
+               i_to_4_byte(mp->packet_size, trackp->pktsize);
+       } else if (is_tao(trackp)) {
+               mp->write_type = WT_TAO;
+               mp->fp = 0;
+               i_to_4_byte(mp->packet_size, 0);
+       } else {
+               errmsgno(EX_BAD, "Unknown write mode.\n");
+               return (-1);
+       }
+       if (trackp->isrc) {
+               mp->ISRC[0] = 0x80;     /* Set ISRC valid */
+               strncpy((char *)&mp->ISRC[1], trackp->isrc, 12);
+
+       } else {
+               fillbytes(&mp->ISRC[0], sizeof (mp->ISRC), '\0');
+       }
+
+#ifdef DEBUG
+       usal_prbytes("CD write parameter:", (Uchar *)mode, len);
+#endif
+       if (!set_mode_params(usalp, "CD write parameter", mode, len, 0, trackp->secsize))
+               return (-1);
+
+       return (0);
+}
+
+static int 
+open_track_mdvd(SCSI *usalp, cdr_t *dp, track_t *trackp)
+{
+       Uchar   mode[0x100];
+       int     len;
+       struct  cd_mode_page_05 *mp;
+
+       if (is_packet(trackp)) {
+              fillbytes((caddr_t)mode, sizeof(mode), '\0');
+         
+              if (!get_mode_params(usalp, 0x05, "DVD write parameter",
+                       mode, (Uchar *)0, (Uchar *)0, (Uchar *)0, &len))
+                     return (-1);
+              if (len == 0)
+                     return (-1);
+
+               mp = (struct cd_mode_page_05 *)
+                     (mode + sizeof(struct scsi_mode_header) +
+                     ((struct scsi_mode_header *)mode)->blockdesc_len);
+
+               mp->write_type = WT_PACKET;
+               mp->LS_V = 1;
+               /*For now we set the link size to 0x10(32k) because Pioneer-A03 only support this */
+               mp->link_size=0x10;
+               mp->fp = 1;
+               i_to_4_byte(mp->packet_size, trackp->pktsize);
+       } else {
+            return 0;
+       }
+       if (!set_mode_params(usalp, "CD write parameter", mode, len, 0, trackp->secsize))
+               return (-1);
+
+       return (0);
+}
+
+static int 
+close_track_mmc(SCSI *usalp, cdr_t *dp, track_t *trackp)
+{
+       int     ret;
+
+       if (!is_tao(trackp) && !is_packet(trackp))
+               return (0);
+
+       if (scsi_flush_cache(usalp, (dp->cdr_cmdflags&F_IMMED) != 0) < 0) {
+               printf("Trouble flushing the cache\n");
+               return (-1);
+       }
+       wait_unit_ready(usalp, 300);            /* XXX Wait for ATAPI */
+       if (is_packet(trackp) && !is_noclose(trackp)) {
+                       /* close the incomplete track */
+               ret = scsi_close_tr_session(usalp, CL_TYPE_TRACK, 0xFF,
+                               (dp->cdr_cmdflags&F_IMMED) != 0);
+               wait_unit_ready(usalp, 300);    /* XXX Wait for ATAPI */
+               return (ret);
+       }
+       return (0);
+}
+
+static int 
+close_track_mdvd(SCSI *usalp, cdr_t *dp, track_t *trackp)
+{
+       int     ret;
+       if (!is_packet(trackp))
+            return (0);
+
+       if (scsi_flush_cache(usalp, (dp->cdr_cmdflags&F_IMMED) != 0) < 0) {
+               printf("Trouble flushing the cache\n");
+               return -1;
+       }
+       wait_unit_ready(usalp, 300);            /* XXX Wait for ATAPI */
+       if (is_packet(trackp) && !is_noclose(trackp)) {
+                       /* close the incomplete track */
+               ret = scsi_close_tr_session(usalp, 1, 0xFF, (dp->cdr_cmdflags&F_IMMED) != 0);
+               wait_unit_ready(usalp, 300);    /* XXX Wait for ATAPI */
+               return (ret);
+       }
+       return (0);
+}
+
+int    toc2sess[] = {
+       SES_DA_ROM,     /* CD-DA                 */
+       SES_DA_ROM,     /* CD-ROM                */
+       SES_XA,         /* CD-ROM XA mode 1      */
+       SES_XA,         /* CD-ROM XA MODE 2      */
+       SES_CDI,        /* CDI                   */
+       SES_DA_ROM,     /* Invalid - use default */
+       SES_DA_ROM,     /* Invalid - use default */
+};
+
+static int 
+open_session_mmc(SCSI *usalp, cdr_t *dp, track_t *trackp)
+{
+       Uchar   mode[0x100];
+       int     len;
+       struct  cd_mode_page_05 *mp;
+
+       fillbytes((caddr_t)mode, sizeof (mode), '\0');
+
+       if (!get_mode_params(usalp, 0x05, "CD write parameter",
+                       mode, (Uchar *)0, (Uchar *)0, (Uchar *)0, &len))
+               return (-1);
+       if (len == 0)
+               return (-1);
+
+       mp = (struct cd_mode_page_05 *)
+               (mode + sizeof (struct scsi_mode_header) +
+               ((struct scsi_mode_header *)mode)->blockdesc_len);
+
+       mp->write_type = WT_TAO; /* fix to allow DAO later */
+       /*
+        * We need to set the right dbtype here because Sony drives
+        * don't like multi session in to be set with DB_ROM_MODE1
+        * which is set by us at the beginning as default as some drives
+        * have illegal default values.
+        */
+       mp->track_mode = st2mode[trackp[0].sectype & ST_MASK];
+       mp->dbtype = trackp[0].dbtype;
+
+       if (!is_tao(trackp) && !is_packet(trackp)) {
+               mp->write_type = WT_SAO;
+               if (dp->cdr_dstat->ds_cdrflags & RF_AUDIOMASTER)
+                       mp->write_type = 8;
+               mp->track_mode = 0;
+               mp->dbtype = DB_RAW;
+       }
+       if (is_raw(trackp)) {
+               mp->write_type = WT_RAW;
+               mp->track_mode = 0;
+
+               if (is_raw16(trackp)) {
+                       mp->dbtype = DB_RAW_PQ;
+               } else if (is_raw96r(trackp)) {
+                       mp->dbtype = DB_RAW_PW_R;
+               } else {
+                       mp->dbtype = DB_RAW_PW;
+               }
+       }
+
+       mp->multi_session = (track_base(trackp)->tracktype & TOCF_MULTI) ?
+                               MS_MULTI : MS_NONE;
+       mp->session_format = toc2sess[track_base(trackp)->tracktype & TOC_MASK];
+
+       if (trackp->isrc) {
+               mp->media_cat_number[0] = 0x80; /* Set MCN valid */
+               strncpy((char *)&mp->media_cat_number[1], trackp->isrc, 13);
+
+       } else {
+               fillbytes(&mp->media_cat_number[0], sizeof (mp->media_cat_number), '\0');
+       }
+#ifdef DEBUG
+       usal_prbytes("CD write parameter:", (Uchar *)mode, len);
+#endif
+       if (!set_mode_params(usalp, "CD write parameter", mode, len, 0, -1))
+               return (-1);
+
+       return (0);
+}
+
+static int 
+open_session_mdvd(SCSI *usalp, cdr_t *dp, track_t *trackp)
+{
+       Uchar   mode[0x100];
+       int     tracks = trackp->tracks;
+
+       int     len;
+       struct  cd_mode_page_05 *mp;
+       Ulong totalsize;
+       int i;
+       int profile;
+
+       fillbytes((caddr_t)mode, sizeof(mode), '\0');
+
+       if (!get_mode_params(usalp, 0x05, "DVD write parameter",
+                       mode, (Uchar *)0, (Uchar *)0, (Uchar *)0, &len))
+               return (-1);
+       if (len == 0)
+               return (-1);
+
+       mp = (struct cd_mode_page_05 *)
+               (mode + sizeof(struct scsi_mode_header) +
+               ((struct scsi_mode_header *)mode)->blockdesc_len);
+       if(is_packet(trackp)){
+         mp->write_type=WT_PACKET;
+         mp->fp=0;
+         mp->BUFE=1;
+         mp->track_mode=1;
+       }else{
+         mp->write_type = WT_SAO; 
+       }
+
+       mp->multi_session = (track_base(trackp)->tracktype & TOCF_MULTI) ?
+                               MS_MULTI : MS_NONE;
+       mp->session_format = toc2sess[track_base(trackp)->tracktype & TOC_MASK];
+
+       /* Enable Burnfree by default, allow to disable. XXX Sucks, duplicated functionality. */
+       if (dp->cdr_cdcap->BUF != 0) {
+               if (lverbose > 2)
+                       fprintf(stderr, 
+                                       "BURN-Free is %s.\n"
+                                       "Turning BURN-Free on\n",
+                                       mp->BUFE?"ON":"OFF");
+               mp->BUFE = 1;
+       }
+       if (driveropts != NULL) {
+               if ((strcmp(driveropts, "noburnproof") == 0 ||
+                                       strcmp(driveropts, "noburnfree") == 0)) {
+                       if(lverbose>1)
+                               fprintf(stderr, "Turning BURN-Free off\n");
+                       mp->BUFE = 0;
+               }
+               else if ((strcmp(driveropts, "burnproof") == 0 ||
+                                       strcmp(driveropts, "burnfree") == 0)) {
+                       /* a NOP, we enable burnfree by default */
+                       if(lverbose>2)
+                               fprintf(stderr, "Found burnproof/burnfree in driveropts, those options are enabled by default now.");
+               }
+               else if (strcmp(driveropts, "help") == 0) {
+                       mmc_opthelp(dp, 0);
+               } 
+               else {
+                       errmsgno(EX_BAD, "Bad driver opts '%s'.\n", driveropts);
+                       mmc_opthelp(dp, EX_BAD);
+               }
+       }
+
+
+       if (!set_mode_params(usalp, "DVD write parameter", mode, len, 0, -1))
+               return (-1);
+
+               
+       totalsize=0;
+       for(i=1;i<=tracks;i++) {
+         totalsize+=trackp[i].tracksecs;
+       }
+       
+       profile = get_curprofile(usalp);
+       if(!is_packet(trackp) && profile != 0x1A){
+         /* in DAO mode we need to reserve space for the track*/
+         if(reserve_track(usalp, totalsize)<0)
+           return (-1);
+         }
+       return (0);
+}
+
+static int 
+waitfix_mmc(SCSI *usalp, int secs)
+{
+       char    dibuf[16];
+       int     i;
+       int     key;
+#define        W_SLEEP 2
+
+       usalp->silent++;
+       for (i = 0; i < secs/W_SLEEP; i++) {
+               if (read_disk_info(usalp, dibuf, sizeof (dibuf)) >= 0) {
+                       usalp->silent--;
+                       return (0);
+               }
+               key = usal_sense_key(usalp);
+               if (key != SC_UNIT_ATTENTION && key != SC_NOT_READY)
+                       break;
+               sleep(W_SLEEP);
+       }
+       usalp->silent--;
+       return (-1);
+#undef W_SLEEP
+}
+
+static int 
+fixate_mmc(SCSI *usalp, cdr_t *dp, track_t *trackp)
+{
+       int     ret = 0;
+       int     key = 0;
+       int     code = 0;
+       struct timeval starttime;
+       struct timeval stoptime;
+       int     dummy = (track_base(trackp)->tracktype & TOCF_DUMMY) != 0;
+
+       if(debug)
+                printf("fixate_mmc\n");
+       starttime.tv_sec = 0;
+       starttime.tv_usec = 0;
+       stoptime = starttime;
+       gettimeofday(&starttime, (struct timezone *)0);
+
+       if (dummy && lverbose)
+               printf("WARNING: Some drives don't like fixation in dummy mode.\n");
+
+       usalp->silent++;
+       if(debug)
+                printf("is_tao: %d,is_packet: %d\n", is_tao(trackp), is_packet(trackp));
+       if (is_tao(trackp) || is_packet(trackp)) {
+               ret = scsi_close_tr_session(usalp, CL_TYPE_SESSION, 0,
+                               (dp->cdr_cmdflags&F_IMMED) != 0);
+       } else {
+               if (scsi_flush_cache(usalp, (dp->cdr_cmdflags&F_IMMED) != 0) < 0) {
+                       if (!scsi_in_progress(usalp))
+                               printf("Trouble flushing the cache\n");
+               }
+       }
+       usalp->silent--;
+       key = usal_sense_key(usalp);
+       code = usal_sense_code(usalp);
+
+       usalp->silent++;
+       if (debug && !unit_ready(usalp)) {
+               fprintf(stderr, "Early return from fixating. Ret: %d Key: %d, Code: %d\n", ret, key, code);
+       }
+       usalp->silent--;
+
+       if (ret >= 0) {
+               wait_unit_ready(usalp, 420/curspeed);   /* XXX Wait for ATAPI */
+               waitfix_mmc(usalp, 420/curspeed);       /* XXX Wait for ATAPI */
+               return (ret);
+       }
+
+       if ((dummy != 0 && (key != SC_ILLEGAL_REQUEST)) ||
+               /*
+                * Try to suppress messages from drives that don't like fixation
+                * in -dummy mode.
+                */
+               ((dummy == 0) &&
+               (((key != SC_UNIT_ATTENTION) && (key != SC_NOT_READY)) ||
+                               ((code != 0x2E) && (code != 0x04))))) {
+               /*
+                * UNIT ATTENTION/2E seems to be a magic for old Mitsumi ATAPI drives
+                * NOT READY/ code 4 qual 7 (logical unit not ready, operation in progress)
+                * seems to be a magic for newer Mitsumi ATAPI drives
+                * NOT READY/ code 4 qual 8 (logical unit not ready, long write in progress)
+                * seems to be a magic for SONY drives
+                * when returning early from fixating.
+                * Try to supress the error message in this case to make
+                * simple minded users less confused.
+                */
+               usal_printerr(usalp);
+               usal_printresult(usalp);        /* XXX restore key/code in future */
+       }
+
+       if (debug && !unit_ready(usalp)) {
+               fprintf(stderr, "Early return from fixating. Ret: %d Key: %d, Code: %d\n", ret, key, code);
+       }
+
+       wait_unit_ready(usalp, 420);     /* XXX Wait for ATAPI */
+       waitfix_mmc(usalp, 420/curspeed); /* XXX Wait for ATAPI */
+
+       if (!dummy &&
+               (ret >= 0 || (key == SC_UNIT_ATTENTION && code == 0x2E))) {
+               /*
+                * Some ATAPI drives (e.g. Mitsumi) imply the
+                * IMMED bit in the SCSI cdb. As there seems to be no
+                * way to properly check for the real end of the
+                * fixating process we wait for the expected time.
+                */
+               gettimeofday(&stoptime, (struct timezone *)0);
+               timevaldiff(&starttime, &stoptime);
+               if (stoptime.tv_sec < (220 / curspeed)) {
+                       unsigned secs;
+
+                       if (lverbose) {
+                               printf("Actual fixating time: %ld seconds\n",
+                                                       (long)stoptime.tv_sec);
+                       }
+                       secs = (280 / curspeed) - stoptime.tv_sec;
+                       if (lverbose) {
+                               printf("ATAPI early return: sleeping %d seconds.\n",
+                                                               secs);
+                       }
+                       sleep(secs);
+               }
+       }
+       return (ret);
+}
+
+static int 
+fixate_mdvd(SCSI *usalp, cdr_t *dp, track_t *trackp)
+{
+       int ret;
+       if (scsi_flush_cache(usalp, (dp->cdr_cmdflags&F_IMMED) != 0) < 0) {
+               printf("Trouble flushing the cache\n");
+               return -1;
+       }
+       wait_unit_ready(usalp, 300);            /* XXX Wait for ATAPI */
+      /*set a really BIG timeout and call fixate_mmc
+        The BIG timeout is needed in case there was a very short rzone to write at the 
+        beginning of the disk, because lead-out needs to be at some distance.
+      */
+       if(debug)
+               printf("fixate_mdvd\n");
+      usal_settimeout(usalp, 1000);
+      if(is_packet(trackp) || dp->profile == 0x1B){
+         scsi_close_tr_session(usalp, CL_TYPE_SESSION, 0, FALSE);
+      }
+      ret = fixate_mmc(usalp, dp, trackp);
+      if (dp->profile == 0x2B) {
+         scsi_close_tr_session(usalp, CL_TYPE_OPEN_SESSION, 0, FALSE);
+         scsi_close_tr_session(usalp, CL_TYPE_FINALISE_MINRAD, 0, FALSE);
+      }
+      usal_settimeout(usalp, 200);
+
+      return ret;
+}
+
+char   *blank_types[] = {
+       "entire disk",
+       "PMA, TOC, pregap",
+       "incomplete track",
+       "reserved track",
+       "tail of track",
+       "closing of last session",
+       "last session",
+       "reserved blanking type",
+};
+
+char   *format_types[] = {
+       "full format",
+       "background format",
+       "forced format",
+};
+
+static int 
+blank_mmc(SCSI *usalp, cdr_t *dp, long addr, int blanktype)
+{
+       BOOL    cdrr     = FALSE;       /* Read CD-R    */
+       BOOL    cdwr     = FALSE;       /* Write CD-R   */
+       BOOL    cdrrw    = FALSE;       /* Read CD-RW   */
+       BOOL    cdwrw    = FALSE;       /* Write CD-RW  */
+       int     ret;
+
+       mmc_check(usalp, &cdrr, &cdwr, &cdrrw, &cdwrw, NULL, NULL);
+       if (!cdwrw)
+               return (blank_dummy(usalp, dp, addr, blanktype));
+
+       if (dp->profile == 0x1A) {
+               printf("Error: this media does not support blanking, ignoring.\n");
+               return (blank_dummy(usalp, dp, addr, blanktype));
+       }
+       if (lverbose) {
+               printf("Blanking %s\n", blank_types[blanktype & 0x07]);
+               flush();
+       }
+
+       ret = scsi_blank(usalp, addr, blanktype, (dp->cdr_cmdflags&F_IMMED) != 0);
+       if (ret < 0)
+               return (ret);
+
+       wait_unit_ready(usalp, 90*60/curspeed); /* XXX Wait for ATAPI */
+       waitfix_mmc(usalp, 90*60/curspeed);     /* XXX Wait for ATAPI */
+       return (ret);
+}
+
+static int format_mdvd(SCSI *usalp, cdr_t *dp, int formattype)
+{
+extern char    *buf;
+       BOOL    dvdwr    = FALSE;       /* Write DVD    */
+       int     ret;
+       int     profile;
+       char    addr[12];
+       struct disk_info *dip;
+
+       if (debug || lverbose > 2)
+               printf("format_mdvd\n");
+       mmc_check(usalp, NULL, NULL, NULL, NULL, NULL, &dvdwr);
+       if (!dvdwr)
+               return (format_dummy(usalp, dp, formattype));
+
+       if (debug || lverbose > 2)
+               printf("format_mdvd: drive is a dvd burner.\n");
+       profile = get_curprofile(usalp);
+       if (profile != 0x1A) {
+               printf("Error: only support DVD+RW formating, ignoring.\n");
+               return (format_dummy(usalp, dp, formattype));
+       }
+       dip = (struct disk_info *)buf;
+       if (get_diskinfo(usalp, dip) < 0)
+               return -1;
+       
+       if (dip->disk_status & 3 && formattype != FORCE_FORMAT) {
+               printf("Error: disk already formated, ignoring.\n");
+               return -1;
+        }
+       addr[0] = 0;           /* "Reserved" */
+       addr[1] = 2;           /* "IMMED" flag */
+       addr[2] = 0;           /* "Descriptor Length" (MSB) */
+       addr[3] = 8;           /* "Descriptor Length" (LSB) */
+       addr[4+0] = 0xff;
+       addr[4+1] = 0xff;
+       addr[4+2] = 0xff;
+       addr[4+3] = 0xff;
+       addr[4+4] = 0x26<<2;
+       addr[4+5] = 0;
+       addr[4+6] = 0;
+       addr[4+7] = 0;
+       if (formattype == FORCE_FORMAT) {
+           printf("format_mdvd: forcing reformat.\n"); 
+           formattype = FULL_FORMAT;
+           addr[4+0] = 0;
+           addr[4+1] = 0;
+           addr[4+2] = 0;
+           addr[4+3] = 0;
+           addr[4+7] = 1;
+       } else {
+           printf("format_mdvd: media is unformated.\n"); 
+       }
+
+       if (lverbose) {
+               printf("Formating %s\n", format_types[formattype & 0x07]);
+               flush();
+       }
+       if (formattype == FULL_FORMAT) {
+               ret = scsi_format(usalp, (caddr_t)&addr, sizeof(addr), FALSE);
+       } else {
+               ret = scsi_format(usalp, (caddr_t)&addr, sizeof(addr), TRUE);
+       }
+       if (ret < 0)
+               return (ret);
+
+       wait_unit_ready(usalp, 90*60/curspeed); /* XXX Wait for ATAPI */
+       waitfix_mmc(usalp, 90*60/curspeed);     /* XXX Wait for ATAPI */
+       return (ret);
+}
+
+static int 
+send_opc_mmc(SCSI *usalp, caddr_t bp, int cnt, int doopc)
+{
+       int     ret;
+
+       usalp->silent++;
+       ret = send_opc(usalp, bp, cnt, doopc);
+       usalp->silent--;
+
+       if (ret >= 0)
+               return (ret);
+
+       /* BEGIN CSTYLED */
+       /*
+        * Hack for a mysterioys drive ....
+        * Device type    : Removable CD-ROM
+        * Version        : 0
+        * Response Format: 1
+        * Vendor_info    : 'RWD     '
+        * Identifikation : 'RW2224          '
+        * Revision       : '2.53'
+        * Device seems to be: Generic mmc CD-RW.
+        *
+        * Performing OPC...
+        * CDB:  54 01 00 00 00 00 00 00 00 00
+        * Sense Bytes: 70 00 06 00 00 00 00 0A 00 00 00 00 5A 03 00 00
+        * Sense Key: 0x6 Unit Attention, Segment 0
+        * Sense Code: 0x5A Qual 0x03 (operator selected write permit) Fru 0x0
+        * Sense flags: Blk 0 (not valid)
+        */
+       /* END CSTYLED */
+       if (usal_sense_key(usalp) == SC_UNIT_ATTENTION &&
+           usal_sense_code(usalp) == 0x5A &&
+           usal_sense_qual(usalp) == 0x03)
+               return (0);
+
+       /*
+        * Do not make the condition:
+        * "Power calibration area almost full" a fatal error.
+        * It just flags that we have a single and last chance to write now.
+        */
+       if ((usal_sense_key(usalp) == SC_RECOVERABLE_ERROR ||
+           usal_sense_key(usalp) == SC_MEDIUM_ERROR) &&
+           usal_sense_code(usalp) == 0x73 &&
+           usal_sense_qual(usalp) == 0x01)
+               return (0);
+
+       /*
+        * Send OPC is optional.
+        */
+       if (usal_sense_key(usalp) != SC_ILLEGAL_REQUEST) {
+               if (usalp->silent <= 0)
+                       usal_printerr(usalp);
+               return (ret);
+       }
+       return (0);
+}
+
+static int 
+opt1_mmc(SCSI *usalp, cdr_t *dp)
+{
+       int     oflags = dp->cdr_dstat->ds_cdrflags;
+
+       if ((dp->cdr_dstat->ds_cdrflags & RF_AUDIOMASTER) != 0) {
+               printf("Turning Audio Master Q. R. on\n");
+               if (set_audiomaster_yamaha(usalp, dp, TRUE) < 0)
+                       return (-1);
+               if (!debug && lverbose <= 1)
+                       dp->cdr_dstat->ds_cdrflags &= ~RF_PRATIP;
+               if (getdisktype_mmc(usalp, dp) < 0) {
+                       dp->cdr_dstat->ds_cdrflags = oflags;
+                       return (-1);
+               }
+               dp->cdr_dstat->ds_cdrflags = oflags;
+               if (oflags & RF_PRATIP) {
+                       msf_t   msf;
+                       lba_to_msf(dp->cdr_dstat->ds_first_leadin, &msf);
+                       printf("New start of lead in: %ld (%02d:%02d/%02d)\n",
+                               (long)dp->cdr_dstat->ds_first_leadin,
+                               msf.msf_min,
+                               msf.msf_sec,
+                               msf.msf_frame);
+                       lba_to_msf(dp->cdr_dstat->ds_maxblocks, &msf);
+                       printf("New start of lead out: %ld (%02d:%02d/%02d)\n",
+                               (long)dp->cdr_dstat->ds_maxblocks,
+                               msf.msf_min,
+                               msf.msf_sec,
+                               msf.msf_frame);
+               }
+       }
+       if (mmc_isplextor(usalp)) {
+               int     gcode;
+
+               if ((dp->cdr_flags & (CDR_SINGLESESS|CDR_HIDE_CDR)) != 0) {
+                       if (ss_hide_plextor(usalp,
+                           (dp->cdr_dstat->ds_cdrflags & RF_SINGLESESS) != 0,
+                           (dp->cdr_dstat->ds_cdrflags & RF_HIDE_CDR) != 0) < 0)
+                               return (-1);
+               }
+
+               if ((dp->cdr_flags & CDR_SPEEDREAD) != 0) {
+                       if (speed_rd_plextor(usalp,
+                           (dp->cdr_dstat->ds_cdrflags & RF_SPEEDREAD) != 0) < 0)
+                               return (-1);
+               }
+
+               if ((dp->cdr_cmdflags & F_SETDROPTS) ||
+                   (wm_base(dp->cdr_dstat->ds_wrmode) == WM_SAO) ||
+                   (wm_base(dp->cdr_dstat->ds_wrmode) == WM_RAW))
+                       gcode = do_gigarec_plextor(usalp);
+               else
+                       gcode = gigarec_plextor(usalp, 0);
+               if (gcode != 0) {
+                       msf_t   msf;
+
+                       dp->cdr_dstat->ds_first_leadin =
+                                       gigarec_mult(gcode, dp->cdr_dstat->ds_first_leadin);
+                       dp->cdr_dstat->ds_maxblocks =
+                                       gigarec_mult(gcode, dp->cdr_dstat->ds_maxblocks);
+
+                       if (oflags & RF_PRATIP) {
+                               lba_to_msf(dp->cdr_dstat->ds_first_leadin, &msf);
+                               printf("New start of lead in: %ld (%02d:%02d/%02d)\n",
+                                       (long)dp->cdr_dstat->ds_first_leadin,
+                                       msf.msf_min,
+                                       msf.msf_sec,
+                                       msf.msf_frame);
+                               lba_to_msf(dp->cdr_dstat->ds_maxblocks, &msf);
+                               printf("New start of lead out: %ld (%02d:%02d/%02d)\n",
+                                       (long)dp->cdr_dstat->ds_maxblocks,
+                                       msf.msf_min,
+                                       msf.msf_sec,
+                                       msf.msf_frame);
+                       }
+               }
+       }
+       return (0);
+}
+
+static int 
+opt2_mmc(SCSI *usalp, cdr_t *dp)
+{
+       Uchar   mode[0x100];
+       Uchar   moder[0x100];
+       int     len;
+       struct  cd_mode_page_05 *mp;
+       struct  ricoh_mode_page_30 *rp = NULL;
+       BOOL    burnfree = FALSE;
+
+       fillbytes((caddr_t)mode, sizeof (mode), '\0');
+
+       if (!get_mode_params(usalp, 0x05, "CD write parameter",
+                       mode, (Uchar *)0, (Uchar *)0, (Uchar *)0, &len))
+               return (-1);
+       if (len == 0)
+               return (-1);
+
+       mp = (struct cd_mode_page_05 *)
+               (mode + sizeof (struct scsi_mode_header) +
+               ((struct scsi_mode_header *)mode)->blockdesc_len);
+
+
+       rp = get_justlink_ricoh(usalp, moder);
+
+       if (dp->cdr_cdcap->BUF != 0) {
+               burnfree = (mp->BUFE != 0);
+       } else if ((dp->cdr_flags & CDR_BURNFREE) != 0) {
+               burnfree = (rp && (rp->BUEFE != 0));
+       }
+
+       if (lverbose>2 && (dp->cdr_flags & CDR_BURNFREE) != 0)
+               printf("BURN-Free is %s.\n", burnfree?"ON":"OFF");
+
+       if (!burnfree && (dp->cdr_dstat->ds_cdrflags & RF_BURNFREE) != 0) {
+               if(lverbose>2)
+                       printf("Turning BURN-Free on\n");
+               burnfree = TRUE;
+       }
+       if (burnfree && (dp->cdr_dstat->ds_cdrflags & RF_BURNFREE) == 0) {
+               if(lverbose>2)
+                       printf("Turning BURN-Free off\n");
+               burnfree = FALSE;
+       }
+       if (dp->cdr_cdcap->BUF != 0) {
+               mp->BUFE = burnfree?1:0;
+       } 
+    else if ((dp->cdr_flags & CDR_BURNFREE) != 0) {
+
+               if (rp)
+                       rp->BUEFE = burnfree?1:0;
+       }
+       if (rp) {
+               /*
+                * Clear Just-Link counter
+                */
+               i_to_2_byte(rp->link_counter, 0);
+               if (xdebug)
+                       usal_prbytes("Mode Select Data ", moder, moder[0]+1);
+
+               if (!set_mode_params(usalp, "Ricoh Vendor Page", moder, moder[0]+1, 0, -1))
+                       return (-1);
+               rp = get_justlink_ricoh(usalp, moder);
+       }
+
+#ifdef DEBUG
+       usal_prbytes("CD write parameter:", (Uchar *)mode, len);
+#endif
+       if (!set_mode_params(usalp, "CD write parameter", mode, len, 0, -1))
+               return (-1);
+
+       if (mmc_isplextor(usalp)) {
+               /*
+                * Clear Burn-Proof counter
+                */
+               usalp->silent++;
+               bpc_plextor(usalp, 1, NULL);
+               usalp->silent--;
+
+               do_varirec_plextor(usalp);
+       }
+
+       return (0);
+}
+
+static int 
+opt1_mdvd(SCSI *usalp, cdr_t *dp)
+{
+       int     oflags = dp->cdr_dstat->ds_cdrflags;
+
+       if ((dp->cdr_dstat->ds_cdrflags & RF_AUDIOMASTER) != 0) {
+               printf("Turning Audio Master Q. R. on\n");
+               if (set_audiomaster_yamaha(usalp, dp, TRUE) < 0)
+                       return (-1);
+               if (!debug && lverbose <= 1)
+                       dp->cdr_dstat->ds_cdrflags &= ~RF_PRATIP;
+               if (getdisktype_mdvd(usalp, dp) < 0) {
+                       dp->cdr_dstat->ds_cdrflags = oflags;
+                       return (-1);
+               }
+               dp->cdr_dstat->ds_cdrflags = oflags;
+               if (oflags & RF_PRATIP) {
+                       msf_t   msf;
+                       lba_to_msf(dp->cdr_dstat->ds_first_leadin, &msf);
+                       printf("New start of lead in: %ld (%02d:%02d/%02d)\n",
+                               (long)dp->cdr_dstat->ds_first_leadin,
+                               msf.msf_min,
+                               msf.msf_sec,
+                               msf.msf_frame);
+                       lba_to_msf(dp->cdr_dstat->ds_maxblocks, &msf);
+                       printf("New start of lead out: %ld (%02d:%02d/%02d)\n",
+                               (long)dp->cdr_dstat->ds_maxblocks,
+                               msf.msf_min,
+                               msf.msf_sec,
+                               msf.msf_frame);
+               }
+       }
+       return (0);
+}
+
+static int
+scsi_sony_write(SCSI *usalp, 
+                caddr_t bp      /* address of buffer */, 
+                long sectaddr   /* disk address (sector) to put */, 
+                long size       /* number of bytes to transfer */, 
+                int blocks      /* sector count */, 
+                BOOL islast     /* last write for track */)
+{
+       return (write_xg5(usalp, bp, sectaddr, size, blocks));
+}
+
+Uchar  db2df[] = {
+       0x00,                   /*  0 2352 bytes of raw data                    */
+       0xFF,                   /*  1 2368 bytes (raw data + P/Q Subchannel)    */
+       0xFF,                   /*  2 2448 bytes (raw data + P-W Subchannel)    */
+       0xFF,                   /*  3 2448 bytes (raw data + P-W raw Subchannel)*/
+       0xFF,                   /*  4 -    Reserved                             */
+       0xFF,                   /*  5 -    Reserved                             */
+       0xFF,                   /*  6 -    Reserved                             */
+       0xFF,                   /*  7 -    Vendor specific                      */
+       0x10,                   /*  8 2048 bytes Mode 1 (ISO/IEC 10149)         */
+       0x30,                   /*  9 2336 bytes Mode 2 (ISO/IEC 10149)         */
+       0xFF,                   /* 10 2048 bytes Mode 2! (CD-ROM XA form 1)     */
+       0xFF,                   /* 11 2056 bytes Mode 2 (CD-ROM XA form 1)      */
+       0xFF,                   /* 12 2324 bytes Mode 2 (CD-ROM XA form 2)      */
+       0xFF,                   /* 13 2332 bytes Mode 2 (CD-ROM XA 1/2+subhdr)  */
+       0xFF,                   /* 14 -    Reserved                             */
+       0xFF,                   /* 15 -    Vendor specific                      */
+};
+
+static int 
+gen_cue_mmc(track_t *trackp, void *vcuep, BOOL needgap)
+{
+       int     tracks = trackp->tracks;
+       int     i;
+       struct mmc_cue  **cuep = vcuep;
+       struct mmc_cue  *cue;
+       struct mmc_cue  *cp;
+       int     ncue = 0;
+       int     icue = 0;
+       int     pgsize;
+       msf_t   m;
+       int     ctl;
+       int     df;
+       int     scms;
+
+       cue = malloc(1);
+
+       for (i = 0; i <= tracks; i++) {
+               ctl = (st2mode[trackp[i].sectype & ST_MASK]) << 4;
+               if (is_copy(&trackp[i]))
+                       ctl |= TM_ALLOW_COPY << 4;
+               if (is_quadro(&trackp[i]))
+                       ctl |= TM_QUADRO << 4;
+               df = db2df[trackp[i].dbtype & 0x0F];
+               if (trackp[i].tracktype == TOC_XA2 &&
+                   trackp[i].sectype   == (SECT_MODE_2_MIX|ST_MODE_RAW)) {
+                       /*
+                        * Hack for CUE with MODE2/CDI and
+                        * trackp[i].dbtype == DB_RAW
+                        */
+                       df = 0x21;
+               }
+
+               if (trackp[i].isrc) {   /* MCN or ISRC */
+                       ncue += 2;
+                       cue = realloc(cue, ncue * sizeof (*cue));
+                       cp = &cue[icue++];
+                       if (i == 0) {
+                               cp->cs_ctladr = 0x02;
+                               movebytes(&trackp[i].isrc[0], &cp->cs_tno, 7);
+                               cp = &cue[icue++];
+                               cp->cs_ctladr = 0x02;
+                               movebytes(&trackp[i].isrc[7], &cp->cs_tno, 7);
+                       } else {
+                               cp->cs_ctladr = 0x03;
+                               cp->cs_tno = i;
+                               movebytes(&trackp[i].isrc[0], &cp->cs_index, 6);
+                               cp = &cue[icue++];
+                               cp->cs_ctladr = 0x03;
+                               cp->cs_tno = i;
+                               movebytes(&trackp[i].isrc[6], &cp->cs_index, 6);
+                       }
+               }
+               if (i == 0) {   /* Lead in */
+                       df &= ~7;       /* Mask off data size & nonRAW subch */
+                       if (df < 0x10)
+                               df |= 1;
+                       else
+                               df |= 4;
+                       if (trackp[0].flags & TI_TEXT)  /* CD-Text in Lead-in*/
+                               df |= 0x40;
+                       lba_to_msf(-150, &m);
+                       cue = realloc(cue, ++ncue * sizeof (*cue));
+                       cp = &cue[icue++];
+                       fillcue(cp, ctl|0x01, i, 0, df, 0, &m);
+               } else {
+                       scms = 0;
+
+                       if (is_scms(&trackp[i]))
+                               scms = 0x80;
+                       pgsize = trackp[i].pregapsize;
+                       if (pgsize == 0 && needgap)
+                               pgsize++;
+                       lba_to_msf(trackp[i].trackstart-pgsize, &m);
+                       cue = realloc(cue, ++ncue * sizeof (*cue));
+                       cp = &cue[icue++];
+                       fillcue(cp, ctl|0x01, i, 0, df, scms, &m);
+
+                       if (trackp[i].nindex == 1) {
+                               lba_to_msf(trackp[i].trackstart, &m);
+                               cue = realloc(cue, ++ncue * sizeof (*cue));
+                               cp = &cue[icue++];
+                               fillcue(cp, ctl|0x01, i, 1, df, scms, &m);
+                       } else {
+                               int     idx;
+                               long    *idxlist;
+
+                               ncue += trackp[i].nindex;
+                               idxlist = trackp[i].tindex;
+                               cue = realloc(cue, ncue * sizeof (*cue));
+
+                               for (idx = 1; idx <= trackp[i].nindex; idx++) {
+                                       lba_to_msf(trackp[i].trackstart + idxlist[idx], &m);
+                                       cp = &cue[icue++];
+                                       fillcue(cp, ctl|0x01, i, idx, df, scms, &m);
+                               }
+                       }
+               }
+       }
+       /* Lead out */
+       ctl = (st2mode[trackp[tracks+1].sectype & ST_MASK]) << 4;
+       if (is_copy(&trackp[i]))
+               ctl |= TM_ALLOW_COPY << 4;
+       if (is_quadro(&trackp[i]))
+               ctl |= TM_QUADRO << 4;
+       df = db2df[trackp[tracks+1].dbtype & 0x0F];
+       if (trackp[i].tracktype == TOC_XA2 &&
+           trackp[i].sectype   == (SECT_MODE_2_MIX|ST_MODE_RAW)) {
+               /*
+                * Hack for CUE with MODE2/CDI and
+                * trackp[i].dbtype == DB_RAW
+                */
+               df = 0x21;
+       }
+       df &= ~7;       /* Mask off data size & nonRAW subch */
+       if (df < 0x10)
+               df |= 1;
+       else
+               df |= 4;
+       lba_to_msf(trackp[tracks+1].trackstart, &m);
+       cue = realloc(cue, ++ncue * sizeof (*cue));
+       cp = &cue[icue++];
+       fillcue(cp, ctl|0x01, 0xAA, 1, df, 0, &m);
+
+       if (lverbose > 1) {
+               for (i = 0; i < ncue; i++) {
+                       usal_prbytes("", (Uchar *)&cue[i], 8);
+               }
+       }
+       if (cuep)
+               *cuep = cue;
+       else
+               free(cue);
+       return (ncue);
+}
+
+static void 
+fillcue(struct mmc_cue *cp  /* The target cue entry */, 
+        int ca              /* Control/adr for this entry */, 
+        int tno             /* Track number for this entry */, 
+        int idx             /* Index for this entry */, 
+        int dataform        /* Data format for this entry */, 
+        int scms            /* Serial copy management */, 
+        msf_t *mp           /* MSF value for this entry */)
+{
+       cp->cs_ctladr = ca;             /* XXX wie lead in */
+       cp->cs_tno = tno;
+       cp->cs_index = idx;
+       cp->cs_dataform = dataform;     /* XXX wie lead in */
+       cp->cs_scms = scms;
+       cp->cs_min = mp->msf_min;
+       cp->cs_sec = mp->msf_sec;
+       cp->cs_frame = mp->msf_frame;
+}
+
+static int 
+send_cue_mmc(SCSI *usalp, cdr_t *dp, track_t *trackp)
+{
+       struct mmc_cue  *cp;
+       int             ncue;
+       int             ret;
+       Uint            i;
+
+       for (i = 1; i <= trackp->tracks; i++) {
+               if (trackp[i].tracksize < (tsize_t)0) {
+                       errmsgno(EX_BAD, "Track %d has unknown length.\n", i);
+                       return (-1);
+               }
+       }
+       ncue = (*dp->cdr_gen_cue)(trackp, &cp, FALSE);
+
+       usalp->silent++;
+       ret = send_cue_sheet(usalp, (caddr_t)cp, ncue*8);
+       usalp->silent--;
+       free(cp);
+       if (ret < 0) {
+               errmsgno(EX_BAD, "CUE sheet not accepted. Retrying with minimum pregapsize = 1.\n");
+               ncue = (*dp->cdr_gen_cue)(trackp, &cp, TRUE);
+               ret = send_cue_sheet(usalp, (caddr_t)cp, ncue*8);
+               if (ret < 0) {
+                       errmsgno(EX_BAD,
+                       "CUE sheet still not accepted. Please try to write in RAW (-raw96r) mode.\n");
+               }
+               free(cp);
+       }
+       return (ret);
+}
+
+static int 
+stats_mmc(SCSI *usalp, cdr_t *dp)
+{
+       Uchar mode[256];
+       struct  ricoh_mode_page_30 *rp;
+       UInt32_t count;
+
+       if (mmc_isplextor(usalp) && lverbose) {
+               int     sels;
+               int     maxs;
+               int     lasts;
+
+               /*
+                * Run it in silent mode as old drives do not support it.
+                * As this function looks to be a part of the PowerRec
+                * features, we may want to check
+                * dp->cdr_flags & CDR_FORCESPEED
+                */
+               usalp->silent++;
+               if (get_speeds_plextor(usalp, &sels, &maxs, &lasts) >= 0) {
+                       printf("Last selected write speed: %dx\n",
+                                               sels / 176);
+                       printf("Max media write speed:     %dx\n",
+                                               maxs / 176);
+                       printf("Last actual write speed:   %dx\n",
+                                               lasts / 176);
+               }
+               usalp->silent--;
+       }
+
+       if ((dp->cdr_dstat->ds_cdrflags & RF_BURNFREE) == 0)
+               return (0);
+
+       if (mmc_isplextor(usalp)) {
+               int     i = 0;
+               int     ret;
+
+               /*
+                * Read Burn-Proof counter
+                */
+               usalp->silent++;
+               ret = bpc_plextor(usalp, 2, &i);
+               usalp->silent--;
+               if (ret < 0)
+                       return (-1);
+               count = i;
+               /*
+                * Clear Burn-Proof counter
+                */
+               bpc_plextor(usalp, 1, NULL);
+       } else {
+               rp = get_justlink_ricoh(usalp, mode);
+               if (rp)
+                       count = a_to_u_2_byte(rp->link_counter);
+               else
+                       return (-1);
+       }
+       if (lverbose) {
+               if (count == 0)
+                       printf("BURN-Free was never needed.\n");
+               else
+                       printf("BURN-Free was %d times used.\n",
+                               (int)count);
+       }
+       return (0);
+}
+/*--------------------------------------------------------------------------*/
+static BOOL 
+mmc_isplextor(SCSI *usalp)
+{
+       if (usalp->inq != NULL &&
+                       strncmp(usalp->inq->vendor_info, "PLEXTOR", 7) == 0) {
+               return (TRUE);
+       }
+       return (FALSE);
+}
+
+static BOOL 
+mmc_isyamaha(SCSI *usalp)
+{
+       if (usalp->inq != NULL &&
+                       strncmp(usalp->inq->vendor_info, "YAMAHA", 6) == 0) {
+               return (TRUE);
+       }
+       return (FALSE);
+}
+
+static void 
+do_varirec_plextor(SCSI *usalp)
+{
+       char    *p;
+       int     voff;
+
+       p = hasdrvopt(driveropts, "varirec=");
+       if (p == NULL || curspeed != 4) {
+               if (check_varirec_plextor(usalp) >= 0)
+                       varirec_plextor(usalp, FALSE, 0);
+       } else {
+               if (*astoi(p, &voff) != '\0')
+                       comerrno(EX_BAD,
+                               "Bad varirec value '%s'.\n", p);
+               if (check_varirec_plextor(usalp) < 0)
+                       comerrno(EX_BAD, "Drive does not support VariRec.\n");
+               varirec_plextor(usalp, TRUE, voff);
+       }
+}
+
+/*
+ * GigaRec value table
+ */
+struct gr {
+       Uchar   val;
+       char    vadd;
+       char    *name;
+} gr[] = {
+       { 0x00, 0,  "off", },
+       { 0x00, 0,  "1.0", },
+       { 0x01, 2,  "1.2", },
+       { 0x02, 3,  "1.3", },
+       { 0x03, 4,  "1.4", },
+       { 0x81, -2, "0.8", },
+       { 0x82, -3, "0.7", },
+       { 0x83, -4, "0.6", },
+       { 0x00, 0,  NULL, },
+};
+
+static int 
+do_gigarec_plextor(SCSI *usalp)
+{
+       char    *p;
+       int     val = 0;        /* Make silly GCC happy */
+
+       p = hasdrvopt(driveropts, "gigarec=");
+       if (p == NULL) {
+               if (check_gigarec_plextor(usalp) >= 0)
+                       gigarec_plextor(usalp, 0);
+       } else {
+               struct gr *gp = gr;
+
+               for (; gp->name != NULL; gp++) {
+                       if (streql(p, gp->name)) {
+                               val = gp->val;
+                               break;
+                       }
+               }
+               if (gp->name == NULL)
+                       comerrno(EX_BAD,
+                               "Bad gigarec value '%s'.\n", p);
+               if (check_gigarec_plextor(usalp) < 0)
+                       comerrno(EX_BAD, "Drive does not support GigaRec.\n");
+               return (gigarec_plextor(usalp, val));
+       }
+       return (0);
+}
+
+static int 
+drivemode_plextor(SCSI *usalp, caddr_t bp, int cnt, int modecode, void *modeval)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->flags = SCG_DISRE_ENA;
+       if (modeval == NULL) {
+               scmd->flags |= SCG_RECV_DATA;
+               scmd->addr = bp;
+               scmd->size = cnt;
+       } else {
+               scmd->cdb.g5_cdb.res = 0x08;
+       }
+       scmd->cdb_len = SC_G5_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+       scmd->cdb.g5_cdb.cmd = 0xE9;
+       scmd->cdb.g5_cdb.lun = usal_lun(usalp);
+       scmd->cdb.g1_cdb.addr[0] = modecode;
+       if (modeval)
+               movebytes(modeval, &scmd->cdb.g1_cdb.addr[1], 6);
+       else
+               i_to_2_byte(&scmd->cdb.g1_cdb.count[2], cnt);
+
+       usalp->cmdname = "plextor drive mode";
+
+       if (usal_cmd(usalp) < 0)
+               return (-1);
+       return (0);
+}
+
+/*
+ * #defines for drivemode_plextor()...
+ */
+#define        MODE_CODE_SH    0x01    /* Mode code for Single Session & Hide-CDR */
+#define        MB1_SS          0x01    /* Single Session Mode                     */
+#define        MB1_HIDE_CDR    0x02    /* Hide CDR Media                          */
+
+#define        MODE_CODE_VREC  0x02    /* Mode code for Vari Rec                  */
+
+#define        MODE_CODE_GREC  0x04    /* Mode code for Giga Rec                  */
+
+#define        MODE_CODE_SPEED 0xbb    /* Mode code for Speed Read                */
+#define        MBbb_SPEAD_READ 0x01    /* Spead Read                              */
+                               /* Danach Speed auf 0xFFFF 0xFFFF setzen   */
+
+static int 
+drivemode2_plextor(SCSI *usalp, caddr_t bp, int cnt, int modecode, void *modeval)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->flags = SCG_DISRE_ENA;
+       if (modeval == NULL) {
+               scmd->flags |= SCG_RECV_DATA;
+               scmd->addr = bp;
+               scmd->size = cnt;
+       } else {
+               scmd->cdb.g5_cdb.res = 0x08;
+       }
+       scmd->cdb_len = SC_G5_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+       scmd->cdb.g5_cdb.cmd = 0xED;
+       scmd->cdb.g5_cdb.lun = usal_lun(usalp);
+       scmd->cdb.g1_cdb.addr[0] = modecode;
+       if (modeval)
+               scmd->cdb.g5_cdb.reladr = *(char *)modeval != 0 ? 1 : 0;
+       else
+               i_to_2_byte(&scmd->cdb.g1_cdb.count[1], cnt);
+
+       usalp->cmdname = "plextor drive mode2";
+
+       if (usal_cmd(usalp) < 0)
+               return (-1);
+
+       return (0);
+}
+
+static int 
+check_varirec_plextor(SCSI *usalp)
+{
+       int     modecode = 2;
+       Uchar   getmode[8];
+
+       fillbytes(getmode, sizeof (getmode), '\0');
+       usalp->silent++;
+       if (drivemode_plextor(usalp, (caddr_t)getmode, sizeof (getmode), modecode, NULL) < 0) {
+               usalp->silent--;
+               return (-1);
+       }
+       usalp->silent--;
+
+       return (0);
+}
+
+static int 
+check_gigarec_plextor(SCSI *usalp)
+{
+       int     modecode = 4;
+       Uchar   getmode[8];
+
+       fillbytes(getmode, sizeof (getmode), '\0');
+       usalp->silent++;
+       if (drivemode_plextor(usalp, (caddr_t)getmode, sizeof (getmode), modecode, NULL) < 0) {
+               usalp->silent--;
+               return (-1);
+       }
+       usalp->silent--;
+
+       return (0);
+}
+
+static int 
+varirec_plextor(SCSI *usalp, BOOL on, int val)
+{
+       int     modecode = 2;
+       Uchar   setmode[8];
+       Uchar   getmode[8];
+
+       fillbytes(getmode, sizeof (getmode), '\0');
+       usalp->silent++;
+       if (drivemode_plextor(usalp, (caddr_t)getmode, sizeof (getmode), modecode, NULL) < 0) {
+               usalp->silent--;
+               return (-1);
+       }
+       usalp->silent--;
+
+       if (lverbose > 1)
+               usal_prbytes("Modes", getmode, sizeof (getmode));
+
+
+       fillbytes(setmode, sizeof (setmode), '\0');
+       setmode[0] = on?1:0;
+       if (on) {
+               if (val < -2 || val > 2)
+                       comerrno(EX_BAD, "Bad VariRec offset %d\n", val);
+               printf("Turning Varirec on.\n");
+               printf("Varirec offset is %d.\n", val);
+
+               if (val > 0) {
+                       setmode[1] = val & 0x7F;
+               } else {
+                       setmode[1] = (-val) & 0x7F;
+                       setmode[1] |= 0x80;
+               }
+       }
+
+       if (drivemode_plextor(usalp, NULL, 0, modecode, setmode) < 0)
+               return (-1);
+
+       fillbytes(getmode, sizeof (getmode), '\0');
+       if (drivemode_plextor(usalp, (caddr_t)getmode, sizeof (getmode), modecode, NULL) < 0)
+               return (-1);
+
+       if (lverbose > 1)
+               usal_prbytes("Modes", getmode, sizeof (getmode));
+
+       return (0);
+}
+
+static int 
+gigarec_plextor(SCSI *usalp, int val)
+{
+       int     modecode = 4;
+       Uchar   setmode[8];
+       Uchar   getmode[8];
+
+       fillbytes(getmode, sizeof (getmode), '\0');
+       usalp->silent++;
+       if (drivemode_plextor(usalp, (caddr_t)getmode, sizeof (getmode), modecode, NULL) < 0) {
+               usalp->silent--;
+               return (-1);
+       }
+       usalp->silent--;
+
+       if (lverbose > 1)
+               usal_prbytes("Modes", getmode, sizeof (getmode));
+
+
+       fillbytes(setmode, sizeof (setmode), '\0');
+       setmode[1] = val;
+
+       if (drivemode_plextor(usalp, NULL, 0, modecode, setmode) < 0)
+               return (-1);
+
+       fillbytes(getmode, sizeof (getmode), '\0');
+       if (drivemode_plextor(usalp, (caddr_t)getmode, sizeof (getmode), modecode, NULL) < 0)
+               return (-1);
+
+       if (lverbose > 1)
+               usal_prbytes("Modes", getmode, sizeof (getmode));
+
+       {
+               struct gr *gp = gr;
+
+               for (; gp->name != NULL; gp++) {
+                       if (getmode[3] == gp->val)
+                               break;
+               }
+               if (gp->name == NULL)
+                       printf("Unknown GigaRec value 0x%X.\n", getmode[3]);
+               else
+                       printf("GigaRec %sis %s.\n", gp->val?"value ":"", gp->name);
+       }
+       return (getmode[3]);
+}
+
+static Int32_t 
+gigarec_mult(int code, Int32_t val)
+{
+       Int32_t add;
+       struct gr *gp = gr;
+
+       for (; gp->name != NULL; gp++) {
+               if (code == gp->val)
+                       break;
+       }
+       if (gp->vadd == 0)
+               return (val);
+
+       add = val * gp->vadd / 10;
+       return (val + add);
+}
+
+static int 
+check_ss_hide_plextor(SCSI *usalp)
+{
+       int     modecode = 1;
+       Uchar   getmode[8];
+
+       fillbytes(getmode, sizeof (getmode), '\0');
+       usalp->silent++;
+       if (drivemode_plextor(usalp, (caddr_t)getmode, sizeof (getmode), modecode, NULL) < 0) {
+               usalp->silent--;
+               return (-1);
+       }
+       usalp->silent--;
+
+       return (getmode[2] & 0x03);
+}
+
+static int 
+check_speed_rd_plextor(SCSI *usalp)
+{
+       int     modecode = 0xBB;
+       Uchar   getmode[8];
+
+       fillbytes(getmode, sizeof (getmode), '\0');
+       usalp->silent++;
+       if (drivemode_plextor(usalp, (caddr_t)getmode, sizeof (getmode), modecode, NULL) < 0) {
+               usalp->silent--;
+               return (-1);
+       }
+       usalp->silent--;
+
+       return (getmode[2] & 0x01);
+}
+
+static int 
+check_powerrec_plextor(SCSI *usalp)
+{
+       int     modecode = 0;
+       Uchar   getmode[8];
+
+       fillbytes(getmode, sizeof (getmode), '\0');
+       usalp->silent++;
+       if (drivemode2_plextor(usalp, (caddr_t)getmode, sizeof (getmode), modecode, NULL) < 0) {
+               usalp->silent--;
+               return (-1);
+       }
+       usalp->silent--;
+
+       if (getmode[2] & 1)
+               return (1);
+
+       return (0);
+}
+
+static int 
+ss_hide_plextor(SCSI *usalp, BOOL do_ss, BOOL do_hide)
+{
+       int     modecode = 1;
+       Uchar   setmode[8];
+       Uchar   getmode[8];
+       BOOL    is_ss;
+       BOOL    is_hide;
+
+       fillbytes(getmode, sizeof (getmode), '\0');
+       usalp->silent++;
+       if (drivemode_plextor(usalp, (caddr_t)getmode, sizeof (getmode), modecode, NULL) < 0) {
+               usalp->silent--;
+               return (-1);
+       }
+       usalp->silent--;
+
+       if (lverbose > 1)
+               usal_prbytes("Modes", getmode, sizeof (getmode));
+
+
+       is_ss = (getmode[2] & MB1_SS) != 0;
+       is_hide = (getmode[2] & MB1_HIDE_CDR) != 0;
+
+       if (lverbose > 0) {
+               printf("Single session is %s.\n", is_ss ? "ON":"OFF");
+               printf("Hide CDR is %s.\n", is_hide ? "ON":"OFF");
+       }
+
+       fillbytes(setmode, sizeof (setmode), '\0');
+       setmode[0] = getmode[2];                /* Copy over old values */
+       if (do_ss >= 0) {
+               if (do_ss)
+                       setmode[0] |= MB1_SS;
+               else
+                       setmode[0] &= ~MB1_SS;
+       }
+       if (do_hide >= 0) {
+               if (do_hide)
+                       setmode[0] |= MB1_HIDE_CDR;
+               else
+                       setmode[0] &= ~MB1_HIDE_CDR;
+       }
+
+       if (do_ss >= 0 && do_ss != is_ss)
+               printf("Turning single session %s.\n", do_ss?"on":"off");
+       if (do_hide >= 0 && do_hide != is_hide)
+               printf("Turning hide CDR %s.\n", do_hide?"on":"off");
+
+       if (drivemode_plextor(usalp, NULL, 0, modecode, setmode) < 0)
+               return (-1);
+
+       fillbytes(getmode, sizeof (getmode), '\0');
+       if (drivemode_plextor(usalp, (caddr_t)getmode, sizeof (getmode), modecode, NULL) < 0)
+               return (-1);
+
+       if (lverbose > 1)
+               usal_prbytes("Modes", getmode, sizeof (getmode));
+
+       return (0);
+}
+
+static int 
+speed_rd_plextor(SCSI *usalp, BOOL do_speedrd)
+{
+       int     modecode = 0xBB;
+       Uchar   setmode[8];
+       Uchar   getmode[8];
+       BOOL    is_speedrd;
+
+       fillbytes(getmode, sizeof (getmode), '\0');
+       usalp->silent++;
+       if (drivemode_plextor(usalp, (caddr_t)getmode, sizeof (getmode), modecode, NULL) < 0) {
+               usalp->silent--;
+               return (-1);
+       }
+       usalp->silent--;
+
+       if (lverbose > 1)
+               usal_prbytes("Modes", getmode, sizeof (getmode));
+
+
+       is_speedrd = (getmode[2] & MBbb_SPEAD_READ) != 0;
+
+       if (lverbose > 0)
+               printf("Speed-Read is %s.\n", is_speedrd ? "ON":"OFF");
+
+       fillbytes(setmode, sizeof (setmode), '\0');
+       setmode[0] = getmode[2];                /* Copy over old values */
+       if (do_speedrd >= 0) {
+               if (do_speedrd)
+                       setmode[0] |= MBbb_SPEAD_READ;
+               else
+                       setmode[0] &= ~MBbb_SPEAD_READ;
+       }
+
+       if (do_speedrd >= 0 && do_speedrd != is_speedrd)
+               printf("Turning Speed-Read %s.\n", do_speedrd?"on":"off");
+
+       if (drivemode_plextor(usalp, NULL, 0, modecode, setmode) < 0)
+               return (-1);
+
+       fillbytes(getmode, sizeof (getmode), '\0');
+       if (drivemode_plextor(usalp, (caddr_t)getmode, sizeof (getmode), modecode, NULL) < 0)
+               return (-1);
+
+       if (lverbose > 1)
+               usal_prbytes("Modes", getmode, sizeof (getmode));
+
+       /*
+        * Set current read speed to new max value.
+        */
+       if (do_speedrd >= 0 && do_speedrd != is_speedrd)
+               scsi_set_speed(usalp, 0xFFFF, -1, ROTCTL_CAV);
+
+       return (0);
+}
+
+static int 
+powerrec_plextor(SCSI *usalp, BOOL do_powerrec)
+{
+       int     modecode = 0;
+       Uchar   setmode[8];
+       Uchar   getmode[8];
+       BOOL    is_powerrec;
+       int     speed;
+
+       fillbytes(getmode, sizeof (getmode), '\0');
+       usalp->silent++;
+       if (drivemode2_plextor(usalp, (caddr_t)getmode, sizeof (getmode), modecode, NULL) < 0) {
+               usalp->silent--;
+               return (-1);
+       }
+       usalp->silent--;
+
+       if (lverbose > 1)
+               usal_prbytes("Modes", getmode, sizeof (getmode));
+
+
+       is_powerrec = (getmode[2] & 1) != 0;
+
+       speed = a_to_u_2_byte(&getmode[4]);
+
+       if (lverbose > 0) {
+               printf("Power-Rec is %s.\n", is_powerrec ? "ON":"OFF");
+               printf("Power-Rec write speed:     %dx (recommended)\n", speed / 176);
+       }
+
+       fillbytes(setmode, sizeof (setmode), '\0');
+       setmode[0] = getmode[2];                /* Copy over old values */
+       if (do_powerrec >= 0) {
+               if (do_powerrec)
+                       setmode[0] |= 1;
+               else
+                       setmode[0] &= ~1;
+       }
+
+       if (do_powerrec >= 0 && do_powerrec != is_powerrec)
+               printf("Turning Power-Rec %s.\n", do_powerrec?"on":"off");
+
+       if (drivemode2_plextor(usalp, NULL, 0, modecode, setmode) < 0)
+               return (-1);
+
+       fillbytes(getmode, sizeof (getmode), '\0');
+       if (drivemode2_plextor(usalp, (caddr_t)getmode, sizeof (getmode), modecode, NULL) < 0)
+               return (-1);
+
+       if (lverbose > 1)
+               usal_prbytes("Modes", getmode, sizeof (getmode));
+
+       return (0);
+}
+
+static int 
+get_speeds_plextor(SCSI *usalp, int *selp, int *maxp, int *lastp)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+       char    buf[10];
+       int     i;
+
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       fillbytes((caddr_t)buf, sizeof (buf), '\0');
+       scmd->flags = SCG_DISRE_ENA;
+       scmd->flags |= SCG_RECV_DATA;
+       scmd->addr = buf;
+       scmd->size = sizeof (buf);
+       scmd->cdb_len = SC_G5_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+       scmd->cdb.g5_cdb.cmd = 0xEB;
+       scmd->cdb.g5_cdb.lun = usal_lun(usalp);
+
+       i_to_2_byte(&scmd->cdb.g1_cdb.count[1], sizeof (buf));
+
+       usalp->cmdname = "plextor get speedlist";
+
+       if (usal_cmd(usalp) < 0)
+               return (-1);
+
+       i = a_to_u_2_byte(&buf[4]);
+       if (selp)
+               *selp = i;
+
+       i = a_to_u_2_byte(&buf[6]);
+       if (maxp)
+               *maxp = i;
+
+       i = a_to_u_2_byte(&buf[8]);
+       if (lastp)
+               *lastp = i;
+
+       return (0);
+}
+
+static int 
+bpc_plextor(SCSI *usalp, int mode, int *bpp)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+       char    buf[4];
+       int     i;
+
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       fillbytes((caddr_t)buf, sizeof (buf), '\0');
+       scmd->flags = SCG_DISRE_ENA;
+       scmd->flags |= SCG_RECV_DATA;
+       scmd->addr = buf;
+       scmd->size = sizeof (buf);
+       scmd->cdb_len = SC_G5_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+       scmd->cdb.g5_cdb.cmd = 0xF5;
+       scmd->cdb.g5_cdb.lun = usal_lun(usalp);
+
+       scmd->cdb.g5_cdb.addr[1] = 0x08;
+       scmd->cdb.g5_cdb.addr[2] = mode;
+
+       i_to_2_byte(&scmd->cdb.g1_cdb.count[1], sizeof (buf));
+
+       usalp->cmdname = "plextor read bpc";
+
+       if (usal_cmd(usalp) < 0)
+               return (-1);
+
+       if (usal_getresid(usalp) > 2)
+               return (0);
+
+       i = a_to_u_2_byte(buf);
+       if (bpp)
+               *bpp = i;
+
+       return (0);
+}
+
+static int 
+set_audiomaster_yamaha(SCSI *usalp, cdr_t *dp, BOOL keep_mode)
+{
+       Uchar   mode[0x100];
+       int     len;
+       int     ret = 0;
+       struct  cd_mode_page_05 *mp;
+
+       if (xdebug && !keep_mode)
+               printf("Checking for Yamaha Audio Master feature: ");
+
+       /*
+        * Do not reset mp->test_write (-dummy) here.
+        */
+       deflt_writemodes_mmc(usalp, FALSE);
+
+       fillbytes((caddr_t)mode, sizeof (mode), '\0');
+
+       usalp->silent++;
+       if (!get_mode_params(usalp, 0x05, "CD write parameter",
+                       mode, (Uchar *)0, (Uchar *)0, (Uchar *)0, &len)) {
+               usalp->silent--;
+               return (-1);
+       }
+       if (len == 0) {
+               usalp->silent--;
+               return (-1);
+       }
+
+       mp = (struct cd_mode_page_05 *)
+               (mode + sizeof (struct scsi_mode_header) +
+               ((struct scsi_mode_header *)mode)->blockdesc_len);
+#ifdef DEBUG
+       usal_prbytes("CD write parameter:", (Uchar *)mode, len);
+#endif
+
+       /*
+        * Do not set mp->test_write (-dummy) here. It should be set
+        * only at one place and only one time.
+        */
+       mp->BUFE = 0;
+
+       mp->write_type = 8;
+       mp->track_mode = 0;
+       mp->dbtype = DB_RAW;
+
+       if (!set_mode_params(usalp, "CD write parameter", mode, len, 0, -1))
+               ret = -1;
+
+       /*
+        * Do not reset mp->test_write (-dummy) here.
+        */
+       if (!keep_mode || ret < 0)
+               deflt_writemodes_mmc(usalp, FALSE);
+       usalp->silent--;
+
+       return (ret);
+}
+
+struct 
+ricoh_mode_page_30 *get_justlink_ricoh(SCSI *usalp, Uchar *mode)
+{
+       Uchar   modec[0x100];
+       int     len;
+       struct  ricoh_mode_page_30 *mp;
+
+       usalp->silent++;
+       if (!get_mode_params(usalp, 0x30, "Ricoh Vendor Page", mode, modec, NULL, NULL, &len)) {
+               usalp->silent--;
+               return ((struct ricoh_mode_page_30 *)0);
+       }
+       usalp->silent--;
+
+       /*
+        * SCSI mode header + 6 bytes mode page 30.
+        * This is including the Burn-Free counter.
+        */
+       if (len < 10)
+               return ((struct ricoh_mode_page_30 *)0);
+
+       if (xdebug) {
+               fprintf(stderr, "Mode len: %d\n", len);
+               usal_prbytes("Mode Sense Data ", mode, len);
+               usal_prbytes("Mode Sence CData", modec, len);
+       }
+
+       mp = (struct ricoh_mode_page_30 *)
+               (mode + sizeof (struct scsi_mode_header) +
+               ((struct scsi_mode_header *)mode)->blockdesc_len);
+
+       /*
+        * 6 bytes mode page 30.
+        * This is including the Burn-Free counter.
+        */
+       if ((len - ((Uchar *)mp - mode) -1) < 5)
+               return ((struct ricoh_mode_page_30 *)0);
+
+       if (xdebug) {
+               fprintf(stderr, "Burnfree counter: %d\n", a_to_u_2_byte(mp->link_counter));
+       }
+       return (mp);
+}
+
+static int 
+force_speed_yamaha(SCSI *usalp, int readspeed, int writespeed)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->flags = SCG_DISRE_ENA;
+       scmd->cdb_len = SC_G5_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+       scmd->cdb.g5_cdb.cmd = 0xBB;
+       scmd->cdb.g5_cdb.lun = usal_lun(usalp);
+
+       if (readspeed < 0)
+               i_to_2_byte(&scmd->cdb.g5_cdb.addr[0], 0xFFFF);
+       else
+               i_to_2_byte(&scmd->cdb.g5_cdb.addr[0], readspeed);
+       if (writespeed < 0)
+               i_to_2_byte(&scmd->cdb.g5_cdb.addr[2], 0xFFFF);
+       else
+               i_to_2_byte(&scmd->cdb.g5_cdb.addr[2], writespeed);
+
+       scmd->cdb.cmd_cdb[11] = 0x80;
+
+       usalp->cmdname = "yamaha force cd speed";
+
+       if (usal_cmd(usalp) < 0)
+               return (-1);
+       return (0);
+}
+
+static BOOL
+get_tattoo_yamaha(SCSI *usalp, BOOL print, Int32_t *irp, Int32_t *orp)
+{
+       Uchar   mode[0x100];
+       int     len;
+       UInt32_t ival;
+       UInt32_t oval;
+       Uchar   *mp;
+
+       usalp->silent++;
+       if (!get_mode_params(usalp, 0x31, "Yamaha Tattoo Page", mode, NULL, NULL, NULL, &len)) {
+               usalp->silent--;
+               return (FALSE);
+       }
+       usalp->silent--;
+
+       /*
+        * SCSI mode header + 16 bytes mode page 31.
+        * This is including the Burn-Free counter.
+        */
+       if (len < 20)
+               return (FALSE);
+
+       mp = (Uchar *)
+               (mode + sizeof (struct scsi_mode_header) +
+               ((struct scsi_mode_header *)mode)->blockdesc_len);
+
+       /*
+        * 10 bytes mode page 31.
+        * This is including the Burn-Free counter.
+        */
+       if ((len - ((Uchar *)mp - mode) -1) < 10)
+               return (FALSE);
+
+       ival = a_to_u_3_byte(&mp[4]);
+       oval = a_to_u_3_byte(&mp[7]);
+
+       if (irp)
+               *irp = ival;
+       if (orp)
+               *orp = oval;
+
+       if (print && ival > 0 && oval > 0) {
+               printf("DiskT@2 inner r: %d\n", (int)ival);
+               printf("DiskT@2 outer r: %d\n", (int)oval);
+               printf("DiskT@2 image size: 3744 x %d pixel.\n",
+                                               (int)(oval-ival)+1);
+       }
+
+       return (TRUE);
+}
+
+static int 
+do_tattoo_yamaha(SCSI *usalp, FILE *f)
+{
+       Int32_t ival = 0;
+       Int32_t oval = 0;
+       Int32_t lines;
+       off_t   fsize;
+       char    *buf = usalp->bufptr;
+       long    bufsize = usalp->maxbuf;
+       long    nsecs;
+       long    amt;
+
+       nsecs = bufsize / 2048;
+       bufsize = nsecs * 2048;
+
+       if (!get_tattoo_yamaha(usalp, FALSE, &ival, &oval)) {
+               errmsgno(EX_BAD, "Cannot get DiskT@2 info.\n");
+               return (-1);
+       }
+
+       if (ival == 0 || oval == 0) {
+               errmsgno(EX_BAD, "DiskT@2 info not valid.\n");
+               return (-1);
+       }
+
+       lines = oval - ival + 1;
+       fsize = filesize(f);
+       if ((fsize % 3744) != 0 || fsize < (lines*3744)) {
+               errmsgno(EX_BAD, "Illegal DiskT@2 file size.\n");
+               return (-1);
+       }
+       if (fsize > (lines*3744))
+               fsize = lines*3744;
+
+       if (lverbose)
+               printf("Starting to write DiskT@2 data.\n");
+       fillbytes(buf, bufsize, '\0');
+       if ((amt = fileread(f, buf, bufsize)) <= 0) {
+               errmsg("DiskT@2 file read error.\n");
+               return (-1);
+       }
+
+       if (yamaha_write_buffer(usalp, 1, 0, ival, amt/2048, buf, amt) < 0) {
+               errmsgno(EX_BAD, "DiskT@2 1st write error.\n");
+               return (-1);
+       }
+       amt = (amt+2047) / 2048 * 2048;
+       fsize -= amt;
+
+       while (fsize > 0) {
+               fillbytes(buf, bufsize, '\0');
+               if ((amt = fileread(f, buf, bufsize)) <= 0) {
+                       errmsg("DiskT@2 file read error.\n");
+                       return (-1);
+               }
+               amt = (amt+2047) / 2048 * 2048;
+               fsize -= amt;
+               if (yamaha_write_buffer(usalp, 1, 0, 0, amt/2048, buf, amt) < 0) {
+                       errmsgno(EX_BAD, "DiskT@2 write error.\n");
+                       return (-1);
+               }
+       }
+
+       if (yamaha_write_buffer(usalp, 1, 0, oval, 0, buf, 0) < 0) {
+               errmsgno(EX_BAD, "DiskT@2 final error.\n");
+               return (-1);
+       }
+
+       wait_unit_ready(usalp, 1000);   /* Wait for DiskT@2 */
+       waitfix_mmc(usalp, 1000);       /* Wait for DiskT@2 */
+
+       return (0);
+}
+
+/*
+ * Yamaha specific version of 'write buffer' that offers an additional
+ * Parameter Length 'parlen' parameter.
+ */
+static int 
+yamaha_write_buffer(SCSI *usalp, int mode, int bufferid, long offset,
+                    long parlen, void *buffer, long buflen)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+               Uchar   *CDB;
+
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->addr = buffer;
+       scmd->size = buflen;
+       scmd->flags = SCG_DISRE_ENA;
+       scmd->cdb_len = SC_G1_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+       scmd->cdb.g1_cdb.cmd = 0x3B;
+
+       CDB    = (Uchar *)scmd->cdb.cmd_cdb;
+       CDB[1] = mode & 7;
+       CDB[2] = bufferid;
+       i_to_3_byte(&CDB[3], offset);
+       i_to_3_byte(&CDB[6], parlen);
+
+       usalp->cmdname = "write_buffer";
+
+       if (usal_cmd(usalp) >= 0)
+               return (1);
+       return (0);
+}
+
+static int 
+dvd_dual_layer_split(SCSI *usalp, cdr_t *dp, long tsize)
+{
+    unsigned char      xb[12];
+    long       l0_size;
+    
+    /* Get the Layer 0 defined data zone*/
+    if (read_dvd_structure(usalp, (caddr_t)xb, 12, 0, 0, 0x20) >= 0) {
+       if ((xb[1] | xb[0] << 8) < 13) {
+           fprintf(stderr, "dvd_dual_layer_split: read_dvd_structure returns invalid data\n");
+           return 1;
+       }
+       if (xb[4] & 0x80) {
+           printf("L0 zone size already set\n");
+           return 1;
+       }
+       l0_size = xb[11] | xb[10] << 8 | xb[9] << 16 | xb[8] << 24;
+       if (tsize < l0_size) {
+           fprintf(stderr, "track size smaller than one layer, use --force to force burning.");
+           return 0;
+       }
+       printf("L0 size: %ld (track size %ld)\n", l0_size, tsize);
+       l0_size = tsize / 2;
+       l0_size = l0_size - 1 + 16 - (l0_size - 1) % 16;
+       printf("New L0 size: %ld\n", l0_size);
+
+       memset (xb, 0, sizeof(xb));
+       xb[1]  = sizeof(xb) - 2;
+       xb[8]  = l0_size >> 24;
+       xb[9]  = l0_size >> 16;
+       xb[10] = l0_size >> 8;
+       xb[11] = l0_size;
+       if (send_dvd_structure(usalp, (caddr_t)xb, 12, 0, 0x20)) {
+           fprintf(stderr, "dvd_dual_layer_split: send_dvd_structure failed, could not set middle zone location.\n");
+           return 0;
+       }
+    }
+   return 1;
+}
diff --git a/wodim/drv_philips.c b/wodim/drv_philips.c
new file mode 100644 (file)
index 0000000..13cf8ed
--- /dev/null
@@ -0,0 +1,1346 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)drv_philips.c   1.69 05/05/16 Copyright 1997-2005 J. Schilling */
+/*
+ *     CDR device implementation for
+ *     Philips/Yamaha/Ricoh/Plasmon
+ *
+ *     Copyright (c) 1997-2005 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <mconfig.h>
+
+#include <stdio.h>
+#include <unixstd.h>   /* Include sys/types.h to make off_t available */
+#include <standard.h>
+#include <intcvt.h>
+#include <schily.h>
+
+#include <usal/scsireg.h>
+#include <usal/scsitransp.h>
+#include <usal/usalcmd.h>
+#include <usal/scsidefs.h>     /* XXX Only for DEV_RICOH_RO_1060C */
+
+#include "wodim.h"
+
+extern int     debug;
+extern int     lverbose;
+
+static int     load_unload_philips(SCSI *usalp, int);
+static int     philips_load(SCSI *usalp, cdr_t *dp);
+static int     philips_unload(SCSI *usalp, cdr_t *dp);
+static int     philips_dumbload(SCSI *usalp, cdr_t *dp);
+static int     philips_dumbunload(SCSI *usalp, cdr_t *dp);
+static int     plasmon_buf(SCSI *, long *, long *);
+static int     recover_philips(SCSI *usalp, cdr_t *dp, int);
+static int     speed_select_yamaha(SCSI *usalp, cdr_t *dp, int *speedp);
+static int     speed_select_philips(SCSI *usalp, cdr_t *dp, int *speedp);
+static int     speed_select_oldphilips(SCSI *usalp, cdr_t *dp, int *speedp);
+static int     speed_select_dumbphilips(SCSI *usalp, cdr_t *dp, int *speedp);
+static int     speed_select_pioneer(SCSI *usalp, cdr_t *dp, int *speedp);
+static int     philips_init(SCSI *usalp, cdr_t *dp);
+static int     philips_getdisktype(SCSI *usalp, cdr_t *dp);
+static BOOL    capacity_philips(SCSI *usalp, long *lp);
+static int     first_writable_addr_philips(SCSI *usalp, long *, int, int, int, 
+                                                                                                                int);
+static int     next_wr_addr_philips(SCSI *usalp, track_t *trackp, long *ap);
+static int     reserve_track_philips(SCSI *usalp, unsigned long);
+static int     scsi_cdr_write_philips(SCSI *usalp, caddr_t bp, long sectaddr, 
+                                                                                                 long size, int blocks, BOOL islast);
+static int     write_track_info_philips(SCSI *usalp, int);
+static int     write_track_philips(SCSI *usalp, long, int);
+static int     open_track_philips(SCSI *usalp, cdr_t *dp, track_t *trackp);
+static int     open_track_plasmon(SCSI *usalp, cdr_t *dp, track_t *trackp);
+static int     open_track_oldphilips(SCSI *usalp, cdr_t *dp, track_t *trackp);
+static int     open_track_yamaha(SCSI *usalp, cdr_t *dp, track_t *trackp);
+static int     close_track_philips(SCSI *usalp, cdr_t *dp, track_t *trackp);
+static int     fixation_philips(SCSI *usalp, cdr_t *dp, track_t *trackp);
+
+static int     philips_attach(SCSI *usalp, cdr_t *);
+static int     plasmon_attach(SCSI *usalp, cdr_t *);
+static int     ricoh_attach(SCSI *usalp, cdr_t *);
+static int     philips_getlilo(SCSI *usalp, long *lilenp, long *lolenp);
+
+
+struct cdd_52x_mode_page_21 {  /* write track information */
+               MP_P_CODE;              /* parsave & pagecode */
+       Uchar   p_len;                  /* 0x0E = 14 Bytes */
+       Uchar   res_2;
+       Uchar   sectype;
+       Uchar   track;
+       Uchar   ISRC[9];
+       Uchar   res[2];
+};
+
+struct cdd_52x_mode_page_23 {  /* speed selection */
+               MP_P_CODE;              /* parsave & pagecode */
+       Uchar   p_len;                  /* 0x06 = 6 Bytes */
+       Uchar   speed;
+       Uchar   dummy;
+       Uchar   res[4];
+
+};
+
+#if defined(_BIT_FIELDS_LTOH)  /* Intel byteorder */
+
+struct yamaha_mode_page_31 {   /* drive configuration */
+               MP_P_CODE;              /* parsave & pagecode */
+       Uchar   p_len;                  /* 0x02 = 2 Bytes */
+       Uchar   res;
+       Ucbit   dummy           : 4;
+       Ucbit   speed           : 4;
+};
+
+#else                          /* Motorola byteorder */
+
+struct yamaha_mode_page_31 {   /* drive configuration */
+               MP_P_CODE;              /* parsave & pagecode */
+       Uchar   p_len;                  /* 0x02 = 2 Bytes */
+       Uchar   res;
+       Ucbit   speed           : 4;
+       Ucbit   dummy           : 4;
+};
+#endif
+
+struct cdd_52x_mode_data {
+       struct scsi_mode_header header;
+       union cdd_pagex {
+               struct cdd_52x_mode_page_21     page21;
+               struct cdd_52x_mode_page_23     page23;
+               struct yamaha_mode_page_31      page31;
+       } pagex;
+};
+
+
+cdr_t  cdr_philips_cdd521O = {
+       0, 0,
+       CDR_TAO|CDR_TRAYLOAD,
+       CDR_CDRW_NONE,
+       2, 2,
+       "philips_cdd521_old",
+       "driver for Philips old CDD-521",
+       0,
+       (dstat_t *)0,
+       drive_identify,
+       philips_attach,
+       philips_init,
+       philips_getdisktype,
+       philips_load,
+       philips_unload,
+       buf_dummy,
+       recovery_needed,
+       recover_philips,
+       speed_select_oldphilips,
+       select_secsize,
+       next_wr_addr_philips,
+       reserve_track_philips,
+       scsi_cdr_write_philips,
+       (int(*)(track_t *, void *, BOOL))cmd_dummy,     /* gen_cue */
+       no_sendcue,
+       (int(*)(SCSI *, cdr_t *, track_t *))cmd_dummy, /* leadin */
+       open_track_oldphilips,
+       close_track_philips,
+       (int(*)(SCSI *, cdr_t *, track_t *))cmd_dummy,
+       cmd_dummy,
+       cmd_dummy,                                      /* abort        */
+       read_session_offset_philips,
+       fixation_philips,
+       cmd_dummy,                                      /* stats        */
+       blank_dummy,
+       format_dummy,
+       (int(*)(SCSI *, caddr_t, int, int))NULL,        /* no OPC       */
+       cmd_dummy,                                      /* opt1         */
+       cmd_dummy,                                      /* opt2         */
+};
+
+cdr_t  cdr_philips_dumb = {
+       0, 0,
+       CDR_TAO|CDR_TRAYLOAD,
+       CDR_CDRW_NONE,
+       2, 2,
+       "philips_dumb",
+       "driver for Philips CDD-521 with pessimistic assumptions",
+       0,
+       (dstat_t *)0,
+       drive_identify,
+       philips_attach,
+       philips_init,
+       philips_getdisktype,
+       philips_dumbload,
+       philips_dumbunload,
+       buf_dummy,
+       recovery_needed,
+       recover_philips,
+       speed_select_dumbphilips,
+       select_secsize,
+       next_wr_addr_philips,
+       reserve_track_philips,
+       scsi_cdr_write_philips,
+       (int(*)(track_t *, void *, BOOL))cmd_dummy,     /* gen_cue */
+       no_sendcue,
+       (int(*)(SCSI *, cdr_t *, track_t *))cmd_dummy, /* leadin */
+       open_track_oldphilips,
+       close_track_philips,
+       (int(*)(SCSI *, cdr_t *, track_t *))cmd_dummy,
+       cmd_dummy,
+       cmd_dummy,                                      /* abort        */
+       read_session_offset_philips,
+       fixation_philips,
+       cmd_dummy,                                      /* stats        */
+       blank_dummy,
+       format_dummy,
+       (int(*)(SCSI *, caddr_t, int, int))NULL,        /* no OPC       */
+       cmd_dummy,                                      /* opt1         */
+       cmd_dummy,                                      /* opt2         */
+};
+
+cdr_t  cdr_philips_cdd521 = {
+       0, 0,
+       CDR_TAO|CDR_TRAYLOAD,
+       CDR_CDRW_NONE,
+       2, 2,
+       "philips_cdd521",
+       "driver for Philips CDD-521",
+       0,
+       (dstat_t *)0,
+       drive_identify,
+       philips_attach,
+       philips_init,
+       philips_getdisktype,
+       philips_load,
+       philips_unload,
+       buf_dummy,
+       recovery_needed,
+       recover_philips,
+       speed_select_philips,
+       select_secsize,
+       next_wr_addr_philips,
+       reserve_track_philips,
+       scsi_cdr_write_philips,
+       (int(*)(track_t *, void *, BOOL))cmd_dummy,     /* gen_cue */
+       no_sendcue,
+       (int(*)(SCSI *, cdr_t *, track_t *))cmd_dummy, /* leadin */
+       open_track_philips,
+       close_track_philips,
+       (int(*)(SCSI *, cdr_t *, track_t *))cmd_dummy,
+       cmd_dummy,
+       cmd_dummy,                                      /* abort        */
+       read_session_offset_philips,
+       fixation_philips,
+       cmd_dummy,                                      /* stats        */
+       blank_dummy,
+       format_dummy,
+       (int(*)(SCSI *, caddr_t, int, int))NULL,        /* no OPC       */
+       cmd_dummy,                                      /* opt1         */
+       cmd_dummy,                                      /* opt2         */
+};
+
+cdr_t  cdr_philips_cdd522 = {
+       0, 0,
+/*     CDR_TAO|CDR_SAO|CDR_TRAYLOAD,*/
+       CDR_TAO|CDR_TRAYLOAD,
+       CDR_CDRW_NONE,
+       2, 2,
+       "philips_cdd522",
+       "driver for Philips CDD-522",
+       0,
+       (dstat_t *)0,
+       drive_identify,
+       philips_attach,
+       philips_init,
+       philips_getdisktype,
+       philips_load,
+       philips_unload,
+       buf_dummy,
+       recovery_needed,
+       recover_philips,
+       speed_select_philips,
+       select_secsize,
+       next_wr_addr_philips,
+       reserve_track_philips,
+       scsi_cdr_write_philips,
+       (int(*)(track_t *, void *, BOOL))cmd_dummy,     /* gen_cue */
+       no_sendcue,
+       (int(*)(SCSI *, cdr_t *, track_t *))cmd_dummy, /* leadin */
+       open_track_philips,
+       close_track_philips,
+       (int(*)(SCSI *, cdr_t *, track_t *))cmd_dummy,
+       cmd_dummy,
+       cmd_dummy,                                      /* abort        */
+       read_session_offset_philips,
+       fixation_philips,
+       cmd_dummy,                                      /* stats        */
+       blank_dummy,
+       format_dummy,
+       (int(*)(SCSI *, caddr_t, int, int))NULL,        /* no OPC       */
+       cmd_dummy,                                      /* opt1         */
+       cmd_dummy,                                      /* opt2         */
+};
+
+cdr_t  cdr_tyuden_ew50 = {
+       0, 0,
+       CDR_TAO|CDR_TRAYLOAD|CDR_SWABAUDIO,
+       CDR_CDRW_NONE,
+       2, 2,
+       "tyuden_ew50",
+       "driver for Taiyo Yuden EW-50",
+       0,
+       (dstat_t *)0,
+       drive_identify,
+       philips_attach,
+       philips_init,
+       philips_getdisktype,
+       philips_load,
+       philips_unload,
+       buf_dummy,
+       recovery_needed,
+       recover_philips,
+       speed_select_philips,
+       select_secsize,
+       next_wr_addr_philips,
+       reserve_track_philips,
+       scsi_cdr_write_philips,
+       (int(*)(track_t *, void *, BOOL))cmd_dummy,     /* gen_cue */
+       no_sendcue,
+       (int(*)(SCSI *, cdr_t *, track_t *))cmd_dummy, /* leadin */
+       open_track_philips,
+       close_track_philips,
+       (int(*)(SCSI *, cdr_t *, track_t *))cmd_dummy,
+       cmd_dummy,
+       cmd_dummy,                                      /* abort        */
+       read_session_offset_philips,
+       fixation_philips,
+       cmd_dummy,                                      /* stats        */
+       blank_dummy,
+       format_dummy,
+       (int(*)(SCSI *, caddr_t, int, int))NULL,        /* no OPC       */
+       cmd_dummy,                                      /* opt1         */
+       cmd_dummy,                                      /* opt2         */
+};
+
+cdr_t  cdr_kodak_pcd600 = {
+       0, 0,
+       CDR_TAO|CDR_TRAYLOAD,
+       CDR_CDRW_NONE,
+       6, 6,
+       "kodak_pcd_600",
+       "driver for Kodak PCD-600",
+       0,
+       (dstat_t *)0,
+       drive_identify,
+       philips_attach,
+       philips_init,
+       philips_getdisktype,
+       philips_load,
+       philips_unload,
+       buf_dummy,
+       recovery_needed,
+       recover_philips,
+       speed_select_philips,
+       select_secsize,
+       next_wr_addr_philips,
+       reserve_track_philips,
+       scsi_cdr_write_philips,
+       (int(*)(track_t *, void *, BOOL))cmd_dummy,     /* gen_cue */
+       no_sendcue,
+       (int(*)(SCSI *, cdr_t *, track_t *))cmd_dummy, /* leadin */
+       open_track_oldphilips,
+       close_track_philips,
+       (int(*)(SCSI *, cdr_t *, track_t *))cmd_dummy,
+       cmd_dummy,
+       cmd_dummy,                                      /* abort        */
+       read_session_offset_philips,
+       fixation_philips,
+       cmd_dummy,                                      /* stats        */
+       blank_dummy,
+       format_dummy,
+       (int(*)(SCSI *, caddr_t, int, int))NULL,        /* no OPC       */
+       cmd_dummy,                                      /* opt1         */
+       cmd_dummy,                                      /* opt2         */
+};
+
+cdr_t  cdr_plasmon_rf4100 = {
+       0, 0,
+       CDR_TAO|CDR_TRAYLOAD,
+       CDR_CDRW_NONE,
+       2, 4,
+       "plasmon_rf4100",
+       "driver for Plasmon RF 4100",
+       0,
+       (dstat_t *)0,
+       drive_identify,
+       plasmon_attach,
+       philips_init,
+       philips_getdisktype,
+       philips_load,
+       philips_unload,
+       plasmon_buf,
+       recovery_needed,
+       recover_philips,
+       speed_select_philips,
+       select_secsize,
+       next_wr_addr_philips,
+       reserve_track_philips,
+       scsi_cdr_write_philips,
+       (int(*)(track_t *, void *, BOOL))cmd_dummy,     /* gen_cue */
+       no_sendcue,
+       (int(*)(SCSI *, cdr_t *, track_t *))cmd_dummy, /* leadin */
+       open_track_plasmon,
+       close_track_philips,
+       (int(*)(SCSI *, cdr_t *, track_t *))cmd_dummy,
+       cmd_dummy,
+       cmd_dummy,                                      /* abort        */
+       read_session_offset_philips,
+       fixation_philips,
+       cmd_dummy,                                      /* stats        */
+       blank_dummy,
+       format_dummy,
+       (int(*)(SCSI *, caddr_t, int, int))NULL,        /* no OPC       */
+       cmd_dummy,                                      /* opt1         */
+       cmd_dummy,                                      /* opt2         */
+};
+
+cdr_t  cdr_pioneer_dw_s114x = {
+       0, 0,
+       CDR_TAO|CDR_TRAYLOAD|CDR_SWABAUDIO,
+       CDR_CDRW_NONE,
+       2, 4,
+       "pioneer_dws114x",
+       "driver for Pioneer DW-S114X",
+       0,
+       (dstat_t *)0,
+       drive_identify,
+       philips_attach,
+       philips_init,
+       philips_getdisktype,
+       scsi_load,
+       scsi_unload,
+       buf_dummy,
+       recovery_needed,
+       recover_philips,
+       speed_select_pioneer,
+       select_secsize,
+       next_wr_addr_philips,
+       reserve_track_philips,
+       scsi_cdr_write_philips,
+       (int(*)(track_t *, void *, BOOL))cmd_dummy,     /* gen_cue */
+       no_sendcue,
+       (int(*)(SCSI *, cdr_t *, track_t *))cmd_dummy, /* leadin */
+/*     open_track_yamaha,*/
+/*???*/        open_track_oldphilips,
+       close_track_philips,
+       (int(*)(SCSI *, cdr_t *, track_t *))cmd_dummy,
+       cmd_dummy,
+       cmd_dummy,                                      /* abort        */
+       read_session_offset_philips,
+       fixation_philips,
+       cmd_dummy,                                      /* stats        */
+       blank_dummy,
+       format_dummy,
+       (int(*)(SCSI *, caddr_t, int, int))NULL,        /* no OPC       */
+       cmd_dummy,                                      /* opt1         */
+       cmd_dummy,                                      /* opt2         */
+};
+
+cdr_t  cdr_yamaha_cdr100 = {
+       0, 0,
+/*     CDR_TAO|CDR_SAO|CDR_CADDYLOAD|CDR_SWABAUDIO,*/
+       CDR_TAO|CDR_CADDYLOAD|CDR_SWABAUDIO,
+       CDR_CDRW_NONE,
+       2, 4,
+       "yamaha_cdr100",
+       "driver for Yamaha CDR-100 / CDR-102",
+       0,
+       (dstat_t *)0,
+       drive_identify,
+       philips_attach,
+       philips_init,
+       drive_getdisktype,
+       scsi_load,
+       philips_unload,
+       buf_dummy,
+       recovery_needed,
+       recover_philips,
+       speed_select_yamaha,
+       select_secsize,
+       next_wr_addr_philips,
+       reserve_track_philips,
+       scsi_cdr_write_philips,
+       (int(*)(track_t *, void *, BOOL))cmd_dummy,     /* gen_cue */
+       no_sendcue,
+       (int(*)(SCSI *, cdr_t *, track_t *))cmd_dummy, /* leadin */
+       open_track_yamaha,
+       close_track_philips,
+       (int(*)(SCSI *, cdr_t *, track_t *))cmd_dummy,
+       cmd_dummy,
+       cmd_dummy,                                      /* abort        */
+       read_session_offset_philips,
+       fixation_philips,
+       cmd_dummy,                                      /* stats        */
+       blank_dummy,
+       format_dummy,
+       (int(*)(SCSI *, caddr_t, int, int))NULL,        /* no OPC       */
+       cmd_dummy,                                      /* opt1         */
+       cmd_dummy,                                      /* opt2         */
+};
+
+cdr_t  cdr_ricoh_ro1060 = {
+       0, 0,
+/*     CDR_TAO|CDR_SAO|CDR_CADDYLOAD,*/
+       CDR_TAO|CDR_CADDYLOAD,
+       CDR_CDRW_NONE,
+       2, 2,
+       "ricoh_ro1060c",
+       "driver for Ricoh RO-1060C",
+       0,
+       (dstat_t *)0,
+       drive_identify,
+       ricoh_attach,
+       philips_init,
+       philips_getdisktype,
+       scsi_load,
+       scsi_unload,
+       buf_dummy,
+       recovery_needed,
+       recover_philips,
+       speed_select_yamaha,
+       select_secsize,
+       next_wr_addr_philips,
+       reserve_track_philips,
+       scsi_cdr_write_philips,
+       (int(*)(track_t *, void *, BOOL))cmd_dummy,     /* gen_cue */
+       no_sendcue,
+       (int(*)(SCSI *, cdr_t *, track_t *))cmd_dummy, /* leadin */
+       open_track_philips,
+       close_track_philips,
+       (int(*)(SCSI *, cdr_t *, track_t *))cmd_dummy,
+       cmd_dummy,
+       cmd_dummy,                                      /* abort        */
+       read_session_offset_philips,
+       fixation_philips,
+       cmd_dummy,                                      /* stats        */
+       blank_dummy,
+       format_dummy,
+       (int(*)(SCSI *, caddr_t, int, int))NULL,        /* no OPC       */
+       cmd_dummy,                                      /* opt1         */
+       cmd_dummy,                                      /* opt2         */
+};
+
+cdr_t  cdr_ricoh_ro1420 = {
+       0, 0,
+/*     CDR_TAO|CDR_SAO|CDR_CADDYLOAD,*/
+       CDR_TAO|CDR_CADDYLOAD,
+       CDR_CDRW_NONE,
+       2, 2,
+       "ricoh_ro1420c",
+       "driver for Ricoh RO-1420C",
+       0,
+       (dstat_t *)0,
+       drive_identify,
+       ricoh_attach,
+       philips_init,
+       philips_getdisktype,
+       scsi_load,
+       scsi_unload,
+       buf_dummy,
+       recovery_needed,
+       recover_philips,
+       speed_select_yamaha,
+       select_secsize,
+       next_wr_addr_philips,
+       reserve_track_philips,
+       scsi_cdr_write_philips,
+       (int(*)(track_t *, void *, BOOL))cmd_dummy,     /* gen_cue */
+       no_sendcue,
+       (int(*)(SCSI *, cdr_t *, track_t *))cmd_dummy, /* leadin */
+       open_track_philips,
+       close_track_philips,
+       (int(*)(SCSI *, cdr_t *, track_t *))cmd_dummy,
+       cmd_dummy,
+       cmd_dummy,                                      /* abort        */
+       read_session_offset_philips,
+       fixation_philips,
+       cmd_dummy,                                      /* stats        */
+       blank_dummy,
+       format_dummy,
+       (int(*)(SCSI *, caddr_t, int, int))NULL,        /* no OPC       */
+       cmd_dummy,                                      /* opt1         */
+       cmd_dummy,                                      /* opt2         */
+};
+
+
+static int load_unload_philips(SCSI *usalp, int load)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->flags = SCG_DISRE_ENA;
+       scmd->cdb_len = SC_G1_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+       scmd->cdb.g1_cdb.cmd = 0xE7;
+       scmd->cdb.g1_cdb.lun = usal_lun(usalp);
+       scmd->cdb.g1_cdb.count[1] = !load;
+
+       usalp->cmdname = "philips medium load/unload";
+
+       if (usal_cmd(usalp) < 0)
+               return (-1);
+       return (0);
+}
+
+static int 
+philips_load(SCSI *usalp, cdr_t *dp)
+{
+       return (load_unload_philips(usalp, 1));
+}
+
+static int 
+philips_unload(SCSI *usalp, cdr_t *dp)
+{
+       return (load_unload_philips(usalp, 0));
+}
+
+static int 
+philips_dumbload(SCSI *usalp, cdr_t *dp)
+{
+       int     ret;
+
+       usalp->silent++;
+       ret = load_unload_philips(usalp, 1);
+       usalp->silent--;
+       if (ret < 0)
+               return (scsi_load(usalp, dp));
+       return (0);
+}
+
+static int 
+philips_dumbunload(SCSI *usalp, cdr_t *dp)
+{
+       int     ret;
+
+       usalp->silent++;
+       ret = load_unload_philips(usalp, 0);
+       usalp->silent--;
+       if (ret < 0)
+               return (scsi_unload(usalp, dp));
+       return (0);
+}
+
+static int 
+plasmon_buf(SCSI *usalp, 
+            long *sp /* Size pointer */, 
+            long *fp /* Free space pointer */)
+{
+       /*
+        * There's no way to obtain these values from the
+        * Plasmon RF41xx devices.  This function stub is only
+        * present to prevent cdrecord.c from calling the READ BUFFER
+        * SCSI cmd which is implemented non standard compliant in
+        * the Plasmon drive. Calling READ BUFFER would only jam the Plasmon
+        * as the non standard implementation in the Plasmon firmware
+        * expects different parameters.
+        */
+
+       if (sp)
+               *sp = 0L;
+       if (fp)
+               *fp = 0L;
+
+       return (100);   /* 100 % */
+}
+
+static int 
+recover_philips(SCSI *usalp, cdr_t *dp, int track)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->flags = SCG_DISRE_ENA;
+       scmd->cdb_len = SC_G1_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+       scmd->cdb.g1_cdb.cmd = 0xEC;
+       scmd->cdb.g1_cdb.lun = usal_lun(usalp);
+
+       usalp->cmdname = "philips recover";
+
+       if (usal_cmd(usalp) < 0)
+               return (-1);
+       return (0);
+}
+
+static int 
+speed_select_yamaha(SCSI *usalp, cdr_t *dp, int *speedp)
+{
+       struct  scsi_mode_page_header   *mp;
+       char                            mode[256];
+       int                             len = 16;
+       int                             page = 0x31;
+       struct yamaha_mode_page_31      *xp;
+       struct cdd_52x_mode_data md;
+       int     count;
+       int     speed = 1;
+       BOOL    dummy = (dp->cdr_cmdflags & F_DUMMY) != 0;
+
+       if (speedp) {
+               speed = *speedp;
+       } else {
+               fillbytes((caddr_t)mode, sizeof (mode), '\0');
+
+               if (!get_mode_params(usalp, page, "Speed/Dummy information",
+                       (Uchar *)mode, (Uchar *)0, (Uchar *)0, (Uchar *)0, &len)) {
+                       return (-1);
+               }
+               if (len == 0)
+                       return (-1);
+
+               mp = (struct scsi_mode_page_header *)
+                       (mode + sizeof (struct scsi_mode_header) +
+                       ((struct scsi_mode_header *)mode)->blockdesc_len);
+
+               xp = (struct yamaha_mode_page_31 *)mp;
+               speed = xp->speed;
+       }
+
+       fillbytes((caddr_t)&md, sizeof (md), '\0');
+
+       count  = sizeof (struct scsi_mode_header) +
+               sizeof (struct yamaha_mode_page_31);
+
+       speed >>= 1;
+       md.pagex.page31.p_code = 0x31;
+       md.pagex.page31.p_len =  0x02;
+       md.pagex.page31.speed = speed;
+       md.pagex.page31.dummy = dummy?1:0;
+
+       return (mode_select(usalp, (Uchar *)&md, count, 0, usalp->inq->data_format >= 2));
+}
+
+static int 
+speed_select_philips(SCSI *usalp, cdr_t *dp, int *speedp)
+{
+       struct  scsi_mode_page_header   *mp;
+       char                            mode[256];
+       int                             len = 20;
+       int                             page = 0x23;
+       struct cdd_52x_mode_page_23     *xp;
+       struct cdd_52x_mode_data        md;
+       int                             count;
+       int                             speed = 1;
+       BOOL                            dummy = (dp->cdr_cmdflags & F_DUMMY) != 0;
+
+       if (speedp) {
+               speed = *speedp;
+       } else {
+               fillbytes((caddr_t)mode, sizeof (mode), '\0');
+
+               if (!get_mode_params(usalp, page, "Speed/Dummy information",
+                       (Uchar *)mode, (Uchar *)0, (Uchar *)0, (Uchar *)0, &len)) {
+                       return (-1);
+               }
+               if (len == 0)
+                       return (-1);
+
+               mp = (struct scsi_mode_page_header *)
+                       (mode + sizeof (struct scsi_mode_header) +
+                       ((struct scsi_mode_header *)mode)->blockdesc_len);
+
+               xp = (struct cdd_52x_mode_page_23 *)mp;
+               speed = xp->speed;
+       }
+
+       fillbytes((caddr_t)&md, sizeof (md), '\0');
+
+       count  = sizeof (struct scsi_mode_header) +
+               sizeof (struct cdd_52x_mode_page_23);
+
+       md.pagex.page23.p_code = 0x23;
+       md.pagex.page23.p_len =  0x06;
+       md.pagex.page23.speed = speed;
+       md.pagex.page23.dummy = dummy?1:0;
+
+       return (mode_select(usalp, (Uchar *)&md, count, 0, usalp->inq->data_format >= 2));
+}
+
+static int 
+speed_select_pioneer(SCSI *usalp, cdr_t *dp, int *speedp)
+{
+       if (speedp != 0 && *speedp < 2) {
+               *speedp = 2;
+               if (lverbose)
+                       printf("WARNING: setting to minimum speed (2).\n");
+       }
+       return (speed_select_philips(usalp, dp, speedp));
+}
+
+static int 
+speed_select_oldphilips(SCSI *usalp, cdr_t *dp, int *speedp)
+{
+       BOOL    dummy = (dp->cdr_cmdflags & F_DUMMY) != 0;
+
+       if (lverbose)
+               printf("WARNING: ignoring selected speed.\n");
+       if (dummy) {
+               errmsgno(EX_BAD, "Cannot set dummy writing for this device.\n");
+               return (-1);
+       }
+       return (0);
+}
+
+static int 
+speed_select_dumbphilips(SCSI *usalp, cdr_t *dp, int *speedp)
+{
+       if (speed_select_philips(usalp, dp, speedp) < 0)
+               return (speed_select_oldphilips(usalp, dp, speedp));
+       return (0);
+}
+
+static int 
+philips_init(SCSI *usalp, cdr_t *dp)
+{
+       return ((*dp->cdr_set_speed_dummy)(usalp, dp, NULL));
+}
+
+
+#define        IS(what, flag)  printf("  Is %s%s\n", flag?"":"not ", what);
+
+static int 
+philips_getdisktype(SCSI *usalp, cdr_t *dp)
+{
+       dstat_t *dsp = dp->cdr_dstat;
+       char    sbuf[16];
+       long    dummy;
+       long    lilen;
+       long    lolen;
+       msf_t   msf;
+       int     audio = -1;
+
+       usalp->silent++;
+       dummy = (*dp->cdr_next_wr_address)(usalp, (track_t *)0, &lilen);
+       usalp->silent--;
+
+       /*
+        * Check for "Command sequence error" first.
+        */
+       if ((dsp->ds_cdrflags & RF_WRITE) != 0 &&
+           dummy < 0 &&
+           (usal_sense_key(usalp) != SC_ILLEGAL_REQUEST ||
+                                               usal_sense_code(usalp) != 0x2C)) {
+               reload_media(usalp, dp);
+       }
+
+       usalp->silent++;
+       if (read_subchannel(usalp, sbuf, 0, 12, 0, 1, 0xf0) >= 0) {
+               if (sbuf[2] == 0 && sbuf[3] == 8)
+                       audio = (sbuf[7] & 0x40) != 0;
+       }
+       usalp->silent--;
+
+       if ((dp->cdr_dstat->ds_cdrflags & RF_PRATIP) != 0 &&
+                                               dummy >= 0 && lilen == 0) {
+               usalp->silent++;
+               dummy = philips_getlilo(usalp, &lilen, &lolen);
+               usalp->silent--;
+
+               if (dummy >= 0) {
+/*                     printf("lead-in len: %d lead-out len: %d\n", lilen, lolen);*/
+                       lba_to_msf(-150 - lilen, &msf);
+
+                       printf("ATIP info from disk:\n");
+                       if (audio >= 0)
+                               IS("unrestricted", audio);
+                       if (audio == 1 || (audio == 0 && (sbuf[7] & 0x3F) != 0x3F))
+                               printf("  Disk application code: %d\n", sbuf[7] & 0x3F);
+                       printf("  ATIP start of lead in:  %ld (%02d:%02d/%02d)\n",
+                               -150 - lilen, msf.msf_min, msf.msf_sec, msf.msf_frame);
+
+                       if (capacity_philips(usalp, &lolen)) {
+                               lba_to_msf(lolen, &msf);
+                               printf(
+                               "  ATIP start of lead out: %ld (%02d:%02d/%02d)\n",
+                               lolen, msf.msf_min, msf.msf_sec, msf.msf_frame);
+                       }
+                       lba_to_msf(-150 - lilen, &msf);
+                       pr_manufacturer(&msf,
+                                       FALSE,          /* Always not erasable */
+                                       audio > 0);     /* Audio from read subcode */
+               }
+       }
+
+       if (capacity_philips(usalp, &lolen)) {
+               dsp->ds_maxblocks = lolen;
+               dsp->ds_maxrblocks = disk_rcap(&msf, dsp->ds_maxblocks,
+                                       FALSE,          /* Always not erasable */
+                                       audio > 0);     /* Audio from read subcode */
+       }
+       usalp->silent++;
+       /*read_subchannel(usalp, bp, track, cnt, msf, subq, fmt); */
+
+       if (read_subchannel(usalp, sbuf, 0, 14, 0, 0, 0xf1) >= 0)
+               usal_prbytes("Disk bar code:", (Uchar *)sbuf, 14 - usal_getresid(usalp));
+       usalp->silent--;
+
+       return (drive_getdisktype(usalp, dp));
+}
+
+static BOOL 
+capacity_philips(SCSI *usalp, long *lp)
+{
+       long    l = 0L;
+       BOOL    succeed = TRUE;
+
+       usalp->silent++;
+       if (read_B0(usalp, FALSE, NULL, &l) >= 0) {
+               if (debug)
+                       printf("lead out B0: %ld\n", l);
+               *lp = l;
+       } else if (read_trackinfo(usalp, 0xAA, &l, NULL, NULL, NULL, NULL) >= 0) {
+               if (debug)
+                       printf("lead out AA: %ld\n", l);
+               *lp = l;
+       } if (read_capacity(usalp) >= 0) {
+               l = usalp->cap->c_baddr + 1;
+               if (debug)
+                       printf("lead out capacity: %ld\n", l);
+       } else {
+               succeed = FALSE;
+       }
+       *lp = l;
+       usalp->silent--;
+       return (succeed);
+}
+
+struct fwa {
+       char    len;
+       char    addr[4];
+       char    res;
+};
+
+static int 
+first_writable_addr_philips(SCSI *usalp, long *ap, int track, int isaudio, 
+                                                                               int preemp, int npa)
+{
+       struct  fwa     fwa;
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)&fwa, sizeof (fwa), '\0');
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->addr = (caddr_t)&fwa;
+       scmd->size = sizeof (fwa);
+       scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
+       scmd->cdb_len = SC_G1_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+       scmd->cdb.g1_cdb.cmd = 0xE2;
+       scmd->cdb.g1_cdb.lun = usal_lun(usalp);
+       scmd->cdb.g1_cdb.addr[0] = track;
+       scmd->cdb.g1_cdb.addr[1] = isaudio ? (preemp ? 5 : 4) : 1;
+
+       scmd->cdb.g1_cdb.count[0] = npa?1:0;
+       scmd->cdb.g1_cdb.count[1] = sizeof (fwa);
+
+       usalp->cmdname = "first writeable address philips";
+
+       if (usal_cmd(usalp) < 0)
+               return (-1);
+
+       if (ap)
+               *ap = a_to_4_byte(fwa.addr);
+       return (0);
+}
+
+static int 
+next_wr_addr_philips(SCSI *usalp, track_t *trackp, long *ap)
+{
+
+/*     if (first_writable_addr_philips(usalp, ap, 0, 0, 0, 1) < 0)*/
+       if (first_writable_addr_philips(usalp, ap, 0, 0, 0, 0) < 0)
+               return (-1);
+       return (0);
+}
+
+static int 
+reserve_track_philips(SCSI *usalp, unsigned long len)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->flags = SCG_DISRE_ENA;
+       scmd->cdb_len = SC_G1_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+       scmd->cdb.g1_cdb.cmd = 0xE4;
+       scmd->cdb.g1_cdb.lun = usal_lun(usalp);
+       i_to_4_byte(&scmd->cdb.g1_cdb.addr[3], len);
+
+       usalp->cmdname = "philips reserve_track";
+
+       if (usal_cmd(usalp) < 0)
+               return (-1);
+       return (0);
+}
+
+static int 
+scsi_cdr_write_philips(SCSI *usalp, 
+                       caddr_t bp       /* address of buffer */,
+                       long sectaddr    /* disk address (sector) to put */,
+                       long size        /* number of bytes to transfer */, 
+                       int blocks       /* sector count */, 
+                       BOOL islast      /* last write for track */)
+{
+       return (write_xg0(usalp, bp, 0, size, blocks));
+}
+
+static int 
+write_track_info_philips(SCSI *usalp, int sectype)
+{
+       struct cdd_52x_mode_data md;
+       int     count = sizeof (struct scsi_mode_header) +
+                       sizeof (struct cdd_52x_mode_page_21);
+
+       fillbytes((caddr_t)&md, sizeof (md), '\0');
+       md.pagex.page21.p_code = 0x21;
+       md.pagex.page21.p_len =  0x0E;
+                               /* is sectype ok ??? */
+       md.pagex.page21.sectype = sectype & ST_MASK;
+       md.pagex.page21.track = 0;      /* 0 : create new track */
+
+       return (mode_select(usalp, (Uchar *)&md, count, 0, usalp->inq->data_format >= 2));
+}
+
+static int 
+write_track_philips(SCSI *usalp, 
+                                                       long track /* track number 0 == new track */, 
+                       int sectype)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->flags = SCG_DISRE_ENA|SCG_CMD_RETRY;
+/*     scmd->flags = SCG_DISRE_ENA;*/
+       scmd->cdb_len = SC_G1_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+       scmd->cdb.g1_cdb.cmd = 0xE6;
+       scmd->cdb.g1_cdb.lun = usal_lun(usalp);
+       g1_cdbaddr(&scmd->cdb.g1_cdb, track);
+       scmd->cdb.g1_cdb.res6 = sectype & ST_MASK;
+
+       usalp->cmdname = "philips write_track";
+
+       if (usal_cmd(usalp) < 0)
+               return (-1);
+       return (0);
+}
+
+static int 
+open_track_philips(SCSI *usalp, cdr_t *dp, track_t *trackp)
+{
+       if (select_secsize(usalp, trackp->secsize) < 0)
+               return (-1);
+
+       if (write_track_info_philips(usalp, trackp->sectype) < 0)
+               return (-1);
+
+       if (write_track_philips(usalp, 0, trackp->sectype) < 0)
+               return (-1);
+
+       return (0);
+}
+
+static int 
+open_track_plasmon(SCSI *usalp, cdr_t *dp, track_t *trackp)
+{
+       if (select_secsize(usalp, trackp->secsize) < 0)
+               return (-1);
+
+       if (write_track_info_philips(usalp, trackp->sectype) < 0)
+               return (-1);
+
+       return (0);
+}
+
+static int 
+open_track_oldphilips(SCSI *usalp, cdr_t *dp, track_t *trackp)
+{
+       if (write_track_philips(usalp, 0, trackp->sectype) < 0)
+               return (-1);
+
+       return (0);
+}
+
+static int 
+open_track_yamaha(SCSI *usalp, cdr_t *dp, track_t *trackp)
+{
+       if (select_secsize(usalp, trackp->secsize) < 0)
+               return (-1);
+
+       if (write_track_philips(usalp, 0, trackp->sectype) < 0)
+               return (-1);
+
+       return (0);
+}
+
+static int 
+close_track_philips(SCSI *usalp, cdr_t *dp, track_t *trackp)
+{
+       return (scsi_flush_cache(usalp, FALSE));
+}
+
+static int fixation_philips(SCSI *usalp, cdr_t *dp, track_t *trackp)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->flags = SCG_DISRE_ENA;
+       scmd->cdb_len = SC_G1_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+       scmd->timeout = 8 * 60;         /* Needs up to 4 minutes */
+       scmd->cdb.g1_cdb.cmd = 0xE9;
+       scmd->cdb.g1_cdb.lun = usal_lun(usalp);
+       scmd->cdb.g1_cdb.count[1] =
+                       ((track_base(trackp)->tracktype & TOCF_MULTI) ? 8 : 0) |
+                       (track_base(trackp)->tracktype & TOC_MASK);
+
+       usalp->cmdname = "philips fixation";
+
+       if (usal_cmd(usalp) < 0)
+               return (-1);
+       return (0);
+}
+
+static const char *sd_cdd_521_error_str[] = {
+       "\003\000tray out",                             /* 0x03 */
+       "\062\000write data error with CU",             /* 0x32 */      /* Yamaha */
+       "\063\000monitor atip error",                   /* 0x33 */
+       "\064\000absorbtion control error",             /* 0x34 */
+#ifdef YAMAHA_CDR_100
+       /* Is this the same ??? */
+       "\120\000write operation in progress",          /* 0x50 */
+#endif
+       "\127\000unable to read TOC/PMA/Subcode/ATIP",  /* 0x57 */
+       "\132\000operator medium removal request",      /* 0x5a */
+       "\145\000verify failed",                        /* 0x65 */
+       "\201\000illegal track number",                 /* 0x81 */
+       "\202\000command now not valid",                /* 0x82 */
+       "\203\000medium removal is prevented",          /* 0x83 */
+       "\204\000tray out",                             /* 0x84 */
+       "\205\000track at one not in PMA",              /* 0x85 */
+       "\240\000stopped on non data block",            /* 0xa0 */
+       "\241\000invalid start adress",                 /* 0xa1 */
+       "\242\000attampt to cross track-boundary",      /* 0xa2 */
+       "\243\000illegal medium",                       /* 0xa3 */
+       "\244\000disk write protected",                 /* 0xa4 */
+       "\245\000application code conflict",            /* 0xa5 */
+       "\246\000illegal blocksize for command",        /* 0xa6 */
+       "\247\000blocksize conflict",                   /* 0xa7 */
+       "\250\000illegal transfer length",              /* 0xa8 */
+       "\251\000request for fixation failed",          /* 0xa9 */
+       "\252\000end of medium reached",                /* 0xaa */
+#ifdef REAL_CDD_521
+       "\253\000non reserved reserved track",          /* 0xab */
+#else
+       "\253\000illegal track number",                 /* 0xab */
+#endif
+       "\254\000data track length error",              /* 0xac */
+       "\255\000buffer under run",                     /* 0xad */
+       "\256\000illegal track mode",                   /* 0xae */
+       "\257\000optical power calibration error",      /* 0xaf */
+       "\260\000calibration area almost full",         /* 0xb0 */
+       "\261\000current program area empty",           /* 0xb1 */
+       "\262\000no efm at search address",             /* 0xb2 */
+       "\263\000link area encountered",                /* 0xb3 */
+       "\264\000calibration area full",                /* 0xb4 */
+       "\265\000dummy data blocks added",              /* 0xb5 */
+       "\266\000block size format conflict",           /* 0xb6 */
+       "\267\000current command aborted",              /* 0xb7 */
+       "\270\000program area not empty",               /* 0xb8 */
+#ifdef YAMAHA_CDR_100
+       /* Used while writing lead in in DAO */
+       "\270\000write leadin in progress",             /* 0xb8 */
+#endif
+       "\271\000parameter list too large",             /* 0xb9 */
+       "\277\000buffer overflow",                      /* 0xbf */      /* Yamaha */
+       "\300\000no barcode available",                 /* 0xc0 */
+       "\301\000barcode reading error",                /* 0xc1 */
+       "\320\000recovery needed",                      /* 0xd0 */
+       "\321\000cannot recover track",                 /* 0xd1 */
+       "\322\000cannot recover pma",                   /* 0xd2 */
+       "\323\000cannot recover leadin",                /* 0xd3 */
+       "\324\000cannot recover leadout",               /* 0xd4 */
+       "\325\000cannot recover opc",                   /* 0xd5 */
+       "\326\000eeprom failure",                       /* 0xd6 */
+       "\340\000laser current over",                   /* 0xe0 */      /* Yamaha */
+       "\341\000servo adjustment over",                /* 0xe0 */      /* Yamaha */
+       NULL
+};
+
+static const char *sd_ro1420_error_str[] = {
+       "\004\000logical unit is in process of becoming ready", /* 04 00 */
+       "\011\200radial skating error",                         /* 09 80 */
+       "\011\201sledge servo failure",                         /* 09 81 */
+       "\011\202pll no lock",                                  /* 09 82 */
+       "\011\203servo off track",                              /* 09 83 */
+       "\011\204atip sync error",                              /* 09 84 */
+       "\011\205atip/subcode jumped error",                    /* 09 85 */
+       "\127\300subcode not found",                            /* 57 C0 */
+       "\127\301atip not found",                               /* 57 C1 */
+       "\127\302no atip or subcode",                           /* 57 C2 */
+       "\127\303pma error",                                    /* 57 C3 */
+       "\127\304toc read error",                               /* 57 C4 */
+       "\127\305disk informatoion error",                      /* 57 C5 */
+       "\144\200read in leadin",                               /* 64 80 */
+       "\144\201read in leadout",                              /* 64 81 */
+       "\201\000illegal track",                                /* 81 00 */
+       "\202\000command not now valid",                        /* 82 00 */
+       "\220\000reserve track check error",                    /* 90 00 */
+       "\220\001verify blank error",                           /* 90 01 */
+       "\221\001mode of last track error",                     /* 91 01 */
+       "\222\000header search error",                          /* 92 00 */
+       "\230\001header monitor error",                         /* 98 01 */
+       "\230\002edc error",                                    /* 98 02 */
+       "\230\003read link, run-in run-out",                    /* 98 03 */
+       "\230\004last one block error",                         /* 98 04 */
+       "\230\005illegal blocksize",                            /* 98 05 */
+       "\230\006not all data transferred",                     /* 98 06 */
+       "\230\007cdbd over run error",                          /* 98 07 */
+       "\240\000stopped on non_data block",                    /* A0 00 */
+       "\241\000invalid start address",                        /* A1 00 */
+       "\243\000illegal medium",                               /* A3 00 */
+       "\246\000illegal blocksize for command",                /* A6 00 */
+       "\251\000request for fixation failed",                  /* A9 00 */
+       "\252\000end of medium reached",                        /* AA 00 */
+       "\253\000illegal track number",                         /* AB 00 */
+       "\255\000buffer underrun",                              /* AD 00 */
+       "\256\000illegal track mode",                           /* AE 00 */
+       "\257\200power range error",                            /* AF 80 */
+       "\257\201moderation error",                             /* AF 81 */
+       "\257\202beta upper range error",                       /* AF 82 */
+       "\257\203beta lower range error",                       /* AF 83 */
+       "\257\204alpha upper range error",                      /* AF 84 */
+       "\257\205alpha lower range error",                      /* AF 85 */
+       "\257\206alpha and power range error",                  /* AF 86 */
+       "\260\000calibration area almost full",                 /* B0 00 */
+       "\261\000current program area empty",                   /* B1 00 */
+       "\262\000no efm at search address",                     /* B2 00 */
+       "\264\000calibration area full",                        /* B4 00 */
+       "\265\000dummy blocks added",                           /* B5 00 */
+       "\272\000write audio on reserved track",                /* BA 00 */
+       "\302\200syscon rom error",                             /* C2 80 */
+       "\302\201syscon ram error",                             /* C2 81 */
+       "\302\220efm encoder error",                            /* C2 90 */
+       "\302\221efm decoder error",                            /* C2 91 */
+       "\302\222servo ic error",                               /* C2 92 */
+       "\302\223motor controller error",                       /* C2 93 */
+       "\302\224dac error",                                    /* C2 94 */
+       "\302\225syscon eeprom error",                          /* C2 95 */
+       "\302\240block decoder communication error",            /* C2 A0 */
+       "\302\241block encoder communication error",            /* C2 A1 */
+       "\302\242block encoder/decoder path error",             /* C2 A2 */
+       "\303\000CD-R engine selftest error",                   /* C3 xx */
+       "\304\000buffer parity error",                          /* C4 00 */
+       "\305\000data transfer error",                          /* C5 00 */
+       "\340\00012V failure",                                  /* E0 00 */
+       "\341\000undefined syscon error",                       /* E1 00 */
+       "\341\001syscon communication error",                   /* E1 01 */
+       "\341\002unknown syscon error",                         /* E1 02 */
+       "\342\000syscon not ready",                             /* E2 00 */
+       "\343\000command rejected",                             /* E3 00 */
+       "\344\000command not accepted",                         /* E4 00 */
+       "\345\000verify error at beginning of track",           /* E5 00 */
+       "\345\001verify error at ending of track",              /* E5 01 */
+       "\345\002verify error at beginning of lead-in",         /* E5 02 */
+       "\345\003verify error at ending of lead-in",            /* E5 03 */
+       "\345\004verify error at beginning of lead-out",        /* E5 04 */
+       "\345\005verify error at ending of lead-out",           /* E5 05 */
+       "\377\000command phase timeout error",                  /* FF 00 */
+       "\377\001data in phase timeout error",                  /* FF 01 */
+       "\377\002data out phase timeout error",                 /* FF 02 */
+       "\377\003status phase timeout error",                   /* FF 03 */
+       "\377\004message in phase timeout error",               /* FF 04 */
+       "\377\005message out phase timeout error",              /* FF 05 */
+       NULL
+};
+
+static int 
+philips_attach(SCSI *usalp, cdr_t *dp)
+{
+       usal_setnonstderrs(usalp, sd_cdd_521_error_str);
+       return (0);
+}
+
+static int 
+plasmon_attach(SCSI *usalp, cdr_t *dp)
+{
+       usalp->inq->data_format = 1;    /* Correct the ly */
+
+       usal_setnonstderrs(usalp, sd_cdd_521_error_str);
+       return (0);
+}
+
+static int 
+ricoh_attach(SCSI *usalp, cdr_t *dp)
+{
+       if (dp == &cdr_ricoh_ro1060) {
+               errmsgno(EX_BAD, "No support for Ricoh RO-1060C\n");
+               return (-1);
+       }
+       usal_setnonstderrs(usalp, sd_ro1420_error_str);
+       return (0);
+}
+
+static int 
+philips_getlilo(SCSI *usalp, long *lilenp, long *lolenp)
+{
+       char    buf[4];
+       long    li, lo;
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->addr = buf;
+       scmd->size = sizeof (buf);
+       scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
+       scmd->cdb_len = SC_G1_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+       scmd->cdb.g1_cdb.cmd = 0xEE;    /* Read session info */
+       scmd->cdb.g1_cdb.lun = usal_lun(usalp);
+       g1_cdblen(&scmd->cdb.g1_cdb, sizeof (buf));
+
+       usalp->cmdname = "philips read session info";
+
+       if (usal_cmd(usalp) < 0)
+               return (-1);
+
+       if (usalp->verbose)
+               usal_prbytes("Session info data: ", (Uchar *)buf, sizeof (buf) - usal_getresid(usalp));
+
+       li = a_to_u_2_byte(buf);
+       lo = a_to_u_2_byte(&buf[2]);
+
+       if (lilenp)
+               *lilenp = li;
+       if (lolenp)
+               *lolenp = lo;
+
+       return (0);
+}
diff --git a/wodim/drv_simul.c b/wodim/drv_simul.c
new file mode 100644 (file)
index 0000000..f7f7e06
--- /dev/null
@@ -0,0 +1,393 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)drv_simul.c     1.48 05/05/16 Copyright 1998-2005 J. Schilling */
+/*
+ *     Simulation device driver
+ *
+ *     Copyright (c) 1998-2005 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef        DEBUG
+#define        DEBUG
+#endif
+#include <mconfig.h>
+
+#include <stdio.h>
+#include <standard.h>
+#include <stdxlib.h>
+#include <unixstd.h>
+#include <errno.h>
+#include <strdefs.h>
+#include <timedefs.h>
+#include <utypes.h>
+#include <btorder.h>
+#include <schily.h>
+
+/*#include <usalio.h>*/
+#include <usal/scsidefs.h>
+#include <usal/scsireg.h>
+#include <usal/scsitransp.h>
+
+#include <libport.h>
+
+#include "wodim.h"
+
+extern int     silent;
+extern int     verbose;
+extern int     lverbose;
+
+static int     simul_load(SCSI *usalp, cdr_t *);
+static int     simul_unload(SCSI *usalp, cdr_t *);
+static cdr_t   *identify_simul(SCSI *usalp, cdr_t *, struct scsi_inquiry *);
+static int     init_simul(SCSI *usalp, cdr_t *dp);
+static int     getdisktype_simul(SCSI *usalp, cdr_t *dp);
+static int     speed_select_simul(SCSI *usalp, cdr_t *dp, int *speedp);
+static int     next_wr_addr_simul(SCSI *usalp, track_t *trackp, long *ap);
+static int     cdr_write_simul(SCSI *usalp, caddr_t bp, long sectaddr, long size, 
+                                                                                int blocks, BOOL islast);
+static int     open_track_simul(SCSI *usalp, cdr_t *dp, track_t *trackp);
+static int     close_track_simul(SCSI *usalp, cdr_t *dp, track_t *trackp);
+static int     open_session_simul(SCSI *usalp, cdr_t *dp, track_t *trackp);
+static int     fixate_simul(SCSI *usalp, cdr_t *dp, track_t *trackp);
+static void    tv_sub(struct timeval *tvp1, struct timeval *tvp2);
+
+static int simul_load(SCSI *usalp, cdr_t *dp)
+{
+       return (0);
+}
+
+static int simul_unload(SCSI *usalp, cdr_t *dp)
+{
+       return (0);
+}
+
+cdr_t  cdr_cdr_simul = {
+       0, 0,
+       CDR_TAO|CDR_SAO|CDR_PACKET|CDR_RAW|CDR_RAW16|CDR_RAW96P|CDR_RAW96R|CDR_SRAW96P|CDR_SRAW96R|CDR_TRAYLOAD|CDR_SIMUL,
+       CDR_CDRW_ALL,
+       40, 372,
+       "cdr_simul",
+       "simulation CD-R driver for timing/speed tests",
+       0,
+       (dstat_t *)0,
+       identify_simul,
+       drive_attach,
+       init_simul,
+       getdisktype_simul,
+       simul_load,
+       simul_unload,
+       buf_dummy,
+       cmd_dummy,                                      /* recovery_needed */
+       (int(*)(SCSI *, cdr_t *, int))cmd_dummy,        /* recover      */
+       speed_select_simul,
+       select_secsize,
+       next_wr_addr_simul,
+       (int(*)(SCSI *, Ulong))cmd_ill, /* reserve_track        */
+       cdr_write_simul,
+       (int(*)(track_t *, void *, BOOL))cmd_dummy,     /* gen_cue */
+       (int(*)(SCSI *usalp, cdr_t *, track_t *))cmd_dummy, /* send_cue */
+       (int(*)(SCSI *, cdr_t *, track_t *))cmd_dummy, /* leadin */
+       open_track_simul,
+       close_track_simul,
+       open_session_simul,
+       cmd_dummy,
+       cmd_dummy,                                      /* abort        */
+       read_session_offset,
+       fixate_simul,
+       cmd_dummy,                                      /* stats        */
+       blank_dummy,
+       format_dummy,
+       (int(*)(SCSI *, caddr_t, int, int))NULL,        /* no OPC       */
+       cmd_dummy,                                      /* opt1         */
+       cmd_dummy,                                      /* opt2         */
+};
+
+cdr_t  cdr_dvd_simul = {
+       0, 0,
+       CDR_TAO|CDR_SAO|CDR_PACKET|CDR_RAW|CDR_RAW16|CDR_RAW96P|CDR_RAW96R|CDR_SRAW96P|CDR_SRAW96R|CDR_DVD|CDR_TRAYLOAD|CDR_SIMUL,
+       CDR_CDRW_ALL,
+       2, 1000,
+       "dvd_simul",
+       "simulation DVD-R driver for timing/speed tests",
+       0,
+       (dstat_t *)0,
+       identify_simul,
+       drive_attach,
+       init_simul,
+       getdisktype_simul,
+       simul_load,
+       simul_unload,
+       buf_dummy,
+       cmd_dummy,                                      /* recovery_needed */
+       (int(*)(SCSI *, cdr_t *, int))cmd_dummy,        /* recover      */
+       speed_select_simul,
+       select_secsize,
+       next_wr_addr_simul,
+       (int(*)(SCSI *, Ulong))cmd_ill, /* reserve_track        */
+       cdr_write_simul,
+       (int(*)(track_t *, void *, BOOL))cmd_dummy,     /* gen_cue */
+       (int(*)(SCSI *usalp, cdr_t *, track_t *))cmd_dummy, /* send_cue */
+       (int(*)(SCSI *, cdr_t *, track_t *))cmd_dummy, /* leadin */
+       open_track_simul,
+       close_track_simul,
+       open_session_simul,
+       cmd_dummy,
+       cmd_dummy,                                      /* abort        */
+       read_session_offset,
+       fixate_simul,
+       cmd_dummy,                                      /* stats        */
+       blank_dummy,
+       format_dummy,
+       (int(*)(SCSI *, caddr_t, int, int))NULL,        /* no OPC       */
+       cmd_dummy,                                      /* opt1         */
+       cmd_dummy,                                      /* opt2         */
+};
+
+static cdr_t *
+identify_simul(SCSI *usalp, cdr_t *dp, struct scsi_inquiry *ip)
+{
+       return (dp);
+}
+
+static long    simul_nwa;
+static int     simul_speed = 1;
+static int     simul_dummy;
+static int     simul_isdvd;
+static int     simul_bufsize = 1024;
+static Uint    sleep_rest;
+static Uint    sleep_max;
+static Uint    sleep_min;
+
+static int
+init_simul(SCSI *usalp, cdr_t *dp)
+{
+       return (speed_select_simul(usalp, dp, NULL));
+}
+
+static int
+getdisktype_simul(SCSI *usalp, cdr_t *dp)
+{
+       dstat_t *dsp = dp->cdr_dstat;
+
+       if (strcmp(dp->cdr_drname, cdr_cdr_simul.cdr_drname) == 0) {
+               dsp->ds_maxblocks = 333000;
+               simul_isdvd = FALSE;
+       } else {
+               dsp->ds_maxblocks = 2464153;    /* 4.7 GB  */
+/*             dsp->ds_maxblocks = 1927896;*/  /* 3.95 GB */
+               dsp->ds_flags |= DSF_DVD;
+               simul_isdvd = TRUE;
+       }
+       return (drive_getdisktype(usalp, dp));
+}
+
+
+static int
+speed_select_simul(SCSI *usalp, cdr_t *dp, int *speedp)
+{
+       long    val;
+       char    *p;
+       BOOL    dummy = (dp->cdr_cmdflags & F_DUMMY) != 0;
+
+       if (speedp)
+               simul_speed = *speedp;
+       simul_dummy = dummy;
+
+       if ((p = getenv("CDR_SIMUL_BUFSIZE")) != NULL) {
+               if (getnum(p, &val) == 1)
+                       simul_bufsize = val / 1024;
+       }
+
+       /*
+        * sleep_max is the time to empty the drive's buffer in Âµs.
+        * sector size is from 2048 bytes to 2352 bytes.
+        * If sector size is 2048 bytes, 1k takes 6.666 ms.
+        * If sector size is 2352 bytes, 1k takes 5.805 ms.
+        * We take the 6 ms as an average between both values.
+        * simul_bufsize is the number of kilobytes in drive buffer.
+        */
+       sleep_max = 6 * 1000 * simul_bufsize / simul_speed;
+
+       /*
+        * DVD single speed is 1385 * 1000 Bytes/s (676.27 sectors/s)
+        */
+       if ((dp->cdr_flags & CDR_DVD) != 0)
+               sleep_max = 739 * simul_bufsize / simul_speed;
+
+       if (lverbose) {
+               printf("Simulation drive buffer size: %d KB\n", simul_bufsize);
+               printf("Maximum reserve time in drive buffer: %d.%3.3d ms for speed %dx\n",
+                                       sleep_max / 1000,
+                                       sleep_max % 1000,
+                                       simul_speed);
+       }
+       return (0);
+}
+
+static int
+next_wr_addr_simul(SCSI *usalp, track_t *trackp, long *ap)
+{
+       /*
+        * This will most likely not 100% correct for TAO CDs
+        * but it is better than returning 0 in all cases.
+        */
+       if (ap)
+               *ap = simul_nwa;
+       return (0);
+}
+
+
+static int
+cdr_write_simul(SCSI *usalp, caddr_t bp /* address of buffer */, 
+                long sectaddr   /* disk address (sector) to put */, 
+                long size       /* number of bytes to transfer */, 
+                int blocks      /* sector count */, 
+                BOOL islast     /* last write for track */)
+{
+       Uint    sleep_time;
+       Uint    sleep_diff;
+
+       struct timeval  tv1;
+    static     struct timeval  tv2;
+
+       if (lverbose > 1 && islast)
+               printf("\nWriting last record for this track.\n");
+
+       simul_nwa += blocks;
+
+       gettimeofday(&tv1, (struct timezone *)0);
+       if (tv2.tv_sec != 0) {          /* Already did gettimeofday(&tv2) */
+               tv_sub(&tv1, &tv2);
+               if (sleep_rest != 0) {
+                       sleep_diff = tv1.tv_sec * 1000000 + tv1.tv_usec;
+
+                       if (sleep_min > (sleep_rest - sleep_diff))
+                               sleep_min = (sleep_rest - sleep_diff);
+
+                       if (sleep_diff > sleep_rest) {
+                               printf("\aBuffer underrun: actual delay was %d.%3.3d ms, max delay was %d.%3.3d ms.\n",
+                                               sleep_diff / 1000,
+                                               sleep_diff % 1000,
+                                               sleep_rest / 1000,
+                                               sleep_rest % 1000);
+                               if (!simul_dummy)
+                                       return (-1);
+                       }
+                       /*
+                        * If we spent time outside the write function
+                        * subtract this time.
+                        */
+                       sleep_diff = tv1.tv_sec * 1000000 + tv1.tv_usec;
+                       if (sleep_rest >= sleep_diff)
+                               sleep_rest -= sleep_diff;
+                       else
+                               sleep_rest = 0;
+               }
+       }
+       /*
+        * Speed 1 ist 150 Sektoren/s
+        * Bei DVD 767.27 Sektoren/s
+        */
+       sleep_time = 1000000 * blocks / 75 / simul_speed;
+       if (simul_isdvd)
+               sleep_time = 1000000 * blocks / 676 / simul_speed;
+
+       sleep_time += sleep_rest;
+
+       if (sleep_time > sleep_max) {
+               int     mod;
+               long    rsleep;
+
+               sleep_rest = sleep_max;
+               sleep_time -= sleep_rest;
+               mod = sleep_time % 20000;
+               sleep_rest += mod;
+               sleep_time -= mod;
+               if (sleep_time > 0) {
+                       gettimeofday(&tv1, (struct timezone *)0);
+                       usleep(sleep_time);
+                       gettimeofday(&tv2, (struct timezone *)0);
+                       tv2.tv_sec -= tv1.tv_sec;
+                       tv2.tv_usec -= tv1.tv_usec;
+                       rsleep = tv2.tv_sec * 1000000 + tv2.tv_usec;
+                       sleep_rest -= rsleep - sleep_time;
+               }
+       } else {
+               sleep_rest = sleep_time;
+       }
+
+       gettimeofday(&tv2, (struct timezone *)0);
+       return (size);
+}
+
+static int
+open_track_simul(SCSI *usalp, cdr_t *dp, track_t *trackp)
+{
+       sleep_min = 999 * 1000000;
+       return (0);
+}
+
+static int
+close_track_simul(SCSI *usalp, cdr_t *dp, track_t *trackp)
+{
+       if (lverbose) {
+               printf("Remaining reserve time in drive buffer: %d.%3.3d ms\n",
+                                       sleep_rest / 1000,
+                                       sleep_rest % 1000);
+               printf("Minimum reserve time in drive buffer: %d.%3.3d ms\n",
+                                       sleep_min / 1000,
+                                       sleep_min % 1000);
+       }
+       usleep(sleep_rest);
+       sleep_rest = 0;
+       return (0);
+}
+
+static int
+open_session_simul(SCSI *usalp, cdr_t *dp, track_t *trackp)
+{
+       simul_nwa = 0L;
+       return (0);
+}
+
+static int
+fixate_simul(SCSI *usalp, cdr_t *dp, track_t *trackp)
+{
+       return (0);
+}
+
+static void
+tv_sub(struct timeval *tvp1, struct timeval *tvp2)
+{
+       tvp1->tv_sec -= tvp2->tv_sec;
+       tvp1->tv_usec -= tvp2->tv_usec;
+
+       while (tvp1->tv_usec < 0) {
+               tvp1->tv_usec += 1000000;
+               tvp1->tv_sec -= 1;
+       }
+}
diff --git a/wodim/drv_sony.c b/wodim/drv_sony.c
new file mode 100644 (file)
index 0000000..af8af68
--- /dev/null
@@ -0,0 +1,1364 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)drv_sony.c      1.72 05/05/16 Copyright 1997-2005 J. Schilling */
+/*
+ *     CDR device implementation for
+ *     Sony
+ *
+ *     Copyright (c) 1997-2005 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*#define      SONY_DEBUG*/
+
+#include <mconfig.h>
+
+#include <stdio.h>
+#include <stdxlib.h>
+#include <unixstd.h>   /* Include sys/types.h to make off_t available */
+#include <standard.h>
+#include <fctldefs.h>
+#include <errno.h>
+#include <strdefs.h>
+#include <timedefs.h>
+
+#include <utypes.h>
+#include <btorder.h>
+#include <intcvt.h>
+#include <schily.h>
+
+#include <usal/usalcmd.h>
+#include <usal/scsidefs.h>
+#include <usal/scsireg.h>
+#include <usal/scsitransp.h>
+
+#include "wodim.h"
+
+#ifdef SONY_DEBUG
+#      define          inc_verbose()   usalp->verbose++
+#      define          dec_verbose()   usalp->verbose--
+#else
+#      define          inc_verbose()
+#      define          dec_verbose()
+#endif
+
+extern int     debug;
+extern int     lverbose;
+
+#if defined(_BIT_FIELDS_LTOH)  /* Intel byteorder */
+
+struct sony_924_mode_page_20 { /* mastering information */
+               MP_P_CODE;              /* parsave & pagecode */
+       Uchar   p_len;                  /* 0x06 = 6 Bytes */
+       Uchar   subcode_header_off;
+       Ucbit   res3_0          : 1;
+       Ucbit   speudo          : 1;
+       Ucbit   res3_2          : 1;
+       Ucbit   c2po            : 1;
+       Ucbit   subcode_ecc     : 1;
+       Ucbit   res3_567        : 3;
+       Uchar   res_4;
+       Uchar   cue_sheet_opt;
+       Uchar   res[2];
+};
+
+#else                          /* Motorola byteorder */
+
+struct sony_924_mode_page_20 { /* mastering information */
+               MP_P_CODE;              /* parsave & pagecode */
+       Uchar   p_len;                  /* 0x06 = 6 Bytes */
+       Uchar   subcode_header_off;
+       Ucbit   res3_567        : 3;
+       Ucbit   subcode_ecc     : 1;
+       Ucbit   c2po            : 1;
+       Ucbit   res3_2          : 1;
+       Ucbit   speudo          : 1;
+       Ucbit   res3_0          : 1;
+       Uchar   res_4;
+       Uchar   cue_sheet_opt;
+       Uchar   res[2];
+};
+#endif
+
+struct sony_924_mode_page_22 { /* disk information */
+               MP_P_CODE;              /* parsave & pagecode */
+       Uchar   p_len;                  /* 0x1E = 30 Bytes */
+       Uchar   disk_style;
+       Uchar   disk_type;
+       Uchar   first_track;
+       Uchar   last_track;
+       Uchar   numsess;
+       Uchar   res_7;
+       Uchar   disk_appl_code[4];
+       Uchar   last_start_time[4];
+       Uchar   disk_status;
+       Uchar   num_valid_nra;
+       Uchar   track_info_track;
+       Uchar   post_gap;
+       Uchar   disk_id_code[4];
+       Uchar   lead_in_start[4];
+       Uchar   res[4];
+};
+
+struct sony_924_mode_page_23 { /* track information */
+               MP_P_CODE;              /* parsave & pagecode */
+       Uchar   p_len;                  /* 0x22 = 34 Bytes */
+       Uchar   res_2;
+       Uchar   track_num;
+       Uchar   data_form;
+       Uchar   write_method;
+       Uchar   session;
+       Uchar   track_status;
+       Uchar   start_lba[4];
+       Uchar   next_recordable_addr[4];
+       Uchar   blank_area_cap[4];
+       Uchar   fixed_packet_size[4];
+       Uchar   res_24;
+       Uchar   starting_msf[3];
+       Uchar   res_28;
+       Uchar   ending_msf[3];
+       Uchar   res_32;
+       Uchar   next_rec_time[3];
+};
+
+struct sony_924_mode_page_31 { /* drive speed */
+               MP_P_CODE;              /* parsave & pagecode */
+       Uchar   p_len;                  /* 0x02 = 2 Bytes */
+       Uchar   speed;
+       Uchar   res;
+};
+
+struct cdd_52x_mode_data {
+       struct scsi_mode_header header;
+       union cdd_pagex {
+               struct sony_924_mode_page_20    page_s20;
+               struct sony_924_mode_page_22    page_s22;
+               struct sony_924_mode_page_23    page_s23;
+               struct sony_924_mode_page_31    page_s31;
+       } pagex;
+};
+
+struct sony_write_parameter {
+       Uchar   res0;                   /* Reserved (must be zero)      */
+       Uchar   len;                    /* Parameter length 0x32 == 52  */
+       Uchar   res2;                   /* Reserved (must be zero)      */
+#if defined(_BIT_FIELDS_LTOH)  /* Intel byteorder */
+       Ucbit   res3_05         : 6;    /* Reserved                     */
+       Ucbit   ms              : 2;    /* Multi session mode           */
+#else                          /* Motorola byteorder */
+       Ucbit   ms              : 2;    /* Multi session mode           */
+       Ucbit   res3_05         : 6;    /* Reserved                     */
+#endif
+       Uchar   resx[12];
+#if defined(_BIT_FIELDS_LTOH)  /* Intel byteorder */
+       Ucbit   res16_06        : 7;    /* Reserved                     */
+       Ucbit   mcval           : 1;    /* MCN valid                    */
+#else                          /* Motorola byteorder */
+       Ucbit   mcval           : 1;    /* MCN valid                    */
+       Ucbit   res16_06        : 7;    /* Reserved                     */
+#endif
+       Uchar   mcn[15];
+#if defined(_BIT_FIELDS_LTOH)  /* Intel byteorder */
+       Ucbit   res32_06        : 7;    /* Reserved                     */
+       Ucbit   icval           : 1;    /* ISRC valid                   */
+#else                          /* Motorola byteorder */
+       Ucbit   icval           : 1;    /* ISRC valid                   */
+       Ucbit   res32_06        : 7;    /* Reserved                     */
+#endif
+       Uchar   isrc[15];
+       Uchar   subheader[4];
+};
+
+struct sony_cue {
+       Uchar   cs_ctladr;              /* CTL/ADR for this track       */
+       Uchar   cs_tno;                 /* This track number            */
+       Uchar   cs_index;               /* Index within this track      */
+       Uchar   cs_dataform;            /* Data form                    */
+                                       /* Bit 0..5 Main channel Format */
+                                       /* Bit 6..7 SubChannel format   */
+       Uchar   cs_zero;                /* Reserved or MCN/ISRC         */
+       Uchar   cs_min;                 /* Absolute time minutes        */
+       Uchar   cs_sec;                 /* Absolute time seconds        */
+       Uchar   cs_frame;               /* Absolute time frames         */
+};
+
+
+#define        strbeg(s1, s2)  (strstr((s2), (s1)) == (s2))
+
+static int     write_start_sony(SCSI *usalp, caddr_t bp, int size);
+static int     write_continue_sony(SCSI *usalp, caddr_t bp, long sectaddr, 
+                                                                                         long size, int blocks, BOOL islast);
+static int     discontinue_sony(SCSI *usalp);
+static int     write_track_sony(SCSI *usalp, long track, int sectype);
+static int     close_track_sony(SCSI *usalp, cdr_t *dp, track_t *trackp);
+static int     flush_sony(SCSI *usalp, int track);
+static int     finalize_sony(SCSI *usalp, cdr_t *dp, track_t *trackp);
+static int     recover_sony(SCSI *usalp, cdr_t *dp, int track);
+static int     set_wr_parameter_sony(SCSI *usalp, caddr_t bp, int size);
+static int     next_wr_addr_sony(SCSI *usalp, track_t *trackp, long *ap);
+static int     reserve_track_sony(SCSI *usalp, unsigned long len);
+static int     init_sony(SCSI *usalp, cdr_t *dp);
+static int     getdisktype_sony(SCSI *usalp, cdr_t *dp);
+static void    di_to_dstat_sony(struct sony_924_mode_page_22 *dip, 
+                                                                                 dstat_t *dsp);
+static int     speed_select_sony(SCSI *usalp, cdr_t *dp, int *speedp);
+static int     next_writable_address_sony(SCSI *usalp, long *ap, int track, 
+                                                                                                               int sectype, int tracktype);
+static int     new_track_sony(SCSI *usalp, int track, int sectype, 
+                                                                               int tracktype);
+static int     open_track_sony(SCSI *usalp, cdr_t *dp, track_t *trackp);
+static int     open_session_sony(SCSI *usalp, cdr_t *dp, track_t *trackp);
+static int     abort_session_sony(SCSI *usalp, cdr_t *dp);
+static int     get_page22_sony(SCSI *usalp, char *mode);
+static int     gen_cue_sony(track_t *trackp, void *vcuep, BOOL needgap);
+static void    fillcue(struct sony_cue *cp, int ca, int tno, int idx, int dataform, int scms, msf_t *mp);
+static int     send_cue_sony(SCSI *usalp, cdr_t *dp, track_t *trackp);
+static int     write_leadin_sony(SCSI *usalp, cdr_t *dp, track_t *trackp);
+static int     sony_attach(SCSI *usalp, cdr_t *dp);
+#ifdef SONY_DEBUG
+static void    print_sony_mp22(struct sony_924_mode_page_22 *xp, int len);
+static void    print_sony_mp23(struct sony_924_mode_page_23 *xp, int len);
+#endif
+static int     buf_cap_sony(SCSI *usalp, long *, long *);
+
+cdr_t  cdr_sony_cdu924 = {
+       0, 0,
+       CDR_TAO|CDR_SAO|CDR_CADDYLOAD|CDR_SWABAUDIO,
+       CDR_CDRW_NONE,
+       2, 4,
+       "sony_cdu924",
+       "driver for Sony CDU-924 / CDU-948",
+       0,
+       (dstat_t *)0,
+       drive_identify,
+       sony_attach,
+       init_sony,
+       getdisktype_sony,
+       scsi_load,
+       scsi_unload,
+       buf_cap_sony,
+       cmd_dummy,                                      /* recovery_needed */
+       recover_sony,
+       speed_select_sony,
+       select_secsize,
+       next_wr_addr_sony,
+       reserve_track_sony,
+       write_continue_sony,
+       gen_cue_sony,
+       send_cue_sony,
+       write_leadin_sony,
+       open_track_sony,
+       close_track_sony,
+       open_session_sony,
+       cmd_dummy,
+       abort_session_sony,
+       read_session_offset_philips,
+       finalize_sony,
+       cmd_dummy,                                      /* stats        */
+       blank_dummy,
+       format_dummy,
+       (int(*)(SCSI *, caddr_t, int, int))NULL,        /* no OPC       */
+       cmd_dummy,                                      /* opt1         */
+       cmd_dummy,                                      /* opt2         */
+};
+
+static int
+write_start_sony(SCSI *usalp, caddr_t bp, int size)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->addr = bp;
+       scmd->size = size;
+       scmd->flags = SCG_DISRE_ENA|SCG_CMD_RETRY;
+       scmd->cdb_len = SC_G1_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+       scmd->sense_len = 26;
+       scmd->cdb.g1_cdb.cmd = 0xE0;
+       scmd->cdb.g1_cdb.lun = usal_lun(usalp);
+       g0_cdbaddr(&scmd->cdb.g0_cdb, size); /* Hack, but Sony is silly */
+
+       usalp->cmdname = "write_start";
+
+       if (usal_cmd(usalp) < 0)
+               return (-1);
+       return (0);
+}
+
+static int
+write_continue_sony(SCSI *usalp, 
+                    caddr_t bp      /* address of buffer */, 
+                    long sectaddr   /* disk address (sector) to put */, 
+                    long size       /* number of bytes to transfer */, 
+                    int blocks      /* sector count */, 
+                    BOOL islast     /* last write for track */)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->addr = bp;
+       scmd->size = size;
+       scmd->flags = SCG_DISRE_ENA|SCG_CMD_RETRY;
+       scmd->cdb_len = SC_G1_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+       scmd->cdb.g1_cdb.cmd = 0xE1;
+       scmd->cdb.g1_cdb.lun = usal_lun(usalp);
+       g0_cdbaddr(&scmd->cdb.g0_cdb, size); /* Hack, but Sony is silly */
+
+       usalp->cmdname = "write_continue";
+
+       if (usal_cmd(usalp) < 0) {
+               /*
+                * XXX This seems to happen only sometimes.
+                */
+               if (usal_sense_code(usalp) != 0x80)
+                       return (-1);
+       }
+       return (size - usal_getresid(usalp));
+}
+
+static int
+discontinue_sony(SCSI *usalp)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->flags = SCG_DISRE_ENA|SCG_CMD_RETRY;
+       scmd->cdb_len = SC_G1_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+       scmd->cdb.g1_cdb.cmd = 0xE2;
+       scmd->cdb.g1_cdb.lun = usal_lun(usalp);
+
+       usalp->cmdname = "discontinue";
+
+       if (usal_cmd(usalp) < 0)
+               return (-1);
+       return (0);
+}
+
+static int
+write_track_sony(SCSI *usalp, 
+                 long track     /* track number 0 == new track */, 
+                 int sectype    /* no sectype for Sony write track */)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->flags = SCG_DISRE_ENA|SCG_CMD_RETRY;
+       scmd->cdb_len = SC_G1_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+       scmd->cdb.g1_cdb.cmd = 0xF5;
+       scmd->cdb.g1_cdb.lun = usal_lun(usalp);
+       g1_cdbaddr(&scmd->cdb.g1_cdb, track);
+
+       usalp->cmdname = "write_track";
+
+       if (usal_cmd(usalp) < 0)
+               return (-1);
+       return (0);
+}
+
+/* XXX NOCH NICHT FERTIG */
+static int
+close_track_sony(SCSI *usalp, cdr_t *dp, track_t *trackp)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+       int     track = 0;
+
+       if (!is_tao(trackp) && !is_packet(trackp))
+               return (0);
+
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->flags = SCG_DISRE_ENA;
+       scmd->cdb_len = SC_G1_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+       scmd->cdb.g1_cdb.cmd = 0xF0;
+       scmd->cdb.g1_cdb.lun = usal_lun(usalp);
+       g1_cdbaddr(&scmd->cdb.g1_cdb, track);
+/* XXX Padding ??? (bit 0 in addr[0] / CDB[2]) */
+
+       usalp->cmdname = "close_track";
+
+       if (usal_cmd(usalp) < 0)
+               return (-1);
+
+       /*
+        * Clear the silly "error situation" from Sony´ dummy write end
+        * but notify if real errors occurred.
+        */
+       usalp->silent++;
+       if (test_unit_ready(usalp) < 0 && usal_sense_code(usalp) != 0xD4) {
+               usalp->cmdname = "close_track/test_unit_ready";
+               usal_printerr(usalp);
+       }
+       usalp->silent--;
+
+       return (0);
+}
+
+static int
+finalize_sony(SCSI *usalp, cdr_t *dp, track_t *trackp)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+       int     dummy = track_base(trackp)->tracktype & TOCF_DUMMY;
+
+       if (!is_tao(trackp) && !is_packet(trackp)) {
+               wait_unit_ready(usalp, 240);
+               return (0);
+       }
+       if (dummy) {
+               printf("Fixating is not possible in dummy write mode.\n");
+               return (0);
+       }
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->flags = SCG_DISRE_ENA;
+       scmd->cdb_len = SC_G1_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+       scmd->timeout = 8 * 60;         /* Needs up to 4 minutes */
+       scmd->cdb.g1_cdb.cmd = 0xF1;
+       scmd->cdb.g1_cdb.lun = usal_lun(usalp);
+       scmd->cdb.g1_cdb.count[1] = ((track_base(trackp)->tracktype & TOCF_MULTI) ? 1 : 0);
+/* XXX Padding ??? (bit 0 in addr[0] / CDB[2]) */
+
+       usalp->cmdname = "finalize";
+
+       if (usal_cmd(usalp) < 0)
+               return (-1);
+       return (0);
+}
+
+static int
+flush_sony(SCSI *usalp, int track)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->flags = SCG_DISRE_ENA;
+       scmd->cdb_len = SC_G1_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+       scmd->timeout = 8 * 60;         /* Needs up to 4 minutes */
+       scmd->cdb.g1_cdb.cmd = 0xF2;
+       scmd->cdb.g1_cdb.lun = usal_lun(usalp);
+       scmd->cdb.cmd_cdb[5] = track;
+/* XXX POE ???    (bit 1 in addr[0] / CDB[2]) */
+/* XXX Padding ??? (bit 0 in addr[0] / CDB[2]) */
+/* XXX Partial flush ??? (CDB[3]) */
+
+       usalp->cmdname = "flush";
+
+       if (usal_cmd(usalp) < 0)
+               return (-1);
+       return (0);
+}
+
+static int
+recover_sony(SCSI *usalp, cdr_t *dp, int track)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->flags = SCG_DISRE_ENA;
+       scmd->cdb_len = SC_G1_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+       scmd->cdb.g1_cdb.cmd = 0xF6;
+       scmd->cdb.g1_cdb.lun = usal_lun(usalp);
+       scmd->cdb.g1_cdb.addr[3] = track;
+
+       usalp->cmdname = "recover";
+
+       if (usal_cmd(usalp) < 0)
+               return (-1);
+       return (0);
+}
+
+static int
+set_wr_parameter_sony(SCSI *usalp, caddr_t bp, int size)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->addr = bp;
+       scmd->size = size;
+       scmd->flags = SCG_DISRE_ENA;
+       scmd->cdb_len = SC_G1_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+       scmd->cdb.g1_cdb.cmd = 0xF8;
+       scmd->cdb.g1_cdb.lun = usal_lun(usalp);
+       g1_cdblen(&scmd->cdb.g1_cdb, size);
+
+       usalp->cmdname = "set_write_parameter";
+
+       if (usal_cmd(usalp) < 0)
+               return (-1);
+       return (0);
+}
+
+static int
+next_wr_addr_sony(SCSI *usalp, track_t *trackp, long *ap)
+{
+       if (next_writable_address_sony(usalp, ap, 0, 0, 0) < 0)
+               return (-1);
+       return (0);
+}
+
+static int
+reserve_track_sony(SCSI *usalp, unsigned long len)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->flags = SCG_DISRE_ENA;
+       scmd->cdb_len = SC_G1_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+       scmd->cdb.g1_cdb.cmd = 0xF3;
+       scmd->cdb.g1_cdb.lun = usal_lun(usalp);
+       i_to_4_byte(&scmd->cdb.g1_cdb.addr[3], len);
+
+       usalp->cmdname = "reserve_track";
+
+       if (usal_cmd(usalp) < 0)
+               return (-1);
+       return (0);
+}
+
+static int
+init_sony(SCSI *usalp, cdr_t *dp)
+{
+       return (speed_select_sony(usalp, dp, NULL));
+}
+
+
+#define        IS(what, flag)  printf("  Is %s%s\n", flag?"":"not ", what);
+
+static int
+getdisktype_sony(SCSI *usalp, cdr_t *dp)
+{
+       dstat_t *dsp = dp->cdr_dstat;
+       long    dummy;
+       long    lst;
+       msf_t   msf;
+
+       char                    mode[256];
+       struct scsi_mode_page_header    *mp;
+       struct sony_924_mode_page_22    *xp;
+
+       dummy = get_page22_sony(usalp, mode);
+       if (dummy >= 0) {
+               mp = (struct scsi_mode_page_header *)
+                       (mode + sizeof (struct scsi_mode_header) +
+                       ((struct scsi_mode_header *)mode)->blockdesc_len);
+
+               xp = (struct sony_924_mode_page_22 *)mp;
+
+               if (xp->disk_appl_code[0] == 0xFF)
+                       dummy = -1;
+       } else {
+               return (drive_getdisktype(usalp, dp));
+       }
+
+       if ((dp->cdr_dstat->ds_cdrflags & RF_PRATIP) != 0 && dummy >= 0) {
+
+               printf("ATIP info from disk:\n");
+               printf("  Indicated writing power: %d\n",
+                               (unsigned)(xp->disk_appl_code[1] & 0x70) >> 4);
+               IS("unrestricted", xp->disk_appl_code[2] & 0x40);
+               printf("  Disk application code: %d\n", xp->disk_appl_code[2] & 0x3F);
+               msf.msf_min = xp->lead_in_start[1];
+               msf.msf_sec = xp->lead_in_start[2];
+               msf.msf_frame = xp->lead_in_start[3];
+               lst = msf_to_lba(msf.msf_min, msf.msf_sec, msf.msf_frame, FALSE);
+               if (lst  < -150) {
+                       /*
+                        * The Sony CDU 920 seems to deliver 00:00/00 for
+                        * lead-in start time, dont use it.
+                        */
+                       printf("  ATIP start of lead in:  %ld (%02d:%02d/%02d)\n",
+                               msf_to_lba(msf.msf_min, msf.msf_sec, msf.msf_frame, FALSE),
+                               msf.msf_min, msf.msf_sec, msf.msf_frame);
+               }
+               msf.msf_min = xp->last_start_time[1];
+               msf.msf_sec = xp->last_start_time[2];
+               msf.msf_frame = xp->last_start_time[3];
+               printf("  ATIP start of lead out: %ld (%02d:%02d/%02d)\n",
+                       msf_to_lba(msf.msf_min, msf.msf_sec, msf.msf_frame, TRUE),
+                       msf.msf_min, msf.msf_sec, msf.msf_frame);
+               if (lst  < -150) {
+                       /*
+                        * The Sony CDU 920 seems to deliver 00:00/00 for
+                        * lead-in start time, dont use it.
+                        */
+                       msf.msf_min = xp->lead_in_start[1];
+                       msf.msf_sec = xp->lead_in_start[2];
+                       msf.msf_frame = xp->lead_in_start[3];
+                       pr_manufacturer(&msf,
+                                       FALSE,  /* Always not erasable */
+                                       (xp->disk_appl_code[2] & 0x40) != 0);
+               }
+       }
+       if (dummy >= 0)
+               di_to_dstat_sony(xp, dsp);
+       return (drive_getdisktype(usalp, dp));
+}
+
+static void
+di_to_dstat_sony(struct sony_924_mode_page_22 *dip, dstat_t *dsp)
+{
+       msf_t   msf;
+
+       dsp->ds_diskid = a_to_u_4_byte(dip->disk_id_code);
+#ifdef PROTOTYPES
+       if (dsp->ds_diskid != 0xFFFFFFFFUL)
+#else
+       if (dsp->ds_diskid != (Ulong)0xFFFFFFFF)
+#endif
+               dsp->ds_flags |= DSF_DID_V;
+       dsp->ds_diskstat = (dip->disk_status >> 6) & 0x03;
+#ifdef XXX
+       /*
+        * There seems to be no MMC equivalent...
+        */
+       dsp->ds_sessstat = dip->sess_status;
+#endif
+
+       dsp->ds_maxblocks = msf_to_lba(dip->last_start_time[1],
+                                       dip->last_start_time[2],
+                                       dip->last_start_time[3], TRUE);
+       /*
+        * Check for 0xFF:0xFF/0xFF which is an indicator for a complete disk
+        */
+       if (dsp->ds_maxblocks == 716730)
+               dsp->ds_maxblocks = -1L;
+
+       if (dsp->ds_first_leadin == 0) {
+               dsp->ds_first_leadin = msf_to_lba(dip->lead_in_start[1],
+                                               dip->lead_in_start[2],
+                                               dip->lead_in_start[3], FALSE);
+               /*
+                * Check for illegal values (> 0)
+                * or for empty field (-150) with CDU-920.
+                */
+               if (dsp->ds_first_leadin > 0 || dsp->ds_first_leadin == -150)
+                       dsp->ds_first_leadin = 0;
+       }
+
+       if (dsp->ds_last_leadout == 0 && dsp->ds_maxblocks >= 0)
+               dsp->ds_last_leadout = dsp->ds_maxblocks;
+
+       msf.msf_min = dip->lead_in_start[1];
+       msf.msf_sec = dip->lead_in_start[2];
+       msf.msf_frame = dip->lead_in_start[3];
+       dsp->ds_maxrblocks = disk_rcap(&msf, dsp->ds_maxblocks,
+                                       FALSE,  /* Always not erasable */
+                                       (dip->disk_appl_code[2] & 0x40) != 0);
+}
+
+
+int    sony_speeds[] = {
+               -1,             /* Speed null is not allowed */
+               0,              /* Single speed */
+               1,              /* Double speed */
+               -1,             /* Three times */
+               3,              /* Quad speed */
+};
+
+static int
+speed_select_sony(SCSI *usalp, cdr_t *dp, int *speedp)
+{
+       struct cdd_52x_mode_data md;
+       int     count;
+       int     err;
+       int     speed = 1;
+       BOOL    dummy = (dp->cdr_cmdflags & F_DUMMY) != 0;
+
+       if (speedp) {
+               speed = *speedp;
+               if (speed < 1 || speed > 4 || sony_speeds[speed] < 0)
+                       return (-1);
+       }
+
+       fillbytes((caddr_t)&md, sizeof (md), '\0');
+
+       count  = sizeof (struct scsi_mode_header) +
+               sizeof (struct sony_924_mode_page_20);
+
+       md.pagex.page_s20.p_code = 0x20;
+       md.pagex.page_s20.p_len =  0x06;
+       md.pagex.page_s20.speudo = dummy?1:0;
+
+       /*
+        * Set Cue sheet option. This is documented for the 924 and
+        * seems to be supported for the 948 too.
+        */
+       md.pagex.page_s20.cue_sheet_opt = 0x03;
+
+       err = mode_select(usalp, (Uchar *)&md, count, 0, 1);
+       if (err < 0)
+               return (err);
+
+       if (speedp == 0)
+               return (0);
+
+       fillbytes((caddr_t)&md, sizeof (md), '\0');
+
+       count  = sizeof (struct scsi_mode_header) +
+               sizeof (struct sony_924_mode_page_31);
+
+       md.pagex.page_s31.p_code = 0x31;
+       md.pagex.page_s31.p_len =  0x02;
+       md.pagex.page_s31.speed = sony_speeds[speed];
+
+       return (mode_select(usalp, (Uchar *)&md, count, 0, 1));
+}
+
+static int
+next_writable_address_sony(SCSI *usalp, long *ap, int track, int sectype, 
+                           int tracktype)
+{
+       struct  scsi_mode_page_header *mp;
+       char                    mode[256];
+       int                     len = 0x30;
+       int                     page = 0x23;
+       struct sony_924_mode_page_23    *xp;
+
+       fillbytes((caddr_t)mode, sizeof (mode), '\0');
+
+       inc_verbose();
+       if (!get_mode_params(usalp, page, "CD track information",
+                       (Uchar *)mode, (Uchar *)0, (Uchar *)0, (Uchar *)0, &len)) {
+               dec_verbose();
+               return (-1);
+       }
+       dec_verbose();
+       if (len == 0)
+               return (-1);
+
+       mp = (struct scsi_mode_page_header *)
+               (mode + sizeof (struct scsi_mode_header) +
+               ((struct scsi_mode_header *)mode)->blockdesc_len);
+
+
+       xp = (struct sony_924_mode_page_23 *)mp;
+
+#ifdef SONY_DEBUG
+       print_sony_mp23(xp, len);
+#endif
+       if (ap)
+               *ap = a_to_4_byte(xp->next_recordable_addr);
+       return (0);
+}
+
+
+static int
+new_track_sony(SCSI *usalp, int track, int sectype, int tracktype)
+{
+       struct  scsi_mode_page_header *mp;
+       char                    mode[256];
+       int                     len = 0x30;
+       int                     page = 0x23;
+       struct sony_924_mode_page_23    *xp;
+       int     i;
+
+       fillbytes((caddr_t)mode, sizeof (mode), '\0');
+       get_page22_sony(usalp, mode);
+
+       fillbytes((caddr_t)mode, sizeof (mode), '\0');
+
+       inc_verbose();
+       if (!get_mode_params(usalp, page, "CD track information",
+                       (Uchar *)mode, (Uchar *)0, (Uchar *)0, (Uchar *)0, &len)) {
+               dec_verbose();
+               return (-1);
+       }
+       dec_verbose();
+       if (len == 0)
+               return (-1);
+
+       mp = (struct scsi_mode_page_header *)
+               (mode + sizeof (struct scsi_mode_header) +
+               ((struct scsi_mode_header *)mode)->blockdesc_len);
+
+
+       xp = (struct sony_924_mode_page_23 *)mp;
+
+#ifdef SONY_DEBUG
+       print_sony_mp23(xp, len);
+#endif
+
+       xp->write_method = 0;   /* Track at one recording */
+
+       if (sectype & ST_AUDIOMASK) {
+               xp->data_form = (sectype & ST_MASK) == ST_AUDIO_PRE ? 0x02 : 0x00;
+       } else {
+               if (tracktype == TOC_ROM) {
+                       xp->data_form = (sectype & ST_MASK) == ST_ROM_MODE1 ? 0x10 : 0x11;
+               } else if (tracktype == TOC_XA1) {
+                       xp->data_form = 0x12;
+               } else if (tracktype == TOC_XA2) {
+                       xp->data_form = 0x12;
+               } else if (tracktype == TOC_CDI) {
+                       xp->data_form = 0x12;
+               }
+       }
+
+       ((struct scsi_modesel_header *)mode)->sense_data_len    = 0;
+       ((struct scsi_modesel_header *)mode)->res2              = 0;
+
+       i = ((struct scsi_mode_header *)mode)->blockdesc_len;
+       if (i > 0) {
+               i_to_3_byte(
+                       ((struct scsi_mode_data *)mode)->blockdesc.nlblock,
+                                                               0);
+       }
+
+       if (mode_select(usalp, (Uchar *)mode, len, 0, usalp->inq->data_format >= 2) < 0) {
+               return (-1);
+       }
+
+       return (0);
+}
+
+static int
+open_track_sony(SCSI *usalp, cdr_t *dp, track_t *trackp)
+{
+       if (!is_tao(trackp) && !is_packet(trackp)) {
+               if (trackp->pregapsize > 0 && (trackp->flags & TI_PREGAP) == 0) {
+                       if (lverbose) {
+                               printf("Writing pregap for track %d at %ld\n",
+                                       (int)trackp->trackno,
+                                       trackp->trackstart-trackp->pregapsize);
+                       }
+                       /*
+                        * XXX Do we need to check isecsize too?
+                        */
+                       pad_track(usalp, dp, trackp,
+                               trackp->trackstart-trackp->pregapsize,
+                               (Llong)trackp->pregapsize*trackp->secsize,
+                                       FALSE, 0);
+               }
+               return (0);
+       }
+
+       if (select_secsize(usalp, trackp->secsize) < 0)
+               return (-1);
+
+       if (new_track_sony(usalp, trackp->trackno, trackp->sectype, trackp->tracktype & TOC_MASK) < 0)
+               return (-1);
+
+       if (write_track_sony(usalp, 0L, trackp->sectype) < 0)
+               return (-1);
+
+       return (0);
+}
+
+static int
+open_session_sony(SCSI *usalp, cdr_t *dp, track_t *trackp)
+{
+       struct  scsi_mode_page_header *mp;
+       char                    mode[256];
+       int     i;
+       int     len = 0x30;
+       struct sony_924_mode_page_22    *xp;
+
+       fillbytes((caddr_t)mode, sizeof (mode), '\0');
+
+       if ((len = get_page22_sony(usalp, mode)) < 0)
+               return (-1);
+
+       mp = (struct scsi_mode_page_header *)
+               (mode + sizeof (struct scsi_mode_header) +
+               ((struct scsi_mode_header *)mode)->blockdesc_len);
+
+       xp = (struct sony_924_mode_page_22 *)mp;
+
+       xp->disk_type = toc2sess[track_base(trackp)->tracktype & TOC_MASK];
+
+       if (is_tao(track_base(trackp))) {
+#ifdef __needed__
+               if ((track_base(trackp)->tracktype & TOC_MASK) == TOC_DA)
+                       xp->disk_style = 0x80;
+               else
+                       xp->disk_style = 0xC0;
+#endif
+       } else if (is_sao(track_base(trackp))) {
+               /*
+                * We may only change this value if the disk is empty.
+                * i.e. when disk_status & 0xC0 == 0x00
+                */
+               if ((xp->disk_status & 0xC0) != 0) {
+                       if (xp->disk_style != 0x00)
+                               errmsgno(EX_BAD, "Cannot change disk stile for recorded disk.\n");
+               }
+               xp->disk_style = 0x00;
+       }
+
+       ((struct scsi_modesel_header *)mode)->sense_data_len    = 0;
+       ((struct scsi_modesel_header *)mode)->res2              = 0;
+
+       i = ((struct scsi_mode_header *)mode)->blockdesc_len;
+       if (i > 0) {
+               i_to_3_byte(
+                       ((struct scsi_mode_data *)mode)->blockdesc.nlblock,
+                                                               0);
+       }
+
+       if (mode_select(usalp, (Uchar *)mode, len, 0, usalp->inq->data_format >= 2) < 0) {
+               return (-1);
+       }
+/*
+ * XXX set write parameter für SAO mit Multi Session (948 only?)
+ * XXX set_wr_parameter_sony(usalp, bp, size);
+ */
+       return (0);
+}
+
+static int
+abort_session_sony(SCSI *usalp, cdr_t *dp)
+{
+       return (discontinue_sony(usalp));
+}
+
+static int
+get_page22_sony(SCSI *usalp, char *mode)
+{
+       struct  scsi_mode_page_header *mp;
+       int     len = 0x30;
+       int     page = 0x22;
+       struct sony_924_mode_page_22    *xp;
+
+       fillbytes((caddr_t)mode, sizeof (mode), '\0');
+
+       inc_verbose();
+       if (!get_mode_params(usalp, page, "CD disk information",
+                       (Uchar *)mode, (Uchar *)0, (Uchar *)0, (Uchar *)0, &len)) {
+               dec_verbose();
+               return (-1);
+       }
+       dec_verbose();
+       if (len == 0)
+               return (-1);
+
+       mp = (struct scsi_mode_page_header *)
+               (mode + sizeof (struct scsi_mode_header) +
+               ((struct scsi_mode_header *)mode)->blockdesc_len);
+
+       xp = (struct sony_924_mode_page_22 *)mp;
+
+#ifdef SONY_DEBUG
+       print_sony_mp22(xp, len);
+#endif
+       return (len);
+}
+
+/*--------------------------------------------------------------------------*/
+
+static Uchar   db2df[] = {
+       0x01,                   /*  0 2352 bytes of raw data                    */
+       0xFF,                   /*  1 2368 bytes (raw data + P/Q Subchannel)    */
+       0xFF,                   /*  2 2448 bytes (raw data + P-W Subchannel)    */
+       0xFF,                   /*  3 2448 bytes (raw data + P-W raw Subchannel)*/
+       0xFF,                   /*  4 -    Reserved                             */
+       0xFF,                   /*  5 -    Reserved                             */
+       0xFF,                   /*  6 -    Reserved                             */
+       0xFF,                   /*  7 -    Vendor specific                      */
+       0x11,                   /*  8 2048 bytes Mode 1 (ISO/IEC 10149)         */
+       0xFF,                   /*  9 2336 bytes Mode 2 (ISO/IEC 10149)         */
+       0xFF,                   /* 10 2048 bytes Mode 2! (CD-ROM XA form 1)     */
+       0xFF,                   /* 11 2056 bytes Mode 2 (CD-ROM XA form 1)      */
+       0xFF,                   /* 12 2324 bytes Mode 2 (CD-ROM XA form 2)      */
+       0xFF,                   /* 13 2332 bytes Mode 2 (CD-ROM XA 1/2+subhdr)  */
+       0xFF,                   /* 14 -    Reserved                             */
+       0xFF,                   /* 15 -    Vendor specific                      */
+};
+
+static int
+gen_cue_sony(track_t *trackp, void *vcuep, BOOL needgap)
+{
+       int     tracks = trackp->tracks;
+       int     i;
+       struct sony_cue **cuep = vcuep;
+       struct sony_cue *cue;
+       struct sony_cue *cp;
+       int     ncue = 0;
+       int     icue = 0;
+       int     pgsize;
+       msf_t   m;
+       int     ctl;
+       int     df;
+       int     scms;
+
+       cue = malloc(1);
+
+       for (i = 0; i <= tracks; i++) {
+               ctl = (st2mode[trackp[i].sectype & ST_MASK]) << 4;
+               if (is_copy(&trackp[i]))
+                       ctl |= TM_ALLOW_COPY << 4;
+               df = db2df[trackp[i].dbtype & 0x0F];
+
+#ifdef __supported__
+               if (trackp[i].isrc) {   /* MCN or ISRC */
+                       ncue += 2;
+                       cue = realloc(cue, ncue * sizeof (*cue));
+                       cp = &cue[icue++];
+                       if (i == 0) {
+                               cp->cs_ctladr = 0x02;
+                               movebytes(&trackp[i].isrc[0], &cp->cs_tno, 7);
+                               cp = &cue[icue++];
+                               cp->cs_ctladr = 0x02;
+                               movebytes(&trackp[i].isrc[7], &cp->cs_tno, 7);
+                       } else {
+                               cp->cs_ctladr = 0x03;
+                               cp->cs_tno = i;
+                               movebytes(&trackp[i].isrc[0], &cp->cs_index, 6);
+                               cp = &cue[icue++];
+                               cp->cs_ctladr = 0x03;
+                               cp->cs_tno = i;
+                               movebytes(&trackp[i].isrc[6], &cp->cs_index, 6);
+                       }
+               }
+#endif
+               if (i == 0) {   /* Lead in */
+                       df &= ~7;
+                       if (trackp[0].flags & TI_TEXT)  /* CD-Text in Lead-in*/
+                               df |= 0xC0;
+                       lba_to_msf(-150, &m);
+                       cue = realloc(cue, ++ncue * sizeof (*cue));
+                       cp = &cue[icue++];
+                       fillcue(cp, ctl|0x01, i, 0, df, 0, &m);
+               } else {
+                       scms = 0;
+
+                       if (is_scms(&trackp[i]))
+                               scms = 0x80;
+                       pgsize = trackp[i].pregapsize;
+                       if (pgsize == 0 && needgap)
+                               pgsize++;
+                       lba_to_msf(trackp[i].trackstart-pgsize, &m);
+                       cue = realloc(cue, ++ncue * sizeof (*cue));
+                       cp = &cue[icue++];
+                       fillcue(cp, ctl|0x01, i, 0, df, scms, &m);
+
+                       if (trackp[i].nindex == 1) {
+                               lba_to_msf(trackp[i].trackstart, &m);
+                               cue = realloc(cue, ++ncue * sizeof (*cue));
+                               cp = &cue[icue++];
+                               fillcue(cp, ctl|0x01, i, 1, df, scms, &m);
+                       } else {
+                               int     idx;
+                               long    *idxlist;
+
+                               ncue += trackp[i].nindex;
+                               idxlist = trackp[i].tindex;
+                               cue = realloc(cue, ncue * sizeof (*cue));
+
+                               for (idx = 1; idx <= trackp[i].nindex; idx++) {
+                                       lba_to_msf(trackp[i].trackstart + idxlist[idx], &m);
+                                       cp = &cue[icue++];
+                                       fillcue(cp, ctl|0x01, i, idx, df, scms, &m);
+                               }
+                       }
+               }
+       }
+       /* Lead out */
+       ctl = (st2mode[trackp[tracks+1].sectype & ST_MASK]) << 4;
+       df = db2df[trackp[tracks+1].dbtype & 0x0F];
+       df &= ~7;
+       lba_to_msf(trackp[tracks+1].trackstart, &m);
+       cue = realloc(cue, ++ncue * sizeof (*cue));
+       cp = &cue[icue++];
+       fillcue(cp, ctl|0x01, 0xAA, 1, df, 0, &m);
+
+       if (lverbose > 1) {
+               for (i = 0; i < ncue; i++) {
+                       usal_prbytes("", (Uchar *)&cue[i], 8);
+               }
+       }
+       if (cuep)
+               *cuep = cue;
+       else
+               free(cue);
+       return (ncue);
+}
+
+
+static void
+fillcue(struct sony_cue *cp     /* The target cue entry */, 
+        int ca                  /* Control/adr for this entry */, 
+        int tno                 /* Track number for this entry */, 
+        int idx                 /* Index for this entry */, 
+        int dataform            /* Data format for this entry */, 
+        int scms                /* Serial copy management */, 
+        msf_t *mp               /* MSF value for this entry */)
+{
+       cp->cs_ctladr = ca;
+       if (tno <= 99)
+               cp->cs_tno = to_bcd(tno);
+       else
+               cp->cs_tno = tno;
+       cp->cs_index = to_bcd(idx);
+       cp->cs_dataform = dataform;
+       cp->cs_zero = scms;
+       cp->cs_min = to_bcd(mp->msf_min);
+       cp->cs_sec = to_bcd(mp->msf_sec);
+       cp->cs_frame = to_bcd(mp->msf_frame);
+}
+
+static int
+send_cue_sony(SCSI *usalp, cdr_t *dp, track_t *trackp)
+{
+       struct sony_cue *cp;
+       int             ncue;
+       int             ret;
+       Uint            i;
+       struct timeval starttime;
+       struct timeval stoptime;
+       int             disktype;
+
+       disktype = toc2sess[track_base(trackp)->tracktype & TOC_MASK];
+
+       for (i = 1; i <= trackp->tracks; i++) {
+               if (trackp[i].tracksize < (tsize_t)0) {
+                       errmsgno(EX_BAD, "Track %d has unknown length.\n", i);
+                       return (-1);
+               }
+       }
+       ncue = (*dp->cdr_gen_cue)(trackp, &cp, FALSE);
+
+       starttime.tv_sec = 0;
+       starttime.tv_usec = 0;
+       stoptime = starttime;
+       gettimeofday(&starttime, (struct timezone *)0);
+
+       usalp->silent++;
+       ret  = write_start_sony(usalp, (caddr_t)cp, ncue*8);
+       usalp->silent--;
+       free(cp);
+       if (ret < 0) {
+               errmsgno(EX_BAD, "CUE sheet not accepted. Retrying with minimum pregapsize = 1.\n");
+               ncue = (*dp->cdr_gen_cue)(trackp, &cp, TRUE);
+               ret  = write_start_sony(usalp, (caddr_t)cp, ncue*8);
+               free(cp);
+       }
+       if (ret >= 0 && lverbose) {
+               gettimeofday(&stoptime, (struct timezone *)0);
+               prtimediff("Write Lead-in time: ", &starttime, &stoptime);
+       }
+       return (ret);
+}
+
+static int
+write_leadin_sony(SCSI *usalp, cdr_t *dp, track_t *trackp)
+{
+       Uint    i;
+       long    startsec = 0L;
+
+/*     if (flags & F_SAO) {*/
+       if (wm_base(dp->cdr_dstat->ds_wrmode) == WM_SAO) {
+               if (debug || lverbose) {
+                       printf("Sending CUE sheet...\n");
+                       flush();
+               }
+               if (trackp[0].flags & TI_TEXT) {
+                       if (dp->cdr_speeddef != 4) {
+                               errmsgno(EX_BAD,
+                               "The CDU-924 does not support CD-Text, disabling.\n");
+
+                               trackp[0].flags &= ~TI_TEXT;
+                       }
+               }
+               if ((*dp->cdr_send_cue)(usalp, dp, trackp) < 0) {
+                       errmsgno(EX_BAD, "Cannot send CUE sheet.\n");
+                       return (-1);
+               }
+
+               if (trackp[0].flags & TI_TEXT) {
+                       startsec = dp->cdr_dstat->ds_first_leadin;
+                       printf("SAO startsec: %ld\n", startsec);
+               } else {
+                       startsec = -150;
+               }
+               if (debug)
+                       printf("SAO startsec: %ld\n", startsec);
+
+               if (trackp[0].flags & TI_TEXT) {
+                       if (startsec > 0) {
+                               errmsgno(EX_BAD, "CD-Text must be in first session.\n");
+                               return (-1);
+                       }
+                       if (debug || lverbose)
+                               printf("Writing lead-in...\n");
+                       if (write_cdtext(usalp, dp, startsec) < 0)
+                               return (-1);
+
+                       dp->cdr_dstat->ds_cdrflags |= RF_LEADIN;
+               } else for (i = 1; i <= trackp->tracks; i++) {
+                       trackp[i].trackstart += startsec +150;
+               }
+       }
+       return (0);
+}
+
+/*--------------------------------------------------------------------------*/
+
+static const char *sd_cdu_924_error_str[] = {
+
+       "\200\000write complete",                               /* 80 00 */
+       "\201\000logical unit is reserved",                     /* 81 00 */
+       "\205\000audio address not valid",                      /* 85 00 */
+       "\210\000illegal cue sheet",                            /* 88 00 */
+       "\211\000inappropriate command",                        /* 89 00 */
+
+       "\266\000media load mechanism failed",                  /* B6 00 */
+       "\271\000audio play operation aborted",                 /* B9 00 */
+       "\277\000buffer overflow for read all subcodes command", /* BF 00 */
+       "\300\000unrecordable disk",                            /* C0 00 */
+       "\301\000illegal track status",                         /* C1 00 */
+       "\302\000reserved track present",                       /* C2 00 */
+       "\303\000buffer data size error",                       /* C3 00 */
+       "\304\001illegal data form for reserve track command",  /* C4 01 */
+       "\304\002unable to reserve track, because track mode has been changed", /* C4 02 */
+       "\305\000buffer error during at once recording",        /* C5 00 */
+       "\306\001unwritten area encountered",                   /* C6 01 */
+       "\306\002link blocks encountered",                      /* C6 02 */
+       "\306\003nonexistent block encountered",                /* C6 03 */
+       "\307\000disk style mismatch",                          /* C7 00 */
+       "\310\000no table of contents",                         /* C8 00 */
+       "\311\000illegal block length for write command",       /* C9 00 */
+       "\312\000power calibration error",                      /* CA 00 */
+       "\313\000write error",                                  /* CB 00 */
+       "\313\001write error track recovered",                  /* CB 01 */
+       "\314\000not enough space",                             /* CC 00 */
+       "\315\000no track present to finalize",                 /* CD 00 */
+       "\316\000unrecoverable track descriptor encountered",   /* CE 00 */
+       "\317\000damaged track present",                        /* CF 00 */
+       "\320\000pma area full",                                /* D0 00 */
+       "\321\000pca area full",                                /* D1 00 */
+       "\322\000unrecoverable damaged track cause too small writing area",     /* D2 00 */
+       "\323\000no bar code",                                  /* D3 00 */
+       "\323\001not enough bar code margin",                   /* D3 01 */
+       "\323\002no bar code start pattern",                    /* D3 02 */
+       "\323\003illegal bar code length",                      /* D3 03 */
+       "\323\004illegal bar code format",                      /* D3 04 */
+       "\324\000exit from pseudo track at once recording",     /* D4 00 */
+       NULL
+};
+
+static int
+sony_attach(SCSI *usalp, cdr_t *dp)
+{
+       if (usalp->inq != NULL) {
+               if (strbeg("CD-R   CDU94", usalp->inq->prod_ident)) {
+                       dp->cdr_speeddef = 4;
+               }
+       }
+       usal_setnonstderrs(usalp, sd_cdu_924_error_str);
+       return (0);
+}
+
+#ifdef SONY_DEBUG
+static void
+print_sony_mp22(struct sony_924_mode_page_22 *xp, int len)
+{
+       printf("disk style: %X\n", xp->disk_style);
+       printf("disk type: %X\n", xp->disk_type);
+       printf("first track: %X\n", xp->first_track);
+       printf("last track: %X\n", xp->last_track);
+       printf("numsess:    %X\n", xp->numsess);
+       printf("disk appl code: %lX\n", a_to_u_4_byte(xp->disk_appl_code));
+       printf("last start time: %lX\n", a_to_u_4_byte(xp->last_start_time));
+       printf("disk status: %X\n", xp->disk_status);
+       printf("num valid nra: %X\n", xp->num_valid_nra);
+       printf("track info track: %X\n", xp->track_info_track);
+       printf("post gap: %X\n", xp->post_gap);
+       printf("disk id code: %lX\n", a_to_u_4_byte(xp->disk_id_code));
+       printf("lead in start: %lX\n", a_to_u_4_byte(xp->lead_in_start));
+}
+
+static void
+print_sony_mp23(struct sony_924_mode_page_23 *xp, int len)
+{
+       printf("len: %d\n", len);
+
+       printf("track num: %X\n", xp->track_num);
+       printf("data form: %X\n", xp->data_form);
+       printf("write method: %X\n", xp->write_method);
+       printf("session: %X\n", xp->session);
+       printf("track status: %X\n", xp->track_status);
+
+/*
+ * XXX Check for signed/unsigned a_to_*() conversion.
+ */
+       printf("start lba: %lX\n", a_to_4_byte(xp->start_lba));
+       printf("next recordable addr: %lX\n", a_to_4_byte(xp->next_recordable_addr));
+       printf("blank area cap: %lX\n", a_to_u_4_byte(xp->blank_area_cap));
+       printf("fixed packet size: %lX\n", a_to_u_4_byte(xp->fixed_packet_size));
+       printf("starting msf: %lX\n", a_to_u_4_byte(xp->starting_msf));
+       printf("ending msf: %lX\n", a_to_u_4_byte(xp->ending_msf));
+       printf("next rec time: %lX\n", a_to_u_4_byte(xp->next_rec_time));
+}
+#endif
+
+static int
+buf_cap_sony(SCSI *usalp, long *sp, long *fp)
+{
+       char    resp[8];
+       Ulong   freespace;
+       Ulong   bufsize;
+       int     per;
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->addr = (caddr_t)resp;
+       scmd->size = sizeof (resp);
+       scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
+       scmd->cdb_len = SC_G1_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+       scmd->cdb.g1_cdb.cmd = 0xEC;            /* Read buffer cap */
+       scmd->cdb.g1_cdb.lun = usal_lun(usalp);
+
+       usalp->cmdname = "read buffer cap sony";
+
+       if (usal_cmd(usalp) < 0)
+               return (-1);
+
+       bufsize   = a_to_u_3_byte(&resp[1]);
+       freespace = a_to_u_3_byte(&resp[5]);
+       if (sp)
+               *sp = bufsize;
+       if (fp)
+               *fp = freespace;
+
+       if (usalp->verbose || (sp == 0 && fp == 0))
+               printf("BFree: %ld K BSize: %ld K\n", freespace >> 10, bufsize >> 10);
+
+       if (bufsize == 0)
+               return (0);
+       per = (100 * (bufsize - freespace)) / bufsize;
+       if (per < 0)
+               return (0);
+       if (per > 100)
+               return (100);
+       return (per);
+}
diff --git a/wodim/fifo.c b/wodim/fifo.c
new file mode 100644 (file)
index 0000000..2f70f5b
--- /dev/null
@@ -0,0 +1,878 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)fifo.c  1.49 06/02/08 Copyright 1989,1997-2006 J. Schilling */
+/*
+ *     A "fifo" that uses shared memory between two processes
+ *
+ *     The actual code is a mixture of borrowed code from star's fifo.c
+ *     and a proposal from Finn Arne Gangstad <finnag@guardian.no>
+ *     who had the idea to use a ring buffer to handle average size chunks.
+ *
+ *     Copyright (c) 1989,1997-2006 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef        DEBUG
+#define        DEBUG
+#endif
+/*#define      XDEBUG*/
+#include <mconfig.h>
+
+  /* We always wish FIFO unless it is disabled below */
+#ifndef FIFO
+#define FIFO
+#endif
+
+#if    defined(HAVE_OS_H) && \
+       defined(HAVE_CLONE_AREA) && defined(HAVE_CREATE_AREA) && \
+       defined(HAVE_DELETE_AREA)
+#include <OS.h>
+#      define  HAVE_BEOS_AREAS /* BeOS/Zeta */
+#endif
+#if    !defined(HAVE_SMMAP) && !defined(HAVE_USGSHM) && \
+       !defined(HAVE_DOSALLOCSHAREDMEM) && !defined(HAVE_BEOS_AREAS)
+#undef FIFO                    /* We cannot have a FIFO on this platform */
+#endif
+#if    !defined(HAVE_FORK)
+#undef FIFO                    /* We cannot have a FIFO on this platform */
+#endif
+#ifdef FIFO
+#if !defined(USE_MMAP) && !defined(USE_USGSHM)
+#define        USE_MMAP
+#endif
+#ifndef        HAVE_SMMAP
+#      undef   USE_MMAP
+#      define  USE_USGSHM      /* now SYSV shared memory is the default*/
+#endif
+#ifdef USE_MMAP                /* Only want to have one implementation */
+#      undef   USE_USGSHM      /* mmap() is preferred                  */
+#endif
+
+#ifdef HAVE_DOSALLOCSHAREDMEM  /* This is for OS/2 */
+#      undef   USE_MMAP
+#      undef   USE_USGSHM
+#      define  USE_OS2SHM
+#endif
+
+#ifdef HAVE_BEOS_AREAS         /* This is for BeOS/Zeta */
+#      undef   USE_MMAP
+#      undef   USE_USGSHM
+#      undef   USE_OS2SHM
+#      define  USE_BEOS_AREAS
+#endif
+
+#include <stdio.h>
+#include <stdxlib.h>
+#include <unixstd.h>   /* includes <sys/types.h> */
+#include <utypes.h>
+#include <fctldefs.h>
+#if defined(HAVE_SMMAP) && defined(USE_MMAP)
+#include <mmapdefs.h>
+#endif
+#include <waitdefs.h>
+#include <standard.h>
+#include <errno.h>
+#include <signal.h>
+#include <libport.h>
+#include <schily.h>
+
+#include "wodim.h"
+#include "xio.h"
+
+#ifdef DEBUG
+#ifdef XDEBUG
+FILE   *ef;
+#define        USDEBUG1        if (debug) {if (s == owner_reader) fprintf(ef, "r"); else fprintf(ef, "w"); fflush(ef); }
+#define        USDEBUG2        if (debug) {if (s == owner_reader) fprintf(ef, "R"); else fprintf(ef, "W"); fflush(ef); }
+#else
+#define        USDEBUG1
+#define        USDEBUG2
+#endif
+#define EDEBUG(a)   if (debug) schily_error a
+#else
+#define        EDEBUG(a)
+#define        USDEBUG1
+#define        USDEBUG2
+#endif
+
+#define        palign(x, a)    (((char *)(x)) + ((a) - 1 - (((UIntptr_t)((x)-1))%(a))))
+
+typedef enum faio_owner {
+       owner_none,             /* Unused in real life                      */
+       owner_writer,           /* owned by process that writes into FIFO   */
+       owner_faio,             /* Intermediate state when buf still in use */
+       owner_reader            /* owned by process that reads from FIFO    */
+} fowner_t;
+
+char   *onames[] = {
+       "none",
+       "writer",
+       "faio",
+       "reader",
+};
+
+typedef struct faio {
+       int     len;
+       volatile fowner_t owner;
+       volatile int users;
+       short   fd;
+       short   saved_errno;
+       char    *bufp;
+} faio_t;
+
+struct faio_stats {
+       long    puts;
+       long    gets;
+       long    empty;
+       long    full;
+       long    done;
+       long    cont_low;
+       int     users;
+} *sp;
+
+#define        MIN_BUFFERS     3
+
+#define        MSECS   1000
+#define        SECS    (1000*MSECS)
+
+/*
+ * Note: WRITER_MAXWAIT & READER_MAXWAIT need to be greater than the SCSI
+ * timeout for commands that write to the media. This is currently 200s
+ * if we are in SAO mode.
+ */
+/* microsecond delay between each buffer-ready probe by writing process */
+#define        WRITER_DELAY    (20*MSECS)
+#define        WRITER_MAXWAIT  (240*SECS)      /* 240 seconds max wait for data */
+
+/* microsecond delay between each buffer-ready probe by reading process */
+#define        READER_DELAY    (80*MSECS)
+#define        READER_MAXWAIT  (240*SECS)      /* 240 seconds max wait for reader */
+
+static char    *buf;
+static char    *bufbase;
+static char    *bufend;
+static long    buflen;                 /* The size of the FIFO buffer */
+
+extern int     debug;
+extern int     lverbose;
+
+void   init_fifo(long);
+#ifdef USE_MMAP
+static char    *mkshare(int size);
+#endif
+#ifdef USE_USGSHM
+static char    *mkshm(int size);
+#endif
+#ifdef USE_OS2SHM
+static char    *mkos2shm(int size);
+#endif
+#ifdef USE_BEOS_AREAS
+static char    *mkbeosshm(int size);
+static void    beosshm_child(void);
+#endif
+
+BOOL   init_faio(track_t *trackp, int);
+BOOL   await_faio(void);
+void   kill_faio(void);
+int    wait_faio(void);
+static void    faio_reader(track_t *trackp);
+static void    faio_read_track(track_t *trackp);
+static void    faio_wait_on_buffer(faio_t *f, fowner_t s, unsigned long delay,
+                                                                                         unsigned long max_wait);
+static int     faio_read_segment(int fd, faio_t *f, track_t *track, long secno, 
+                                                                                       int len);
+static faio_t  *faio_ref(int n);
+int    faio_read_buf(int f, char *bp, int size);
+int    faio_get_buf(int f, char **bpp, int size);
+void   fifo_stats(void);
+int    fifo_percent(BOOL addone);
+
+
+void
+init_fifo(long fs)
+{
+       int     pagesize;
+
+       if (fs == 0L)
+               return;
+
+       pagesize = getpagesize();
+       buflen = roundup(fs, pagesize) + pagesize;
+       EDEBUG(("fs: %ld buflen: %ld\n", fs, buflen));
+
+#if    defined(USE_MMAP)
+       buf = mkshare(buflen);
+#endif
+#if    defined(USE_USGSHM)
+       buf = mkshm(buflen);
+#endif
+#if    defined(USE_OS2SHM)
+       buf = mkos2shm(buflen);
+#endif
+#if    defined(USE_BEOS_AREAS)
+       buf = mkbeosshm(buflen);
+#endif
+
+       bufbase = buf;
+       bufend = buf + buflen;
+       EDEBUG(("buf: %p bufend: %p, buflen: %ld\n", buf, bufend, buflen));
+       buf = palign(buf, pagesize);
+       buflen -= buf - bufbase;
+       EDEBUG(("buf: %p bufend: %p, buflen: %ld (align %ld)\n", buf, bufend, buflen, (long)(buf - bufbase)));
+
+       /*
+        * Dirty the whole buffer. This can die with various signals if
+        * we're trying to lock too much memory
+        */
+       fillbytes(buf, buflen, '\0');
+
+#ifdef XDEBUG
+       if (debug)
+               ef = fopen("/tmp/ef", "w");
+#endif
+}
+
+#ifdef USE_MMAP
+static char *
+mkshare(int size)
+{
+       int     f;
+       char    *addr;
+
+#ifdef MAP_ANONYMOUS   /* HP/UX */
+       f = -1;
+       addr = mmap(0, mmap_sizeparm(size),
+                       PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, f, 0);
+#else
+       if ((f = open("/dev/zero", O_RDWR)) < 0)
+               comerr("Cannot open '/dev/zero'.\n");
+       addr = mmap(0, mmap_sizeparm(size),
+                       PROT_READ|PROT_WRITE, MAP_SHARED, f, 0);
+#endif
+       if (addr == (char *)-1)
+               comerr("Cannot get mmap for %d Bytes on /dev/zero.\n", size);
+       if (f >= 0)
+               close(f);
+
+       if (debug) errmsgno(EX_BAD, "shared memory segment attached at: %p size %d\n",
+                               (void *)addr, size);
+
+       return (addr);
+}
+#endif
+
+#ifdef USE_USGSHM
+#include <sys/ipc.h>
+#include <sys/shm.h>
+static char *
+mkshm(int size)
+{
+       int     id;
+       char    *addr;
+       /*
+        * Unfortunately, a declaration of shmat() is missing in old
+        * implementations such as AT&T SVr0 and SunOS.
+        * We cannot add this definition here because the return-type
+        * changed on newer systems.
+        *
+        * We will get a warning like this:
+        *
+        * warning: assignment of pointer from integer lacks a cast
+        * or
+        * warning: illegal combination of pointer and integer, op =
+        */
+/*     extern  char *shmat();*/
+
+       if ((id = shmget(IPC_PRIVATE, size, IPC_CREAT|0600)) == -1)
+               comerr("shmget failed\n");
+
+       if (debug) errmsgno(EX_BAD, "shared memory segment allocated: %d\n", id);
+
+       if ((addr = shmat(id, (char *)0, 0600)) == (char *)-1)
+               comerr("shmat failed\n");
+
+       if (debug) errmsgno(EX_BAD, "shared memory segment attached at: %p size %d\n",
+                               (void *)addr, size);
+
+       if (shmctl(id, IPC_RMID, 0) < 0)
+               comerr("shmctl failed to detach shared memory segment\n");
+
+#ifdef SHM_LOCK
+       /*
+        * Although SHM_LOCK is standard, it seems that all versions of AIX
+        * ommit this definition.
+        */
+       if (shmctl(id, SHM_LOCK, 0) < 0)
+               comerr("shmctl failed to lock shared memory segment\n");
+#endif
+
+       return (addr);
+}
+#endif
+
+#ifdef USE_OS2SHM
+static char *
+mkos2shm(int size)
+{
+       char    *addr;
+
+       /*
+        * The OS/2 implementation of shm (using shm.dll) limits the size of one shared
+        * memory segment to 0x3fa000 (aprox. 4MBytes). Using OS/2 native API we have
+        * no such restriction so I decided to use it allowing fifos of arbitrary size.
+        */
+       if (DosAllocSharedMem(&addr, NULL, size, 0X100L | 0x1L | 0x2L | 0x10L))
+               comerr("DosAllocSharedMem() failed\n");
+
+       if (debug) errmsgno(EX_BAD, "shared memory allocated attached at: %p size %d\n",
+                               (void *)addr, size);
+
+       return (addr);
+}
+#endif
+
+#ifdef USE_BEOS_AREAS
+static area_id faio_aid;
+static void    *faio_addr;
+static char    faio_name[32];
+
+static char *
+mkbeosshm(int size)
+{
+       snprintf(faio_name, sizeof (faio_name), "cdrecord FIFO %lld",
+               (Llong)getpid());
+
+       faio_aid = create_area(faio_name, &faio_addr,
+                       B_ANY_ADDRESS,
+                       size,
+                       B_NO_LOCK, B_READ_AREA|B_WRITE_AREA);
+       if (faio_addr == NULL) {
+               comerrno(faio_aid,
+                       "Cannot get create_area for %d Bytes FIFO.\n", size);
+       }
+       if (debug) errmsgno(EX_BAD, "shared memory allocated attached at: %p size %d\n",
+                               (void *)faio_addr, size);
+       return (faio_addr);
+}
+
+static void
+beosshm_child()
+{
+       /*
+        * Delete the area created by fork that is copy-on-write.
+        */
+       delete_area(area_for(faio_addr));
+       /*
+        * Clone (share) the original one.
+        */
+       faio_aid = clone_area(faio_name, &faio_addr,
+                       B_ANY_ADDRESS, B_READ_AREA|B_WRITE_AREA,
+                       faio_aid);
+       if (bufbase != faio_addr) {
+               errmsgno(EX_BAD, "Panic FIFO addr.\n");
+               return (FALSE);
+       }
+}
+#endif
+
+static int     faio_buffers;
+static int     faio_buf_size;
+static int     buf_idx = 0;            /* Initialize to fix an Amiga bug   */
+static int     buf_idx_reader = 0;     /* Separate var to allow vfork()    */
+                                       /* buf_idx_reader is for the process */
+                                       /* that fills the FIFO              */
+static pid_t   faio_pid = -1;
+static BOOL    faio_didwait;
+
+#ifdef AMIGA
+/*
+ * On Amiga fork will be replaced by the speciall vfork() like call ix_vfork,
+ * which lets the parent asleep. The child process later wakes up the parent
+ * process by calling ix_fork_resume().
+ */
+#define        fork()           ix_vfork()
+#define        __vfork_resume() ix_vfork_resume()
+
+#else  /* !AMIGA */
+#define        __vfork_resume()
+#endif
+
+
+/*#define      faio_ref(n)     (&((faio_t *)buf)[n])*/
+
+
+BOOL
+init_faio(track_t *trackp, int bufsize)
+{
+       int     n;
+       faio_t  *f;
+       int     pagesize;
+       char    *base;
+
+       if (buflen == 0L)
+               return (FALSE);
+
+       pagesize = getpagesize();
+       faio_buf_size = bufsize;
+       f = (faio_t *)buf;
+
+       /*
+        * Compute space for buffer headers.
+        * Round bufsize up to pagesize to make each FIFO segment
+        * properly page aligned.
+        */
+       bufsize = roundup(bufsize, pagesize);
+       faio_buffers = (buflen - sizeof (*sp)) / bufsize;
+       EDEBUG(("bufsize: %d buffers: %d hdrsize %ld\n", bufsize, faio_buffers, (long)faio_buffers * sizeof (struct faio)));
+
+       /*
+        * Reduce buffer space by header space.
+        */
+       n = sizeof (*sp) + faio_buffers * sizeof (struct faio);
+       n = roundup(n, pagesize);
+       faio_buffers = (buflen-n) / bufsize;
+       EDEBUG(("bufsize: %d buffers: %d hdrsize %ld\n", bufsize, faio_buffers, (long)faio_buffers * sizeof (struct faio)));
+
+       if (faio_buffers < MIN_BUFFERS) {
+               errmsgno(EX_BAD,
+                       "write-buffer too small, minimum is %dk. Disabling.\n",
+                                               MIN_BUFFERS*bufsize/1024);
+               return (FALSE);
+       }
+
+       if (debug)
+               printf("Using %d buffers of %d bytes.\n", faio_buffers, faio_buf_size);
+
+       f = (faio_t *)buf;
+       base = buf + roundup(sizeof (*sp) + faio_buffers * sizeof (struct faio),
+                               pagesize);
+
+       for (n = 0; n < faio_buffers; n++, f++, base += bufsize) {
+               /* Give all the buffers to the file reader process */
+               f->owner = owner_writer;
+               f->users = 0;
+               f->bufp = base;
+               f->fd = -1;
+       }
+       sp = (struct faio_stats *)f;    /* point past headers */
+       sp->gets = sp->puts = sp->done = 0L;
+       sp->users = 1;
+
+       faio_pid = fork();
+       if (faio_pid < 0)
+               comerr("fork(2) failed");
+
+       if (faio_pid == 0) {
+               /*
+                * child (background) process that fills the FIFO.
+                */
+               raisepri(1);            /* almost max priority */
+
+#ifdef USE_OS2SHM
+               DosGetSharedMem(buf, 3); /* PAG_READ|PAG_WRITE */
+#endif
+#ifdef USE_BEOS_AREAS
+               beosshm_child();
+#endif
+               /* Ignoring SIGALRM cures the SCO usleep() bug */
+/*             signal(SIGALRM, SIG_IGN);*/
+               __vfork_resume();       /* Needed on some platforms */
+               faio_reader(trackp);
+               /* NOTREACHED */
+       } else {
+#ifdef __needed__
+               Uint    t;
+#endif
+
+               faio_didwait = FALSE;
+
+               /*
+                * XXX We used to close all track files in the foreground
+                * XXX process. This was not correct before we used "xio"
+                * XXX and with "xio" it will start to fail because we need
+                * XXX the fd handles for the faio_get_buf() function.
+                */
+#ifdef __needed__
+               /* close all file-descriptors that only the child will use */
+               for (t = 1; t <= trackp->tracks; t++) {
+                       if (trackp[t].xfp != NULL)
+                               xclose(trackp[t].xfp);
+               }
+#endif
+       }
+
+       return (TRUE);
+}
+
+BOOL
+await_faio()
+{
+       int     n;
+       int     lastfd = -1;
+       faio_t  *f;
+
+       /*
+        * Wait until the reader is active and has filled the buffer.
+        */
+       if (lverbose || debug) {
+               printf("Waiting for reader process to fill input buffer ... ");
+               flush();
+       }
+
+       faio_wait_on_buffer(faio_ref(faio_buffers - 1), owner_reader,
+                           500*MSECS, 0);
+
+       if (lverbose || debug)
+               printf("input buffer ready.\n");
+
+       sp->empty = sp->full = 0L;      /* set correct stat state */
+       sp->cont_low = faio_buffers;    /* set cont to max value  */
+
+       f = faio_ref(0);
+       for (n = 0; n < faio_buffers; n++, f++) {
+               if (f->fd != lastfd &&
+                       f->fd == STDIN_FILENO && f->len == 0) {
+                       errmsgno(EX_BAD, "Premature EOF on stdin.\n");
+                       kill(faio_pid, SIGKILL);
+                       return (FALSE);
+               }
+               lastfd = f->fd;
+       }
+       return (TRUE);
+}
+
+void
+kill_faio()
+{
+       if (faio_pid > 0)
+               kill(faio_pid, SIGKILL);
+  faio_pid=-1;
+}
+
+int
+wait_faio()
+{
+       if (faio_pid > 0 && !faio_didwait)
+               return (wait(0));
+       faio_didwait = TRUE;
+       return (0);
+}
+
+static void
+faio_reader(track_t *trackp)
+{
+       /* This function should not return, but _exit. */
+       Uint    trackno;
+
+       if (debug)
+               printf("\nfaio_reader starting\n");
+
+       for (trackno = 1; trackno <= trackp->tracks; trackno++) {
+               if (debug)
+                       printf("\nfaio_reader reading track %u\n", trackno);
+               faio_read_track(&trackp[trackno]);
+       }
+       sp->done++;
+       if (debug)
+               printf("\nfaio_reader all tracks read, exiting\n");
+
+       /* Prevent hang if buffer is larger than all the tracks combined */
+       if (sp->gets == 0)
+               faio_ref(faio_buffers - 1)->owner = owner_reader;
+
+#ifdef USE_OS2SHM
+       DosFreeMem(buf);
+       sleep(30000);   /* XXX If calling _exit() here the parent process seems to be blocked */
+                       /* XXX This should be fixed soon */
+#endif
+       if (debug)
+               fprintf(stderr, "\nfaio_reader _exit(0)\n");
+       _exit(0);
+}
+
+#ifndef        faio_ref
+static faio_t *
+faio_ref(int n)
+{
+       return (&((faio_t *)buf)[n]);
+}
+#endif
+
+
+static void
+faio_read_track(track_t *trackp)
+{
+       int     fd = -1;
+       int     bytespt = trackp->secsize * trackp->secspt;
+       int     secspt = trackp->secspt;
+       int     l;
+       long    secno = trackp->trackstart;
+       tsize_t tracksize = trackp->tracksize;
+       tsize_t bytes_read = (tsize_t)0;
+       long    bytes_to_read;
+
+       if (trackp->xfp != NULL)
+               fd = xfileno(trackp->xfp);
+
+       if (bytespt > faio_buf_size) {
+               comerrno(EX_BAD,
+               "faio_read_track fatal: secsize %d secspt %d, bytespt(%d) > %d !!\n",
+                       trackp->secsize, trackp->secspt, bytespt,
+                       faio_buf_size);
+       }
+
+       do {
+               bytes_to_read = bytespt;
+               if (tracksize > 0) {
+                       if ((tracksize - bytes_read) > bytespt) {
+                               bytes_to_read = bytespt;
+                       } else {
+                               bytes_to_read = tracksize - bytes_read;
+                       }
+               }
+               l = faio_read_segment(fd, faio_ref(buf_idx_reader), trackp, secno, bytes_to_read);
+               if (++buf_idx_reader >= faio_buffers)
+                       buf_idx_reader = 0;
+               if (l <= 0)
+                       break;
+               bytes_read += l;
+               secno += secspt;
+       } while (tracksize < 0 || bytes_read < tracksize);
+
+       xclose(trackp->xfp);    /* Don't keep files open longer than neccesary */
+}
+
+static void
+#ifdef PROTOTYPES
+faio_wait_on_buffer(faio_t *f, fowner_t s,
+                       unsigned long delay,
+                       unsigned long max_wait)
+#else
+faio_wait_on_buffer(faio_t *f, fowner_t *s, unsigned long delay, unsigned long max_wait)
+#endif
+{
+       unsigned long max_loops;
+
+       if (f->owner == s)
+               return;         /* return immediately if the buffer is ours */
+
+       if (s == owner_reader)
+               sp->empty++;
+       else
+               sp->full++;
+
+       max_loops = max_wait / delay + 1;
+
+       while (max_wait == 0 || max_loops--) {
+               USDEBUG1;
+               usleep(delay);
+               USDEBUG2;
+
+               if (f->owner == s)
+                       return;
+       }
+       if (debug) {
+               errmsgno(EX_BAD,
+               "%lu microseconds passed waiting for %d current: %d idx: %ld\n",
+               max_wait, s, f->owner, (long)(f - faio_ref(0))/sizeof (*f));
+       }
+       comerrno(EX_BAD, "faio_wait_on_buffer for %s timed out.\n",
+       (s > owner_reader || s < owner_none) ? "bad_owner" : onames[s-owner_none]);
+}
+
+static int
+faio_read_segment(int fd, faio_t *f, track_t *trackp, long secno, int len)
+{
+       int l;
+
+       faio_wait_on_buffer(f, owner_writer, WRITER_DELAY, WRITER_MAXWAIT);
+
+       f->fd = fd;
+       l = fill_buf(fd, trackp, secno, f->bufp, len);
+       f->len = l;
+       f->saved_errno = geterrno();
+       f->owner = owner_reader;
+       f->users = sp->users;
+
+       sp->puts++;
+
+       return (l);
+}
+
+int
+faio_read_buf(int fd, char *bp, int size)
+{
+       char *bufp;
+
+       int len = faio_get_buf(fd, &bufp, size);
+       if (len > 0) {
+               movebytes(bufp, bp, len);
+       }
+       return (len);
+}
+
+int
+faio_get_buf(int fd, char **bpp, int size)
+{
+       faio_t  *f;
+       int     len;
+
+again:
+       f = faio_ref(buf_idx);
+       if (f->owner == owner_faio) {
+               f->owner = owner_writer;
+               if (++buf_idx >= faio_buffers)
+                       buf_idx = 0;
+               f = faio_ref(buf_idx);
+       }
+
+       if ((sp->puts - sp->gets) < sp->cont_low && sp->done == 0) {
+               EDEBUG(("gets: %ld puts: %ld cont: %ld low: %ld\n", sp->gets, sp->puts, sp->puts - sp->gets, sp->cont_low));
+               sp->cont_low = sp->puts - sp->gets;
+       }
+       faio_wait_on_buffer(f, owner_reader, READER_DELAY, READER_MAXWAIT);
+       len = f->len;
+
+       if (f->fd != fd) {
+               if (f->len == 0) {
+                       /*
+                        * If the tracksize for this track was known, and
+                        * the tracksize is 0 mod bytespt, this happens.
+                        */
+                       goto again;
+               }
+               comerrno(EX_BAD,
+               "faio_get_buf fatal: fd=%d, f->fd=%d, f->len=%d f->errno=%d\n",
+               fd, f->fd, f->len, f->saved_errno);
+       }
+       if (size < len) {
+               comerrno(EX_BAD,
+               "unexpected short read-attempt in faio_get_buf. size = %d, len = %d\n",
+               size, len);
+       }
+
+       if (len < 0)
+               seterrno(f->saved_errno);
+
+       sp->gets++;
+
+       *bpp = f->bufp;
+       if (--f->users <= 0)
+               f->owner = owner_faio;
+       return (len);
+}
+
+void
+fifo_stats()
+{
+       if (sp == NULL) /* We might not use a FIFO */
+               return;
+
+       errmsgno(EX_BAD, "fifo had %ld puts and %ld gets.\n",
+               sp->puts, sp->gets);
+       errmsgno(EX_BAD, "fifo was %ld times empty and %ld times full, min fill was %ld%%.\n",
+               sp->empty, sp->full, (100L*sp->cont_low)/faio_buffers);
+}
+
+int
+fifo_percent(BOOL addone)
+{
+       int     percent;
+
+       if (sp == NULL) /* We might not use a FIFO */
+               return (-1);
+
+       if (sp->done)
+               return (100);
+       percent = (100*(sp->puts + 1 - sp->gets)/faio_buffers);
+       if (percent > 100)
+               return (100);
+       return (percent);
+}
+#else  /* FIFO */
+
+#include <standard.h>
+#include <utypes.h>    /* includes sys/types.h */
+#include <schily.h>
+
+#include "wodim.h"
+
+void   init_fifo(long);
+BOOL   init_faio(track_t *track, int);
+BOOL   await_faio(void);
+void   kill_faio(void);
+int    wait_faio(void);
+int    faio_read_buf(int f, char *bp, int size);
+int    faio_get_buf(int f, char **bpp, int size);
+void   fifo_stats(void);
+int    fifo_percent(BOOL addone);
+
+
+void init_fifo(long fs)
+{
+       errmsgno(EX_BAD, "Fifo not supported.\n");
+}
+
+BOOL init_faio(track_t *track, 
+               int bufsize /* The size of a single transfer buffer */)
+{
+       return (FALSE);
+}
+
+BOOL await_faio()
+{
+       return (TRUE);
+}
+
+void kill_faio()
+{
+}
+
+int wait_faio()
+{
+       return (0);
+}
+
+int faio_read_buf(int fd, char *bp, int size)
+{
+       return (0);
+}
+
+int faio_get_buf(int fd, char **bpp, int size)
+{
+       return (0);
+}
+
+void fifo_stats()
+{
+}
+
+int fifo_percent(BOOL addone)
+{
+       return (-1);
+}
+
+#endif /* FIFO */
diff --git a/wodim/getnum.c b/wodim/getnum.c
new file mode 100644 (file)
index 0000000..ed13df9
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)getnum.c        1.2 04/03/02 Copyright 1984-2002, 2004 J. Schilling */
+/*
+ *     Number conversion routines to implement 'dd' like options.
+ *
+ *     Copyright (c) 1984-2002, 2004 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <mconfig.h>
+#include <standard.h>
+#include <utypes.h>
+#include <schily.h>
+
+static Llong   number(char *arg, int *retp);
+int    getnum(char *arg, long *valp);
+int    getllnum(char *arg, Llong *lvalp);
+
+static Llong
+number(register char *arg, int *retp)
+{
+       Llong   val     = 0;
+
+       if (*retp != 1)
+               return (val);
+       if (*arg == '\0') {
+               *retp = -1;
+       } else if (*(arg = astoll(arg, &val))) {
+               if (*arg == 'p' || *arg == 'P') {
+                       val *= (1024*1024);
+                       val *= (1024*1024*1024);
+                       arg++;
+
+               } else if (*arg == 't' || *arg == 'T') {
+                       val *= (1024*1024);
+                       val *= (1024*1024);
+                       arg++;
+
+               } else if (*arg == 'g' || *arg == 'G') {
+                       val *= (1024*1024*1024);
+                       arg++;
+
+               } else if (*arg == 'm' || *arg == 'M') {
+                       val *= (1024*1024);
+                       arg++;
+
+               } else if (*arg == 'f' || *arg == 'F') {
+                       val *= 2352;
+                       arg++;
+
+               } else if (*arg == 's' || *arg == 'S') {
+                       val *= 2048;
+                       arg++;
+
+               } else if (*arg == 'k' || *arg == 'K') {
+                       val *= 1024;
+                       arg++;
+
+               } else if (*arg == 'b' || *arg == 'B') {
+                       val *= 512;
+                       arg++;
+
+               } else if (*arg == 'w' || *arg == 'W') {
+                       val *= 2;
+                       arg++;
+               }
+               if (*arg == '*' || *arg == 'x')
+                       val *= number(++arg, retp);
+               else if (*arg != '\0')
+                       *retp = -1;
+       }
+       return (val);
+}
+
+int
+getnum(char *arg, long *valp)
+{
+       Llong   llval;
+       int     ret = 1;
+
+       llval = number(arg, &ret);
+       *valp = llval;
+       if (*valp != llval) {
+               errmsgno(EX_BAD,
+                       "Value %lld is too large for data type 'long'.\n",
+                                                                       llval);
+               ret = -1;
+       }
+       return (ret);
+}
+
+int
+getllnum(char *arg, Llong *lvalp)
+{
+       int     ret = 1;
+
+       *lvalp = number(arg, &ret);
+       return (ret);
+}
diff --git a/wodim/iso9660.h b/wodim/iso9660.h
new file mode 100644 (file)
index 0000000..efcb212
--- /dev/null
@@ -0,0 +1,180 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)iso9660.h       1.5 04/03/02 Copyright 1996, 2004 J. Schilling */
+/*
+ *     Copyright (c) 1996, 2004 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#define        _delta(from, to)        ((to) - (from) + 1)
+
+#define        VD_BOOT         0
+#define        VD_PRIMARY      1
+#define        VD_SUPPLEMENT   2
+#define        VD_PARTITION    3
+#define        VD_TERM         255
+
+#define        VD_ID           "CD001"
+
+struct iso9660_voldesc {
+       char    vd_type         [_delta(1, 1)];
+       char    vd_id           [_delta(2, 6)];
+       char    vd_version      [_delta(7, 7)];
+       char    vd_fill         [_delta(8, 2048)];
+};
+
+struct iso9660_boot_voldesc {
+       char    vd_type         [_delta(1, 1)];
+       char    vd_id           [_delta(2, 6)];
+       char    vd_version      [_delta(7, 7)];
+       char    vd_bootsys      [_delta(8, 39)];
+       char    vd_bootid       [_delta(40, 71)];
+       char    vd_bootcode     [_delta(72, 2048)];
+};
+
+struct iso9660_pr_voldesc {
+       char    vd_type                 [_delta(1,      1)];
+       char    vd_id                   [_delta(2,      6)];
+       char    vd_version              [_delta(7,      7)];
+       char    vd_unused1              [_delta(8,      8)];
+       char    vd_system_id            [_delta(9,      40)];
+       char    vd_volume_id            [_delta(41,     72)];
+       char    vd_unused2              [_delta(73,     80)];
+       char    vd_volume_space_size    [_delta(81,     88)];
+       char    vd_unused3              [_delta(89,     120)];
+       char    vd_volume_set_size      [_delta(121,    124)];
+       char    vd_volume_seq_number    [_delta(125,    128)];
+       char    vd_lbsize               [_delta(129,    132)];
+       char    vd_path_table_size      [_delta(133,    140)];
+       char    vd_pos_path_table_l     [_delta(141,    144)];
+       char    vd_opt_pos_path_table_l [_delta(145,    148)];
+       char    vd_pos_path_table_m     [_delta(149,    152)];
+       char    vd_opt_pos_path_table_m [_delta(153,    156)];
+       char    vd_root_dir             [_delta(157,    190)];
+       char    vd_volume_set_id        [_delta(191,    318)];
+       char    vd_publisher_id         [_delta(319,    446)];
+       char    vd_data_preparer_id     [_delta(447,    574)];
+       char    vd_application_id       [_delta(575,    702)];
+       char    vd_copyr_file_id        [_delta(703,    739)];
+       char    vd_abstr_file_id        [_delta(740,    776)];
+       char    vd_bibl_file_id         [_delta(777,    813)];
+       char    vd_create_time          [_delta(814,    830)];
+       char    vd_mod_time             [_delta(831,    847)];
+       char    vd_expiry_time          [_delta(848,    864)];
+       char    vd_effective_time       [_delta(865,    881)];
+       char    vd_file_struct_vers     [_delta(882,    882)];
+       char    vd_reserved1            [_delta(883,    883)];
+       char    vd_application_use      [_delta(884,    1395)];
+       char    vd_fill                 [_delta(1396,   2048)];
+};
+
+struct iso9660_dir {
+       char    dr_len                  [_delta(1,      1)];
+       char    dr_eattr_len            [_delta(2,      2)];
+       char    dr_eattr_pos            [_delta(3,      10)];
+       char    dr_data_len             [_delta(11,     18)];
+       char    dr_recording_time       [_delta(19,     25)];
+       char    dr_file_flags           [_delta(26,     26)];
+       char    dr_file_unit_size       [_delta(27,     27)];
+       char    dr_interleave_gap       [_delta(28,     28)];
+       char    dr_volume_seq_number    [_delta(29,     32)];
+       char    dr_file_name_len        [_delta(33,     33)];
+       char    dr_file_name            [_delta(34,     34)];
+};
+
+struct iso9660_dtime {
+       unsigned char   dt_year;
+       unsigned char   dt_month;
+       unsigned char   dt_day;
+       unsigned char   dt_hour;
+       unsigned char   dt_minute;
+       unsigned char   dt_second;
+               char    dt_gmtoff;
+};
+
+struct iso9660_ltime {
+       char    lt_year                 [_delta(1,      4)];
+       char    lt_month                [_delta(5,      6)];
+       char    lt_day                  [_delta(7,      8)];
+       char    lt_hour                 [_delta(9,      10)];
+       char    lt_minute               [_delta(11,     12)];
+       char    lt_second               [_delta(13,     14)];
+       char    lt_hsecond              [_delta(15,     16)];
+       char    lt_gmtoff               [_delta(17,     17)];
+};
+
+struct iso9660_path_table {
+       char    pt_di_len               [_delta(1,      1)];
+       char    pt_eattr_len            [_delta(2,      2)];
+       char    pt_eattr_pos            [_delta(3,      6)];
+       char    pt_di_parent            [_delta(7,      8)];
+       char    pt_name                 [_delta(9,      9)];
+};
+
+struct iso9660_eattr {
+       char    ea_owner                [_delta(1,      4)];
+       char    ea_group                [_delta(5,      8)];
+       char    ea_perm                 [_delta(9,      10)];
+       char    ea_ctime                [_delta(11,     27)];
+       char    ea_mtime                [_delta(28,     44)];
+       char    ea_extime               [_delta(45,     61)];
+       char    ea_eftime               [_delta(62,     78)];
+       char    ea_record_format        [_delta(79,     79)];
+       char    ea_record_attr          [_delta(80,     80)];
+       char    ea_record_len           [_delta(81,     84)];
+       char    ea_system_id            [_delta(85,     116)];
+       char    ea_system_use           [_delta(117,    180)];
+       char    ea_version              [_delta(181,    181)];
+       char    ea_esc_seq_len          [_delta(182,    182)];
+       char    ea_reserved1            [_delta(183,    246)];
+       char    ea_appl_use_len         [_delta(247,    250)];
+       char    ea_appl_use             [_delta(251,    251)];  /* actually more */
+/*     char    ea_esc_seq              [_delta(xxx,    xxx)];  */
+
+};
+
+#define        PERM_MB_ONE     0xAAAA
+
+#define        PERM_RSYS       0x0001
+#define        PERM_XSYS       0x0004
+
+#define        PERM_RUSR       0x0010
+#define        PERM_XUSR       0x0040
+
+#define        PERM_RGRP       0x0100
+#define        PERM_XGRP       0x0400
+
+#define        PERM_ROTH       0x1000
+#define        PERM_XOTH       0x4000
+
+
+#define        GET_UBYTE(a)    a_to_u_byte(a)
+#define        GET_SBYTE(a)    a_to_byte(a)
+#define        GET_SHORT(a)    a_to_u_2_byte(&((unsigned char *) (a))[0])
+#define        GET_BSHORT(a)   a_to_u_2_byte(&((unsigned char *) (a))[2])
+#define        GET_INT(a)      a_to_4_byte(&((unsigned char *) (a))[0])
+#define        GET_LINT(a)     la_to_4_byte(&((unsigned char *) (a))[0])
+#define        GET_BINT(a)     a_to_4_byte(&((unsigned char *) (a))[4])
diff --git a/wodim/isosize.c b/wodim/isosize.c
new file mode 100644 (file)
index 0000000..b3f6624
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)isosize.c       1.9 04/03/02 Copyright 1996, 2001-2004 J. Schilling */
+/*
+ *     Copyright (c) 1996, 2001-2004 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <mconfig.h>
+#include <statdefs.h>
+#include <unixstd.h>
+#include <standard.h>
+#include <utypes.h>
+#include <intcvt.h>
+
+#include "iso9660.h"
+#include "wodim.h"     /* to verify isosize() prototype */
+
+Llong  isosize(int f);
+
+Llong
+isosize(int f)
+{
+       struct iso9660_voldesc          vd;
+       struct iso9660_pr_voldesc       *vp;
+       Llong                           isize;
+       struct stat                     sb;
+       mode_t                          mode;
+
+       /*
+        * First check if a bad guy tries to call isosize()
+        * with an unappropriate file descriptor.
+        * return -1 in this case.
+        */
+       if (isatty(f))
+               return ((Llong)-1);
+       if (fstat(f, &sb) < 0)
+               return ((Llong)-1);
+       mode = sb.st_mode & S_IFMT;
+       if (!S_ISREG(mode) && !S_ISBLK(mode) && !S_ISCHR(mode))
+               return ((Llong)-1);
+
+       if (lseek(f, (off_t)(16L * 2048L), SEEK_SET) == -1)
+               return ((Llong)-1);
+
+       vp = (struct iso9660_pr_voldesc *) &vd;
+
+       do {
+               read(f, &vd, sizeof (vd)); /* FIXME: check return value */
+               if (GET_UBYTE(vd.vd_type) == VD_PRIMARY)
+                       break;
+
+       } while (GET_UBYTE(vd.vd_type) != VD_TERM);
+
+       lseek(f, (off_t)0L, SEEK_SET);
+
+       if (GET_UBYTE(vd.vd_type) != VD_PRIMARY)
+               return (-1L);
+
+       isize = (Llong)GET_BINT(vp->vd_volume_space_size);
+       isize *= GET_BSHORT(vp->vd_lbsize);
+       return (isize);
+}
diff --git a/wodim/misc.c b/wodim/misc.c
new file mode 100644 (file)
index 0000000..ada60a4
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)misc.c  1.4 04/03/02 Copyright 1998, 2001-2004 J. Schilling */
+/*
+ *     Misc support functions
+ *
+ *     Copyright (c) 1998, 2001-2004 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <mconfig.h>
+#include <timedefs.h>
+#include <stdio.h>
+#include <standard.h>
+#include <schily.h>
+
+void   timevaldiff(struct timeval *start, struct timeval *stop);
+void   prtimediff(const char *fmt, struct timeval *start, struct timeval *stop);
+
+void
+timevaldiff(struct timeval *start, struct timeval *stop)
+{
+       struct timeval tv;
+
+       tv.tv_sec = stop->tv_sec - start->tv_sec;
+       tv.tv_usec = stop->tv_usec - start->tv_usec;
+       while (tv.tv_usec > 1000000) {
+               tv.tv_usec -= 1000000;
+               tv.tv_sec += 1;
+       }
+       while (tv.tv_usec < 0) {
+               tv.tv_usec += 1000000;
+               tv.tv_sec -= 1;
+       }
+       *stop = tv;
+}
+
+void
+prtimediff(const char *fmt, struct timeval *start, struct timeval *stop)
+{
+       struct timeval tv;
+
+       tv.tv_sec = stop->tv_sec - start->tv_sec;
+       tv.tv_usec = stop->tv_usec - start->tv_usec;
+       while (tv.tv_usec > 1000000) {
+               tv.tv_usec -= 1000000;
+               tv.tv_sec += 1;
+       }
+       while (tv.tv_usec < 0) {
+               tv.tv_usec += 1000000;
+               tv.tv_sec -= 1;
+       }
+       /*
+        * We need to cast timeval->* to long because
+        * of the broken sys/time.h in Linux.
+        */
+       printf("%s%4ld.%03lds\n", fmt, (long)tv.tv_sec, (long)tv.tv_usec/1000);
+       flush();
+}
diff --git a/wodim/mmcvendor.h b/wodim/mmcvendor.h
new file mode 100644 (file)
index 0000000..3c71afc
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)mmcvendor.h     1.3 04/03/01 Copyright 2002-2004 J. Schilling */
+/*
+ *     Copyright (c) 2002-2004 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef        _MMCVENDOR_H
+#define        _MMCVENDOR_H
+
+#include <utypes.h>
+#include <btorder.h>
+
+#if defined(_BIT_FIELDS_LTOH)  /* Intel bitorder */
+
+struct ricoh_mode_page_30 {
+               MP_P_CODE;              /* parsave & pagecode */
+       Uchar   p_len;                  /* 0xE = 14 Bytes */
+       Ucbit   BUEFS           :1;     /* Burn-Free supported  */
+       Ucbit   TWBFS           :1;     /* Test Burn-Free sup.  */
+       Ucbit   res_2_23        :2;
+       Ucbit   ARSCS           :1;     /* Auto read speed control supp. */
+       Ucbit   AWSCS           :1;     /* Auto write speed control supp. */
+       Ucbit   res_2_67        :2;
+       Ucbit   BUEFE           :1;     /* Burn-Free enabled    */
+       Ucbit   res_2_13        :3;
+       Ucbit   ARSCE           :1;     /* Auto read speed control enabled */
+       Ucbit   AWSCD           :1;     /* Auto write speed control disabled */
+       Ucbit   res_3_67        :2;
+       Uchar   link_counter[2];        /* Burn-Free link counter */
+       Uchar   res[10];                /* Padding up to 16 bytes */
+};
+
+#else                          /* Motorola bitorder */
+
+struct ricoh_mode_page_30 {
+               MP_P_CODE;              /* parsave & pagecode */
+       Uchar   p_len;                  /* 0xE = 14 Bytes */
+       Ucbit   res_2_67        :2;
+       Ucbit   AWSCS           :1;     /* Auto write speed control supp. */
+       Ucbit   ARSCS           :1;     /* Auto read speed control supp. */
+       Ucbit   res_2_23        :2;
+       Ucbit   TWBFS           :1;     /* Test Burn-Free sup.  */
+       Ucbit   BUEFS           :1;     /* Burn-Free supported  */
+       Ucbit   res_3_67        :2;
+       Ucbit   AWSCD           :1;     /* Auto write speed control disabled */
+       Ucbit   ARSCE           :1;     /* Auto read speed control enabled */
+       Ucbit   res_2_13        :3;
+       Ucbit   BUEFE           :1;     /* Burn-Free enabled    */
+       Uchar   link_counter[2];        /* Burn-Free link counter */
+       Uchar   res[10];                /* Padding up to 16 bytes */
+};
+#endif
+
+struct cd_mode_vendor {
+       struct scsi_mode_header header;
+       union cd_v_pagex {
+               struct ricoh_mode_page_30 page30;
+       } pagex;
+};
+
+
+#endif /* _MMCVENDOR_H */
diff --git a/wodim/modes.c b/wodim/modes.c
new file mode 100644 (file)
index 0000000..6718352
--- /dev/null
@@ -0,0 +1,289 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)modes.c 1.25 04/03/02 Copyright 1988, 1997-2001, 2004 J. Schilling */
+/*
+ *     SCSI mode page handling
+ *
+ *     Copyright (c) 1988, 1997-2001, 2004 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <mconfig.h>
+#include <utypes.h>
+#include <standard.h>
+#include <schily.h>
+#include <usal/usalcmd.h>
+#include <usal/scsireg.h>
+#include <usal/scsitransp.h>
+
+#include "wodim.h"
+
+int    scsi_compliant;
+
+static BOOL    has_mode_page(SCSI *usalp, int page, char *pagename, int *lenp);
+BOOL   get_mode_params(SCSI *usalp, int page, char *pagename, Uchar *modep, 
+                                                        Uchar *cmodep, Uchar *dmodep, Uchar *smodep, int *lenp);
+BOOL   set_mode_params(SCSI *usalp, char *pagename, Uchar *modep, int len, 
+                                                        int save, int secsize);
+
+#define        XXX
+
+#ifdef XXX
+static BOOL
+has_mode_page(SCSI *usalp, int page, char *pagename, int *lenp)
+{
+       Uchar   mode[0x100];
+       int     hdlen;
+       int     len = 1;                                /* Nach SCSI Norm */
+       int     try = 0;
+       struct  scsi_mode_page_header *mp;
+
+       /*
+        * ATAPI drives (used e.g. by IOMEGA) from y2k have the worst firmware
+        * I've seen. They create DMA buffer overruns if we request less than
+        * 3 bytes with 6 byte mode sense which equals 4 byte with 10 byte mode
+        * sense. In order to prevent repeated bus resets, we remember this
+        * bug.
+        *
+        * IOMEGA claims that they are using Philips clone drives but a Philips
+        * drive I own does not have the problem.
+        */
+       if ((usalp->dflags & DRF_MODE_DMA_OVR) != 0)
+               len = sizeof (struct scsi_mode_header);
+again:
+       fillbytes((caddr_t)mode, sizeof (mode), '\0');
+       if (lenp)
+               *lenp = 0;
+
+       usalp->silent++;
+       (void) unit_ready(usalp);
+/* Maxoptix bringt Aborted cmd 0x0B mit code 0x4E (overlapping cmds)*/
+
+       /*
+        * The Matsushita CW-7502 will sometimes deliver a zeroed
+        * mode page 2A if "Page n default" is used instead of "current".
+        */
+       if (mode_sense(usalp, mode, len, page, 0) < 0) {        /* Page n current */
+               usalp->silent--;
+               if (len < (int)sizeof (struct scsi_mode_header) && try == 0) {
+                       len = sizeof (struct scsi_mode_header);
+                       goto again;
+               }
+               return (FALSE);
+       } else {
+               if (len > 1 && try == 0) {
+                       /*
+                        * If we come here, we got a hard failure with the
+                        * fist try. Remember this (IOMEGA USB) firmware bug.
+                        */
+                       if ((usalp->dflags & DRF_MODE_DMA_OVR) == 0) {
+                               /* XXX if (!nowarn) */
+                               errmsgno(EX_BAD,
+                               "Warning: controller creates hard SCSI failure when retrieving %s page.\n",
+                                                               pagename);
+                               usalp->dflags |= DRF_MODE_DMA_OVR;
+                       }
+               }
+               len = ((struct scsi_mode_header *)mode)->sense_data_len + 1;
+       }
+       /*
+        * ATAPI drives as used by IOMEGA may receive a SCSI bus device reset
+        * in between these two mode sense commands.
+        */
+       (void) unit_ready(usalp);
+       if (mode_sense(usalp, mode, len, page, 0) < 0) {        /* Page n current */
+               usalp->silent--;
+               return (FALSE);
+       }
+       usalp->silent--;
+
+       if (usalp->verbose)
+               usal_prbytes("Mode Sense Data", mode, len - usal_getresid(usalp));
+       hdlen = sizeof (struct scsi_mode_header) +
+                       ((struct scsi_mode_header *)mode)->blockdesc_len;
+       mp = (struct scsi_mode_page_header *)(mode + hdlen);
+       if (usalp->verbose)
+               usal_prbytes("Mode Page  Data", (Uchar *)mp, mp->p_len+2);
+
+       if (mp->p_len == 0) {
+               if (!scsi_compliant && try == 0) {
+                       len = hdlen;
+                       /*
+                        * add sizeof page header (page # + len byte)
+                        * (should normaly result in len == 14)
+                        * this allowes to work with:
+                        *      Quantum Q210S   (wants at least 13)
+                        *      MD2x            (wants at least 4)
+                        */
+                       len += 2;
+                       try++;
+                       goto again;
+               }
+               /* XXX if (!nowarn) */
+               errmsgno(EX_BAD,
+                       "Warning: controller returns zero sized %s page.\n",
+                                                               pagename);
+       }
+       if (!scsi_compliant &&
+           (len < (int)(mp->p_len + hdlen + 2))) {
+               len = mp->p_len + hdlen + 2;
+
+               /* XXX if (!nowarn) */
+               errmsgno(EX_BAD,
+                       "Warning: controller returns wrong size for %s page.\n",
+                                                               pagename);
+       }
+       if (mp->p_code != page) {
+               /* XXX if (!nowarn) */
+               errmsgno(EX_BAD,
+                       "Warning: controller returns wrong page %X for %s page (%X).\n",
+                                               mp->p_code, pagename, page);
+               return (FALSE);
+       }
+
+       if (lenp)
+               *lenp = len;
+       return (mp->p_len > 0);
+}
+#endif
+
+BOOL
+get_mode_params(SCSI *usalp, int page, char *pagename, Uchar *modep, 
+                Uchar *cmodep, Uchar *dmodep, Uchar *smodep, int *lenp)
+{
+       int     len;
+       BOOL    ret = TRUE;
+
+#ifdef XXX
+       if (lenp)
+               *lenp = 0;
+       if (!has_mode_page(usalp, page, pagename, &len)) {
+               if (!usalp->silent) errmsgno(EX_BAD,
+                       "Warning: controller does not support %s page.\n",
+                                                               pagename);
+               return (FALSE);
+       }
+       if (lenp)
+               *lenp = len;
+#else
+       if (lenp == 0)
+               len = 0xFF;
+#endif
+
+       if (modep) {
+               fillbytes(modep, 0x100, '\0');
+               usalp->silent++;
+               (void) unit_ready(usalp);
+               usalp->silent--;
+               if (mode_sense(usalp, modep, len, page, 0) < 0) { /* Page x current */
+                       errmsgno(EX_BAD, "Cannot get %s data.\n", pagename);
+                       ret = FALSE;
+               } else if (usalp->verbose) {
+                       usal_prbytes("Mode Sense Data", modep, len - usal_getresid(usalp));
+               }
+       }
+
+       if (cmodep) {
+               fillbytes(cmodep, 0x100, '\0');
+               usalp->silent++;
+               (void) unit_ready(usalp);
+               usalp->silent--;
+               if (mode_sense(usalp, cmodep, len, page, 1) < 0) { /* Page x change */
+                       errmsgno(EX_BAD, "Cannot get %s mask.\n", pagename);
+                       ret = FALSE;
+               } else if (usalp->verbose) {
+                       usal_prbytes("Mode Sense Data", cmodep, len - usal_getresid(usalp));
+               }
+       }
+
+       if (dmodep) {
+               fillbytes(dmodep, 0x100, '\0');
+               usalp->silent++;
+               (void) unit_ready(usalp);
+               usalp->silent--;
+               if (mode_sense(usalp, dmodep, len, page, 2) < 0) { /* Page x default */
+                       errmsgno(EX_BAD, "Cannot get default %s data.\n",
+                                                               pagename);
+                       ret = FALSE;
+               } else if (usalp->verbose) {
+                       usal_prbytes("Mode Sense Data", dmodep, len - usal_getresid(usalp));
+               }
+       }
+
+       if (smodep) {
+               fillbytes(smodep, 0x100, '\0');
+               usalp->silent++;
+               (void) unit_ready(usalp);
+               usalp->silent--;
+               if (mode_sense(usalp, smodep, len, page, 3) < 0) { /* Page x saved */
+                       errmsgno(EX_BAD, "Cannot get saved %s data.\n", pagename);
+                       ret = FALSE;
+               } else if (usalp->verbose) {
+                       usal_prbytes("Mode Sense Data", smodep, len - usal_getresid(usalp));
+               }
+       }
+
+       return (ret);
+}
+
+BOOL
+set_mode_params(SCSI *usalp, char *pagename, Uchar *modep, int len, int save, 
+                int secsize)
+{
+       int     i;
+
+       ((struct scsi_modesel_header *)modep)->sense_data_len   = 0;
+       ((struct scsi_modesel_header *)modep)->res2             = 0;
+
+       i = ((struct scsi_mode_header *)modep)->blockdesc_len;
+       if (i > 0) {
+               i_to_3_byte(
+                       ((struct scsi_mode_data *)modep)->blockdesc.nlblock,
+                                                               0);
+               if (secsize >= 0)
+               i_to_3_byte(((struct scsi_mode_data *)modep)->blockdesc.lblen,
+                                                       secsize);
+       }
+
+       usalp->silent++;
+       (void) unit_ready(usalp);
+       usalp->silent--;
+       if (save == 0 || mode_select(usalp, modep, len, save, usalp->inq->data_format >= 2) < 0) {
+               usalp->silent++;
+               (void) unit_ready(usalp);
+               usalp->silent--;
+               if (mode_select(usalp, modep, len, 0, usalp->inq->data_format >= 2) < 0) {
+                       if (usalp->silent == 0) {
+                               errmsgno(EX_BAD,
+                                       "Warning: using default %s data.\n",
+                                       pagename);
+                               usal_prbytes("Mode Select Data", modep, len);
+                       }
+                       return (FALSE);
+               }
+       }
+       return (TRUE);
+}
diff --git a/wodim/movesect.c b/wodim/movesect.c
new file mode 100644 (file)
index 0000000..ef4bc70
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)movesect.c      1.3 04/03/02 Copyright 2001, 2004 J. Schilling */
+/*
+ *     Copyright (c) 2001, 2004 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <mconfig.h>
+#include <standard.h>
+#include <utypes.h>
+#include <schily.h>
+
+#include "wodim.h"
+#include "movesect.h"
+
+void   scatter_secs(track_t *trackp, char *bp, int nsecs);
+
+/*
+ * Scatter input sector size records over buffer to make them
+ * output sector size.
+ *
+ * If input sector size is less than output sector size,
+ *
+ *     | sector_0 || sector_1 || ... || sector_n ||
+ *
+ * will be convterted into:
+ *
+ *     | sector_0 |grass|| sector_1 |grass|| ... || sector_n |grass||
+ *
+ *     Sector_n must me moved n * grass_size forward,
+ *     Sector_1 must me moved 1 * grass_size forward
+ *
+ *
+ * If output sector size is less than input sector size,
+ *
+ *     | sector_0 |grass|| sector_1 |grass|| ... || sector_n |grass||
+ *
+ * will be convterted into:
+ *
+ *     | sector_0 || sector_1 || ... || sector_n ||
+ *
+ *     Sector_1 must me moved 1 * grass_size backward,
+ *     Sector_n must me moved n * grass_size backward,
+ *
+ *     Sector_0 must never be moved.
+ */
+void
+scatter_secs(track_t *trackp, char *bp, int nsecs)
+{
+       char    *from;
+       char    *to;
+       int     isecsize = trackp->isecsize;
+       int     secsize = trackp->secsize;
+       int     i;
+
+       if (secsize == isecsize)
+               return;
+
+       nsecs -= 1;     /* we do not move sector # 0 */
+
+       if (secsize < isecsize) {
+               from = bp + isecsize;
+               to   = bp + secsize;
+
+               for (i = nsecs; i > 0; i--) {
+                       movebytes(from, to, secsize);
+                       from += isecsize;
+                       to   += secsize;
+               }
+       } else {
+               from = bp + (nsecs * isecsize);
+               to   = bp + (nsecs * secsize);
+
+               for (i = nsecs; i > 0; i--) {
+                       movebytes(from, to, isecsize);
+                       from -= isecsize;
+                       to   -= secsize;
+               }
+       }
+}
diff --git a/wodim/movesect.h b/wodim/movesect.h
new file mode 100644 (file)
index 0000000..64f09b7
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)movesect.h      1.1 01/06/02 Copyright 2001 J. Schilling */
+/*
+ *     Copyright (c) 2001 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef        _MOVESECT_H
+#define        _MOVESECT_H
+
+#define        move2352(from, to)      movebytes(from, to, 2352)
+#define        move2336(from, to)      movebytes(from, to, 2336)
+#define        move2048(from, to)      movebytes(from, to, 2048)
+
+#define        fill2352(p, val)        fillbytes(p, 2352, val)
+#define        fill2048(p, val)        fillbytes(p, 2048, val)
+#define        fill96(p, val)          fillbytes(p, 96, val)
+
+extern void    scatter_secs(track_t *trackp, char *bp, int nsecs);
+
+#endif
diff --git a/wodim/scsi_cdr.c b/wodim/scsi_cdr.c
new file mode 100644 (file)
index 0000000..fbb8270
--- /dev/null
@@ -0,0 +1,2918 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)scsi_cdr.c      1.137 04/05/25 Copyright 1995-2004 J. Schilling */
+/*
+ *     SCSI command functions for cdrecord
+ *     covering pre-MMC standard functions up to MMC-2
+ *
+ *     Copyright (c) 1995-2004 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * NOTICE:     The Philips CDD 521 has several firmware bugs.
+ *             One of them is not to respond to a SCSI selection
+ *             within 200ms if the general load on the
+ *             SCSI bus is high. To deal with this problem
+ *             most of the SCSI commands are send with the
+ *             SCG_CMD_RETRY flag enabled.
+ */
+#include <mconfig.h>
+
+#include <stdio.h>
+#include <standard.h>
+#include <stdxlib.h>
+#include <unixstd.h>
+#include <fctldefs.h>
+#include <errno.h>
+#include <strdefs.h>
+#include <timedefs.h>
+
+#include <utypes.h>
+#include <btorder.h>
+#include <intcvt.h>
+#include <schily.h>
+
+#include <usal/usalcmd.h>
+#include <usal/scsidefs.h>
+#include <usal/scsireg.h>
+#include <usal/scsitransp.h>
+
+#include "scsimmc.h"
+#include "wodim.h"
+#include "scsi_scan.h"
+
+#define        strbeg(s1, s2)  (strstr((s2), (s1)) == (s2))
+
+BOOL   unit_ready(SCSI *usalp);
+BOOL   wait_unit_ready(SCSI *usalp, int secs);
+BOOL   scsi_in_progress(SCSI *usalp);
+BOOL   cdr_underrun(SCSI *usalp);
+int    test_unit_ready(SCSI *usalp);
+int    rezero_unit(SCSI *usalp);
+int    request_sense(SCSI *usalp);
+int    request_sense_b(SCSI *usalp, caddr_t bp, int cnt);
+int    inquiry(SCSI *usalp, caddr_t, int);
+int    read_capacity(SCSI *usalp);
+void   print_capacity(SCSI *usalp, FILE *f);
+int    scsi_load_unload(SCSI *usalp, int);
+int    scsi_prevent_removal(SCSI *usalp, int);
+int    scsi_start_stop_unit(SCSI *usalp, int, int, BOOL immed);
+int    scsi_set_speed(SCSI *usalp, int readspeed, int writespeed, int rotctl);
+int    scsi_get_speed(SCSI *usalp, int *readspeedp, int *writespeedp);
+int    qic02(SCSI *usalp, int);
+int    write_xscsi(SCSI *usalp, caddr_t, long, long, int);
+int    write_xg0(SCSI *usalp, caddr_t, long, long, int);
+int    write_xg1(SCSI *usalp, caddr_t, long, long, int);
+int    write_xg5(SCSI *usalp, caddr_t, long, long, int);
+int    seek_scsi(SCSI *usalp, long addr);
+int    seek_g0(SCSI *usalp, long addr);
+int    seek_g1(SCSI *usalp, long addr);
+int    scsi_flush_cache(SCSI *usalp, BOOL immed);
+int    read_buffer(SCSI *usalp, caddr_t bp, int cnt, int mode);
+int    write_buffer(SCSI *usalp, char *buffer, long length, int mode, 
+                                                int bufferid, long offset);
+int    read_subchannel(SCSI *usalp, caddr_t bp, int track, int cnt, int msf, 
+                                                        int subq, int fmt);
+int    read_toc(SCSI *usalp, caddr_t, int, int, int, int);
+int    read_toc_philips(SCSI *usalp, caddr_t, int, int, int, int);
+int    read_header(SCSI *usalp, caddr_t, long, int, int);
+int    read_disk_info(SCSI *usalp, caddr_t, int);
+int    read_track_info(SCSI *usalp, caddr_t, int type, int addr, int cnt);
+int    read_rzone_info(SCSI *usalp, caddr_t bp, int cnt);
+int    reserve_tr_rzone(SCSI *usalp, long size);
+int    read_dvd_structure(SCSI *usalp, caddr_t bp, int cnt, int addr, int layer, 
+                                                                int fmt);
+int    send_dvd_structure(SCSI *usalp, caddr_t bp, int cnt, int layer, int fmt);
+int    send_opc(SCSI *usalp, caddr_t, int cnt, int doopc);
+int    read_track_info_philips(SCSI *usalp, caddr_t, int, int);
+int    scsi_close_tr_session(SCSI *usalp, int type, int track, BOOL immed);
+int    read_master_cue(SCSI *usalp, caddr_t bp, int sheet, int cnt);
+int    send_cue_sheet(SCSI *usalp, caddr_t bp, long size);
+int    read_buff_cap(SCSI *usalp, long *, long *);
+int    scsi_blank(SCSI *usalp, long addr, int blanktype, BOOL immed);
+int    scsi_format(SCSI *usalp, caddr_t addr, int size, BOOL background);
+int    scsi_set_streaming(SCSI *usalp, caddr_t addr, int size);
+BOOL   allow_atapi(SCSI *usalp, BOOL new);
+int    mode_select(SCSI *usalp, Uchar *, int, int, int);
+int    mode_sense(SCSI *usalp, Uchar *dp, int cnt, int page, int pcf);
+int    mode_select_sg0(SCSI *usalp, Uchar *, int, int, int);
+int    mode_sense_sg0(SCSI *usalp, Uchar *dp, int cnt, int page, int pcf);
+int    mode_select_g0(SCSI *usalp, Uchar *, int, int, int);
+int    mode_select_g1(SCSI *usalp, Uchar *, int, int, int);
+int    mode_sense_g0(SCSI *usalp, Uchar *dp, int cnt, int page, int pcf);
+int    mode_sense_g1(SCSI *usalp, Uchar *dp, int cnt, int page, int pcf);
+int    read_tochdr(SCSI *usalp, cdr_t *, int *, int *);
+int    read_cdtext(SCSI *usalp);
+int    read_trackinfo(SCSI *usalp, int, long *, struct msf *, int *, int *, 
+                                                       int *);
+int    read_B0(SCSI *usalp, BOOL isbcd, long *b0p, long *lop);
+int    read_session_offset(SCSI *usalp, long *);
+int    read_session_offset_philips(SCSI *usalp, long *);
+int    sense_secsize(SCSI *usalp, int current);
+int    select_secsize(SCSI *usalp, int);
+BOOL   is_cddrive(SCSI *usalp);
+BOOL   is_unknown_dev(SCSI *usalp);
+int    read_scsi(SCSI *usalp, caddr_t, long, int);
+int    read_g0(SCSI *usalp, caddr_t, long, int);
+int    read_g1(SCSI *usalp, caddr_t, long, int);
+BOOL   getdev(SCSI *usalp, BOOL);
+void   printinq(SCSI *usalp, FILE *f);
+void   printdev(SCSI *usalp);
+BOOL   do_inquiry(SCSI *usalp, BOOL);
+BOOL   recovery_needed(SCSI *usalp, cdr_t *);
+int    scsi_load(SCSI *usalp, cdr_t *);
+int    scsi_unload(SCSI *usalp, cdr_t *);
+int    scsi_cdr_write(SCSI *usalp, caddr_t bp, long sectaddr, long size, 
+                                                       int blocks, BOOL islast);
+struct cd_mode_page_2A * mmc_cap(SCSI *usalp, Uchar *modep);
+void   mmc_getval(struct cd_mode_page_2A *mp, BOOL *cdrrp, BOOL *cdwrp, 
+                                         BOOL *cdrrwp, BOOL *cdwrwp, BOOL *dvdp, BOOL *dvdwp);
+BOOL   is_mmc(SCSI *usalp, BOOL *cdwp, BOOL *dvdwp);
+BOOL   mmc_check(SCSI *usalp, BOOL *cdrrp, BOOL *cdwrp, BOOL *cdrrwp, 
+                                        BOOL *cdwrwp, BOOL *dvdp, BOOL *dvdwp);
+static void    print_speed(char *fmt, int val);
+void   print_capabilities(SCSI *usalp);
+
+BOOL
+unit_ready(SCSI *usalp)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       if (test_unit_ready(usalp) >= 0)                /* alles OK */
+               return (TRUE);
+       else if (scmd->error >= SCG_FATAL)      /* nicht selektierbar */
+               return (FALSE);
+
+       if (usal_sense_key(usalp) == SC_UNIT_ATTENTION) {
+               if (test_unit_ready(usalp) >= 0)        /* alles OK */
+                       return (TRUE);
+       }
+       if ((usal_cmd_status(usalp) & ST_BUSY) != 0) {
+               /*
+                * Busy/reservation_conflict
+                */
+               usleep(500000);
+               if (test_unit_ready(usalp) >= 0)        /* alles OK */
+                       return (TRUE);
+       }
+       if (usal_sense_key(usalp) == -1) {      /* non extended Sense */
+               if (usal_sense_code(usalp) == 4)        /* NOT_READY */
+                       return (FALSE);
+               return (TRUE);
+       }
+                                               /* FALSE wenn NOT_READY */
+       return (usal_sense_key(usalp) != SC_NOT_READY);
+}
+
+BOOL
+wait_unit_ready(SCSI *usalp, int secs)
+{
+       int     i;
+       int     c;
+       int     k;
+       int     ret;
+
+       usalp->silent++;
+       ret = test_unit_ready(usalp);           /* eat up unit attention */
+       if (ret < 0)
+               ret = test_unit_ready(usalp);   /* got power on condition? */
+       usalp->silent--;
+
+       if (ret >= 0)                           /* success that's enough */
+               return (TRUE);
+
+       usalp->silent++;
+       for (i = 0; i < secs && (ret = test_unit_ready(usalp)) < 0; i++) {
+               if (usalp->scmd->scb.busy != 0) {
+                       sleep(1);
+                       continue;
+               }
+               c = usal_sense_code(usalp);
+               k = usal_sense_key(usalp);
+               /*
+                * Abort quickly if it does not make sense to wait.
+                * 0x30 == Cannot read medium
+                * 0x3A == Medium not present
+                */
+               if ((k == SC_NOT_READY && (c == 0x3A || c == 0x30)) ||
+                   (k == SC_MEDIUM_ERROR)) {
+                       if (usalp->silent <= 1)
+                               usal_printerr(usalp);
+                       usalp->silent--;
+                       return (FALSE);
+               }
+               sleep(1);
+       }
+       usalp->silent--;
+       if (ret < 0)
+               return (FALSE);
+       return (TRUE);
+}
+
+BOOL
+scsi_in_progress(SCSI *usalp)
+{
+       if (usal_sense_key(usalp) == SC_NOT_READY &&
+               /*
+                * Logigal unit not ready operation/long_write in progress
+                */
+           usal_sense_code(usalp) == 0x04 &&
+           (usal_sense_qual(usalp) == 0x04 || /* CyberDr. "format in progress"*/
+           usal_sense_qual(usalp) == 0x07 || /* "operation in progress"            */
+           usal_sense_qual(usalp) == 0x08)) { /* "long write in progress"    */
+               return (TRUE);
+       } else {
+               if (usalp->silent <= 1)
+                       usal_printerr(usalp);
+       }
+       return (FALSE);
+}
+
+BOOL
+cdr_underrun(SCSI *usalp)
+{
+       if ((usal_sense_key(usalp) != SC_ILLEGAL_REQUEST &&
+           usal_sense_key(usalp) != SC_MEDIUM_ERROR))
+               return (FALSE);
+
+       if ((usal_sense_code(usalp) == 0x21 &&
+           (usal_sense_qual(usalp) == 0x00 ||  /* logical block address out of range */
+           usal_sense_qual(usalp) == 0x02)) || /* invalid address for write */
+
+           (usal_sense_code(usalp) == 0x0C &&
+           usal_sense_qual(usalp) == 0x09)) {  /* write error - loss of streaming */
+               return (TRUE);
+       }
+       /*
+        * XXX Bei manchen Brennern kommt mach dem der Brennvorgang bereits
+        * XXX eine Weile gelaufen ist ein 5/24/0 Invalid field in CDB.
+        * XXX Daher sollte man testen ob schon geschrieben wurde...
+        */
+       return (FALSE);
+}
+
+int
+test_unit_ready(SCSI *usalp)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->addr = (caddr_t)0;
+       scmd->size = 0;
+       scmd->flags = SCG_DISRE_ENA | (usalp->silent ? SCG_SILENT:0);
+       scmd->cdb_len = SC_G0_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+       scmd->cdb.g0_cdb.cmd = SC_TEST_UNIT_READY;
+       scmd->cdb.g0_cdb.lun = usal_lun(usalp);
+
+       usalp->cmdname = "test unit ready";
+
+       return (usal_cmd(usalp));
+}
+
+int
+rezero_unit(SCSI *usalp)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->addr = (caddr_t)0;
+       scmd->size = 0;
+       scmd->flags = SCG_DISRE_ENA;
+       scmd->cdb_len = SC_G0_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+       scmd->cdb.g0_cdb.cmd = SC_REZERO_UNIT;
+       scmd->cdb.g0_cdb.lun = usal_lun(usalp);
+
+       usalp->cmdname = "rezero unit";
+
+       return (usal_cmd(usalp));
+}
+
+int
+request_sense(SCSI *usalp)
+{
+               char    sensebuf[CCS_SENSE_LEN];
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->addr = sensebuf;
+       scmd->size = sizeof (sensebuf);
+       scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
+       scmd->cdb_len = SC_G0_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+       scmd->cdb.g0_cdb.cmd = SC_REQUEST_SENSE;
+       scmd->cdb.g0_cdb.lun = usal_lun(usalp);
+       scmd->cdb.g0_cdb.count = CCS_SENSE_LEN;
+
+       usalp->cmdname = "request_sense";
+
+       if (usal_cmd(usalp) < 0)
+               return (-1);
+       usal_prsense((Uchar *)sensebuf, CCS_SENSE_LEN - usal_getresid(usalp));
+       return (0);
+}
+
+int
+request_sense_b(SCSI *usalp, caddr_t bp, int cnt)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->addr = bp;
+       scmd->size = cnt;
+       scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
+       scmd->cdb_len = SC_G0_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+       scmd->cdb.g0_cdb.cmd = SC_REQUEST_SENSE;
+       scmd->cdb.g0_cdb.lun = usal_lun(usalp);
+       scmd->cdb.g0_cdb.count = cnt;
+
+       usalp->cmdname = "request_sense";
+
+       if (usal_cmd(usalp) < 0)
+               return (-1);
+       return (0);
+}
+
+int
+inquiry(SCSI *usalp, caddr_t bp, int cnt)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes(bp, cnt, '\0');
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->addr = bp;
+       scmd->size = cnt;
+       scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
+       scmd->cdb_len = SC_G0_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+       scmd->cdb.g0_cdb.cmd = SC_INQUIRY;
+       scmd->cdb.g0_cdb.lun = usal_lun(usalp);
+       scmd->cdb.g0_cdb.count = cnt;
+
+       usalp->cmdname = "inquiry";
+
+       if (usal_cmd(usalp) < 0)
+               return (-1);
+       if (usalp->verbose)
+               usal_prbytes("Inquiry Data   :", (Uchar *)bp, cnt - usal_getresid(usalp));
+       return (0);
+}
+
+int
+read_capacity(SCSI *usalp)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->addr = (caddr_t)usalp->cap;
+       scmd->size = sizeof (struct scsi_capacity);
+       scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
+       scmd->cdb_len = SC_G1_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+       scmd->cdb.g1_cdb.cmd = 0x25;    /* Read Capacity */
+       scmd->cdb.g1_cdb.lun = usal_lun(usalp);
+       g1_cdblen(&scmd->cdb.g1_cdb, 0); /* Full Media */
+
+       usalp->cmdname = "read capacity";
+
+       if (usal_cmd(usalp) < 0) {
+               return (-1);
+       } else {
+               long    cbsize;
+               long    cbaddr;
+
+               /*
+                * c_bsize & c_baddr are signed Int32_t
+                * so we use signed int conversion here.
+                */
+               cbsize = a_to_4_byte(&usalp->cap->c_bsize);
+               cbaddr = a_to_4_byte(&usalp->cap->c_baddr);
+               usalp->cap->c_bsize = cbsize;
+               usalp->cap->c_baddr = cbaddr;
+       }
+       return (0);
+}
+
+void
+print_capacity(SCSI *usalp, FILE *f)
+{
+       long    kb;
+       long    mb;
+       long    prmb;
+       double  dkb;
+
+       dkb =  (usalp->cap->c_baddr+1.0) * (usalp->cap->c_bsize/1024.0);
+       kb = dkb;
+       mb = dkb / 1024.0;
+       prmb = dkb / 1000.0 * 1.024;
+       fprintf(f, "Capacity: %ld Blocks = %ld kBytes = %ld MBytes = %ld prMB\n",
+               (long)usalp->cap->c_baddr+1, kb, mb, prmb);
+       fprintf(f, "Sectorsize: %ld Bytes\n", (long)usalp->cap->c_bsize);
+}
+
+int
+scsi_load_unload(SCSI *usalp, int load)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->flags = SCG_DISRE_ENA;
+       scmd->cdb_len = SC_G5_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+       scmd->cdb.g5_cdb.cmd = 0xA6;
+       scmd->cdb.g5_cdb.lun = usal_lun(usalp);
+       scmd->cdb.g5_cdb.addr[1] = load?3:2;
+       scmd->cdb.g5_cdb.count[2] = 0; /* slot # */
+
+       usalp->cmdname = "medium load/unload";
+
+       if (usal_cmd(usalp) < 0)
+               return (-1);
+       return (0);
+}
+
+int
+scsi_prevent_removal(SCSI *usalp, int prevent)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->flags = SCG_DISRE_ENA;
+       scmd->cdb_len = SC_G0_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+       scmd->cdb.g0_cdb.cmd = 0x1E;
+       scmd->cdb.g0_cdb.lun = usal_lun(usalp);
+       scmd->cdb.g0_cdb.count = prevent & 1;
+
+       usalp->cmdname = "prevent/allow medium removal";
+
+       if (usal_cmd(usalp) < 0)
+               return (-1);
+       return (0);
+}
+
+
+int
+scsi_start_stop_unit(SCSI *usalp, int flg, int loej, BOOL immed)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->flags = SCG_DISRE_ENA;
+       scmd->cdb_len = SC_G0_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+       scmd->cdb.g0_cdb.cmd = 0x1B;    /* Start Stop Unit */
+       scmd->cdb.g0_cdb.lun = usal_lun(usalp);
+       scmd->cdb.g0_cdb.count = (flg ? 1:0) | (loej ? 2:0);
+
+       if (immed)
+               scmd->cdb.cmd_cdb[1] |= 0x01;
+
+       usalp->cmdname = "start/stop unit";
+
+       return (usal_cmd(usalp));
+}
+
+int
+scsi_set_streaming(SCSI *usalp, caddr_t perf_desc, int size)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->addr = perf_desc;
+       scmd->size = size;
+       scmd->flags = SCG_DISRE_ENA;
+       scmd->cdb_len = SC_G5_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+       scmd->cdb.g5_cdb.cmd = 0xB6;
+       scmd->cdb.cmd_cdb[11] = 0;
+       scmd->cdb.cmd_cdb[10] = size;
+
+       usalp->cmdname = "set streaming";
+
+  if(usalp->verbose) 
+     fprintf(stderr, "scsi_set_streaming\n");
+       if (usal_cmd(usalp) < 0)
+               return (-1);
+       return (0);
+}
+    
+int
+scsi_set_speed(SCSI *usalp, int readspeed, int writespeed, int rotctl)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->flags = SCG_DISRE_ENA;
+       scmd->cdb_len = SC_G5_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+       scmd->cdb.g5_cdb.cmd = 0xBB;
+       scmd->cdb.g5_cdb.lun = usal_lun(usalp);
+
+       if (readspeed < 0)
+               i_to_2_byte(&scmd->cdb.g5_cdb.addr[0], 0xFFFF);
+       else
+               i_to_2_byte(&scmd->cdb.g5_cdb.addr[0], readspeed);
+       if (writespeed < 0)
+               i_to_2_byte(&scmd->cdb.g5_cdb.addr[2], 0xFFFF);
+       else
+               i_to_2_byte(&scmd->cdb.g5_cdb.addr[2], writespeed);
+
+       scmd->cdb.cmd_cdb[1] |= rotctl & 0x03;
+
+       usalp->cmdname = "set cd speed";
+
+       if (usal_cmd(usalp) < 0)
+               return (-1);
+       return (0);
+}
+
+int
+scsi_get_speed(SCSI *usalp, int *readspeedp, int *writespeedp)
+{
+       struct  cd_mode_page_2A *mp;
+       Uchar   m[256];
+       int     val;
+
+       usalp->silent++;
+       mp = mmc_cap(usalp, m); /* Get MMC capabilities in allocated mp */
+       usalp->silent--;
+       if (mp == NULL)
+               return (-1);    /* Pre SCSI-3/mmc drive         */
+
+       val = a_to_u_2_byte(mp->cur_read_speed);
+       if (readspeedp)
+               *readspeedp = val;
+
+       if (mp->p_len >= 28)
+               val = a_to_u_2_byte(mp->v3_cur_write_speed);
+       else
+               val = a_to_u_2_byte(mp->cur_write_speed);
+       if (writespeedp)
+               *writespeedp = val;
+
+       return (0);
+}
+
+
+int
+qic02(SCSI *usalp, int cmd)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->addr = (caddr_t)0;
+       scmd->size = 0;
+       scmd->flags = SCG_DISRE_ENA;
+       scmd->cdb_len = SC_G0_CDBLEN;
+       scmd->sense_len = DEF_SENSE_LEN;
+       scmd->cdb.g0_cdb.cmd = 0x0D;    /* qic02 Sysgen SC4000 */
+       scmd->cdb.g0_cdb.lun = usal_lun(usalp);
+       scmd->cdb.g0_cdb.mid_addr = cmd;
+
+       usalp->cmdname = "qic 02";
+       return (usal_cmd(usalp));
+}
+
+#define        G0_MAXADDR      0x1FFFFFL
+
+int 
+write_xscsi(SCSI *usalp, caddr_t bp, long addr, long size, int cnt)
+{
+       if (addr <= G0_MAXADDR)
+               return (write_xg0(usalp, bp, addr, size, cnt));
+       else
+               return (write_xg1(usalp, bp, addr, size, cnt));
+}
+
+int 
+write_xg0(SCSI *usalp, 
+          caddr_t bp    /* address of buffer */, 
+          long addr     /* disk address (sector) to put */, 
+          long size     /* number of bytes to transfer */, 
+          int cnt       /* sectorcount */)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->addr = bp;
+       scmd->size = size;
+       scmd->flags = SCG_DISRE_ENA|SCG_CMD_RETRY;
+/*     scmd->flags = SCG_DISRE_ENA;*/
+       scmd->cdb_len = SC_G0_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+       scmd->cdb.g0_cdb.cmd = SC_WRITE;
+       scmd->cdb.g0_cdb.lun = usal_lun(usalp);
+       g0_cdbaddr(&scmd->cdb.g0_cdb, addr);
+       scmd->cdb.g0_cdb.count = cnt;
+
+       usalp->cmdname = "write_g0";
+
+       if (usal_cmd(usalp) < 0)
+               return (-1);
+       return (size - usal_getresid(usalp));
+}
+
+int 
+write_xg1(SCSI *usalp, 
+          caddr_t bp    /* address of buffer */, 
+          long addr     /* disk address (sector) to put */, 
+          long size     /* number of bytes to transfer */, 
+          int cnt       /* sectorcount */)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->addr = bp;
+       scmd->size = size;
+       scmd->flags = SCG_DISRE_ENA|SCG_CMD_RETRY;
+/*     scmd->flags = SCG_DISRE_ENA;*/
+       scmd->cdb_len = SC_G1_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+       scmd->cdb.g1_cdb.cmd = SC_EWRITE;
+       scmd->cdb.g1_cdb.lun = usal_lun(usalp);
+       g1_cdbaddr(&scmd->cdb.g1_cdb, addr);
+       g1_cdblen(&scmd->cdb.g1_cdb, cnt);
+
+       usalp->cmdname = "write_g1";
+
+       if (usal_cmd(usalp) < 0)
+               return (-1);
+       return (size - usal_getresid(usalp));
+}
+
+int 
+write_xg5(SCSI *usalp,
+          caddr_t bp    /* address of buffer */, 
+          long addr     /* disk address (sector) to put */, 
+          long size     /* number of bytes to transfer */, 
+          int cnt       /* sectorcount */)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->addr = bp;
+       scmd->size = size;
+       scmd->flags = SCG_DISRE_ENA|SCG_CMD_RETRY;
+/*     scmd->flags = SCG_DISRE_ENA;*/
+       scmd->cdb_len = SC_G5_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+       scmd->cdb.g5_cdb.cmd = 0xAA;
+       scmd->cdb.g5_cdb.lun = usal_lun(usalp);
+       g5_cdbaddr(&scmd->cdb.g5_cdb, addr);
+       g5_cdblen(&scmd->cdb.g5_cdb, cnt);
+
+       usalp->cmdname = "write_g5";
+
+       if (usal_cmd(usalp) < 0)
+               return (-1);
+       return (size - usal_getresid(usalp));
+}
+
+int
+seek_scsi(SCSI *usalp, long addr)
+{
+       if (addr <= G0_MAXADDR)
+               return (seek_g0(usalp, addr));
+       else
+               return (seek_g1(usalp, addr));
+}
+
+int
+seek_g0(SCSI *usalp, long addr)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->flags = SCG_DISRE_ENA;
+       scmd->cdb_len = SC_G0_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+       scmd->cdb.g0_cdb.cmd = 0x0B;    /* Seek */
+       scmd->cdb.g0_cdb.lun = usal_lun(usalp);
+       g0_cdbaddr(&scmd->cdb.g0_cdb, addr);
+
+       usalp->cmdname = "seek_g0";
+
+       return (usal_cmd(usalp));
+}
+
+int
+seek_g1(SCSI *usalp, long addr)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->flags = SCG_DISRE_ENA;
+       scmd->cdb_len = SC_G1_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+       scmd->cdb.g1_cdb.cmd = 0x2B;    /* Seek G1 */
+       scmd->cdb.g1_cdb.lun = usal_lun(usalp);
+       g1_cdbaddr(&scmd->cdb.g1_cdb, addr);
+
+       usalp->cmdname = "seek_g1";
+
+       return (usal_cmd(usalp));
+}
+
+int
+scsi_flush_cache(SCSI *usalp, BOOL immed)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->flags = SCG_DISRE_ENA;
+       scmd->cdb_len = SC_G1_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+       scmd->timeout = 2 * 60;         /* Max: sizeof (CDR-cache)/150KB/s */
+       scmd->cdb.g1_cdb.cmd = 0x35;
+       scmd->cdb.g1_cdb.lun = usal_lun(usalp);
+
+       if (immed)
+               scmd->cdb.cmd_cdb[1] |= 0x02;
+
+       usalp->cmdname = "flush cache";
+
+       if (usal_cmd(usalp) < 0)
+               return (-1);
+       return (0);
+}
+
+int
+read_buffer(SCSI *usalp, caddr_t bp, int cnt, int mode)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->addr = bp;
+       scmd->size = cnt;
+       scmd->dma_read = 1;
+       scmd->cdb_len = SC_G1_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+       scmd->cdb.g1_cdb.cmd = 0x3C;    /* Read Buffer */
+       scmd->cdb.g1_cdb.lun = usal_lun(usalp);
+       scmd->cdb.cmd_cdb[1] |= (mode & 7);
+       g1_cdblen(&scmd->cdb.g1_cdb, cnt);
+
+       usalp->cmdname = "read buffer";
+
+       return (usal_cmd(usalp));
+}
+
+int
+write_buffer(SCSI *usalp, char *buffer, long length, int mode, int bufferid, 
+             long offset)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+       char                    *cdb;
+
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->addr = buffer;
+       scmd->size = length;
+       scmd->flags = SCG_DISRE_ENA|SCG_CMD_RETRY;
+       scmd->cdb_len = SC_G1_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+
+       cdb = (char *)scmd->cdb.cmd_cdb;
+
+       cdb[0] = 0x3B;
+       cdb[1] = mode & 7;
+       cdb[2] = bufferid;
+       cdb[3] = offset >> 16;
+       cdb[4] = (offset >> 8) & 0xff;
+       cdb[5] = offset & 0xff;
+       cdb[6] = length >> 16;
+       cdb[7] = (length >> 8) & 0xff;
+       cdb[8] = length & 0xff;
+
+       usalp->cmdname = "write_buffer";
+
+       if (usal_cmd(usalp) >= 0)
+               return (1);
+       return (0);
+}
+
+int
+read_subchannel(SCSI *usalp, caddr_t bp, int track, int cnt, int msf, int subq, 
+                                        int fmt)
+
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->addr = bp;
+       scmd->size = cnt;
+       scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
+       scmd->cdb_len = SC_G1_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+       scmd->cdb.g1_cdb.cmd = 0x42;
+       scmd->cdb.g1_cdb.lun = usal_lun(usalp);
+       if (msf)
+               scmd->cdb.g1_cdb.res = 1;
+       if (subq)
+               scmd->cdb.g1_cdb.addr[0] = 0x40;
+       scmd->cdb.g1_cdb.addr[1] = fmt;
+       scmd->cdb.g1_cdb.res6 = track;
+       g1_cdblen(&scmd->cdb.g1_cdb, cnt);
+
+       usalp->cmdname = "read subchannel";
+
+       if (usal_cmd(usalp) < 0)
+               return (-1);
+       return (0);
+}
+
+int
+read_toc(SCSI *usalp, caddr_t bp, int track, int cnt, int msf, int fmt)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->addr = bp;
+       scmd->size = cnt;
+       scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
+       scmd->cdb_len = SC_G1_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+       scmd->cdb.g1_cdb.cmd = 0x43;
+       scmd->cdb.g1_cdb.lun = usal_lun(usalp);
+       if (msf)
+               scmd->cdb.g1_cdb.res = 1;
+       scmd->cdb.g1_cdb.addr[0] = fmt & 0x0F;
+       scmd->cdb.g1_cdb.res6 = track;
+       g1_cdblen(&scmd->cdb.g1_cdb, cnt);
+
+       usalp->cmdname = "read toc";
+
+       if (usal_cmd(usalp) < 0)
+               return (-1);
+       return (0);
+}
+
+int
+read_toc_philips(SCSI *usalp, caddr_t bp, int track, int cnt, int msf, int fmt)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->addr = bp;
+       scmd->size = cnt;
+       scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
+       scmd->cdb_len = SC_G1_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+       scmd->timeout = 4 * 60;         /* May last  174s on a TEAC CD-R55S */
+       scmd->cdb.g1_cdb.cmd = 0x43;
+       scmd->cdb.g1_cdb.lun = usal_lun(usalp);
+       if (msf)
+               scmd->cdb.g1_cdb.res = 1;
+       scmd->cdb.g1_cdb.res6 = track;
+       g1_cdblen(&scmd->cdb.g1_cdb, cnt);
+
+       if (fmt & 1)
+               scmd->cdb.g1_cdb.vu_96 = 1;
+       if (fmt & 2)
+               scmd->cdb.g1_cdb.vu_97 = 1;
+
+       usalp->cmdname = "read toc";
+
+       if (usal_cmd(usalp) < 0)
+               return (-1);
+       return (0);
+}
+
+int
+read_header(SCSI *usalp, caddr_t bp, long addr, int cnt, int msf)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->addr = bp;
+       scmd->size = cnt;
+       scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
+       scmd->cdb_len = SC_G1_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+       scmd->cdb.g1_cdb.cmd = 0x44;
+       scmd->cdb.g1_cdb.lun = usal_lun(usalp);
+       if (msf)
+               scmd->cdb.g1_cdb.res = 1;
+       g1_cdbaddr(&scmd->cdb.g1_cdb, addr);
+       g1_cdblen(&scmd->cdb.g1_cdb, cnt);
+
+       usalp->cmdname = "read header";
+
+       if (usal_cmd(usalp) < 0)
+               return (-1);
+       return (0);
+}
+
+int
+read_disk_info(SCSI *usalp, caddr_t bp, int cnt)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->addr = bp;
+       scmd->size = cnt;
+       scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
+       scmd->cdb_len = SC_G1_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+       scmd->timeout = 4 * 60;         /* Needs up to 2 minutes */
+       scmd->cdb.g1_cdb.cmd = 0x51;
+       scmd->cdb.g1_cdb.lun = usal_lun(usalp);
+       g1_cdblen(&scmd->cdb.g1_cdb, cnt);
+
+       usalp->cmdname = "read disk info";
+
+       if (usal_cmd(usalp) < 0)
+               return (-1);
+       return (0);
+}
+
+int
+read_track_info(SCSI *usalp, caddr_t bp, int type, int addr, int cnt)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->addr = bp;
+       scmd->size = cnt;
+       scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
+       scmd->cdb_len = SC_G1_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+       scmd->timeout = 4 * 60;         /* Needs up to 2 minutes */
+       scmd->cdb.g1_cdb.cmd = 0x52;
+       scmd->cdb.g1_cdb.lun = usal_lun(usalp);
+/*     scmd->cdb.cmd_cdb[1] = type & 0x03;*/
+       scmd->cdb.cmd_cdb[1] = type;
+       g1_cdbaddr(&scmd->cdb.g1_cdb, addr);    /* LBA/Track/Session */
+       g1_cdblen(&scmd->cdb.g1_cdb, cnt);
+
+       usalp->cmdname = "read track info";
+
+       if (usal_cmd(usalp) < 0)
+               return (-1);
+       return (0);
+}
+
+int
+reserve_track(SCSI *usalp, Ulong size)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)scmd, sizeof(*scmd), '\0');
+       scmd->flags = SCG_DISRE_ENA;
+       scmd->cdb_len = SC_G1_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+       scmd->cdb.g1_cdb.cmd = 0x53;
+       scmd->cdb.g1_cdb.lun = usal_lun(usalp);
+       i_to_4_byte(&scmd->cdb.g1_cdb.addr[3], size);
+
+       usalp->cmdname = "reserve track";
+
+       if (usal_cmd(usalp) < 0) 
+               return (-1);
+
+       return (0);
+
+}
+
+int
+read_rzone_info(SCSI *usalp, caddr_t bp, int cnt)
+{
+       return (read_track_info(usalp, bp, TI_TYPE_LBA, 0, cnt));
+}
+
+int
+reserve_tr_rzone(SCSI *usalp, long size /* number of blocks */)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->addr = (caddr_t)0;
+       scmd->size = 0;
+       scmd->flags = SCG_DISRE_ENA|SCG_CMD_RETRY;
+       scmd->cdb_len = SC_G1_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+       scmd->cdb.g1_cdb.cmd = 0x53;
+       scmd->cdb.g1_cdb.lun = usal_lun(usalp);
+
+       i_to_4_byte(&scmd->cdb.g1_cdb.addr[3], size);
+
+       usalp->cmdname = "reserve_track_rzone";
+
+       if (usal_cmd(usalp) < 0)
+               return (-1);
+       return (0);
+}
+
+int
+read_dvd_structure(SCSI *usalp, caddr_t bp, int cnt, int addr, int layer, 
+                   int fmt)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->addr = bp;
+       scmd->size = cnt;
+       scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
+       scmd->cdb_len = SC_G5_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+       scmd->timeout = 4 * 60;         /* Needs up to 2 minutes ??? */
+       scmd->cdb.g5_cdb.cmd = 0xAD;
+       scmd->cdb.g5_cdb.lun = usal_lun(usalp);
+       g5_cdbaddr(&scmd->cdb.g5_cdb, addr);
+       g5_cdblen(&scmd->cdb.g5_cdb, cnt);
+       scmd->cdb.g5_cdb.count[0] = layer;
+       scmd->cdb.g5_cdb.count[1] = fmt;
+
+       usalp->cmdname = "read dvd structure";
+
+       if (usal_cmd(usalp) < 0)
+               return (-1);
+       return (0);
+}
+
+int
+send_dvd_structure(SCSI *usalp, caddr_t bp, int cnt, int layer, int fmt)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->addr = bp;
+       scmd->size = cnt;
+       scmd->flags = SCG_DISRE_ENA;
+       scmd->cdb_len = SC_G5_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+       scmd->timeout = 4 * 60;         /* Needs up to 2 minutes ??? */
+       scmd->cdb.g5_cdb.cmd = 0xBF;
+       scmd->cdb.g5_cdb.lun = usal_lun(usalp);
+       g5_cdblen(&scmd->cdb.g5_cdb, cnt);
+
+       scmd->cdb.cmd_cdb[7] = fmt;
+
+       usalp->cmdname = "send dvd structure";
+
+       if (usal_cmd(usalp) < 0)
+               return (-1);
+       return (0);
+}
+
+int
+send_opc(SCSI *usalp, caddr_t bp, int cnt, int doopc)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->addr = bp;
+       scmd->size = cnt;
+       scmd->flags = SCG_DISRE_ENA;
+       scmd->cdb_len = SC_G1_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+       scmd->timeout = 60;
+       scmd->cdb.g1_cdb.cmd = 0x54;
+       scmd->cdb.g1_cdb.lun = usal_lun(usalp);
+       scmd->cdb.g1_cdb.reladr = doopc?1:0;
+       g1_cdblen(&scmd->cdb.g1_cdb, cnt);
+
+       usalp->cmdname = "send opc";
+
+       if (usal_cmd(usalp) < 0)
+               return (-1);
+       return (0);
+}
+
+int
+read_track_info_philips(SCSI *usalp, caddr_t bp, int track, int cnt)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->addr = bp;
+       scmd->size = cnt;
+       scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
+       scmd->cdb_len = SC_G1_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+       scmd->cdb.g1_cdb.cmd = 0xE5;
+       scmd->cdb.g1_cdb.lun = usal_lun(usalp);
+       g1_cdbaddr(&scmd->cdb.g1_cdb, track);
+       g1_cdblen(&scmd->cdb.g1_cdb, cnt);
+
+       usalp->cmdname = "read track info";
+
+       if (usal_cmd(usalp) < 0)
+               return (-1);
+       return (0);
+}
+
+int
+scsi_close_tr_session(SCSI *usalp, int type, int track, BOOL immed)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->flags = SCG_DISRE_ENA;
+       scmd->cdb_len = SC_G1_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+       scmd->timeout = 8 * 60;         /* Needs up to 4 minutes */
+       scmd->cdb.g1_cdb.cmd = 0x5B;
+       scmd->cdb.g1_cdb.lun = usal_lun(usalp);
+       scmd->cdb.g1_cdb.addr[0] = type;
+       scmd->cdb.g1_cdb.addr[3] = track;
+
+       if (immed)
+               scmd->cdb.g1_cdb.reladr = 1;
+/*             scmd->cdb.cmd_cdb[1] |= 0x01;*/
+#ifdef nono
+       scmd->cdb.g1_cdb.reladr = 1;    /* IMM hack to test Mitsumi behaviour*/
+#endif
+
+       usalp->cmdname = "close track/session";
+
+       if (usal_cmd(usalp) < 0)
+               return (-1);
+       return (0);
+}
+
+int
+read_master_cue(SCSI *usalp, caddr_t bp, int sheet, int cnt)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->addr = bp;
+       scmd->size = cnt;
+       scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
+       scmd->cdb_len = SC_G1_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+       scmd->cdb.g1_cdb.cmd = 0x59;            /* Read master cue */
+       scmd->cdb.g1_cdb.lun = usal_lun(usalp);
+       scmd->cdb.g1_cdb.addr[2] = sheet;
+       g1_cdblen(&scmd->cdb.g1_cdb, cnt);
+
+       usalp->cmdname = "read master cue";
+
+       if (usal_cmd(usalp) < 0)
+               return (-1);
+       return (0);
+}
+
+int
+send_cue_sheet(SCSI *usalp, caddr_t bp, long size)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->addr = bp;
+       scmd->size = size;
+       scmd->flags = SCG_DISRE_ENA;
+       scmd->cdb_len = SC_G1_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+       scmd->cdb.g1_cdb.cmd = 0x5D;    /* Send CUE sheet */
+       scmd->cdb.g1_cdb.lun = usal_lun(usalp);
+       g1_cdblen(&scmd->cdb.g1_cdb, size);
+
+       usalp->cmdname = "send_cue_sheet";
+
+       if (usal_cmd(usalp) < 0)
+               return (-1);
+       return (size - scmd->resid);
+}
+
+int
+read_buff_cap(SCSI *usalp, long *sp, long *fp)
+{
+       char    resp[12];
+       Ulong   freespace;
+       Ulong   bufsize;
+       int     per;
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->addr = (caddr_t)resp;
+       scmd->size = sizeof (resp);
+       scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
+       scmd->cdb_len = SC_G1_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+       scmd->cdb.g1_cdb.cmd = 0x5C;            /* Read buffer cap */
+       scmd->cdb.g1_cdb.lun = usal_lun(usalp);
+       g1_cdblen(&scmd->cdb.g1_cdb, sizeof (resp));
+
+       usalp->cmdname = "read buffer cap";
+
+       if (usal_cmd(usalp) < 0)
+               return (-1);
+
+       bufsize   = a_to_u_4_byte(&resp[4]);
+       freespace = a_to_u_4_byte(&resp[8]);
+       if (sp)
+               *sp = bufsize;
+       if (fp)
+               *fp = freespace;
+
+       if (usalp->verbose || (sp == 0 && fp == 0))
+               printf("BFree: %ld K BSize: %ld K\n", freespace >> 10, bufsize >> 10);
+
+       if (bufsize == 0)
+               return (0);
+       per = (100 * (bufsize - freespace)) / bufsize;
+       if (per < 0)
+               return (0);
+       if (per > 100)
+               return (100);
+       return (per);
+}
+
+int
+scsi_blank(SCSI *usalp, long addr, int blanktype, BOOL immed)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->flags = SCG_DISRE_ENA;
+       scmd->cdb_len = SC_G5_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+       scmd->timeout = 160 * 60; /* full blank at 1x could take 80 minutes */
+       scmd->cdb.g5_cdb.cmd = 0xA1;    /* Blank */
+       scmd->cdb.g0_cdb.high_addr = blanktype;
+       g1_cdbaddr(&scmd->cdb.g5_cdb, addr);
+
+       if (immed)
+               scmd->cdb.g5_cdb.res |= 8;
+/*             scmd->cdb.cmd_cdb[1] |= 0x10;*/
+
+       usalp->cmdname = "blank unit";
+
+       return (usal_cmd(usalp));
+}
+
+int
+scsi_format(SCSI *usalp, caddr_t addr, int size, BOOL background)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+       int progress=0, ret=-1, pid=-1;
+       unsigned char sense_table[18];
+       int i;
+       
+       printf("scsi_format: preparing\n");
+
+       fillbytes((caddr_t)scmd, sizeof(*scmd), '\0');
+       scmd->addr = addr;
+       scmd->size = size;
+       scmd->flags = SCG_DISRE_ENA;
+       scmd->cdb_len = SC_G5_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+       scmd->timeout = 160 * 60;     /* Do not know what to set */
+       scmd->cdb.g5_cdb.cmd = 0x04;   /* Format Unit */
+       scmd->cdb.cmd_cdb[1] = 0x11;  /* "FmtData" and "Format Code" */
+       scmd->cdb.cmd_cdb[5] = 0;
+
+       usalp->cmdname = "format unit";
+
+       printf("scsi_format: running\n");
+       ret = (usal_cmd(usalp));
+       printf("scsi_format: post processing %d\n", ret);
+       if (ret == -1) return ret;
+       if (background) {
+               if ((pid=fork()) == (pid_t)-1)
+                       perror ("- [unable to fork()]");
+               else {
+                       if (!pid) {
+                           while (1) {
+                               if (test_unit_ready(usalp) >= 0)
+                                   break;
+                               sleep(1);
+                           }
+                           return ret;
+                       }
+               }
+       }
+       printf("Formating in progress: 0.00 %% done.");
+       sleep(20);
+       i = 0;
+       while (progress < 0xfff0 && !(progress == 0 && i > 50)) {
+               test_unit_ready(usalp);
+               request_sense_b(usalp, (caddr_t)sense_table, 18);
+               progress = sense_table[16]<<8|sense_table[17];
+               printf("\rFormating in progress: %.2f %% done [%d].                           ", (float)(progress*100)/0x10000,progress);
+               usleep(100000);
+               i++;
+               /*for (i=0; i < 18; i++) {
+                   printf("%d ", sense_table[i]);
+               }*/
+       }
+       sleep(10);
+       printf("\rFormating in progress: 100.00 %% done.        \n");
+       if (pid) exit (0);
+       return ret;
+}
+
+/*
+ * XXX First try to handle ATAPI:
+ * XXX ATAPI cannot handle SCSI 6 byte commands.
+ * XXX We try to simulate 6 byte mode sense/select.
+ */
+static BOOL    is_atapi;
+
+BOOL
+allow_atapi(SCSI *usalp, BOOL new)
+{
+       BOOL    old = is_atapi;
+       Uchar   mode[256];
+
+       if (new == old)
+               return (old);
+
+       usalp->silent++;
+       /*
+        * If a bad drive has been reset before, we may need to fire up two
+        * test unit ready commands to clear status.
+        */
+       (void) unit_ready(usalp);
+       if (new &&
+           mode_sense_g1(usalp, mode, 8, 0x3F, 0) < 0) {       /* All pages current */
+               new = FALSE;
+       }
+       usalp->silent--;
+
+       is_atapi = new;
+       return (old);
+}
+
+int
+mode_select(SCSI *usalp, Uchar *dp, int cnt, int smp, int pf)
+{
+       if (is_atapi)
+               return (mode_select_sg0(usalp, dp, cnt, smp, pf));
+       return (mode_select_g0(usalp, dp, cnt, smp, pf));
+}
+
+int
+mode_sense(SCSI *usalp, Uchar *dp, int cnt, int page, int pcf)
+{
+       if (is_atapi)
+               return (mode_sense_sg0(usalp, dp, cnt, page, pcf));
+       return (mode_sense_g0(usalp, dp, cnt, page, pcf));
+}
+
+/*
+ * Simulate mode select g0 with mode select g1.
+ */
+int
+mode_select_sg0(SCSI *usalp, Uchar *dp, int cnt, int smp, int pf)
+{
+       Uchar   xmode[256+4];
+       int     amt = cnt;
+
+       if (amt < 1 || amt > 255) {
+               /* XXX clear SCSI error codes ??? */
+               return (-1);
+       }
+
+       if (amt < 4) {          /* Data length. medium type & VU */
+               amt += 1;
+       } else {
+               amt += 4;
+               movebytes(&dp[4], &xmode[8], cnt-4);
+       }
+       xmode[0] = 0;
+       xmode[1] = 0;
+       xmode[2] = dp[1];
+       xmode[3] = dp[2];
+       xmode[4] = 0;
+       xmode[5] = 0;
+       i_to_2_byte(&xmode[6], (unsigned int)dp[3]);
+
+       if (usalp->verbose) usal_prbytes("Mode Parameters (un-converted)", dp, cnt);
+
+       return (mode_select_g1(usalp, xmode, amt, smp, pf));
+}
+
+/*
+ * Simulate mode sense g0 with mode sense g1.
+ */
+int
+mode_sense_sg0(SCSI *usalp, Uchar *dp, int cnt, int page, int pcf)
+{
+       Uchar   xmode[256+4];
+       int     amt = cnt;
+       int     len;
+
+       if (amt < 1 || amt > 255) {
+               /* XXX clear SCSI error codes ??? */
+               return (-1);
+       }
+
+       fillbytes((caddr_t)xmode, sizeof (xmode), '\0');
+       if (amt < 4) {          /* Data length. medium type & VU */
+               amt += 1;
+       } else {
+               amt += 4;
+       }
+       if (mode_sense_g1(usalp, xmode, amt, page, pcf) < 0)
+               return (-1);
+
+       amt = cnt - usal_getresid(usalp);
+/*
+ * For tests: Solaris 8 & LG CD-ROM always returns resid == amt
+ */
+/*     amt = cnt;*/
+       if (amt > 4)
+               movebytes(&xmode[8], &dp[4], amt-4);
+       len = a_to_u_2_byte(xmode);
+       if (len == 0) {
+               dp[0] = 0;
+       } else if (len < 6) {
+               if (len > 2)
+                       len = 2;
+               dp[0] = len;
+       } else {
+               dp[0] = len - 3;
+       }
+       dp[1] = xmode[2];
+       dp[2] = xmode[3];
+       len = a_to_u_2_byte(&xmode[6]);
+       dp[3] = len;
+
+       if (usalp->verbose) usal_prbytes("Mode Sense Data (converted)", dp, amt);
+       return (0);
+}
+
+int
+mode_select_g0(SCSI *usalp, Uchar *dp, int cnt, int smp, int pf)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->addr = (caddr_t)dp;
+       scmd->size = cnt;
+       scmd->flags = SCG_DISRE_ENA;
+       scmd->cdb_len = SC_G0_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+       scmd->cdb.g0_cdb.cmd = SC_MODE_SELECT;
+       scmd->cdb.g0_cdb.lun = usal_lun(usalp);
+       scmd->cdb.g0_cdb.high_addr = smp ? 1 : 0 | pf ? 0x10 : 0;
+       scmd->cdb.g0_cdb.count = cnt;
+
+       if (usalp->verbose) {
+               fprintf(stderr, "%s ", smp?"Save":"Set ");
+               usal_prbytes("Mode Parameters", dp, cnt);
+       }
+
+       usalp->cmdname = "mode select g0";
+
+       return (usal_cmd(usalp));
+}
+
+int
+mode_select_g1(SCSI *usalp, Uchar *dp, int cnt, int smp, int pf)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->addr = (caddr_t)dp;
+       scmd->size = cnt;
+       scmd->flags = SCG_DISRE_ENA;
+       scmd->cdb_len = SC_G1_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+       scmd->cdb.g1_cdb.cmd = 0x55;
+       scmd->cdb.g1_cdb.lun = usal_lun(usalp);
+       scmd->cdb.g0_cdb.high_addr = smp ? 1 : 0 | pf ? 0x10 : 0;
+       g1_cdblen(&scmd->cdb.g1_cdb, cnt);
+
+       if (usalp->verbose) {
+               printf("%s ", smp?"Save":"Set ");
+               usal_prbytes("Mode Parameters", dp, cnt);
+       }
+
+       usalp->cmdname = "mode select g1";
+
+       return (usal_cmd(usalp));
+}
+
+int
+mode_sense_g0(SCSI *usalp, Uchar *dp, int cnt, int page, int pcf)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->addr = (caddr_t)dp;
+       scmd->size = 0xFF;
+       scmd->size = cnt;
+       scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
+       scmd->cdb_len = SC_G0_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+       scmd->cdb.g0_cdb.cmd = SC_MODE_SENSE;
+       scmd->cdb.g0_cdb.lun = usal_lun(usalp);
+#ifdef nonono
+       scmd->cdb.g0_cdb.high_addr = 1<<4;      /* DBD Disable Block desc. */
+#endif
+       scmd->cdb.g0_cdb.mid_addr = (page&0x3F) | ((pcf<<6)&0xC0);
+       scmd->cdb.g0_cdb.count = page ? 0xFF : 24;
+       scmd->cdb.g0_cdb.count = cnt;
+
+       usalp->cmdname = "mode sense g0";
+
+       if (usal_cmd(usalp) < 0)
+               return (-1);
+       if (usalp->verbose) usal_prbytes("Mode Sense Data", dp, cnt - usal_getresid(usalp));
+       return (0);
+}
+
+int
+mode_sense_g1(SCSI *usalp, Uchar *dp, int cnt, int page, int pcf)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->addr = (caddr_t)dp;
+       scmd->size = cnt;
+       scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
+       scmd->cdb_len = SC_G1_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+       scmd->cdb.g1_cdb.cmd = 0x5A;
+       scmd->cdb.g1_cdb.lun = usal_lun(usalp);
+#ifdef nonono
+       scmd->cdb.g0_cdb.high_addr = 1<<4;      /* DBD Disable Block desc. */
+#endif
+       scmd->cdb.g1_cdb.addr[0] = (page&0x3F) | ((pcf<<6)&0xC0);
+       g1_cdblen(&scmd->cdb.g1_cdb, cnt);
+
+       usalp->cmdname = "mode sense g1";
+
+       if (usal_cmd(usalp) < 0)
+               return (-1);
+       if (usalp->verbose) usal_prbytes("Mode Sense Data", dp, cnt - usal_getresid(usalp));
+       return (0);
+}
+
+struct trackdesc {
+       Uchar   res0;
+
+#if defined(_BIT_FIELDS_LTOH)          /* Intel byteorder */
+       Ucbit   control         : 4;
+       Ucbit   adr             : 4;
+#else                                  /* Motorola byteorder */
+       Ucbit   adr             : 4;
+       Ucbit   control         : 4;
+#endif
+
+       Uchar   track;
+       Uchar   res3;
+       Uchar   addr[4];
+};
+
+struct diskinfo {
+       struct tocheader        hd;
+       struct trackdesc        desc[1];
+};
+
+struct siheader {
+       Uchar   len[2];
+       Uchar   finished;
+       Uchar   unfinished;
+};
+
+struct sidesc {
+       Uchar   sess_number;
+       Uchar   res1;
+       Uchar   track;
+       Uchar   res3;
+       Uchar   addr[4];
+};
+
+struct sinfo {
+       struct siheader hd;
+       struct sidesc   desc[1];
+};
+
+struct trackheader {
+       Uchar   mode;
+       Uchar   res[3];
+       Uchar   addr[4];
+};
+#define        TRM_ZERO        0
+#define        TRM_USER_ECC    1       /* 2048 bytes user data + 288 Bytes ECC/EDC */
+#define        TRM_USER        2       /* All user data (2336 bytes) */
+
+
+int
+read_tochdr(SCSI *usalp, cdr_t *dp, int *fp, int *lp)
+{
+       struct  tocheader *tp;
+       char    xb[256];
+       int     len;
+
+       tp = (struct tocheader *)xb;
+
+       fillbytes((caddr_t)xb, sizeof (xb), '\0');
+       if (read_toc(usalp, xb, 0, sizeof (struct tocheader), 0, FMT_TOC) < 0) {
+               if (usalp->silent == 0)
+                       errmsgno(EX_BAD, "Cannot read TOC header\n");
+               return (-1);
+       }
+       len = a_to_u_2_byte(tp->len) + sizeof (struct tocheader)-2;
+       if (len >= 4) {
+               if (fp)
+                       *fp = tp->first;
+               if (lp)
+                       *lp = tp->last;
+               return (0);
+       }
+       return (-1);
+}
+
+int
+read_cdtext(SCSI *usalp)
+{
+       struct  tocheader *tp;
+       char    xb[256];
+       int     len;
+       char    xxb[10000];
+
+       tp = (struct tocheader *)xb;
+
+       fillbytes((caddr_t)xb, sizeof (xb), '\0');
+       if (read_toc(usalp, xb, 0, sizeof (struct tocheader), 0, FMT_CDTEXT) < 0) {
+               if (usalp->silent == 0 || usalp->verbose > 0)
+                       errmsgno(EX_BAD, "Cannot read CD-Text header\n");
+               return (-1);
+       }
+       len = a_to_u_2_byte(tp->len) + sizeof (struct tocheader)-2;
+       printf("CD-Text len: %d\n", len);
+
+       if (read_toc(usalp, xxb, 0, len, 0, FMT_CDTEXT) < 0) {
+               if (usalp->silent == 0)
+                       errmsgno(EX_BAD, "Cannot read CD-Text\n");
+               return (-1);
+       }
+       {
+               FILE    *f = fileopen("cdtext.dat", "wctb");
+               filewrite(f, xxb, len);
+       }
+       return (0);
+}
+
+int
+read_trackinfo(SCSI *usalp, int track, long *offp, struct msf *msfp, int *adrp, 
+                                       int *controlp, int *modep)
+{
+       struct  diskinfo *dp;
+       char    xb[256];
+       int     len;
+
+       dp = (struct diskinfo *)xb;
+
+       fillbytes((caddr_t)xb, sizeof (xb), '\0');
+       if (read_toc(usalp, xb, track, sizeof (struct diskinfo), 0, FMT_TOC) < 0) {
+               if (usalp->silent <= 0)
+                       errmsgno(EX_BAD, "Cannot read TOC\n");
+               return (-1);
+       }
+       len = a_to_u_2_byte(dp->hd.len) + sizeof (struct tocheader)-2;
+       if (len <  (int)sizeof (struct diskinfo))
+               return (-1);
+
+       if (offp)
+               *offp = a_to_4_byte(dp->desc[0].addr);
+       if (adrp)
+               *adrp = dp->desc[0].adr;
+       if (controlp)
+               *controlp = dp->desc[0].control;
+
+       if (msfp) {
+               usalp->silent++;
+               if (read_toc(usalp, xb, track, sizeof (struct diskinfo), 1, FMT_TOC)
+                                                                       >= 0) {
+                       msfp->msf_min = dp->desc[0].addr[1];
+                       msfp->msf_sec = dp->desc[0].addr[2];
+                       msfp->msf_frame = dp->desc[0].addr[3];
+               } else if (read_toc(usalp, xb, track, sizeof (struct diskinfo), 0, FMT_TOC)
+                                                                       >= 0) {
+                       /*
+                        * Some drives (e.g. the Philips CDD-522) don't support
+                        * to read the TOC in MSF mode.
+                        */
+                       long off = a_to_4_byte(dp->desc[0].addr);
+
+                       lba_to_msf(off, msfp);
+               } else {
+                       msfp->msf_min = 0;
+                       msfp->msf_sec = 0;
+                       msfp->msf_frame = 0;
+               }
+               usalp->silent--;
+       }
+
+       if (modep == NULL)
+               return (0);
+
+       if (track == 0xAA) {
+               *modep = -1;
+               return (0);
+       }
+
+       fillbytes((caddr_t)xb, sizeof (xb), '\0');
+
+       usalp->silent++;
+       if (read_header(usalp, xb, *offp, 8, 0) >= 0) {
+               *modep = xb[0];
+       } else if (read_track_info_philips(usalp, xb, track, 14) >= 0) {
+               *modep = xb[0xb] & 0xF;
+       } else {
+               *modep = -1;
+       }
+       usalp->silent--;
+       return (0);
+}
+
+int
+read_B0(SCSI *usalp, BOOL isbcd, long *b0p, long *lop)
+{
+       struct  fdiskinfo *dp;
+       struct  ftrackdesc *tp;
+       char    xb[8192];
+       char    *pe;
+       int     len;
+       long    l;
+
+       dp = (struct fdiskinfo *)xb;
+
+       fillbytes((caddr_t)xb, sizeof (xb), '\0');
+       if (read_toc_philips(usalp, xb, 1, sizeof (struct tocheader), 0, FMT_FULLTOC) < 0) {
+               return (-1);
+       }
+       len = a_to_u_2_byte(dp->hd.len) + sizeof (struct tocheader)-2;
+       if (len <  (int)sizeof (struct fdiskinfo))
+               return (-1);
+       if (read_toc_philips(usalp, xb, 1, len, 0, FMT_FULLTOC) < 0) {
+               return (-1);
+       }
+       if (usalp->verbose) {
+               usal_prbytes("TOC data: ", (Uchar *)xb,
+                       len > (int)sizeof (xb) - usal_getresid(usalp) ?
+                               sizeof (xb) - usal_getresid(usalp) : len);
+
+               tp = &dp->desc[0];
+               pe = &xb[len];
+
+               while ((char *)tp < pe) {
+                       usal_prbytes("ENT: ", (Uchar *)tp, 11);
+                       tp++;
+               }
+       }
+       tp = &dp->desc[0];
+       pe = &xb[len];
+
+       for (; (char *)tp < pe; tp++) {
+               if (tp->sess_number != dp->hd.last)
+                       continue;
+               if (tp->point != 0xB0)
+                       continue;
+               if (usalp->verbose)
+                       usal_prbytes("B0: ", (Uchar *)tp, 11);
+               if (isbcd) {
+                       l = msf_to_lba(from_bcd(tp->amin),
+                               from_bcd(tp->asec),
+                               from_bcd(tp->aframe), TRUE);
+               } else {
+                       l = msf_to_lba(tp->amin,
+                               tp->asec,
+                               tp->aframe, TRUE);
+               }
+               if (b0p)
+                       *b0p = l;
+
+               if (usalp->verbose)
+                       printf("B0 start: %ld\n", l);
+
+               if (isbcd) {
+                       l = msf_to_lba(from_bcd(tp->pmin),
+                               from_bcd(tp->psec),
+                               from_bcd(tp->pframe), TRUE);
+               } else {
+                       l = msf_to_lba(tp->pmin,
+                               tp->psec,
+                               tp->pframe, TRUE);
+               }
+
+               if (usalp->verbose)
+                       printf("B0 lout: %ld\n", l);
+               if (lop)
+                       *lop = l;
+               return (0);
+       }
+       return (-1);
+}
+
+
+/*
+ * Return address of first track in last session (SCSI-3/mmc version).
+ */
+int
+read_session_offset(SCSI *usalp, long *offp)
+{
+       struct  diskinfo *dp;
+       char    xb[256];
+       int     len;
+
+       dp = (struct diskinfo *)xb;
+
+       fillbytes((caddr_t)xb, sizeof (xb), '\0');
+       if (read_toc(usalp, (caddr_t)xb, 0, sizeof (struct tocheader), 0, FMT_SINFO) < 0)
+               return (-1);
+
+       if (usalp->verbose)
+               usal_prbytes("tocheader: ",
+               (Uchar *)xb, sizeof (struct tocheader) - usal_getresid(usalp));
+
+       len = a_to_u_2_byte(dp->hd.len) + sizeof (struct tocheader)-2;
+       if (len > (int)sizeof (xb)) {
+               errmsgno(EX_BAD, "Session info too big.\n");
+               return (-1);
+       }
+       if (read_toc(usalp, (caddr_t)xb, 0, len, 0, FMT_SINFO) < 0)
+               return (-1);
+
+       if (usalp->verbose)
+               usal_prbytes("tocheader: ",
+                       (Uchar *)xb, len - usal_getresid(usalp));
+
+       dp = (struct diskinfo *)xb;
+       if (offp)
+               *offp = a_to_u_4_byte(dp->desc[0].addr);
+       return (0);
+}
+
+/*
+ * Return address of first track in last session (pre SCSI-3 version).
+ */
+int
+read_session_offset_philips(SCSI *usalp, long *offp)
+{
+       struct  sinfo *sp;
+       char    xb[256];
+       int     len;
+
+       sp = (struct sinfo *)xb;
+
+       fillbytes((caddr_t)xb, sizeof (xb), '\0');
+       if (read_toc_philips(usalp, (caddr_t)xb, 0, sizeof (struct siheader), 0, FMT_SINFO) < 0)
+               return (-1);
+       len = a_to_u_2_byte(sp->hd.len) + sizeof (struct siheader)-2;
+       if (len > (int)sizeof (xb)) {
+               errmsgno(EX_BAD, "Session info too big.\n");
+               return (-1);
+       }
+       if (read_toc_philips(usalp, (caddr_t)xb, 0, len, 0, FMT_SINFO) < 0)
+               return (-1);
+       /*
+        * Old drives return the number of finished sessions in first/finished
+        * a descriptor is returned for each session.
+        * New drives return the number of the first and last session
+        * one descriptor for the last finished session is returned
+        * as in SCSI-3
+        * In all cases the lowest session number is set to 1.
+        */
+       sp = (struct sinfo *)xb;
+       if (offp)
+               *offp = a_to_u_4_byte(sp->desc[sp->hd.finished-1].addr);
+       return (0);
+}
+
+int
+sense_secsize(SCSI *usalp, int current)
+{
+       Uchar   mode[0x100];
+       Uchar   *p;
+       Uchar   *ep;
+       int     len;
+       int     secsize = -1;
+
+       usalp->silent++;
+       (void) unit_ready(usalp);
+       usalp->silent--;
+
+       /* XXX Quick and dirty, musz verallgemeinert werden !!! */
+
+       fillbytes(mode, sizeof (mode), '\0');
+       usalp->silent++;
+
+       len =   sizeof (struct scsi_mode_header) +
+               sizeof (struct scsi_mode_blockdesc);
+       /*
+        * Wenn wir hier get_mode_params() nehmen bekommen wir die Warnung:
+        * Warning: controller returns wrong page 1 for All pages page (3F).
+        */
+       if (mode_sense(usalp, mode, len, 0x3F, current?0:2) < 0) {
+               fillbytes(mode, sizeof (mode), '\0');
+               if (mode_sense(usalp, mode, len, 0, current?0:2) < 0)   { /* VU (block desc) */
+                       usalp->silent--;
+                       return (-1);
+               }
+       }
+       if (mode[3] == 8) {
+               if (usalp->debug) {
+                       printf("Density: 0x%X\n", mode[4]);
+                       printf("Blocks:  %ld\n", a_to_u_3_byte(&mode[5]));
+                       printf("Blocklen:%ld\n", a_to_u_3_byte(&mode[9]));
+               }
+               secsize = a_to_u_3_byte(&mode[9]);
+       }
+       fillbytes(mode, sizeof (mode), '\0');
+       /*
+        * The ACARD TECH AEC-7720 ATAPI<->SCSI adaptor
+        * chokes if we try to transfer more than 0x40 bytes with
+        * mode_sense of all pages. So try to avoid to run this
+        * command if possible.
+        */
+       if (usalp->debug &&
+           mode_sense(usalp, mode, 0xFE, 0x3F, current?0:2) >= 0) {    /* All Pages */
+
+               ep = mode+mode[0];      /* Points to last byte of data */
+               p = &mode[4];
+               p += mode[3];
+               printf("Pages: ");
+               while (p < ep) {
+                       printf("0x%X ", *p&0x3F);
+                       p += p[1]+2;
+               }
+               printf("\n");
+       }
+       usalp->silent--;
+
+       return (secsize);
+}
+
+int
+select_secsize(SCSI *usalp, int secsize)
+{
+       struct scsi_mode_data md;
+       int     count = sizeof (struct scsi_mode_header) +
+                       sizeof (struct scsi_mode_blockdesc);
+
+       (void) test_unit_ready(usalp);  /* clear any error situation */
+
+       fillbytes((caddr_t)&md, sizeof (md), '\0');
+       md.header.blockdesc_len = 8;
+       i_to_3_byte(md.blockdesc.lblen, secsize);
+
+       return (mode_select(usalp, (Uchar *)&md, count, 0, usalp->inq->data_format >= 2));
+}
+
+BOOL
+is_cddrive(SCSI *usalp)
+{
+       return (usalp->inq->type == INQ_ROMD || usalp->inq->type == INQ_WORM);
+}
+
+BOOL
+is_unknown_dev(SCSI *usalp)
+{
+       return (usalp->dev == DEV_UNKNOWN);
+}
+
+#ifndef        DEBUG
+#define        DEBUG
+#endif
+#ifdef DEBUG
+
+int
+read_scsi(SCSI *usalp, caddr_t bp, long addr, int cnt)
+{
+       if (addr <= G0_MAXADDR && cnt < 256 && !is_atapi)
+               return (read_g0(usalp, bp, addr, cnt));
+       else
+               return (read_g1(usalp, bp, addr, cnt));
+}
+
+int
+read_g0(SCSI *usalp, caddr_t bp, long addr, int cnt)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       if (usalp->cap->c_bsize <= 0)
+               raisecond("capacity_not_set", 0L);
+
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->addr = bp;
+       scmd->size = cnt*usalp->cap->c_bsize;
+       scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
+       scmd->cdb_len = SC_G0_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+       scmd->cdb.g0_cdb.cmd = SC_READ;
+       scmd->cdb.g0_cdb.lun = usal_lun(usalp);
+       g0_cdbaddr(&scmd->cdb.g0_cdb, addr);
+       scmd->cdb.g0_cdb.count = cnt;
+/*     scmd->cdb.g0_cdb.vu_56 = 1;*/
+
+       usalp->cmdname = "read_g0";
+
+       return (usal_cmd(usalp));
+}
+
+int
+read_g1(SCSI *usalp, caddr_t bp, long addr, int cnt)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       if (usalp->cap->c_bsize <= 0)
+               raisecond("capacity_not_set", 0L);
+
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->addr = bp;
+       scmd->size = cnt*usalp->cap->c_bsize;
+       scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
+       scmd->cdb_len = SC_G1_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+       scmd->cdb.g1_cdb.cmd = SC_EREAD;
+       scmd->cdb.g1_cdb.lun = usal_lun(usalp);
+       g1_cdbaddr(&scmd->cdb.g1_cdb, addr);
+       g1_cdblen(&scmd->cdb.g1_cdb, cnt);
+
+       usalp->cmdname = "read_g1";
+
+       return (usal_cmd(usalp));
+}
+#endif /* DEBUG */
+
+BOOL
+getdev(SCSI *usalp, BOOL print)
+{
+               BOOL    got_inquiry = TRUE;
+               char    vendor_info[8+1];
+               char    prod_ident[16+1];
+               char    prod_revision[4+1];
+               int     inq_len = 0;
+       register struct usal_cmd        *scmd = usalp->scmd;
+       register struct scsi_inquiry *inq = usalp->inq;
+
+
+       fillbytes((caddr_t)inq, sizeof (*inq), '\0');
+       usalp->dev = DEV_UNKNOWN;
+       usalp->silent++;
+       (void) unit_ready(usalp);
+       if (scmd->error >= SCG_FATAL &&
+                               !(scmd->scb.chk && scmd->sense_count > 0)) {
+               usalp->silent--;
+               return (FALSE);
+       }
+
+
+/*     if (scmd->error < SCG_FATAL || scmd->scb.chk && scmd->sense_count > 0){*/
+
+       if (inquiry(usalp, (caddr_t)inq, sizeof (*inq)) < 0) {
+               got_inquiry = FALSE;
+       } else {
+               inq_len = sizeof (*inq) - usal_getresid(usalp);
+       }
+       if (!got_inquiry) {
+               if (usalp->verbose) {
+                       printf(
+               "error: %d scb.chk: %d sense_count: %d sense.code: 0x%x\n",
+                               scmd->error, scmd->scb.chk,
+                               scmd->sense_count, scmd->sense.code);
+               }
+                       /*
+                        * Folgende Kontroller kennen das Kommando
+                        * INQUIRY nicht:
+                        *
+                        * ADAPTEC      ACB-4000, ACB-4010, ACB 4070
+                        * SYSGEN       SC4000
+                        *
+                        * Leider reagieren ACB40X0 und ACB5500 identisch
+                        * wenn drive not ready (code == not ready),
+                        * sie sind dann nicht zu unterscheiden.
+                        */
+
+               if (scmd->scb.chk && scmd->sense_count == 4) {
+                       /* Test auf SYSGEN                               */
+                       (void) qic02(usalp, 0x12);      /* soft lock on  */
+                       if (qic02(usalp, 1) < 0) {      /* soft lock off */
+                               usalp->dev = DEV_ACB40X0;
+/*                             usalp->dev = acbdev();*/
+                       } else {
+                               usalp->dev = DEV_SC4000;
+                               inq->type = INQ_SEQD;
+                               inq->removable = 1;
+                       }
+               }
+       } else if (usalp->verbose) {
+               int     i;
+               int     len = inq->add_len + 5;
+               Uchar   ibuf[256+5];
+               Uchar   *ip = (Uchar *)inq;
+               Uchar   c;
+
+               if (len > (int)sizeof (*inq) &&
+                               inquiry(usalp, (caddr_t)ibuf, inq->add_len+5) >= 0) {
+                       len = inq->add_len+5 - usal_getresid(usalp);
+                       ip = ibuf;
+               } else {
+                       len = sizeof (*inq);
+               }
+               printf("Inquiry Data   : ");
+               for (i = 0; i < len; i++) {
+                       c = ip[i];
+                       if (c >= ' ' && c < 0177)
+                               printf("%c", c);
+                       else
+                               printf(".");
+               }
+               printf("\n");
+       }
+
+       strncpy(vendor_info, inq->vendor_info, sizeof (inq->vendor_info));
+       strncpy(prod_ident, inq->prod_ident, sizeof (inq->prod_ident));
+       strncpy(prod_revision, inq->prod_revision, sizeof (inq->prod_revision));
+
+       vendor_info[sizeof (inq->vendor_info)] = '\0';
+       prod_ident[sizeof (inq->prod_ident)] = '\0';
+       prod_revision[sizeof (inq->prod_revision)] = '\0';
+
+       switch (inq->type) {
+
+       case INQ_DASD:
+               if (inq->add_len == 0 && inq->vendor_info[0] != '\0') {
+                       Uchar   *p;
+                       /*
+                        * NT-4.0 creates fake inquiry data for IDE disks.
+                        * Unfortunately, it does not set add_len wo we
+                        * check if vendor_info, prod_ident and prod_revision
+                        * contains valid chars for a CCS inquiry.
+                        */
+                       if (inq_len >= 36)
+                               inq->add_len = 31;
+
+                       for (p = (Uchar *)&inq->vendor_info[0];
+                                       p < (Uchar *)&inq->prod_revision[4];
+                                                                       p++) {
+                               if (*p < 0x20 || *p > 0x7E) {
+                                       inq->add_len = 0;
+                                       break;
+                               }
+                       }
+               }
+               if (inq->add_len == 0) {
+                       if (usalp->dev == DEV_UNKNOWN && got_inquiry) {
+                               usalp->dev = DEV_ACB5500;
+                               strcpy(inq->vendor_info,
+                                       "ADAPTEC ACB-5500        FAKE");
+
+                       } else switch (usalp->dev) {
+
+                               case DEV_ACB40X0:
+                                       strcpy(inq->vendor_info,
+                                                       "ADAPTEC ACB-40X0        FAKE");
+                                       break;
+                               case DEV_ACB4000:
+                                       strcpy(inq->vendor_info,
+                                                       "ADAPTEC ACB-4000        FAKE");
+                                       break;
+                               case DEV_ACB4010:
+                                       strcpy(inq->vendor_info,
+                                                       "ADAPTEC ACB-4010        FAKE");
+                                       break;
+                               case DEV_ACB4070:
+                                       strcpy(inq->vendor_info,
+                                                       "ADAPTEC ACB-4070        FAKE");
+                                       break;
+                       }
+               } else if (inq->add_len < 31) {
+                       usalp->dev = DEV_NON_CCS_DSK;
+
+               } else if (strbeg("EMULEX", vendor_info)) {
+                       if (strbeg("MD21", prod_ident))
+                               usalp->dev = DEV_MD21;
+                       if (strbeg("MD23", prod_ident))
+                               usalp->dev = DEV_MD23;
+                       else
+                               usalp->dev = DEV_CCS_GENDISK;
+               } else if (strbeg("ADAPTEC", vendor_info)) {
+                       if (strbeg("ACB-4520", prod_ident))
+                               usalp->dev = DEV_ACB4520A;
+                       if (strbeg("ACB-4525", prod_ident))
+                               usalp->dev = DEV_ACB4525;
+                       else
+                               usalp->dev = DEV_CCS_GENDISK;
+               } else if (strbeg("SONY", vendor_info) &&
+                                       strbeg("SMO-C501", prod_ident)) {
+                       usalp->dev = DEV_SONY_SMO;
+               } else {
+                       usalp->dev = DEV_CCS_GENDISK;
+               }
+               break;
+
+       case INQ_SEQD:
+               if (usalp->dev == DEV_SC4000) {
+                       strcpy(inq->vendor_info,
+                               "SYSGEN  SC4000          FAKE");
+               } else if (inq->add_len == 0 &&
+                                       inq->removable &&
+                                               inq->ansi_version == 1) {
+                       usalp->dev = DEV_MT02;
+                       strcpy(inq->vendor_info,
+                               "EMULEX  MT02            FAKE");
+               }
+               break;
+
+/*     case INQ_OPTD:*/
+       case INQ_ROMD:
+       case INQ_WORM:
+               if (strbeg("RXT-800S", prod_ident))
+                       usalp->dev = DEV_RXT800S;
+
+               /*
+                * Start of CD-Recorders:
+                */
+               if (strbeg("ACER", vendor_info)) {
+                       if (strbeg("CR-4020C", prod_ident))
+                               usalp->dev = DEV_RICOH_RO_1420C;
+
+               } else if (strbeg("CREATIVE", vendor_info)) {
+                       if (strbeg("CDR2000", prod_ident))
+                               usalp->dev = DEV_RICOH_RO_1060C;
+
+               } else if (strbeg("GRUNDIG", vendor_info)) {
+                       if (strbeg("CDR100IPW", prod_ident))
+                               usalp->dev = DEV_CDD_2000;
+
+               } else if (strbeg("JVC", vendor_info)) {
+                       if (strbeg("XR-W2001", prod_ident))
+                               usalp->dev = DEV_TEAC_CD_R50S;
+                       else if (strbeg("XR-W2010", prod_ident))
+                               usalp->dev = DEV_TEAC_CD_R50S;
+                       else if (strbeg("R2626", prod_ident))
+                               usalp->dev = DEV_TEAC_CD_R50S;
+
+               } else if (strbeg("MITSBISH", vendor_info)) {
+
+#ifdef XXXX_REALLY
+                       /* It's MMC compliant */
+                       if (strbeg("CDRW226", prod_ident))
+                               usalp->dev = DEV_MMC_CDRW;
+#else
+                       /* EMPTY */
+#endif
+
+               } else if (strbeg("MITSUMI", vendor_info)) {
+                       /* Don't know any product string */
+                       usalp->dev = DEV_CDD_522;
+
+               } else if (strbeg("OPTIMA", vendor_info)) {
+                       if (strbeg("CD-R 650", prod_ident))
+                               usalp->dev = DEV_SONY_CDU_924;
+
+               } else if (strbeg("PHILIPS", vendor_info) ||
+                               strbeg("IMS", vendor_info) ||
+                               strbeg("KODAK", vendor_info) ||
+                               strbeg("HP", vendor_info)) {
+
+                       if (strbeg("CDD521/00", prod_ident))
+                               usalp->dev = DEV_CDD_521_OLD;
+                       else if (strbeg("CDD521/02", prod_ident))
+                               usalp->dev = DEV_CDD_521_OLD;           /* PCD 200R? */
+                       else if (strbeg("CDD521", prod_ident))
+                               usalp->dev = DEV_CDD_521;
+
+                       if (strbeg("CDD522", prod_ident))
+                               usalp->dev = DEV_CDD_522;
+                       if (strbeg("PCD225", prod_ident))
+                               usalp->dev = DEV_CDD_522;
+                       if (strbeg("KHSW/OB", prod_ident))      /* PCD600 */
+                               usalp->dev = DEV_PCD_600;
+                       if (strbeg("CDR-240", prod_ident))
+                               usalp->dev = DEV_CDD_2000;
+
+                       if (strbeg("CDD20", prod_ident))
+                               usalp->dev = DEV_CDD_2000;
+                       if (strbeg("CDD26", prod_ident))
+                               usalp->dev = DEV_CDD_2600;
+
+                       if (strbeg("C4324/C4325", prod_ident))
+                               usalp->dev = DEV_CDD_2000;
+                       if (strbeg("CD-Writer 6020", prod_ident))
+                               usalp->dev = DEV_CDD_2600;
+
+               } else if (strbeg("PINNACLE", vendor_info)) {
+                       if (strbeg("RCD-1000", prod_ident))
+                               usalp->dev = DEV_TEAC_CD_R50S;
+                       if (strbeg("RCD5020", prod_ident))
+                               usalp->dev = DEV_TEAC_CD_R50S;
+                       if (strbeg("RCD5040", prod_ident))
+                               usalp->dev = DEV_TEAC_CD_R50S;
+                       if (strbeg("RCD 4X4", prod_ident))
+                               usalp->dev = DEV_TEAC_CD_R50S;
+
+               } else if (strbeg("PIONEER", vendor_info)) {
+                       if (strbeg("CD-WO DW-S114X", prod_ident))
+                               usalp->dev = DEV_PIONEER_DW_S114X;
+                       else if (strbeg("CD-WO DR-R504X", prod_ident))  /* Reoprt from philip@merge.com */
+                               usalp->dev = DEV_PIONEER_DW_S114X;
+                       else if (strbeg("DVD-R DVR-S101", prod_ident))
+                               usalp->dev = DEV_PIONEER_DVDR_S101;
+
+               } else if (strbeg("PLASMON", vendor_info)) {
+                       if (strbeg("RF4100", prod_ident))
+                               usalp->dev = DEV_PLASMON_RF_4100;
+                       else if (strbeg("CDR4220", prod_ident))
+                               usalp->dev = DEV_CDD_2000;
+
+               } else if (strbeg("PLEXTOR", vendor_info)) {
+                       if (strbeg("CD-R   PX-R24CS", prod_ident))
+                               usalp->dev = DEV_RICOH_RO_1420C;
+
+               } else if (strbeg("RICOH", vendor_info)) {
+                       if (strbeg("RO-1420C", prod_ident))
+                               usalp->dev = DEV_RICOH_RO_1420C;
+                       if (strbeg("RO1060C", prod_ident))
+                               usalp->dev = DEV_RICOH_RO_1060C;
+
+               } else if (strbeg("SAF", vendor_info)) {        /* Smart & Friendly */
+                       if (strbeg("CD-R2004", prod_ident) ||
+                           strbeg("CD-R2006 ", prod_ident))
+                               usalp->dev = DEV_SONY_CDU_924;
+                       else if (strbeg("CD-R2006PLUS", prod_ident))
+                               usalp->dev = DEV_TEAC_CD_R50S;
+                       else if (strbeg("CD-RW226", prod_ident))
+                               usalp->dev = DEV_TEAC_CD_R50S;
+                       else if (strbeg("CD-R4012", prod_ident))
+                               usalp->dev = DEV_TEAC_CD_R50S;
+
+               } else if (strbeg("SANYO", vendor_info)) {
+                       if (strbeg("CD-WO CRD-R24S", prod_ident))
+                               usalp->dev = DEV_CDD_521;
+
+               } else if (strbeg("SONY", vendor_info)) {
+                       if (strbeg("CD-R   CDU92", prod_ident) ||
+                           strbeg("CD-R   CDU94", prod_ident))
+                               usalp->dev = DEV_SONY_CDU_924;
+
+               } else if (strbeg("TEAC", vendor_info)) {
+                       if (strbeg("CD-R50S", prod_ident) ||
+                           strbeg("CD-R55S", prod_ident))
+                               usalp->dev = DEV_TEAC_CD_R50S;
+
+               } else if (strbeg("TRAXDATA", vendor_info) ||
+                               strbeg("Traxdata", vendor_info)) {
+                       if (strbeg("CDR4120", prod_ident))
+                               usalp->dev = DEV_TEAC_CD_R50S;
+
+               } else if (strbeg("T.YUDEN", vendor_info)) {
+                       if (strbeg("CD-WO EW-50", prod_ident))
+                               usalp->dev = DEV_TYUDEN_EW50;
+
+               } else if (strbeg("WPI", vendor_info)) {        /* Wearnes */
+                       if (strbeg("CDR-632P", prod_ident))
+                               usalp->dev = DEV_CDD_2600;
+
+               } else if (strbeg("YAMAHA", vendor_info)) {
+                       if (strbeg("CDR10", prod_ident))
+                               usalp->dev = DEV_YAMAHA_CDR_100;
+                       if (strbeg("CDR200", prod_ident))
+                               usalp->dev = DEV_YAMAHA_CDR_400;
+                       if (strbeg("CDR400", prod_ident))
+                               usalp->dev = DEV_YAMAHA_CDR_400;
+
+               } else if (strbeg("MATSHITA", vendor_info)) {
+                       if (strbeg("CD-R   CW-7501", prod_ident))
+                               usalp->dev = DEV_MATSUSHITA_7501;
+                       if (strbeg("CD-R   CW-7502", prod_ident))
+                               usalp->dev = DEV_MATSUSHITA_7502;
+               }
+               if (usalp->dev == DEV_UNKNOWN) {
+                       /*
+                        * We do not have Manufacturer strings for
+                        * the following drives.
+                        */
+                       if (strbeg("CDS615E", prod_ident))      /* Olympus */
+                               usalp->dev = DEV_SONY_CDU_924;
+               }
+               if (usalp->dev == DEV_UNKNOWN && inq->type == INQ_ROMD) {
+                       BOOL    cdrr     = FALSE;
+                       BOOL    cdwr     = FALSE;
+                       BOOL    cdrrw    = FALSE;
+                       BOOL    cdwrw    = FALSE;
+                       BOOL    dvd      = FALSE;
+                       BOOL    dvdwr    = FALSE;
+
+                       usalp->dev = DEV_CDROM;
+
+                       if (mmc_check(usalp, &cdrr, &cdwr, &cdrrw, &cdwrw,
+                                                               &dvd, &dvdwr))
+                               usalp->dev = DEV_MMC_CDROM;
+                       if (cdwr)
+                               usalp->dev = DEV_MMC_CDR;
+                       if (cdwrw)
+                               usalp->dev = DEV_MMC_CDRW;
+                       if (dvd)
+                               usalp->dev = DEV_MMC_DVD;
+                       if (dvdwr)
+                               usalp->dev = DEV_MMC_DVD_WR;
+               }
+               break;
+
+       case INQ_PROCD:
+               if (strbeg("BERTHOLD", vendor_info)) {
+                       if (strbeg("", prod_ident))
+                               usalp->dev = DEV_HRSCAN;
+               }
+               break;
+
+       case INQ_SCAN:
+               usalp->dev = DEV_MS300A;
+               break;
+       }
+       usalp->silent--;
+       if (!print)
+               return (TRUE);
+
+       if (usalp->dev == DEV_UNKNOWN && !got_inquiry) {
+#ifdef PRINT_INQ_ERR
+               usal_printerr(usalp);
+#endif
+               return (FALSE);
+       }
+
+       printinq(usalp, stdout);
+       return (TRUE);
+}
+
+void
+printinq(SCSI *usalp, FILE *f)
+{
+       register struct scsi_inquiry *inq = usalp->inq;
+
+       fprintf(f, "Device type    : ");
+       usal_fprintdev(f, inq);
+       fprintf(f, "Version        : %d\n", inq->ansi_version);
+       fprintf(f, "Response Format: %d\n", inq->data_format);
+       if (inq->data_format >= 2) {
+               fprintf(f, "Capabilities   : ");
+               if (inq->aenc)          fprintf(f, "AENC ");
+               if (inq->termiop)       fprintf(f, "TERMIOP ");
+               if (inq->reladr)        fprintf(f, "RELADR ");
+               if (inq->wbus32)        fprintf(f, "WBUS32 ");
+               if (inq->wbus16)        fprintf(f, "WBUS16 ");
+               if (inq->sync)          fprintf(f, "SYNC ");
+               if (inq->linked)        fprintf(f, "LINKED ");
+               if (inq->cmdque)        fprintf(f, "CMDQUE ");
+               if (inq->softreset)     fprintf(f, "SOFTRESET ");
+               fprintf(f, "\n");
+       }
+       if (inq->add_len >= 31 ||
+                       inq->vendor_info[0] ||
+                       inq->prod_ident[0] ||
+                       inq->prod_revision[0]) {
+               fprintf(f, "Vendor_info    : '%.8s'\n", inq->vendor_info);
+               fprintf(f, "Identification : '%.16s'\n", inq->prod_ident);
+               fprintf(f, "Revision       : '%.4s'\n", inq->prod_revision);
+       }
+}
+
+void
+printdev(SCSI *usalp)
+{
+       printf("Device seems to be: ");
+
+       switch (usalp->dev) {
+
+       case DEV_UNKNOWN:       printf("unknown");              break;
+       case DEV_ACB40X0:       printf("Adaptec 4000/4010/4070"); break;
+       case DEV_ACB4000:       printf("Adaptec 4000");         break;
+       case DEV_ACB4010:       printf("Adaptec 4010");         break;
+       case DEV_ACB4070:       printf("Adaptec 4070");         break;
+       case DEV_ACB5500:       printf("Adaptec 5500");         break;
+       case DEV_ACB4520A:      printf("Adaptec 4520A");        break;
+       case DEV_ACB4525:       printf("Adaptec 4525");         break;
+       case DEV_MD21:          printf("Emulex MD21");          break;
+       case DEV_MD23:          printf("Emulex MD23");          break;
+       case DEV_NON_CCS_DSK:   printf("Generic NON CCS Disk"); break;
+       case DEV_CCS_GENDISK:   printf("Generic CCS Disk");     break;
+       case DEV_SONY_SMO:      printf("Sony SMO-C501");        break;
+       case DEV_MT02:          printf("Emulex MT02");          break;
+       case DEV_SC4000:        printf("Sysgen SC4000");        break;
+       case DEV_RXT800S:       printf("Maxtor RXT800S");       break;
+       case DEV_HRSCAN:        printf("Berthold HR-Scanner");  break;
+       case DEV_MS300A:        printf("Microtek MS300A");      break;
+
+       case DEV_CDROM:         printf("Generic CD-ROM");       break;
+       case DEV_MMC_CDROM:     printf("Generic mmc CD-ROM");   break;
+       case DEV_MMC_CDR:       printf("Generic mmc CD-R");     break;
+       case DEV_MMC_CDRW:      printf("Generic mmc CD-RW");    break;
+       case DEV_MMC_DVD:       printf("Generic mmc2 DVD-ROM"); break;
+       case DEV_MMC_DVD_WR:    printf("Generic mmc2 DVD-R/DVD-RW"); break;
+       case DEV_CDD_521_OLD:   printf("Philips old CDD-521");  break;
+       case DEV_CDD_521:       printf("Philips CDD-521");      break;
+       case DEV_CDD_522:       printf("Philips CDD-522");      break;
+       case DEV_PCD_600:       printf("Kodak PCD-600");        break;
+       case DEV_CDD_2000:      printf("Philips CDD-2000");     break;
+       case DEV_CDD_2600:      printf("Philips CDD-2600");     break;
+       case DEV_YAMAHA_CDR_100:printf("Yamaha CDR-100");       break;
+       case DEV_YAMAHA_CDR_400:printf("Yamaha CDR-400");       break;
+       case DEV_PLASMON_RF_4100:printf("Plasmon RF-4100");     break;
+       case DEV_SONY_CDU_924:  printf("Sony CDU-924S");        break;
+       case DEV_RICOH_RO_1060C:printf("Ricoh RO-1060C");       break;
+       case DEV_RICOH_RO_1420C:printf("Ricoh RO-1420C");       break;
+       case DEV_TEAC_CD_R50S:  printf("Teac CD-R50S");         break;
+       case DEV_MATSUSHITA_7501:printf("Matsushita CW-7501");  break;
+       case DEV_MATSUSHITA_7502:printf("Matsushita CW-7502");  break;
+
+       case DEV_PIONEER_DW_S114X: printf("Pioneer DW-S114X");  break;
+       case DEV_PIONEER_DVDR_S101:printf("Pioneer DVD-R S101"); break;
+
+       default:                printf("Missing Entry for dev %d",
+                                               usalp->dev);    break;
+
+       }
+       printf(".\n");
+
+}
+
+BOOL
+do_inquiry(SCSI *usalp, int print)
+{
+       if (getdev(usalp, print)) {
+               if (print)
+                       printdev(usalp);
+               return (TRUE);
+       } else {
+               return (FALSE);
+       }
+}
+
+BOOL
+recovery_needed(SCSI *usalp, cdr_t *dp)
+{
+               int err;
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       usalp->silent++;
+       err = test_unit_ready(usalp);
+       usalp->silent--;
+
+       if (err >= 0)
+               return (FALSE);
+       else if (scmd->error >= SCG_FATAL)      /* nicht selektierbar */
+               return (FALSE);
+
+       if (scmd->sense.code < 0x70)            /* non extended Sense */
+               return (FALSE);
+
+                                               /* XXX Old Philips code */
+       return (((struct scsi_ext_sense *)&scmd->sense)->sense_code == 0xD0);
+}
+
+int
+scsi_load(SCSI *usalp, cdr_t *dp)
+{
+       int     key;
+       int     code;
+
+       if ((dp->cdr_flags & CDR_CADDYLOAD) == 0) {
+               if (scsi_start_stop_unit(usalp, 1, 1, dp && (dp->cdr_cmdflags&F_IMMED)) >= 0)
+                       return (0);
+       }
+
+       if (wait_unit_ready(usalp, 60))
+               return (0);
+
+       key = usal_sense_key(usalp);
+       code = usal_sense_code(usalp);
+
+       if (key == SC_NOT_READY && (code == 0x3A || code == 0x30)) {
+               errmsgno(EX_BAD, "Cannot load media with %s drive!\n",
+                       (dp->cdr_flags & CDR_CADDYLOAD) ? "caddy" : "this");
+               errmsgno(EX_BAD, "Try to load media by hand.\n");
+       }
+       return (-1);
+}
+
+int
+scsi_unload(SCSI *usalp, cdr_t *dp)
+{
+       return (scsi_start_stop_unit(usalp, 0, 1, dp && (dp->cdr_cmdflags&F_IMMED)));
+}
+
+int 
+scsi_cdr_write(SCSI *usalp, 
+               caddr_t bp       /* address of buffer */, 
+               long sectaddr    /* disk address (sector) to put */, 
+               long size        /* number of bytes to transfer */, 
+               int blocks       /* sector count */, 
+               BOOL islast      /* last write for track */)
+{
+       return (write_xg1(usalp, bp, sectaddr, size, blocks));
+}
+
+struct cd_mode_page_2A *
+mmc_cap(SCSI *usalp, Uchar *modep)
+{
+       int     len;
+       int     val;
+       Uchar   mode[0x100];
+       struct  cd_mode_page_2A *mp;
+       struct  cd_mode_page_2A *mp2;
+
+
+retry:
+       fillbytes((caddr_t)mode, sizeof (mode), '\0');
+
+       if (!get_mode_params(usalp, 0x2A, "CD capabilities",
+                       mode, (Uchar *)0, (Uchar *)0, (Uchar *)0, &len)) {
+
+               if (usal_sense_key(usalp) == SC_NOT_READY) {
+                       if (wait_unit_ready(usalp, 60))
+                               goto retry;
+               }
+               return (NULL);          /* Pre SCSI-3/mmc drive         */
+       }
+
+       if (len == 0)                   /* Pre SCSI-3/mmc drive         */
+               return (NULL);
+
+       mp = (struct cd_mode_page_2A *)
+               (mode + sizeof (struct scsi_mode_header) +
+               ((struct scsi_mode_header *)mode)->blockdesc_len);
+
+       /*
+        * Do some heuristics against pre SCSI-3/mmc VU page 2A
+        * We should test for a minimum p_len of 0x14, but some
+        * buggy CD-ROM readers ommit the write speed values.
+        */
+       if (mp->p_len < 0x10)
+               return (NULL);
+
+       val = a_to_u_2_byte(mp->max_read_speed);
+       if (val != 0 && val < 176)
+               return (NULL);
+
+       val = a_to_u_2_byte(mp->cur_read_speed);
+       if (val != 0 && val < 176)
+               return (NULL);
+
+       len -= sizeof (struct scsi_mode_header) +
+               ((struct scsi_mode_header *)mode)->blockdesc_len;
+       if (modep)
+               mp2 = (struct cd_mode_page_2A *)modep;
+       else
+               mp2 = malloc(len);
+       if (mp2)
+               movebytes(mp, mp2, len);
+
+       return (mp2);
+}
+
+void
+mmc_getval(struct cd_mode_page_2A *mp, 
+           BOOL *cdrrp  /* CD ROM */, 
+           BOOL *cdwrp  /* CD-R writer */, 
+           BOOL *cdrrwp /* CD-RW reader */, 
+           BOOL *cdwrwp /* CD-RW writer */, 
+           BOOL *dvdp   /* DVD reader */, 
+           BOOL *dvdwp  /* DVD writer */)
+{
+       BOOL    isdvd;                          /* Any DVD reader       */
+       BOOL    isdvd_wr;                       /* DVD writer (R / RAM) */
+       BOOL    iscd_wr;                        /* CD  writer           */
+
+       iscd_wr = (mp->cd_r_write != 0) ||      /* SCSI-3/mmc CD-R      */
+                   (mp->cd_rw_write != 0);     /* SCSI-3/mmc CD-RW     */
+
+       if (cdrrp)
+               *cdrrp = (mp->cd_r_read != 0);  /* SCSI-3/mmc CD        */
+       if (cdwrp)
+               *cdwrp = (mp->cd_r_write != 0); /* SCSI-3/mmc CD-R      */
+
+       if (cdrrwp)
+               *cdrrwp = (mp->cd_rw_read != 0); /* SCSI-3/mmc CD       */
+       if (cdwrwp)
+               *cdwrwp = (mp->cd_rw_write != 0); /* SCSI-3/mmc CD-RW   */
+
+       isdvd =                                 /* SCSI-3/mmc2 DVD      */
+               (mp->dvd_ram_read + mp->dvd_r_read  +
+                   mp->dvd_rom_read) != 0;
+
+       isdvd_wr =                              /* SCSI-3/mmc2 DVD writer*/
+               (mp->dvd_ram_write + mp->dvd_r_write) != 0;
+
+       if (dvdp)
+               *dvdp = isdvd;
+       if (dvdwp)
+               *dvdwp = isdvd_wr;
+}
+
+BOOL
+is_mmc(SCSI *usalp, BOOL *cdwp, BOOL *dvdwp)
+{
+       BOOL    cdwr    = FALSE;
+       BOOL    cdwrw   = FALSE;
+
+       if (cdwp)
+               *cdwp = FALSE;
+       if (dvdwp)
+               *dvdwp = FALSE;
+
+       if (!mmc_check(usalp, NULL, &cdwr, NULL, &cdwrw, NULL, dvdwp))
+               return (FALSE);
+
+       if (cdwp)
+               *cdwp = cdwr | cdwrw;
+
+       return (TRUE);
+}
+
+BOOL
+mmc_check(SCSI *usalp, 
+          BOOL *cdrrp   /* CD ROM */, 
+          BOOL *cdwrp   /* CD-R writer */, 
+          BOOL *cdrrwp  /* CD-RW reader */, 
+          BOOL *cdwrwp  /* CD-RW writer */, 
+          BOOL *dvdp    /* DVD reader */, 
+          BOOL *dvdwp   /* DVD writer */)
+{
+       Uchar   mode[0x100];
+       BOOL    was_atapi;
+       struct  cd_mode_page_2A *mp;
+
+       if (usalp->inq->type != INQ_ROMD)
+               return (FALSE);
+
+       fillbytes((caddr_t)mode, sizeof (mode), '\0');
+
+       was_atapi = allow_atapi(usalp, TRUE);
+       usalp->silent++;
+       mp = mmc_cap(usalp, mode);
+       usalp->silent--;
+       allow_atapi(usalp, was_atapi);
+       if (mp == NULL)
+               return (FALSE);
+
+       mmc_getval(mp, cdrrp, cdwrp, cdrrwp, cdwrwp, dvdp, dvdwp);
+
+       return (TRUE);                  /* Generic SCSI-3/mmc CD        */
+}
+
+static void
+print_speed(char *fmt, int val)
+{
+       printf("  %s: %5d kB/s", fmt, val);
+       printf(" (CD %3ux,", val/176);
+       printf(" DVD %2ux)\n", val/1385);
+}
+
+#define        DOES(what, flag)        printf("  Does %s%s\n", flag?"":"not ", what)
+#define        IS(what, flag)          printf("  Is %s%s\n", flag?"":"not ", what)
+#define        VAL(what, val)          printf("  %s: %d\n", what, val[0]*256 + val[1])
+#define        SVAL(what, val)         printf("  %s: %s\n", what, val)
+
+void
+print_capabilities(SCSI *usalp)
+{
+       BOOL    was_atapi;
+       Uchar   mode[0x100];
+       struct  cd_mode_page_2A *mp;
+static const   char    *bclk[4] = {"32", "16", "24", "24 (I2S)"};
+static const   char    *load[8] = {"caddy", "tray", "pop-up", "reserved(3)",
+                               "disc changer", "cartridge changer",
+                               "reserved(6)", "reserved(7)" };
+static const   char    *rotctl[4] = {"CLV/PCAV", "CAV", "reserved(2)", "reserved(3)"};
+
+
+       if (usalp->inq->type != INQ_ROMD)
+               return;
+
+       fillbytes((caddr_t)mode, sizeof (mode), '\0');
+
+       was_atapi = allow_atapi(usalp, TRUE);   /* Try to switch to 10 byte mode cmds */
+       usalp->silent++;
+       mp = mmc_cap(usalp, mode);
+       usalp->silent--;
+       allow_atapi(usalp, was_atapi);
+       if (mp == NULL)
+               return;
+
+       printf("\nDrive capabilities, per");
+       if (mp->p_len >= 28)
+               printf(" MMC-3");
+       else if (mp->p_len >= 24)
+               printf(" MMC-2");
+       else
+               printf(" MMC");
+       printf(" page 2A:\n\n");
+
+       DOES("read CD-R media", mp->cd_r_read);
+       DOES("write CD-R media", mp->cd_r_write);
+       DOES("read CD-RW media", mp->cd_rw_read);
+       DOES("write CD-RW media", mp->cd_rw_write);
+       DOES("read DVD-ROM media", mp->dvd_rom_read);
+       DOES("read DVD-R media", mp->dvd_r_read);
+       DOES("write DVD-R media", mp->dvd_r_write);
+       DOES("read DVD-RAM media", mp->dvd_ram_read);
+       DOES("write DVD-RAM media", mp->dvd_ram_write);
+       DOES("support test writing", mp->test_write);
+       printf("\n");
+       DOES("read Mode 2 Form 1 blocks", mp->mode_2_form_1);
+       DOES("read Mode 2 Form 2 blocks", mp->mode_2_form_2);
+       DOES("read digital audio blocks", mp->cd_da_supported);
+       if (mp->cd_da_supported)
+               DOES("restart non-streamed digital audio reads accurately", mp->cd_da_accurate);
+       DOES("support Buffer-Underrun-Free recording", mp->BUF);
+       DOES("read multi-session CDs", mp->multi_session);
+       DOES("read fixed-packet CD media using Method 2", mp->method2);
+       DOES("read CD bar code", mp->read_bar_code);
+       DOES("read R-W subcode information", mp->rw_supported);
+       if (mp->rw_supported)
+               DOES("return R-W subcode de-interleaved and error-corrected", mp->rw_deint_corr);
+       DOES("read raw P-W subcode data from lead in", mp->pw_in_lead_in);
+       DOES("return CD media catalog number", mp->UPC);
+       DOES("return CD ISRC information", mp->ISRC);
+       DOES("support C2 error pointers", mp->c2_pointers);
+       DOES("deliver composite A/V data", mp->composite);
+       printf("\n");
+       DOES("play audio CDs", mp->audio_play);
+       if (mp->audio_play) {
+               VAL("Number of volume control levels", mp->num_vol_levels);
+               DOES("support individual volume control setting for each channel", mp->sep_chan_vol);
+               DOES("support independent mute setting for each channel", mp->sep_chan_mute);
+               DOES("support digital output on port 1", mp->digital_port_1);
+               DOES("support digital output on port 2", mp->digital_port_2);
+               if (mp->digital_port_1 || mp->digital_port_2) {
+                       DOES("send digital data LSB-first", mp->LSBF);
+                       DOES("set LRCK high for left-channel data", mp->RCK);
+                       DOES("have valid data on falling edge of clock", mp->BCK);
+                       SVAL("Length of data in BCLKs", bclk[mp->length]);
+               }
+       }
+       printf("\n");
+       SVAL("Loading mechanism type", load[mp->loading_type]);
+       DOES("support ejection of CD via START/STOP command", mp->eject);
+       DOES("lock media on power up via prevent jumper", mp->prevent_jumper);
+       DOES("allow media to be locked in the drive via PREVENT/ALLOW command", mp->lock);
+       IS("currently in a media-locked state", mp->lock_state);
+       DOES("support changing side of disk", mp->side_change);
+       DOES("have load-empty-slot-in-changer feature", mp->sw_slot_sel);
+       DOES("support Individual Disk Present feature", mp->disk_present_rep);
+       printf("\n");
+       print_speed("Maximum read  speed", a_to_u_2_byte(mp->max_read_speed));
+       print_speed("Current read  speed", a_to_u_2_byte(mp->cur_read_speed));
+       print_speed("Maximum write speed", a_to_u_2_byte(mp->max_write_speed));
+       if (mp->p_len >= 28)
+               print_speed("Current write speed", a_to_u_2_byte(mp->v3_cur_write_speed));
+       else
+               print_speed("Current write speed", a_to_u_2_byte(mp->cur_write_speed));
+       if (mp->p_len >= 28) {
+               SVAL("Rotational control selected", rotctl[mp->rot_ctl_sel]);
+       }
+       VAL("Buffer size in KB", mp->buffer_size);
+
+       if (mp->p_len >= 24) {
+               VAL("Copy management revision supported", mp->copy_man_rev);
+       }
+
+       if (mp->p_len >= 28) {
+               struct cd_wr_speed_performance *pp;
+               Uint    ndesc;
+               Uint    i;
+               Uint    n;
+
+               ndesc = a_to_u_2_byte(mp->num_wr_speed_des);
+               pp = mp->wr_speed_des;
+               printf("  Number of supported write speeds: %d\n", ndesc);
+               for (i = 0; i < ndesc; i++, pp++) {
+                       printf("  Write speed # %d:", i);
+                       n = a_to_u_2_byte(pp->wr_speed_supp);
+                       printf(" %5d kB/s", n);
+                       printf(" %s", rotctl[pp->rot_ctl_sel]);
+                       printf(" (CD %3ux,", n/176);
+                       printf(" DVD %2ux)\n", n/1385);
+               }
+       }
+
+       /* Generic SCSI-3/mmc CD        */
+}
diff --git a/wodim/scsi_cdr_mmc4.c b/wodim/scsi_cdr_mmc4.c
new file mode 100644 (file)
index 0000000..cb0958a
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)scsi_cdr_mmc4.c 1.1 05/05/16 Copyright 1995-2005 J. Schilling */
+/*
+ *     SCSI command functions for cdrecord
+ *     covering MMC-4
+ *
+ *     Copyright (c) 1995-2005 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <mconfig.h>
+
+#include <stdio.h>
+#include <standard.h>
+#include <stdxlib.h>
+#include <unixstd.h>
+#include <fctldefs.h>
+#include <errno.h>
+#include <strdefs.h>
+#include <timedefs.h>
+
+#include <utypes.h>
+#include <btorder.h>
+#include <intcvt.h>
+#include <schily.h>
+
+#include <usal/usalcmd.h>
+#include <usal/scsidefs.h>
+#include <usal/scsireg.h>
+#include <usal/scsitransp.h>
+
+#include "scsimmc.h"
+#include "wodim.h"
+
+void   print_capabilities_mmc4(SCSI *usalp);
+
+#define        DOES(what, flag)        printf("  Does %s%s\n", flag?"":"not ", what)
+
+
+void
+print_capabilities_mmc4(SCSI *usalp)
+{
+       int     cdrw_types;
+
+       if (usalp->inq->type != INQ_ROMD)
+               return;
+
+       cdrw_types = get_supported_cdrw_media_types(usalp);
+       if (cdrw_types != -1) {
+               printf("\nSupported CD-RW media types according to MMC-4 feature 0x37:\n");
+               DOES("write multi speed       CD-RW media", (cdrw_types & CDR_CDRW_MULTI));
+               DOES("write high  speed       CD-RW media", (cdrw_types & CDR_CDRW_HIGH));
+               DOES("write ultra high speed  CD-RW media", (cdrw_types & CDR_CDRW_ULTRA));
+               DOES("write ultra high speed+ CD-RW media", (cdrw_types & CDR_CDRW_ULTRAP));
+       }
+}
diff --git a/wodim/scsi_mmc.c b/wodim/scsi_mmc.c
new file mode 100644 (file)
index 0000000..f8baa1f
--- /dev/null
@@ -0,0 +1,411 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)scsi_mmc.c      1.13 05/05/16 Copyright 2002-2005 J. Schilling */
+/*
+ *     SCSI command functions for cdrecord
+ *     covering MMC-3 level and above
+ *
+ *     Copyright (c) 2002-2005 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*
+Includes code from http://libburnia.pykix.org/browser/libburn/trunk/libburn/mmc.c?format=txt 
+*/
+
+/*#define      DEBUG*/
+
+#include <mconfig.h>
+
+#include <stdio.h>
+#include <standard.h>
+#include <stdxlib.h>
+#include <unixstd.h>
+#include <fctldefs.h>
+#include <errno.h>
+#include <strdefs.h>
+#include <timedefs.h>
+
+#include <utypes.h>
+#include <btorder.h>
+#include <intcvt.h>
+#include <schily.h>
+
+#include <usal/usalcmd.h>
+#include <usal/scsidefs.h>
+#include <usal/scsireg.h>
+#include <usal/scsitransp.h>
+
+#include "scsimmc.h"
+#include "wodim.h"
+
+extern int     xdebug;
+
+
+
+int    get_configuration(SCSI *usalp, caddr_t bp, int cnt, int st_feature, 
+                                                               int rt);
+static int     get_conflen(SCSI *usalp, int st_feature, int rt);
+int    get_curprofile(SCSI *usalp);
+static int     get_profiles(SCSI *usalp, caddr_t bp, int cnt);
+int    print_profiles(SCSI *usalp);
+int    get_proflist(SCSI *usalp, BOOL *wp, BOOL *cdp, BOOL *dvdp, BOOL *dvdplusp,
+                                                BOOL *ddcdp);
+int    get_wproflist(SCSI *usalp, BOOL *cdp, BOOL *dvdp, BOOL *dvdplusp, 
+                                                 BOOL *ddcdp);
+
+/*
+ * Get feature codes
+ */
+int
+get_configuration(SCSI *usalp, caddr_t bp, int cnt, int st_feature, int rt)
+{
+       register struct usal_cmd        *scmd = usalp->scmd;
+
+       fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
+       scmd->addr = bp;
+       scmd->size = cnt;
+       scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
+       scmd->cdb_len = SC_G1_CDBLEN;
+       scmd->sense_len = CCS_SENSE_LEN;
+       scmd->cdb.g1_cdb.cmd = 0x46;
+       scmd->cdb.g1_cdb.lun = usal_lun(usalp);
+       if (rt & 1)
+               scmd->cdb.g1_cdb.reladr  = 1;
+       if (rt & 2)
+               scmd->cdb.g1_cdb.res  = 1;
+
+       i_to_2_byte(scmd->cdb.g1_cdb.addr, st_feature);
+       g1_cdblen(&scmd->cdb.g1_cdb, cnt);
+
+       usalp->cmdname = "get_configuration";
+
+       return (usal_cmd(usalp));
+}
+
+/*
+ * Retrieve feature code list length
+ */
+static int
+get_conflen(SCSI *usalp, int st_feature, int rt)
+{
+       Uchar   cbuf[8];
+       int     flen;
+       int     i;
+
+       fillbytes(cbuf, sizeof (cbuf), '\0');
+       usalp->silent++;
+       i = get_configuration(usalp, (char *)cbuf, sizeof (cbuf), st_feature, rt);
+       usalp->silent--;
+       if (i < 0)
+               return (-1);
+       i = sizeof (cbuf) - usal_getresid(usalp);
+       if (i < 4)
+               return (-1);
+
+       flen = a_to_u_4_byte(cbuf);
+       if (flen < 4)
+               return (-1);
+       return (flen);
+}
+
+int
+get_curprofile(SCSI *usalp)
+{
+       Uchar   cbuf[8];
+       int     amt;
+       int     flen;
+       int     profile;
+       int     i;
+
+       fillbytes(cbuf, sizeof (cbuf), '\0');
+       usalp->silent++;
+       i = get_configuration(usalp, (char *)cbuf, sizeof (cbuf), 0, 0);
+       usalp->silent--;
+       if (i < 0)
+               return (-1);
+
+       amt = sizeof (cbuf) - usal_getresid(usalp);
+       if (amt < 8)
+               return (-1);
+       flen = a_to_u_4_byte(cbuf);
+       if (flen < 4)
+               return (-1);
+
+       profile = a_to_u_2_byte(&cbuf[6]);
+
+       if (xdebug > 1)
+               usal_prbytes("Features: ", cbuf, amt);
+
+       if (xdebug > 0)
+               printf("feature len: %d current profile 0x%04X (%s) len %d\n",
+                               flen, profile,
+                               mmc_obtain_profile_name(profile), amt);
+
+       return (profile);
+}
+
+static int
+get_profiles(SCSI *usalp, caddr_t bp, int cnt)
+{
+       int     amt;
+       int     flen;
+       int     i;
+
+       flen = get_conflen(usalp, 0, 0);
+       if (flen < 0)
+               return (-1);
+       if (cnt < flen)
+               flen = cnt;
+
+       fillbytes(bp, cnt, '\0');
+       usalp->silent++;
+       i = get_configuration(usalp, (char *)bp, flen, 0, 0);
+       usalp->silent--;
+       if (i < 0)
+               return (-1);
+       amt = flen - usal_getresid(usalp);
+
+       flen = a_to_u_4_byte(bp);
+       if ((flen+4) < amt)
+               amt = flen+4;
+
+       return (amt);
+}
+
+int
+print_profiles(SCSI *usalp)
+{
+       Uchar   cbuf[1024];
+       Uchar   *p;
+       int     flen;
+       int     curprofile;
+       int     profile;
+       int     i;
+       int     n;
+
+       flen = get_profiles(usalp, (caddr_t)cbuf, sizeof (cbuf));
+       if (flen < 0)
+               return (-1);
+
+       p = cbuf;
+       if (xdebug > 1)
+               usal_prbytes("Features: ", cbuf, flen);
+
+       curprofile = a_to_u_2_byte(&p[6]);
+       if (xdebug > 0)
+               printf("feature len: %d current profile 0x%04X (%s)\n",
+                               flen, curprofile,
+                               mmc_obtain_profile_name(curprofile));
+
+       printf("Current: 0x%04X (%s)\n", curprofile,
+                       mmc_obtain_profile_name(curprofile));
+
+       p += 8;         /* Skip feature header  */
+       n = p[3];       /* Additional length    */
+       n /= 4;
+       p += 4;
+
+       for (i = 0; i < n; i++) {
+               profile = a_to_u_2_byte(p);
+               if (xdebug > 0)
+                       printf("Profile: 0x%04X (%s)", profile,
+                                       mmc_obtain_profile_name(profile));
+               else
+                       printf("Profile: ");
+               printf("0x%04X (%s) %s\n", profile,
+                               mmc_obtain_profile_name(profile), 
+                               p[2] & 1 ? "(current)":"");
+               p += 4;
+       }
+       return (curprofile);
+}
+
+int
+get_proflist(SCSI *usalp, BOOL *wp, BOOL *cdp, BOOL *dvdp, BOOL *dvdplusp, 
+             BOOL *ddcdp)
+{
+       Uchar   cbuf[1024];
+       Uchar   *p;
+       int     flen;
+       int     curprofile;
+       int     profile;
+       int     i;
+       int     n;
+       BOOL    wr      = FALSE;
+       BOOL    cd      = FALSE;
+       BOOL    dvd     = FALSE;
+       BOOL    dvdplus = FALSE;
+       BOOL    ddcd    = FALSE;
+
+       flen = get_profiles(usalp, (caddr_t)cbuf, sizeof (cbuf));
+       if (flen < 0)
+               return (-1);
+
+       p = cbuf;
+       if (xdebug > 1)
+               usal_prbytes("Features: ", cbuf, flen);
+
+       curprofile = a_to_u_2_byte(&p[6]);
+       if (xdebug > 0)
+               printf("feature len: %d current profile 0x%04X (%s)\n",
+                               flen, curprofile, 
+                               mmc_obtain_profile_name(curprofile));
+
+       p += 8;         /* Skip feature header  */
+       n = p[3];       /* Additional length    */
+       n /= 4;
+       p += 4;
+
+       for (i = 0; i < n; i++) {
+               profile = a_to_u_2_byte(p);
+               p += 4;
+               if (profile >= 0x0008 && profile < 0x0010)
+                       cd = TRUE;
+               if (profile > 0x0008 && profile < 0x0010)
+                       wr = TRUE;
+
+               if (profile >= 0x0010 && profile < 0x0018)
+                       dvd = TRUE;
+               if (profile > 0x0010 && profile < 0x0018)
+                       wr = TRUE;
+
+               if (profile >= 0x0018 && profile < 0x0020)
+                       dvdplus = TRUE;
+               if (profile > 0x0018 && profile < 0x0020)
+                       wr = TRUE;
+
+               if (profile >= 0x0020 && profile < 0x0028)
+                       ddcd = TRUE;
+               if (profile > 0x0020 && profile < 0x0028)
+                       wr = TRUE;
+       }
+       if (wp)
+               *wp     = wr;
+       if (cdp)
+               *cdp    = cd;
+       if (dvdp)
+               *dvdp   = dvd;
+       if (dvdplusp)
+               *dvdplusp = dvdplus;
+       if (ddcdp)
+               *ddcdp  = ddcd;
+
+       return (curprofile);
+}
+
+int
+get_wproflist(SCSI *usalp, BOOL *cdp, BOOL *dvdp, BOOL *dvdplusp, BOOL *ddcdp)
+{
+       Uchar   cbuf[1024];
+       Uchar   *p;
+       int     flen;
+       int     curprofile;
+       int     profile;
+       int     i;
+       int     n;
+       BOOL    cd      = FALSE;
+       BOOL    dvd     = FALSE;
+       BOOL    dvdplus = FALSE;
+       BOOL    ddcd    = FALSE;
+
+       flen = get_profiles(usalp, (caddr_t)cbuf, sizeof (cbuf));
+       if (flen < 0)
+               return (-1);
+       p = cbuf;
+       curprofile = a_to_u_2_byte(&p[6]);
+
+       p += 8;         /* Skip feature header  */
+       n = p[3];       /* Additional length    */
+       n /= 4;
+       p += 4;
+
+       for (i = 0; i < n; i++) {
+               profile = a_to_u_2_byte(p);
+               p += 4;
+               if (profile > 0x0008 && profile < 0x0010)
+                       cd = TRUE;
+               if (profile > 0x0010 && profile < 0x0018)
+                       dvd = TRUE;
+               if (profile > 0x0018 && profile < 0x0020)
+                       dvdplus = TRUE;
+               if (profile > 0x0020 && profile < 0x0028)
+                       ddcd = TRUE;
+       }
+       if (cdp)
+               *cdp    = cd;
+       if (dvdp)
+               *dvdp   = dvd;
+       if (dvdplusp)
+               *dvdplusp = dvdplus;
+       if (ddcdp)
+               *ddcdp  = ddcd;
+
+       return (curprofile);
+}
+
+
+char *mmc_obtain_profile_name(int profile_number) {
+  static char *texts[0x53] = {NULL};
+  static char *reserved="Reserved/Unknown";
+  int i, max_pno = 0x53;
+  
+  if (texts[0] == NULL) {
+    for (i = 0; i<max_pno; i++)
+      texts[i] = reserved;
+    /* mmc5r04c.pdf , Table 88, human readable profile names */
+    texts[0x01] = "Non-removable disk";
+    texts[0x02] = "Removable disk";
+    texts[0x03] = "MO erasable";
+    texts[0x04] = "Optical write once";
+    texts[0x05] = "AS-MO";
+    texts[0x08] = "CD-ROM";
+    texts[0x09] = "CD-R";
+    texts[0x0a] = "CD-RW";
+    texts[0x10] = "DVD-ROM";
+    texts[0x11] = "DVD-R sequential recording";
+    texts[0x12] = "DVD-RAM";
+    texts[0x13] = "DVD-RW restricted overwrite";
+    texts[0x14] = "DVD-RW sequential recording";
+    texts[0x15] = "DVD-R/DL sequential recording";
+    texts[0x16] = "DVD-R/DL layer jump recording";
+    texts[0x1a] = "DVD+RW";
+    texts[0x1b] = "DVD+R";
+    texts[0x2a] = "DVD+RW/DL";
+    texts[0x2b] = "DVD+R/DL";
+    texts[0x40] = "BD-ROM";
+    texts[0x41] = "BD-R sequential recording";
+    texts[0x42] = "BD-R random recording";
+    texts[0x43] = "BD-RE";
+    texts[0x50] = "HD-DVD-ROM";
+    texts[0x51] = "HD-DVD-R";
+    texts[0x52] = "HD-DVD-RAM";
+  }
+  if (profile_number<0 || profile_number>=max_pno)
+    return "";
+  return texts[profile_number];
+}
+
diff --git a/wodim/scsi_mmc4.c b/wodim/scsi_mmc4.c
new file mode 100644 (file)
index 0000000..1257093
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)scsi_mmc4.c     1.1 05/05/16 Copyright 2002-2005 J. Schilling */
+/*
+ *     SCSI command functions for cdrecord
+ *     covering MMC-4 level and above
+ *
+ *     Copyright (c) 2002-2005 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/* #define     DEBUG */
+#include <mconfig.h>
+
+#include <stdio.h>
+#include <standard.h>
+#include <stdxlib.h>
+#include <unixstd.h>
+#include <fctldefs.h>
+#include <errno.h>
+#include <strdefs.h>
+#include <timedefs.h>
+
+#include <utypes.h>
+#include <btorder.h>
+#include <intcvt.h>
+#include <schily.h>
+
+#include <usal/usalcmd.h>
+#include <usal/scsidefs.h>
+#include <usal/scsireg.h>
+#include <usal/scsitransp.h>
+
+#include "scsimmc.h"
+#include "wodim.h"
+
+ int   get_supported_cdrw_media_types(SCSI *usalp);
+
+/*
+ * Retrieve list of supported cd-rw media types (feature 0x37)
+ */
+int
+get_supported_cdrw_media_types(SCSI *usalp)
+{
+       Uchar   cbuf[16];
+       int     ret;
+       fillbytes(cbuf, sizeof (cbuf), '\0');
+
+       usalp->silent++;
+       ret = get_configuration(usalp, (char *)cbuf, sizeof (cbuf), 0x37, 2);
+       usalp->silent--;
+
+       if (ret < 0)
+               return (-1);
+
+       if (cbuf[3] < 12)       /* Couldn't retrieve feature 0x37       */
+               return (-1);
+
+       return (int)(cbuf[13]);
+}
diff --git a/wodim/scsi_scan.c b/wodim/scsi_scan.c
new file mode 100644 (file)
index 0000000..218d23f
--- /dev/null
@@ -0,0 +1,379 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)scsi_scan.c     1.19 04/04/16 Copyright 1997-2004 J. Schilling */
+/*
+ *     Scan SCSI Bus.
+ *     Stolen from sformat. Need a more general form to
+ *     re-use it in sformat too.
+ *
+ *     Copyright (c) 1997-2004 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <mconfig.h>
+#include <stdio.h>
+#include <errno.h>
+#include <schily.h>
+
+#include <usal/usalcmd.h>
+#include <usal/scsidefs.h>
+#include <usal/scsireg.h>
+#include <usal/scsitransp.h>
+
+#include "scsi_scan.h"
+#include "wodim.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdlib.h>
+
+
+static void    print_product(FILE *f, struct scsi_inquiry *ip);
+int    select_target(SCSI *usalp, FILE *f);
+
+#define MAXDEVCOUNT (256+26)
+
+extern BOOL check_linux_26();
+
+static void print_product(FILE *f, struct  scsi_inquiry *ip) {
+       fprintf(f, "'%.8s' ", ip->vendor_info);
+       fprintf(f, "'%.16s' ", ip->prod_ident);
+       fprintf(f, "'%.4s' ", ip->prod_revision);
+       if (ip->add_len < 31) {
+               fprintf(f, "NON CCS ");
+       }
+       usal_fprintdev(f, ip);
+}
+
+SCSI * open_auto(int64_t need_size, int debug, int lverbose) {
+       int res;
+       SCSI * usalp = NULL;
+       char  errstr[80];
+       
+#ifdef __linux__
+       /* quick-and-dirty code but should do what is supposed to, more quickly */
+
+               /*
+                * For Linux, try these strategies, in order:
+                * 1. stat /dev/cdrw or /dev/dvdrw, depending on size we need.
+                * 2. Read /proc/sys/dev/cdrom/info, look for a CD-R/DVD-R.
+                *    Will fail for kernel 2.4 or if cdrom module not loaded.
+                * 3. stat /dev/cdrom, just assume that it can write media.
+
+     An example for procfs file contents, beware of the TABs
+
+---
+CD-ROM information, Id: cdrom.c 3.20 2003/12/17
+
+drive name:            hdc     hda
+drive speed:           40      40
+drive # of slots:       1       1
+Can close tray:         1       1
+Can open tray:          1       1
+Can lock tray:          1       1
+Can change speed:       1       1
+Can select disk:        0       0
+Can read multisession:  1       1
+Can read MCN:           1       1
+Reports media changed:  1       1
+Can play audio:         1       1
+Can write CD-R:                0       1
+Can write CD-RW:        0       1
+Can read DVD:           1       1
+Can write DVD-R:        0       1
+Can write DVD-RAM:      0       1
+Can read MRW:           0       1
+Can write MRW:          0       1
+Can write RAM:          0       1
+
+---
+*/
+       struct stat statbuf;
+       /* XXX Good guess? BD-RE recorders may not support CDRW anymore... */
+       char *type="CD-R", *key="Can write CD-R:", *guessdev="/dev/cdrw", *result=NULL;
+       FILE *fh;
+
+       if( need_size > 360000*2048 ) {
+               type="DVD-R";
+               guessdev="/dev/dvdrw";
+               key="Can write DVD-R:";
+       }
+
+       if(need_size>10240) /* don't bother with weird numbers */
+               fprintf(stderr, "Looking for a %s drive to store %.2f MiB...\n", type, (float)need_size/1048576.0);
+       if(0==stat(guessdev, &statbuf))
+               result=guessdev;
+       else if(0!= (fh = fopen("/proc/sys/dev/cdrom/info", "r")) ) {
+               /* ok, going the hard way */
+               char *nameline=NULL;
+               static char buf[256];
+               int kn = strlen(key);
+
+               buf[255]='\0';
+
+               while(fgets(buf, sizeof(buf), fh)) {
+                       if(0==strncmp(buf, "drive name:", 11))
+                               nameline=strdup(buf);
+                       if(nameline && 0==strncmp(buf, key, kn)) {
+                               int p=kn;
+                               char *descptr=nameline+11; /* start at the known whitespace */
+                               while(p<sizeof(buf) && buf[p]) {
+                                       if(buf[p]=='1' || buf[p]=='0') {
+                                               /* find the beginning of the descriptor */
+                                               for(;isspace((Uchar) *descptr);descptr++)
+                                                       ;
+                                       }
+                                       if(buf[p]=='1') {
+                                               result=descptr-5;
+                                               /* terminate on space/newline and stop there */
+                                               for(;*descptr;descptr++) {
+                                                       if(isspace((Uchar) *descptr))
+                                                               *(descptr--)='\0';
+                                               }
+                                               strncpy(result, "/dev/", 5);
+                                               break;
+                                       }
+                                       else { /* no hit, move to after word ending */
+                                               for(; *descptr && ! isspace((Uchar) *descptr); descptr++)
+                                                       ;
+                                       }
+                                       p++;
+                               }
+                       }
+
+               }
+               fclose(fh);
+       }
+
+       if(result)
+               fprintf(stderr, "Detected %s drive: %s\n", type, result);
+       if (0==stat("/dev/cdrom", &statbuf)) {
+               result = "/dev/cdrom";
+               fprintf(stderr, "Using /dev/cdrom of unknown capabilities\n");
+       }
+       if(result)
+               return usal_open(result, errstr, sizeof(errstr), debug, lverbose);
+#endif /* __linux__ */
+
+       usalp = usal_open(NULL, errstr, sizeof(errstr), debug, lverbose);
+       if(!usalp)
+               return NULL;
+       res = list_devices(usalp, stdout, 1);
+       if(res>0)
+               return usalp;
+       else
+               usal_close(usalp);
+       return NULL;
+}
+
+int list_devices(SCSI *usalp, FILE *f, int pickup_first) {
+       int     initiator;
+       int     i;
+       int     bus;
+       int     tgt;
+       int     lun = 0;
+       BOOL    have_tgt;
+
+       int fd, ndevs=0;
+       struct stat statbuf;
+       char *lines[MAXDEVCOUNT];
+       char buf[256], perms[8];
+
+
+       usalp->silent++;
+
+       /* XXX should be done before opening usal fprintf(stderr, "Beginning native device scan. This may take a while if devices are busy...\n"); */
+
+       for (bus = 0; bus < 1256; bus++) {
+               usal_settarget(usalp, bus, 0, 0);
+
+               if (!usal_havebus(usalp, bus))
+                       continue;
+
+               initiator = usal_initiator_id(usalp);
+               //fprintf(f, "scsibus%d:\n", bus);
+
+               for (tgt = 0; tgt < 16; tgt++) {
+                       usal_settarget(usalp, bus, tgt, lun);
+                       have_tgt = unit_ready(usalp) || usalp->scmd->error != SCG_FATAL;
+
+                       if (!have_tgt && tgt > 7) {
+                               if (usalp->scmd->ux_errno == EINVAL)
+                                       break;
+                               continue;
+                       }
+
+                       fd=usal_fileno(usalp, bus, tgt, lun);
+                       strcpy(perms,"------");
+                       if(fd>=0 && 0==fstat(fd, &statbuf)) {
+                               if(statbuf.st_mode&S_IRUSR) perms[0]= 'r';
+                               if(statbuf.st_mode&S_IWUSR) perms[1]= 'w';
+                               if(statbuf.st_mode&S_IRGRP) perms[2]= 'r';
+                               if(statbuf.st_mode&S_IWGRP) perms[3]= 'w';
+                               if(statbuf.st_mode&S_IROTH) perms[4]= 'r';
+                               if(statbuf.st_mode&S_IWOTH) perms[5]= 'w';
+                       }
+                       getdev(usalp, FALSE);
+                       if(usalp->inq->type == INQ_ROMD || usalp->inq->type == INQ_WORM) {
+                               char *p;
+
+                               for(p=usalp->inq->vendor_info + 7 ; p >= usalp->inq->vendor_info; p--) {
+                                       if(isspace((unsigned char)*p))
+                                               *p='\0';
+                                       else
+                                               break;
+                               }
+                               for(p=usalp->inq->prod_ident + 15 ; p >= usalp->inq->prod_ident; p--) {
+                                       if(isspace((unsigned char)*p))
+                                               *p='\0';
+                                       else
+                                               break;
+                               }
+                               snprintf(buf, sizeof(buf), "%2d  dev='%s'\t%s : '%.8s' '%.16s'\n", ndevs, usal_natname(usalp, bus, tgt, lun), perms, usalp->inq->vendor_info, usalp->inq->prod_ident);
+                               /* alternative use, only select the first device */
+                               if(pickup_first) {
+                                       printf("Using drive: %s\n", usal_natname(usalp, bus, tgt, lun));
+                                       return 1;
+                               }
+                               lines[ndevs++]=strdup(buf);
+                       }
+
+               }
+       }
+       usalp->silent--;
+
+       /* should have been returned before if there was a recorder */
+       if(pickup_first)
+               return 0;
+
+       /* now start the output */
+
+       fprintf(stdout, "%s: Overview of accessible drives (%d found) :\n"
+                       "-------------------------------------------------------------------------\n",
+                       get_progname(), ndevs);
+       for(i=0;i<ndevs;i++) {
+               fprintf(stdout, "%s", lines[i]);
+               free(lines[i]);
+       }
+       fprintf(stdout, "-------------------------------------------------------------------------\n");
+
+       return ndevs;
+}
+
+int select_target(SCSI *usalp, FILE *f) {
+       int     initiator;
+#ifdef FMT
+       int     cscsibus = usal_scsibus(usalp);
+       int     ctarget  = usal_target(usalp);
+       int     clun     = usal_lun(usalp);
+#endif
+       int     n;
+       int     low     = -1;
+       int     high    = -1;
+       int     amt     = 0;
+       int     bus;
+       int     tgt;
+       int     lun = 0;
+       BOOL    have_tgt;
+
+       usalp->silent++;
+
+       for (bus = 0; bus < 1256; bus++) {
+               usal_settarget(usalp, bus, 0, 0);
+
+               if (!usal_havebus(usalp, bus))
+                       continue;
+
+               initiator = usal_initiator_id(usalp);
+               fprintf(f, "scsibus%d:\n", bus);
+
+               for (tgt = 0; tgt < 16; tgt++) {
+                       n = bus*100 + tgt;
+
+                       usal_settarget(usalp, bus, tgt, lun);
+                       have_tgt = unit_ready(usalp) || usalp->scmd->error != SCG_FATAL;
+
+                       if (!have_tgt && tgt > 7) {
+                               if (usalp->scmd->ux_errno == EINVAL)
+                                       break;
+                               continue;
+                       }
+
+#ifdef FMT
+                       if (print_disknames(bus, tgt, -1) < 8)
+                               fprintf(f, "\t");
+                       else
+                               fprintf(f, " ");
+#else
+                       fprintf(f, "\t");
+#endif
+                       if (fprintf(f, "%d,%d,%d", bus, tgt, lun) < 8)
+                               fprintf(f, "\t");
+                       else
+                               fprintf(f, " ");
+                       fprintf(f, "%3d) ", n);
+                       if (tgt == initiator) {
+                               fprintf(f, "HOST ADAPTOR\n");
+                               continue;
+                       }
+                       if (!have_tgt) {
+                               /*
+                                * Hack: fd -> -2 means no access
+                                */
+                               fprintf(f, "%c\n", usalp->fd == -2 ? '?':'*');
+                               continue;
+                       }
+                       amt++;
+                       if (low < 0)
+                               low = n;
+                       high = n;
+
+                       getdev(usalp, FALSE);
+                       print_product(f, usalp->inq);
+               }
+       }
+       usalp->silent--;
+
+       if (low < 0) {
+               errmsgno(EX_BAD, "No target found.\n");
+               return (0);
+       }
+       n = -1;
+#ifdef FMT
+       getint("Select target", &n, low, high);
+       bus = n/100;
+       tgt = n%100;
+       usal_settarget(usalp, bus, tgt, lun);
+       return (select_unit(usalp));
+
+       usal_settarget(usalp, cscsibus, ctarget, clun);
+#endif
+       return (amt);
+}
+
diff --git a/wodim/scsi_scan.h b/wodim/scsi_scan.h
new file mode 100644 (file)
index 0000000..b1e055b
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)scsi_scan.h     1.3 01/03/12 Copyright 1997 J. Schilling */
+/*
+ *     Interface to scan SCSI Bus.
+ *
+ *     Copyright (c) 1997 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef        _SCSI_SCAN_H
+#define        _SCSI_SCAN_H
+
+#include <usal/scsitransp.h>
+
+extern int     select_target(SCSI *usalp, FILE *f);
+extern int list_devices(SCSI *usalp, FILE *f, int pickup_type);
+extern SCSI * open_auto(int64_t need_size, int debug, int lverbose);
+extern int       scsi_set_streaming(SCSI *usalp, caddr_t addr, int size);
+
+#endif /* _SCSI_SCAN_H */
diff --git a/wodim/scsimmc.h b/wodim/scsimmc.h
new file mode 100644 (file)
index 0000000..a0092fc
--- /dev/null
@@ -0,0 +1,593 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)scsimmc.h       1.11 04/03/01 Copyright 1997-2004 J. Schilling */
+/*
+ *     Definitions for SCSI/mmc compliant drives
+ *
+ *     Copyright (c) 1997-2004 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef        _SCSIMMC_H
+#define        _SCSIMMC_H
+
+#include <utypes.h>
+#include <btorder.h>
+
+typedef struct opc {
+       Uchar   opc_speed[2];
+       Uchar   opc_val[6];
+} opc_t;
+
+#if defined(_BIT_FIELDS_LTOH)  /* Intel bitorder */
+
+struct disk_info {
+       Uchar   data_len[2];            /* Data len without this info   */
+       Ucbit   disk_status     : 2;    /* Status of the disk           */
+       Ucbit   sess_status     : 2;    /* Status of last session       */
+       Ucbit   erasable        : 1;    /* Disk is erasable             */
+       Ucbit   res2            : 3;    /* Reserved                     */
+       Uchar   first_track;            /* # of first track on disk     */
+       Uchar   numsess;                /* # of sessions                */
+       Uchar   first_track_ls;         /* First track in last sessaion */
+       Uchar   last_track_ls;          /* Last track in last sessaion  */
+       Ucbit   bg_format_stat  : 2;    /* Background format status     */
+       Ucbit   dbit            : 1;    /* Dirty Bit of defect table    */
+       Ucbit   res7_34         : 2;    /* Reserved                     */
+       Ucbit   uru             : 1;    /* This is an unrestricted disk */
+       Ucbit   dbc_v           : 1;    /* Disk bar code valid          */
+       Ucbit   did_v           : 1;    /* Disk id valid                */
+       Uchar   disk_type;              /* Disk type                    */
+       Uchar   res9[3];                /* Reserved                     */
+       Uchar   disk_id[4];             /* Disk identification          */
+       Uchar   last_lead_in[4];        /* Last session lead in time    */
+       Uchar   last_lead_out[4];       /* Last session lead out time   */
+       Uchar   disk_barcode[8];        /* Disk bar code                */
+       Uchar   res32;                  /* Reserved                     */
+       Uchar   num_opc_entries;        /* # of OPC table entries       */
+       opc_t   opc_table[1];           /* OPC table                    */
+};
+
+#else                          /* Motorola bitorder */
+
+struct disk_info {
+       Uchar   data_len[2];            /* Data len without this info   */
+       Ucbit   res2            : 3;    /* Reserved                     */
+       Ucbit   erasable        : 1;    /* Disk is erasable             */
+       Ucbit   sess_status     : 2;    /* Status of last session       */
+       Ucbit   disk_status     : 2;    /* Status of the disk           */
+       Uchar   first_track;            /* # of first track on disk     */
+       Uchar   numsess;                /* # of sessions                */
+       Uchar   first_track_ls;         /* First track in last sessaion */
+       Uchar   last_track_ls;          /* Last track in last sessaion  */
+       Ucbit   did_v           : 1;    /* Disk id valid                */
+       Ucbit   dbc_v           : 1;    /* Disk bar code valid          */
+       Ucbit   uru             : 1;    /* This is an unrestricted disk */
+       Ucbit   res7_34         : 2;    /* Reserved                     */
+       Ucbit   dbit            : 1;    /* Dirty Bit of defect table    */
+       Ucbit   bg_format_stat  : 2;    /* Background format status     */
+       Uchar   disk_type;              /* Disk type                    */
+       Uchar   res9[3];                /* Reserved                     */
+       Uchar   disk_id[4];             /* Disk identification          */
+       Uchar   last_lead_in[4];        /* Last session lead in time    */
+       Uchar   last_lead_out[4];       /* Last session lead out time   */
+       Uchar   disk_barcode[8];        /* Disk bar code                */
+       Uchar   res32;                  /* Reserved                     */
+       Uchar   num_opc_entries;        /* # of OPC table entries       */
+       opc_t   opc_table[1];           /* OPC table                    */
+};
+
+#endif
+
+struct cd_mode_data {
+       struct scsi_mode_header header;
+       union cd_pagex  {
+               struct cd_mode_page_05  page05;
+               struct cd_mode_page_2A  page2A;
+       } pagex;
+};
+
+struct tocheader {
+       Uchar   len[2];
+       Uchar   first;
+       Uchar   last;
+};
+
+/*
+ * Full TOC entry
+ */
+struct ftrackdesc {
+       Uchar   sess_number;
+
+#if defined(_BIT_FIELDS_LTOH)          /* Intel byteorder */
+       Ucbit   control         : 4;
+       Ucbit   adr             : 4;
+#else                                  /* Motorola byteorder */
+       Ucbit   adr             : 4;
+       Ucbit   control         : 4;
+#endif
+
+       Uchar   track;
+       Uchar   point;
+       Uchar   amin;
+       Uchar   asec;
+       Uchar   aframe;
+       Uchar   res7;
+       Uchar   pmin;
+       Uchar   psec;
+       Uchar   pframe;
+};
+
+struct fdiskinfo {
+       struct tocheader        hd;
+       struct ftrackdesc       desc[1];
+};
+
+
+
+#if defined(_BIT_FIELDS_LTOH)  /* Intel bitorder */
+
+struct atipdesc {
+       Ucbit   ref_speed       : 3;    /* Reference speed              */
+       Ucbit   res4_3          : 1;    /* Reserved                     */
+       Ucbit   ind_wr_power    : 3;    /* Indicative tgt writing power */
+       Ucbit   res4_7          : 1;    /* Reserved (must be "1")       */
+       Ucbit   res5_05         : 6;    /* Reserved                     */
+       Ucbit   uru             : 1;    /* Disk is for unrestricted use */
+       Ucbit   res5_7          : 1;    /* Reserved (must be "0")       */
+       Ucbit   a3_v            : 1;    /* A 3 Values valid             */
+       Ucbit   a2_v            : 1;    /* A 2 Values valid             */
+       Ucbit   a1_v            : 1;    /* A 1 Values valid             */
+       Ucbit   sub_type        : 3;    /* Disc sub type                */
+       Ucbit   erasable        : 1;    /* Disk is erasable             */
+       Ucbit   res6_7          : 1;    /* Reserved (must be "1")       */
+       Uchar   lead_in[4];             /* Lead in time                 */
+       Uchar   lead_out[4];            /* Lead out time                */
+       Uchar   res15;                  /* Reserved                     */
+       Ucbit   clv_high        : 4;    /* Highes usable CLV recording speed */
+       Ucbit   clv_low         : 3;    /* Lowest usable CLV recording speed */
+       Ucbit   res16_7         : 1;    /* Reserved (must be "0")       */
+       Ucbit   res17_0         : 1;    /* Reserved                     */
+       Ucbit   tgt_y_pow       : 3;    /* Tgt y val of the power mod fun */
+       Ucbit   power_mult      : 3;    /* Power multiplication factor  */
+       Ucbit   res17_7         : 1;    /* Reserved (must be "0")       */
+       Ucbit   res_18_30       : 4;    /* Reserved                     */
+       Ucbit   rerase_pwr_ratio: 3;    /* Recommended erase/write power*/
+       Ucbit   res18_7         : 1;    /* Reserved (must be "1")       */
+       Uchar   res19;                  /* Reserved                     */
+       Uchar   a2[3];                  /* A 2 Values                   */
+       Uchar   res23;                  /* Reserved                     */
+       Uchar   a3[3];                  /* A 3 Vaules                   */
+       Uchar   res27;                  /* Reserved                     */
+};
+
+#else                          /* Motorola bitorder */
+
+struct atipdesc {
+       Ucbit   res4_7          : 1;    /* Reserved (must be "1")       */
+       Ucbit   ind_wr_power    : 3;    /* Indicative tgt writing power */
+       Ucbit   res4_3          : 1;    /* Reserved                     */
+       Ucbit   ref_speed       : 3;    /* Reference speed              */
+       Ucbit   res5_7          : 1;    /* Reserved (must be "0")       */
+       Ucbit   uru             : 1;    /* Disk is for unrestricted use */
+       Ucbit   res5_05         : 6;    /* Reserved                     */
+       Ucbit   res6_7          : 1;    /* Reserved (must be "1")       */
+       Ucbit   erasable        : 1;    /* Disk is erasable             */
+       Ucbit   sub_type        : 3;    /* Disc sub type                */
+       Ucbit   a1_v            : 1;    /* A 1 Values valid             */
+       Ucbit   a2_v            : 1;    /* A 2 Values valid             */
+       Ucbit   a3_v            : 1;    /* A 3 Values valid             */
+       Uchar   lead_in[4];             /* Lead in time                 */
+       Uchar   lead_out[4];            /* Lead out time                */
+       Uchar   res15;                  /* Reserved                     */
+       Ucbit   res16_7         : 1;    /* Reserved (must be "0")       */
+       Ucbit   clv_low         : 3;    /* Lowest usable CLV recording speed */
+       Ucbit   clv_high        : 4;    /* Highes usable CLV recording speed */
+       Ucbit   res17_7         : 1;    /* Reserved (must be "0")       */
+       Ucbit   power_mult      : 3;    /* Power multiplication factor  */
+       Ucbit   tgt_y_pow       : 3;    /* Tgt y val of the power mod fun */
+       Ucbit   res17_0         : 1;    /* Reserved                     */
+       Ucbit   res18_7         : 1;    /* Reserved (must be "1")       */
+       Ucbit   rerase_pwr_ratio: 3;    /* Recommended erase/write power*/
+       Ucbit   res_18_30       : 4;    /* Reserved                     */
+       Uchar   res19;                  /* Reserved                     */
+       Uchar   a2[3];                  /* A 2 Values                   */
+       Uchar   res23;                  /* Reserved                     */
+       Uchar   a3[3];                  /* A 3 Vaules                   */
+       Uchar   res27;                  /* Reserved                     */
+};
+
+#endif
+
+struct atipinfo {
+       struct tocheader        hd;
+       struct atipdesc         desc;
+};
+
+/*
+ * XXX Check how we may merge Track_info & Rzone_info
+ */
+#if defined(_BIT_FIELDS_LTOH)  /* Intel bitorder */
+
+struct track_info {
+       Uchar   data_len[2];            /* Data len without this info   */
+       Uchar   track_number;           /* Track number for this info   */
+       Uchar   session_number;         /* Session number for this info */
+       Uchar   res4;                   /* Reserved                     */
+       Ucbit   track_mode      : 4;    /* Track mode (Q-sub control)   */
+       Ucbit   copy            : 1;    /* This track is a higher copy  */
+       Ucbit   damage          : 1;    /* if 1 & nwa_valid 0: inc track*/
+       Ucbit   res5_67         : 2;    /* Reserved                     */
+       Ucbit   data_mode       : 4;    /* Data mode of this track      */
+       Ucbit   fp              : 1;    /* This is a fixed packet track */
+       Ucbit   packet          : 1;    /* This track is in packet mode */
+       Ucbit   blank           : 1;    /* This is an invisible track   */
+       Ucbit   rt              : 1;    /* This is a reserved track     */
+       Ucbit   nwa_valid       : 1;    /* Next writable addr valid     */
+       Ucbit   res7_17         : 7;    /* Reserved                     */
+       Uchar   track_start[4];         /* Track start address          */
+       Uchar   next_writable_addr[4];  /* Next writable address        */
+       Uchar   free_blocks[4];         /* Free usr blocks in this track*/
+       Uchar   packet_size[4];         /* Packet size if in fixed mode */
+       Uchar   track_size[4];          /* # of user data blocks in trk */
+};
+
+#else                          /* Motorola bitorder */
+
+struct track_info {
+       Uchar   data_len[2];            /* Data len without this info   */
+       Uchar   track_number;           /* Track number for this info   */
+       Uchar   session_number;         /* Session number for this info */
+       Uchar   res4;                   /* Reserved                     */
+       Ucbit   res5_67         : 2;    /* Reserved                     */
+       Ucbit   damage          : 1;    /* if 1 & nwa_valid 0: inc track*/
+       Ucbit   copy            : 1;    /* This track is a higher copy  */
+       Ucbit   track_mode      : 4;    /* Track mode (Q-sub control)   */
+       Ucbit   rt              : 1;    /* This is a reserved track     */
+       Ucbit   blank           : 1;    /* This is an invisible track   */
+       Ucbit   packet          : 1;    /* This track is in packet mode */
+       Ucbit   fp              : 1;    /* This is a fixed packet track */
+       Ucbit   data_mode       : 4;    /* Data mode of this track      */
+       Ucbit   res7_17         : 7;    /* Reserved                     */
+       Ucbit   nwa_valid       : 1;    /* Next writable addr valid     */
+       Uchar   track_start[4];         /* Track start address          */
+       Uchar   next_writable_addr[4];  /* Next writable address        */
+       Uchar   free_blocks[4];         /* Free usr blocks in this track*/
+       Uchar   packet_size[4];         /* Packet size if in fixed mode */
+       Uchar   track_size[4];          /* # of user data blocks in trk */
+};
+
+#endif
+
+/*
+ * XXX Check how we may merge Track_info & Rzone_info
+ */
+#if defined(_BIT_FIELDS_LTOH)  /* Intel bitorder */
+
+struct rzone_info {
+       Uchar   data_len[2];            /* Data len without this info   */
+       Uchar   rzone_num_lsb;          /* RZone number LSB             */
+       Uchar   border_num_lsb;         /* Border number LSB            */
+       Uchar   res_4;                  /* Reserved                     */
+       Ucbit   res5_04         : 5;    /* Reserved                     */
+       Ucbit   damage          : 1;    /* Damaged RZone                */
+       Ucbit   res5_67         : 2;    /* Reserved                     */
+       Ucbit   res6_04         : 5;    /* Reserved                     */
+       Ucbit   incremental     : 1;    /* RZone is to be written incremental */
+       Ucbit   blank           : 1;    /* RZone is blank               */
+       Ucbit   rt              : 1;    /* RZone is reserved            */
+       Ucbit   nwa_v           : 1;    /* Next WR address is valid     */
+       Ucbit   lra_v           : 1;    /* Last rec address is valid    */
+       Ucbit   res7_27         : 6;    /* Reserved                     */
+       Uchar   rzone_start[4];         /* RZone start address          */
+       Uchar   next_recordable_addr[4]; /* Next recordable address     */
+       Uchar   free_blocks[4];         /* Free blocks in RZone         */
+       Uchar   block_factor[4];        /* # of sectors of disc acc unit */
+       Uchar   rzone_size[4];          /* RZone size                   */
+       Uchar   last_recorded_addr[4];  /* Last Recorded addr in RZone  */
+       Uchar   rzone_num_msb;          /* RZone number MSB             */
+       Uchar   border_num_msb;         /* Border number MSB            */
+       Uchar   res_34_35[2];           /* Reserved                     */
+};
+
+#else                          /* Motorola bitorder */
+
+struct rzone_info {
+       Uchar   data_len[2];            /* Data len without this info   */
+       Uchar   rzone_num_lsb;          /* RZone number LSB             */
+       Uchar   border_num_lsb;         /* Border number LSB            */
+       Uchar   res_4;                  /* Reserved                     */
+       Ucbit   res5_67         : 2;    /* Reserved                     */
+       Ucbit   damage          : 1;    /* Damaged RZone                */
+       Ucbit   res5_04         : 5;    /* Reserved                     */
+       Ucbit   rt              : 1;    /* RZone is reserved            */
+       Ucbit   blank           : 1;    /* RZone is blank               */
+       Ucbit   incremental     : 1;    /* RZone is to be written incremental */
+       Ucbit   res6_04         : 5;    /* Reserved                     */
+       Ucbit   res7_27         : 6;    /* Reserved                     */
+       Ucbit   lra_v           : 1;    /* Last rec address is valid    */
+       Ucbit   nwa_v           : 1;    /* Next WR address is valid     */
+       Uchar   rzone_start[4];         /* RZone start address          */
+       Uchar   next_recordable_addr[4]; /* Next recordable address     */
+       Uchar   free_blocks[4];         /* Free blocks in RZone         */
+       Uchar   block_factor[4];        /* # of sectors of disc acc unit */
+       Uchar   rzone_size[4];          /* RZone size                   */
+       Uchar   last_recorded_addr[4];  /* Last Recorded addr in RZone  */
+       Uchar   rzone_num_msb;          /* RZone number MSB             */
+       Uchar   border_num_msb;         /* Border number MSB            */
+       Uchar   res_34_35[2];           /* Reserved                     */
+};
+
+#endif
+
+#if defined(_BIT_FIELDS_LTOH)  /* Intel bitorder */
+
+struct dvd_structure_00 {
+       Uchar   data_len[2];            /* Data len without this info   */
+       Uchar   res23[2];               /* Reserved                     */
+       Ucbit   book_version    : 4;    /* DVD Book version             */
+       Ucbit   book_type       : 4;    /* DVD Book type                */
+       Ucbit   minimum_rate    : 4;    /* Minimum data rate (coded)    */
+       Ucbit   disc_size       : 4;    /* Disc size (coded)            */
+       Ucbit   layer_type      : 4;    /* Layer type                   */
+       Ucbit   track_path      : 1;    /* 0 = parallel, 1 = opposit dir*/
+       Ucbit   numlayers       : 2;    /* Number of Layers (0 == 1)    */
+       Ucbit   res2_7          : 1;    /* Reserved                     */
+       Ucbit   track_density   : 4;    /* Track density (coded)        */
+       Ucbit   linear_density  : 4;    /* Linear data density (coded)  */
+       Uchar   res8;                   /* Reserved                     */
+       Uchar   phys_start[3];          /* Starting Physical sector #   */
+       Uchar   res12;                  /* Reserved                     */
+       Uchar   phys_end[3];            /* End physical data sector #   */
+       Uchar   res16;                  /* Reserved                     */
+       Uchar   end_layer0[3];          /* End sector # in layer        */
+       Ucbit   res20           : 7;    /* Reserved                     */
+       Ucbit   bca             : 1;    /* BCA flag bit                 */
+};
+
+#else                          /* Motorola bitorder */
+
+struct dvd_structure_00 {
+       Uchar   data_len[2];            /* Data len without this info   */
+       Uchar   res23[2];               /* Reserved                     */
+       Ucbit   book_type       : 4;    /* DVD Book type                */
+       Ucbit   book_version    : 4;    /* DVD Book version             */
+       Ucbit   disc_size       : 4;    /* Disc size (coded)            */
+       Ucbit   minimum_rate    : 4;    /* Minimum data rate (coded)    */
+       Ucbit   res2_7          : 1;    /* Reserved                     */
+       Ucbit   numlayers       : 2;    /* Number of Layers (0 == 1)    */
+       Ucbit   track_path      : 1;    /* 0 = parallel, 1 = opposit dir*/
+       Ucbit   layer_type      : 4;    /* Layer type                   */
+       Ucbit   linear_density  : 4;    /* Linear data density (coded)  */
+       Ucbit   track_density   : 4;    /* Track density (coded)        */
+       Uchar   res8;                   /* Reserved                     */
+       Uchar   phys_start[3];          /* Starting Physical sector #   */
+       Uchar   res12;                  /* Reserved                     */
+       Uchar   phys_end[3];            /* End physical data sector #   */
+       Uchar   res16;                  /* Reserved                     */
+       Uchar   end_layer0[3];          /* End sector # in layer        */
+       Ucbit   bca             : 1;    /* BCA flag bit                 */
+       Ucbit   res20           : 7;    /* Reserved                     */
+};
+
+#endif
+
+struct dvd_structure_01 {
+       Uchar   data_len[2];            /* Data len without this info   */
+       Uchar   res23[2];               /* Reserved                     */
+       Uchar   copyr_prot_type;        /* Copyright prot system type   */
+       Uchar   region_mgt_info;        /* Region management info       */
+       Uchar   res67[2];               /* Reserved                     */
+};
+
+struct dvd_structure_02 {
+       Uchar   data_len[2];            /* Data len without this info   */
+       Uchar   res23[2];               /* Reserved                     */
+       Uchar   key_data[2048];         /* Disc Key data                */
+};
+
+struct dvd_structure_03 {
+       Uchar   data_len[2];            /* Data len without this info   */
+       Uchar   res23[2];               /* Reserved                     */
+       Uchar   bca_info[1];            /* BCA information (12-188 bytes)*/
+};
+
+struct dvd_structure_04 {
+       Uchar   data_len[2];            /* Data len without this info   */
+       Uchar   res23[2];               /* Reserved                     */
+       Uchar   man_info[2048];         /* Disc manufacturing info      */
+};
+
+#if defined(_BIT_FIELDS_LTOH)  /* Intel bitorder */
+
+struct dvd_structure_05 {
+       Uchar   data_len[2];            /* Data len without this info   */
+       Uchar   res23[2];               /* Reserved                     */
+       Ucbit   res4_03         : 4;    /* Reserved                     */
+       Ucbit   cgms            : 2;    /* CGMS (see below)             */
+       Ucbit   res4_6          : 1;    /* Reserved                     */
+       Ucbit   cpm             : 1;    /* This is copyrighted material */
+       Uchar   res57[3];               /* Reserved                     */
+};
+
+#else                          /* Motorola bitorder */
+
+struct dvd_structure_05 {
+       Uchar   data_len[2];            /* Data len without this info   */
+       Uchar   res23[2];               /* Reserved                     */
+       Ucbit   cpm             : 1;    /* This is copyrighted material */
+       Ucbit   res4_6          : 1;    /* Reserved                     */
+       Ucbit   cgms            : 2;    /* CGMS (see below)             */
+       Ucbit   res4_03         : 4;    /* Reserved                     */
+       Uchar   res57[3];               /* Reserved                     */
+};
+
+#endif
+
+#define        CGMS_PERMITTED          0       /* Unlimited copy permitted     */
+#define        CGMS_RES                1       /* Reserved                     */
+#define        CGMS_ONE_COPY           2       /* One copy permitted           */
+#define        CGMS_NO_COPY            3       /* No copy permitted            */
+
+struct dvd_structure_0D {
+       Uchar   data_len[2];            /* Data len without this info   */
+       Uchar   res23[2];               /* Reserved                     */
+       Uchar   last_rma_sector[2];     /* Last recorded RMA sector #   */
+       Uchar   rmd_bytes[1];           /* Content of Record man area   */
+};
+
+struct dvd_structure_0E {
+       Uchar   data_len[2];            /* Data len without this info   */
+       Uchar   res23[2];               /* Reserved                     */
+       Uchar   field_id;               /* Field ID (1)                 */
+       Uchar   application_code;       /* Disc Application code        */
+       Uchar   phys_data;              /* Disc Phisical Data           */
+       Uchar   last_recordable_addr[3]; /* Last addr of recordable area */
+       Uchar   res_a[2];               /* Reserved                     */
+       Uchar   field_id_2;             /* Field ID (2)                 */
+       Uchar   ind_wr_power;           /* Recommended writing power    */
+       Uchar   ind_wavelength;         /* Wavelength for ind_wr_power  */
+       Uchar   opt_wr_strategy[4];     /* Optimum write Strategy       */
+       Uchar   res_b[1];               /* Reserved                     */
+       Uchar   field_id_3;             /* Field ID (3)                 */
+       Uchar   man_id[6];              /* Manufacturer ID              */
+       Uchar   res_m1;                 /* Reserved                     */
+       Uchar   field_id_4;             /* Field ID (4)                 */
+       Uchar   man_id2[6];             /* Manufacturer ID              */
+       Uchar   res_m2;                 /* Reserved                     */
+};
+
+struct dvd_structure_0F {
+       Uchar   data_len[2];            /* Data len without this info   */
+       Uchar   res23[2];               /* Reserved                     */
+       Uchar   res45[2];               /* Reserved                     */
+       Uchar   random[2];              /* Random number                */
+       Uchar   year[4];                /* Year (ascii)                 */
+       Uchar   month[2];               /* Month (ascii)                */
+       Uchar   day[2];                 /* Day (ascii)                  */
+       Uchar   hour[2];                /* Hour (ascii)                 */
+       Uchar   minute[2];              /* Minute (ascii)               */
+       Uchar   second[2];              /* Second (ascii)               */
+};
+
+struct dvd_structure_0F_w {
+       Uchar   data_len[2];            /* Data len without this info   */
+       Uchar   res23[2];               /* Reserved                     */
+       Uchar   res45[2];               /* Reserved                     */
+       Uchar   year[4];                /* Year (ascii)                 */
+       Uchar   month[2];               /* Month (ascii)                */
+       Uchar   day[2];                 /* Day (ascii)                  */
+       Uchar   hour[2];                /* Hour (ascii)                 */
+       Uchar   minute[2];              /* Minute (ascii)               */
+       Uchar   second[2];              /* Second (ascii)               */
+};
+
+struct mmc_cue {
+       Uchar   cs_ctladr;              /* CTL/ADR for this track       */
+       Uchar   cs_tno;                 /* This track number            */
+       Uchar   cs_index;               /* Index within this track      */
+       Uchar   cs_dataform;            /* Data form                    */
+       Uchar   cs_scms;                /* Serial copy management       */
+       Uchar   cs_min;                 /* Absolute time minutes        */
+       Uchar   cs_sec;                 /* Absolute time seconds        */
+       Uchar   cs_frame;               /* Absolute time frames         */
+};
+
+struct mmc_performance_header {
+       Uchar   p_datalen[4];           /* Performance Data length      */
+#if defined(_BIT_FIELDS_LTOH)  /* Intel bitorder */
+       Ucbit   p_exept         :1;     /* Nominal vs. Exept. conditions*/
+       Ucbit   p_write         :1;     /* Write vs. Read performance   */
+       Ucbit   p_res_4         :6;     /* Reserved bits...             */
+#else                          /* Motorola bitorder */
+       Ucbit   p_res_4         :6;     /* Reserved bits...             */
+       Ucbit   p_write         :1;     /* Write vs. Read performance   */
+       Ucbit   p_exept         :1;     /* Nominal vs. Exept. conditions*/
+#endif
+       Uchar   p_res[3];               /* Reserved bytes               */
+};
+
+
+struct mmc_performance {               /* Type == 00 (nominal)         */
+       Uchar   start_lba[4];           /* Starting LBA                 */
+       Uchar   start_perf[4];          /* Start Performance            */
+       Uchar   end_lba[4];             /* Ending LBA                   */
+       Uchar   end_perf[4];            /* Ending Performance           */
+};
+
+struct mmc_exceptions {                        /* Type == 00 (execptions)      */
+       Uchar   lba[4];                 /* LBA                          */
+       Uchar   time[2];                /* Time                         */
+};
+
+struct mmc_write_speed {               /* Type == 00 (write speed)     */
+#if defined(_BIT_FIELDS_LTOH)  /* Intel bitorder */
+       Ucbit   p_mrw           :1;     /* Suitable for mixed read/write*/
+       Ucbit   p_exact         :1;     /* Speed count for whole media  */
+       Ucbit   p_rdd           :1;     /* Media rotational control     */
+       Ucbit   p_wrc           :2;     /* Write rotational control     */
+       Ucbit   p_res           :3;     /* Reserved bits...             */
+#else                          /* Motorola bitorder */
+       Ucbit   p_res           :3;     /* Reserved bits...             */
+       Ucbit   p_wrc           :2;     /* Write rotational control     */
+       Ucbit   p_rdd           :1;     /* Media rotational control     */
+       Ucbit   p_exact         :1;     /* Speed count for whole media  */
+       Ucbit   p_mrw           :1;     /* Suitable for mixed read/write*/
+#endif
+       Uchar   res[3];                 /* Reserved Bytes               */
+       Uchar   end_lba[4];             /* Ending LBA                   */
+       Uchar   read_speed[4];          /* Read Speed                   */
+       Uchar   write_speed[4];         /* Write Speed                  */
+};
+
+#define        WRC_DEF_RC      0               /* Media default rotational control */
+#define        WRC_CAV         1               /* CAV                              */
+
+
+struct mmc_streaming {                 /* Performance for set streaming*/
+#if defined(_BIT_FIELDS_LTOH)  /* Intel bitorder */
+       Ucbit   p_ra            :1;     /* Random Acess                 */
+       Ucbit   p_exact         :1;     /* Set values exactly           */
+       Ucbit   p_rdd           :1;     /* Restore unit defaults        */
+       Ucbit   p_wrc           :2;     /* Write rotational control     */
+       Ucbit   p_res           :3;     /* Reserved bits...             */
+#else                          /* Motorola bitorder */
+       Ucbit   p_res           :3;     /* Reserved bits...             */
+       Ucbit   p_wrc           :2;     /* Write rotational control     */
+       Ucbit   p_rdd           :1;     /* Restore unit defaults        */
+       Ucbit   p_exact         :1;     /* Set values exactly           */
+       Ucbit   p_ra            :1;     /* Random Acess                 */
+#endif
+       Uchar   res[3];                 /* Reserved Bytes               */
+       Uchar   start_lba[4];           /* Starting LBA                 */
+       Uchar   end_lba[4];             /* Ending LBA                   */
+       Uchar   read_size[4];           /* Read Size                    */
+       Uchar   read_time[4];           /* Read Time                    */
+       Uchar   write_size[4];          /* Write Size                   */
+       Uchar   write_time[4];          /* Write Time                   */
+};
+
+#endif /* _SCSIMMC_H */
diff --git a/wodim/sector.c b/wodim/sector.c
new file mode 100644 (file)
index 0000000..2c253d6
--- /dev/null
@@ -0,0 +1,263 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)sector.c        1.13 04/03/01 Copyright 2001-2004 J. Schilling */
+/*
+ *     Functions needed to use libedc_ecc from cdrecord
+ *
+ *     Copyright (c) 2001-2004 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <mconfig.h>
+#include <stdio.h>
+#include <standard.h>
+#include <utypes.h>
+#include <timedefs.h>
+#include <schily.h>
+
+#include "wodim.h"
+#include "movesect.h"
+
+#ifdef HAVE_LIB_EDC_ECC
+
+
+#define        LAYER2
+#define        EDC_LAYER2
+#define        ENCODER
+#define        EDC_ENCODER
+#include <ecc.h>
+
+#ifdef DO8
+#define        HAVE_NEW_LIB_EDC
+#endif
+
+int    encspeed(BOOL be_verbose);
+void   encsectors(track_t *trackp, Uchar *bp, int address, int nsecs);
+void   scrsectors(track_t *trackp, Uchar *bp, int address, int nsecs);
+void   encodesector(Uchar *sp, int sectype, int address);
+void   fillsector(Uchar *sp, int sectype, int address);
+
+/*
+ * Sector types known by lib libedc_ecc:
+ */
+#ifdef __comment__
+                               /*   MMC                                        */
+#define        MODE_0          0       /* -> XX  12+4+2336     (12+4uuu von libedc)    */
+#define        MODE_1          1       /* -> 8   12+4+2048+288 (124+4uuu+288 von libedc)*/
+#define        MODE_2          2       /* -> 9   12+4+2336     (12+4uuu von libedc)    */
+#define        MODE_2_FORM_1   3       /* -> 10/11 12+4+8+2048+280 (12+4hhhuuu+280 von libedc)*/
+#define        MODE_2_FORM_2   4       /* -> 12 (eher 13!) 12+4+8+2324+4 (12+4hhhuuu+4 von libedc)*/
+#define        AUDIO           5
+#define        UNKNOWN         6
+#endif
+
+/*
+ * known sector types
+ */
+#ifndef        EDC_MODE_0
+#define        EDC_MODE_0      MODE_0
+#endif
+#ifndef        EDC_MODE_1
+#define        EDC_MODE_1      MODE_1
+#endif
+#ifndef        EDC_MODE_2
+#define        EDC_MODE_2      MODE_2
+#endif
+#ifndef        EDC_MODE_2_FORM_1
+#define        EDC_MODE_2_FORM_1       MODE_2_FORM_1
+#endif
+#ifndef        EDC_MODE_2_FORM_2
+#define        EDC_MODE_2_FORM_2       MODE_2_FORM_2
+#endif
+#ifndef        EDC_AUDIO
+#define        EDC_AUDIO       AUDIO
+#endif
+#ifndef        EDC_UNKNOWN
+#define        EDC_UNKNOWN     UNKNOWN
+#endif
+
+/*
+ * Compute max sector encoding speed
+ */
+int
+encspeed(BOOL be_verbose)
+{
+       track_t t[1];
+       Uchar   sect[2352];
+       int     i;
+       struct  timeval tv;
+       struct  timeval tv2;
+
+       t[0].sectype = ST_MODE_1;
+
+       /*
+        * Encoding speed is content dependant.
+        * Set up a known non-null pattern in the sector before; to make
+        * the result of this test independant of the current stack content.
+        */
+       for (i = 0; i < 2352; ) {
+               sect[i++] = 'J';
+               sect[i++] = 'S';
+       }
+       gettimeofday(&tv, (struct timezone *)0);
+       for (i = 0; i < 75000; i++) {           /* Goes up to 1000x */
+               encsectors(t, sect, 12345, 1);
+               gettimeofday(&tv2, (struct timezone *)0);
+               if (tv2.tv_sec >= (tv.tv_sec+1) &&
+                   tv2.tv_usec >= tv.tv_usec)
+                       break;
+       }
+       if (be_verbose) {
+               printf("Encoding speed : %dx (%d sectors/s) for libedc from Heiko Eißfeldt\n",
+                               (i+74)/75, i);
+       }
+       return ((i+74)/75);
+}
+
+/*
+ * Encode sectors according to trackp->sectype
+ */
+void
+encsectors(track_t *trackp, Uchar *bp, int address, int nsecs)
+{
+       int     sectype = trackp->sectype;
+
+       if ((sectype & ST_MODE_MASK) == ST_MODE_AUDIO)
+               return;
+
+       while (--nsecs >= 0) {
+               encodesector(bp, sectype, address);
+               address++;
+               bp += trackp->secsize;
+       }
+}
+
+
+#ifdef CLONE_WRITE
+
+#define        IS_SECHDR(p)    ((p)[0] == 0 &&                         \
+                       (p)[1] == 0xFF && (p)[2] == 0xFF &&     \
+                       (p)[3] == 0xFF && (p)[4] == 0xFF &&     \
+                       (p)[5] == 0xFF && (p)[6] == 0xFF &&     \
+                       (p)[7] == 0xFF && (p)[8] == 0xFF &&     \
+                       (p)[9] == 0xFF && (p)[10] == 0xFF &&    \
+                       (p)[11] == 0)
+/*
+ * Scramble data sectors without coding (needed for clone writing)
+ */
+void
+scrsectors(track_t *trackp, Uchar *bp, int address, int nsecs)
+{
+       /*
+        * In Clone write mode, we cannot expect that the sector type
+        * of a "track" which really is a file holding the whole disk
+        * is flagged with something that makes sense.
+        *
+        * For this reason, we check each sector if it's a data sector
+        * and needs scrambling.
+        */
+       while (--nsecs >= 0) {
+               if (IS_SECHDR(bp))
+                       scramble_L2(bp);
+               bp += trackp->secsize;
+       }
+}
+#else
+void
+scrsectors(track_t *trackp, Uchar *bp, int address, int nsecs)
+{
+       comerrno(EX_BAD, "Cannot write in clone RAW mode.\n");
+}
+#endif
+
+/*
+ * Encode one sector according to trackp->sectype
+ */
+void
+encodesector(Uchar *sp, int sectype, int address)
+{
+       if (address < -150)
+               address += 450150;
+       else
+               address += 150;
+#define        _address address
+
+
+       switch (sectype & ST_MODE_MASK) {
+
+       case    ST_MODE_0:
+               do_encode_L2(sp, EDC_MODE_0, _address);
+               break;
+
+       case    ST_MODE_1:
+               do_encode_L2(sp, EDC_MODE_1, _address);
+               break;
+
+       case    ST_MODE_2:
+               do_encode_L2(sp, EDC_MODE_2, _address);
+               break;
+
+       case    ST_MODE_2_FORM_1:
+               sp[16+2]   &= ~0x20;    /* Form 1 sector */
+               sp[16+4+2] &= ~0x20;    /* Form 1 sector 2nd copy */
+               /* FALLTHROUGH */
+
+       case    ST_MODE_2_MIXED:
+               do_encode_L2(sp, EDC_MODE_2_FORM_1, _address);
+               break;
+
+       case    ST_MODE_2_FORM_2:
+               sp[16+2]   |= 0x20;     /* Form 2 sector */
+               sp[16+4+2] |= 0x20;     /* Form 2 sector 2nd copy */
+
+               do_encode_L2(sp, EDC_MODE_2_FORM_2, _address);
+               break;
+
+       case    ST_MODE_AUDIO:
+               return;
+       default:
+               fill2352(sp, '\0');
+               return;
+       }
+       if ((sectype & ST_NOSCRAMBLE) == 0) {
+               scramble_L2(sp);
+#ifndef        EDC_SCRAMBLE_NOSWAP
+               swabbytes(sp, 2352);
+#endif
+       }
+}
+
+/*
+ * Create one zero filles encoded sector (according to trackp->sectype)
+ */
+void
+fillsector(Uchar *sp, int sectype, int address)
+{
+       fill2352(sp, '\0');
+       encodesector(sp, sectype, address);
+}
+
+#endif /* HAVE_LIB_EDC_ECC */
diff --git a/wodim/subchan.c b/wodim/subchan.c
new file mode 100644 (file)
index 0000000..7195992
--- /dev/null
@@ -0,0 +1,997 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)subchan.c       1.20 05/06/11 Copyright 2000-2004 J. Schilling */
+/*
+ *     Subchannel processing
+ *
+ *     Copyright (c) 2000-2004 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <mconfig.h>
+#include <stdio.h>
+#include <unixstd.h>
+#include <standard.h>
+#include <utypes.h>
+#include <schily.h>
+
+#include <usal/scsitransp.h>
+
+#include "wodim.h"
+#include "crc16.h"
+
+int    do_leadin(track_t *trackp);
+int    write_leadin(SCSI *usalp, cdr_t *dp, track_t *trackp, int leadinstart);
+int    write_leadout(SCSI *usalp, cdr_t *dp, track_t *trackp);
+void   fillsubch(track_t *trackp, Uchar *sp, int secno, int nsecs);
+void   filltpoint(Uchar *sub, int ctrl_adr, int point, msf_t *mp);
+void   fillttime(Uchar *sub, msf_t *mp);
+static void    filldsubq(Uchar *sub, int ca, int t, int i, msf_t *mrp, 
+                                                                msf_t *mp);
+static void    fillmcn(Uchar *sub, Uchar *mcn);
+static void    fillisrc(Uchar *sub, Uchar *isrc);
+static int     ascii2q(int c);
+static void    qpto16(Uchar *sub, Uchar *subq, int dop);
+void   qpto96(Uchar *sub, Uchar *subq, int dop);
+void   addrw(Uchar *sub, Uchar *subrwptr);
+void   qwto16(Uchar *subq, Uchar *subptr);
+void   subrecodesecs(track_t *trackp, Uchar *bp, int address, int nsecs);
+static void    subinterleave(Uchar *sub);
+
+/*#define      TEST_CRC*/
+#ifdef TEST_CRC
+static void    testcrc(void);
+#endif
+
+/*Die 96 Bits == 12 Bytes haben folgendes Aussehen:*/
+
+struct q {
+       Uchar ctrl_adr; /*  0 (ctrl << 4) | adr          */
+       Uchar track;    /*  1 current track #            */
+       Uchar index;    /*  2 current index #            */
+       Uchar pmin;     /*  3 Relative time minutes part */
+       Uchar psec;     /*  4 Relative time seconds part */
+       Uchar pframe;   /*  5 Relative time frames part  */
+       Uchar zero;     /*  6 */
+       Uchar amin;     /*  7 Absolute time minutes part */
+       Uchar asec;     /*  8 Absolute time seconds part */
+       Uchar aframe;   /*  9 Absolute time frames part  */
+       Uchar crc1;     /* 10   all bits inverted. Polynom is   */
+       Uchar crc2;     /* 11   X^16 + X^12 + X^5 + 1           */
+};
+
+Uchar  _subq[110][12];
+int    _nsubh;
+
+extern int     lverbose;
+extern int     xdebug;
+
+/*
+ * Prepare master sunchannel data for RAW TOC.
+ */
+int
+do_leadin(track_t *trackp)
+{
+       int     tracks = trackp->tracks;
+       msf_t   m;
+       int     ctrl;
+       int     i;
+       int     toctype = trackp[0].tracktype & TOC_MASK;
+
+       if (_nsubh) {
+               if (xdebug)
+                       printf("Using CLONE TOC....\n");
+               return (0);
+       }
+       if (xdebug)
+               printf("Leadin TOC Type: %d\n", trackp[0].tracktype & TOC_MASK);
+       if (lverbose > 1) {
+               for (i = 1; i <= tracks+1; i++)
+                       printf("Track %d start %ld\n", i, trackp[i].trackstart);
+       }
+
+#ifdef TEST_CRC
+       testcrc();
+/*     exit(1);*/
+#endif
+
+       fillbytes(_subq, sizeof (_subq), '\0');
+
+       /*
+        * Fill in point 0xA0 for first track # on disk
+        */
+       ctrl = (st2mode[trackp[0].sectype & ST_MASK]) << 4;
+       if (is_copy(&trackp[0]))
+               ctrl |= TM_ALLOW_COPY << 4;
+       m.msf_min = trackp[1].trackno;
+       /*
+        * Disk Type: 0 = AUDIO/DATA, 0x10 = CDI, 0x20 = XA mode 2
+        */
+       m.msf_sec = toc2sess[toctype & TOC_MASK];
+       m.msf_sec = from_bcd(m.msf_sec);                /* convert to BCD */
+       m.msf_frame = 0;
+       filltpoint(_subq[0], ctrl|0x01, 0xA0, &m);
+       if (lverbose > 2)
+               usal_prbytes("", _subq[0], 12);
+
+       /*
+        * Fill in point 0xA1 for last track # on disk
+        */
+       ctrl = (st2mode[trackp[tracks].sectype & ST_MASK]) << 4;
+       if (is_copy(&trackp[tracks]))
+               ctrl |= TM_ALLOW_COPY << 4;
+       m.msf_min = trackp[tracks].trackno;
+       m.msf_sec = 0;
+       m.msf_frame = 0;
+       filltpoint(_subq[1], ctrl|0x01, 0xA1, &m);
+       if (lverbose > 2)
+               usal_prbytes("", _subq[1], 12);
+
+       /*
+        * Fill in point 0xA2 for lead out start time on disk
+        */
+       lba_to_msf(trackp[tracks+1].trackstart, &m);
+       ctrl = (st2mode[trackp[tracks].sectype & ST_MASK]) << 4;
+       if (is_copy(&trackp[tracks]))
+               ctrl |= TM_ALLOW_COPY << 4;
+       filltpoint(_subq[2], ctrl|0x01, 0xA2, &m);
+       if (lverbose > 2)
+               usal_prbytes("", _subq[2], 12);
+
+       /*
+        * Fill in track start times.
+        */
+       for (i = 1; i <= tracks; i++) {
+               lba_to_msf(trackp[i].trackstart, &m);
+               ctrl = (st2mode[trackp[i].sectype & ST_MASK]) << 4;
+               if (is_copy(&trackp[i]))
+                       ctrl |= TM_ALLOW_COPY << 4;
+               filltpoint(_subq[i-1+3], ctrl|0x01, to_bcd(trackp[i].trackno), &m);     /* track n */
+               if (lverbose > 2)
+                       usal_prbytes("", _subq[i-1+3], 12);
+       }
+       return (0);
+}
+
+/*
+ * Write TOC (lead-in)
+ *
+ * Use previously prepared master subchannel data to create the
+ * subchannel frames for the lead-in.
+ */
+int
+write_leadin(SCSI *usalp, cdr_t *dp, track_t *trackp, int leadinstart)
+{
+       msf_t   m;
+       int     i;
+       Uint    j;
+       Uchar   *bp = usalp->bufptr;
+       Uchar   *subp;
+       Uchar   *sp;
+       int     secsize;
+       int     secspt;
+       int     bytespt;
+       long    amount;
+       int     startsec;
+       long    bytes = 0L;
+       int     textoff = 0;
+       msf_t   msf;
+
+       secsize = trackp[0].secsize;
+       secspt = trackp[0].secspt;
+       bytespt = secspt * secsize;
+
+       lba_to_msf(leadinstart, &msf);
+
+       fillbytes(bp, bytespt, '\0');
+
+       if (_nsubh) {
+               if (xdebug)
+                       printf("Using CLONE LEADIN\n");
+       }
+       if (xdebug) {
+               printf("Leadinstart: %d %d:%d/%d",
+                       leadinstart,
+                       msf.msf_min, msf.msf_sec, msf.msf_frame);
+               printf(" FLAGS: 0x%X sect: %X RAW16:%d secs: %d spt: %d\n",
+                       trackp[0].flags, trackp[0].sectype,
+                       is_raw16(&trackp[0]), secsize, secspt);
+       }
+
+       startsec = leadinstart;
+       sp = bp;
+       subp = bp + 2352;
+       for (i = leadinstart, j = 0; i < -150; i++, j++) {
+               /*
+                * TOC hat folgende unterschiedliche Sub Q Frames:
+                * A0           First Track
+                * A1           Last Track
+                * A3           Lead out start
+                * 1..99        Tracks
+                * ==   3 + N* tracks
+                * Jeder Frame wird 3x wiederholt.
+                */
+               if (_nsubh) {
+                       if (j >= (3*_nsubh))
+                               j = 0;
+               } else {
+                       if (j >= (3*3 + 3*trackp->tracks))
+                               j = 0;
+               }
+               lba_to_msf((long)i, &m);
+               fillttime(_subq[j/3], &m);
+               fillcrc(_subq[j/3], 12);
+               if (xdebug > 2)
+                       usal_prbytes("", _subq[j/3], 12);
+               if (is_raw16(&trackp[0])) {
+                       qpto16(subp, _subq[j/3], 0);
+               } else {
+                       extern Uchar *textsub;
+                       extern int  textlen;
+
+                       qpto96(subp, _subq[j/3], 0);
+                       if (textsub) {
+                               addrw(subp, &textsub[textoff]);
+                               textoff += 96;
+                               if (textoff >= textlen)
+                                       textoff = 0;
+                       }
+/*                     if (is_raw96p(&trackp[0]))*/
+/*                             subinterleave(subp);*/
+               }
+               if ((startsec+secspt-1) == i || i == -151) {
+                       if ((i-startsec+1) < secspt) {
+                               secspt = i-startsec+1;
+                               bytespt = secspt * secsize;
+                       }
+                       encsectors(trackp, bp, startsec, secspt);
+
+                       amount = write_secs(usalp, dp,
+                                       (char *)bp, startsec, bytespt, secspt, FALSE);
+                       if (amount < 0) {
+                               printf("write leadin data: error after %ld bytes\n",
+                                                       bytes);
+                               return (-1);
+                       }
+                       bytes += amount;
+                       startsec = i+1;
+                       sp = bp;
+                       subp = bp + 2352;
+                       continue;
+               }
+               sp += secsize;
+               subp += secsize;
+       }
+       return (0);
+}
+
+/*
+ * Write Track 0xAA (lead-out)
+ */
+int
+write_leadout(SCSI *usalp, cdr_t *dp, track_t *trackp)
+{
+       int     tracks = trackp->tracks;
+       msf_t   m;
+       msf_t   mr;
+       int     ctrl;
+       int     i;
+       int     j;
+       Uchar   *bp = usalp->bufptr;
+       Uchar   *subp;
+       Uchar   *sp;
+       int     secsize;
+       int     secspt;
+       int     bytespt;
+       long    amount;
+       long    startsec;
+       long    endsec;
+       long    bytes = 0L;
+       int     leadoutstart;
+       Uchar   sub[12];
+       BOOL    p;
+       msf_t   msf;
+
+       fillbytes(sub, 12, '\0');
+
+       secsize = trackp[tracks+1].secsize;
+       secspt = trackp[tracks+1].secspt;
+       bytespt = secspt * secsize;
+
+       leadoutstart = trackp[tracks+1].trackstart;
+       lba_to_msf(leadoutstart, &msf);
+
+       fillbytes(bp, bytespt, '\0');
+
+       if (xdebug) {
+               printf("Leadoutstart: %d %d:%d/%d amt %ld",
+                       leadoutstart,
+                       msf.msf_min, msf.msf_sec, msf.msf_frame,
+                       trackp[tracks+1].tracksecs);
+               printf(" FLAGS: 0x%X sect: %X RAW16:%d secs: %d spt: %d\n",
+                       trackp[tracks+1].flags, trackp[tracks+1].sectype,
+                       is_raw16(&trackp[tracks+1]), secsize, secspt);
+       }
+
+       startsec = leadoutstart;
+       endsec = startsec + trackp[tracks+1].tracksecs;
+       sp = bp;
+       subp = bp + 2352;
+       ctrl = (st2mode[trackp->sectype & ST_MASK]) << 4;
+       if (is_copy(trackp))
+               ctrl |= TM_ALLOW_COPY << 4;
+
+       for (i = leadoutstart, j = 0; i < endsec; i++, j++) {
+
+               lba_to_msf((long)i, &m);
+               sec_to_msf((long)j, &mr);
+               filldsubq(sub, ctrl|0x01, 0xAA, 1, &mr, &m);
+               sub[1] = 0xAA;
+               fillcrc(sub, 12);
+               p = (j % 150) < 75;
+               if (j < 150)
+                       p = FALSE;
+               if (xdebug > 2)
+                       usal_prbytes(p?"P":" ", sub, 12);
+
+               if (is_raw16(&trackp[0])) {
+                       qpto16(subp, sub, p);
+               } else {
+                       qpto96(subp, sub, p);
+/*                     if (is_raw96p(&trackp[0]))*/
+/*                             subinterleave(subp);*/
+               }
+               if ((startsec+secspt-1) == i || i == (endsec-1)) {
+                       if ((i-startsec+1) < secspt) {
+                               secspt = i-startsec+1;
+                               bytespt = secspt * secsize;
+                       }
+                       encsectors(trackp, bp, startsec, secspt);
+
+                       amount = write_secs(usalp, dp,
+                                       (char *)bp, startsec, bytespt, secspt, FALSE);
+                       if (amount < 0) {
+                               printf("write leadout data: error after %ld bytes\n",
+                                                       bytes);
+                               return (-1);
+                       }
+                       bytes += amount;
+                       startsec = i+1;
+                       sp = bp;
+                       subp = bp + 2352;
+                       continue;
+               }
+               sp += secsize;
+               subp += secsize;
+       }
+       return (0);
+}
+
+/*
+ * Fill in subchannel data.
+ *
+ * This function is used to prepare the sub channels when writing
+ * the data part of a CD (bewteen lead-in and lead-out).
+ */
+void
+fillsubch(track_t *trackp, 
+          Uchar *sp /* Sector data pointer  */, 
+          int secno /* Starting sector #    */, 
+          int nsecs /* # of sectors to fill */)
+{
+       msf_t   m;
+       msf_t   mr;
+       int     ctrl;
+       int     i;
+       int     rsecno;
+       int     end;
+       int     secsize = trackp->secsize;
+       int     trackno = trackp->trackno;
+       int     nindex = trackp->nindex;
+       int     curindex;
+       long    *tindex = NULL;
+       long    nextindex = 0L;
+       Uchar   sub[12];
+       Uchar   *sup;
+       char    *mcn;
+       /*
+        * In theory this should make fillsubch() non-reenrtrant but it seems
+        * that the probability check at the beginning of the function is
+        * sufficient to make it work as expected.
+        */
+static long    nextmcn = -1000000L;
+static long    nextisrc = -1000000L;
+static Uchar   lastindex = 255;
+
+       fillbytes(sub, 12, '\0');
+
+       mcn = track_base(trackp)->isrc;
+       rsecno = secno - trackp->trackstart;
+       if ((secno + nsecs) > (trackp->trackstart + trackp->tracksecs)) {
+               comerrno(EX_BAD, "Implementation botch: track boundary in buffer.\n");
+       }
+       sup = sp + 2352;
+       if (mcn && (nextmcn < secno || nextmcn > (secno+100))) {
+               nextmcn = secno/100*100 + 99;
+       }
+       if (trackp->isrc && (nextisrc < secno || nextisrc > (secno+100))) {
+               nextisrc = secno/100*100 + 49;
+       }
+       ctrl = (st2mode[trackp->sectype & ST_MASK]) << 4;
+       if (is_copy(trackp))
+               ctrl |= TM_ALLOW_COPY << 4;
+
+#ifdef SUB_DEBUG
+       fprintf(stderr, "Tracknl %d nindex %d trackstart %ld rsecno %d index0start %ld nsecs %d\n",
+       trackno, nindex, trackp->trackstart, rsecno, trackp->index0start, nsecs);
+#endif
+
+       if (rsecno < 0) {
+               /*
+                * Called to manually write pregap null data into the pregap
+                * while 'trackp' points to the curent track. For this reason,
+                * the sectors are before the start of track 'n' index 0.
+                */
+               curindex = 0;
+               end = trackp->trackstart;
+
+       } else if (rsecno > trackp->index0start) {
+               /*
+                * This track contains pregap of next track.
+                * We currently are inside this pregap.
+                */
+               trackno++;
+               curindex = 0;
+               end = trackp->trackstart + trackp->tracksecs;
+       } else {
+               /*
+                * We are inside the normal data part of this track.
+                * This is index_1...index_m for track n.
+                * Set 'end' to 0 in this case although it is only used
+                * if 'index' is 0. But GCC gives a warning that 'end'
+                * might be uninitialized.
+                */
+               end = 0;
+               curindex = 1;
+               if (nindex > 1) {
+                       tindex = trackp->tindex;
+                       nextindex = trackp->tracksecs;
+                       /*
+                        * find current index in list
+                        */
+                       for (curindex = nindex; curindex >= 1; curindex--) {
+                               if (rsecno >= tindex[curindex]) {
+                                       if (curindex < nindex)
+                                               nextindex = tindex[curindex+1];
+                                       break;
+                               }
+                       }
+               }
+       }
+
+       for (i = 0; i < nsecs; i++) {
+
+               if (tindex != NULL && rsecno >= nextindex) {
+                       /*
+                        * Skip to next index in list.
+                        */
+                       if (curindex < nindex) {
+                               curindex++;
+                               nextindex = tindex[curindex+1];
+                       }
+               }
+               if (rsecno == trackp->index0start) {
+                       /*
+                        * This track contains pregap of next track.
+                        */
+                       trackno++;
+                       curindex = 0;
+                       end = trackp->trackstart + trackp->tracksecs;
+               }
+               lba_to_msf((long)secno, &m);
+               if (curindex == 0)
+                       sec_to_msf((long)end-1 - secno, &mr);
+               else
+                       sec_to_msf((long)rsecno, &mr);
+               if (is_scms(trackp)) {
+                       if ((secno % 8) <= 3) {
+                               ctrl &= ~(TM_ALLOW_COPY << 4);
+                       } else {
+                               ctrl |= TM_ALLOW_COPY << 4;
+                       }
+               }
+               filldsubq(sub, ctrl|0x01, trackno, curindex, &mr, &m);
+               if (mcn && (secno == nextmcn)) {
+                       if (curindex == lastindex) {
+                               fillmcn(sub, (Uchar *)mcn);
+                               nextmcn = (secno+1)/100*100 + 99;
+                       } else {
+                               nextmcn++;
+                       }
+               }
+               if (trackp->isrc && (secno == nextisrc)) {
+                       if (curindex == lastindex) {
+                               fillisrc(sub, (Uchar *)trackp->isrc);
+                               nextisrc = (secno+1)/100*100 + 49;
+                       } else {
+                               nextisrc++;
+                       }
+               }
+               fillcrc(sub, 12);
+               if (xdebug > 2)
+                       usal_prbytes(curindex == 0 ? "P":" ", sub, 12);
+               if (is_raw16(trackp)) {
+                       qpto16(sup, sub, curindex == 0);
+               } else {
+                       qpto96(sup, sub, curindex == 0);
+/*                     if (is_raw96p(trackp))*/
+/*                             subinterleave(sup);*/
+               }
+               lastindex = curindex;
+               secno++;
+               rsecno++;
+               sup += secsize;
+       }
+}
+
+
+/*
+ * Fill TOC Point
+ * Ax Werte einfüllen.
+ */
+void
+filltpoint(Uchar *sub, int ctrl_adr, int point, msf_t *mp)
+{
+       sub[0] = ctrl_adr;
+       sub[2] = point;
+       sub[7] = to_bcd(mp->msf_min);
+       sub[8] = to_bcd(mp->msf_sec);
+       sub[9] = to_bcd(mp->msf_frame);
+}
+
+/*
+ * Fill TOC time
+ * Aktuelle Zeit in TOC Sub-Q einfüllen.
+ */
+void
+fillttime(Uchar *sub, msf_t *mp)
+{
+       sub[3] = to_bcd(mp->msf_min);
+       sub[4] = to_bcd(mp->msf_sec);
+       sub[5] = to_bcd(mp->msf_frame);
+}
+
+/*
+ * Q-Sub in Datenbereich füllen.
+ */
+static void
+filldsubq(Uchar *sub, int ca, int t, int i, msf_t *mrp, msf_t *mp)
+{
+       sub[0] = ca;
+       sub[1] = to_bcd(t);
+       sub[2] = to_bcd(i);
+       sub[3] = to_bcd(mrp->msf_min);
+       sub[4] = to_bcd(mrp->msf_sec);
+       sub[5] = to_bcd(mrp->msf_frame);
+
+       sub[7] = to_bcd(mp->msf_min);
+       sub[8] = to_bcd(mp->msf_sec);
+       sub[9] = to_bcd(mp->msf_frame);
+}
+
+/*
+ * Fill MCN
+ * MCN konvertieren und in Sub-Q einfüllen.
+ */
+static void
+fillmcn(Uchar *sub, Uchar *mcn)
+{
+       register int    i;
+       register int    c;
+
+       sub[0] = ADR_MCN;
+       for (i = 1; i <= 8; i++) {
+               c = *mcn++;
+               if (c >= '0' && c <= '9')
+                       sub[i] = (c - '0') << 4;
+               else
+                       sub[i] = 0;
+
+               if (c != '\0')
+                       c = *mcn++;
+               if (c >= '0' && c <= '9')
+                       sub[i] |= (c - '0');
+
+               if (c == '\0') {
+                       i++;
+                       break;
+               }
+       }
+       for (; i <= 8; i++)
+               sub[i] = '\0';
+}
+
+/*
+ * Fill ISRC
+ * ISRC konvertieren und in Sub-Q einfüllen.
+ */
+static void
+fillisrc(Uchar *sub, Uchar *isrc)
+{
+       register int    i;
+       register int    j;
+       Uchar           tmp[13];
+       Uchar           *sp;
+
+       sub[0] = ADR_ISRC;
+       sp = &sub[1];
+
+       /*
+        * Convert into Sub-Q character coding
+        */
+       for (i = 0, j = 0; i < 12; i++) {
+               if (isrc[i+j] == '-')
+                       j++;
+               if (isrc[i+j] == '\0')
+                       break;
+               tmp[i] = ascii2q(isrc[i+j]);
+       }
+       for (; i < 13; i++)
+               tmp[i] = '\0';
+
+       /*
+        * The first 5 chars from e.g. "FI-BAR-99-00312"
+        */
+       sp[0]  = tmp[0] << 2;
+       sp[0] |= (tmp[1] >> 4) & 0x03;
+       sp[1]  = (tmp[1] << 4) & 0xF0;
+       sp[1] |= (tmp[2] >> 2) & 0x0F;
+       sp[2]  = (tmp[2] << 6) & 0xC0;
+       sp[2] |= tmp[3] & 0x3F;
+       sp[3]  = tmp[4] << 2;
+
+       /*
+        * Now 7 digits from e.g. "FI-BAR-99-00312"
+        */
+       for (i = 4, j = 5; i < 8; i++) {
+               sp[i]  = tmp[j++] << 4;
+               sp[i] |= tmp[j++];
+       }
+}
+
+/*
+ * ASCII -> Sub-Q ISRC code conversion
+ */
+static int
+ascii2q(int c)
+{
+       if (c >= '0' && c <= '9')
+               return (c - '0');
+       else if (c >= '@' && c <= 'o')
+               return (0x10 + c - '@');
+       return (0);
+}
+
+/*
+ * Q-Sub auf 16 Bytes blähen und P-Sub addieren
+ *
+ * OUT: sub, IN: subqptr
+ */
+static void
+qpto16(Uchar *sub, Uchar *subqptr, int dop)
+{
+       if (sub != subqptr)
+               movebytes(subqptr, sub, 12);
+       sub[12] = '\0';
+       sub[13] = '\0';
+       sub[14] = '\0';
+       sub[15] = '\0';
+       if (dop)
+               sub[15] |= 0x80;
+
+}
+
+/*
+ * Q-Sub auf 96 Bytes blähen und P-Sub addieren
+ *
+ * OUT: sub, IN: subqptr
+ */
+void
+qpto96(Uchar *sub, Uchar *subqptr, int dop)
+{
+       Uchar   tmp[16];
+       Uchar   *p;
+       int     c;
+       int     i;
+
+       if (subqptr == sub) {
+               /*
+                * Remember 12 byte subchannel data if subchannel
+                * is overlapping.
+                */
+               movebytes(subqptr, tmp, 12);
+               subqptr = tmp;
+       }
+       /*
+        * Clear all subchannel bits in the 96 byte target space.
+        */
+       fillbytes(sub, 96, '\0');
+
+       /* BEGIN CSTYLED */
+       if (dop) for (i = 0, p = sub; i < 96; i++) {
+               *p++ |= 0x80;
+       }
+       for (i = 0, p = sub; i < 12; i++) {
+               c = subqptr[i] & 0xFF;
+/*printf("%02X\n", c);*/
+               if (c & 0x80)
+                       *p++ |= 0x40;
+               else
+                       p++;
+               if (c & 0x40)
+                       *p++ |= 0x40;
+               else
+                       p++;
+               if (c & 0x20)
+                       *p++ |= 0x40;
+               else
+                       p++;
+               if (c & 0x10)
+                       *p++ |= 0x40;
+               else
+                       p++;
+               if (c & 0x08)
+                       *p++ |= 0x40;
+               else
+                       p++;
+               if (c & 0x04)
+                       *p++ |= 0x40;
+               else
+                       p++;
+               if (c & 0x02)
+                       *p++ |= 0x40;
+               else
+                       p++;
+               if (c & 0x01)
+                       *p++ |= 0x40;
+               else
+                       p++;
+       }
+}
+
+/*
+ * Add R-W-Sub (96 Bytes) to P-Q-Sub (96 Bytes)
+ *
+ * OUT: sub, IN: subrwptr
+ */
+void
+addrw(register Uchar *sub, register Uchar *subrwptr)
+{
+       register int    i;
+
+#define        DO8(a)  a; a; a; a; a; a; a; a;
+
+       for (i = 0; i < 12; i++) {
+               DO8(*sub++ |= *subrwptr++ & 0x3F);
+       }
+}
+
+/*
+ * Q-W-Sub (96 Bytes) auf 16 Bytes schrumpfen
+ *
+ * OUT: subq, IN: subptr
+ */
+void
+qwto16(Uchar *subq, Uchar *subptr)
+{
+       register int    i;
+       register int    np = 0;
+       register Uchar  *p;
+               Uchar   tmp[96];
+
+       p = subptr;
+       for (i = 0; i < 96; i++)
+               if (*p++ & 0x80)
+                       np++;
+       p = subptr;
+       if (subptr == subq) {
+               /*
+                * Remember 96 byte subchannel data if subchannel
+                * is overlapping.
+                */
+               movebytes(subptr, tmp, 96);
+               p = tmp;
+       }
+
+       for (i = 0; i < 12; i++) {
+               subq[i] = 0;
+               if (*p++ & 0x40)
+                       subq[i] |= 0x80;
+               if (*p++ & 0x40)
+                       subq[i] |= 0x40;
+               if (*p++ & 0x40)
+                       subq[i] |= 0x20;
+               if (*p++ & 0x40)
+                       subq[i] |= 0x10;
+               if (*p++ & 0x40)
+                       subq[i] |= 0x08;
+               if (*p++ & 0x40)
+                       subq[i] |= 0x04;
+               if (*p++ & 0x40)
+                       subq[i] |= 0x02;
+               if (*p++ & 0x40)
+                       subq[i] |= 0x01;
+       }
+       subq[12] = 0;
+       subq[13] = 0;
+       subq[14] = 0;
+       if (np > (96/2))
+               subq[15] = 0x80;
+}
+
+/*
+ * Recode subchannels of sectors from 2352 + 96 bytes to 2352 + 16 bytes
+ */
+void
+subrecodesecs(track_t *trackp, Uchar *bp, int address, int nsecs)
+{
+       bp += 2352;
+       while (--nsecs >= 0) {
+               qwto16(bp, bp);
+               bp += trackp->isecsize;
+       }
+}
+
+#ifndef        HAVE_LIB_EDC_ECC
+void
+encsectors(track_t *trackp, Uchar *bp, int address, int nsecs)
+{
+       int     sectype = trackp->sectype;
+
+       if ((sectype & ST_MODE_MASK) == ST_MODE_AUDIO)
+               return;
+
+       comerrno(EX_BAD, "Can only write audio sectors in RAW mode.\n");
+}
+
+void
+scrsectors(track_t *trackp, Uchar *bp, int address, int nsecs)
+{
+       comerrno(EX_BAD, "Cannot write in clone RAW mode.\n");
+}
+#endif
+
+/*--------------------------------------------------------------------------*/
+#ifdef TEST_CRC
+
+Uchar  tq[12] = { 0x01, 0x00, 0xA0, 0x98, 0x06, 0x12, 0x00, 0x01, 0x00, 0x00, 0xE3, 0x74 };
+
+/*
+01 00 A0 98 06 12 00 01 00 00 E3 74
+01 00 A0 98 06 13 00 01 00 00 49 25
+01 00 A1 98 06 14 00 13 00 00 44 21
+01 00 A1 98 06 15 00 13 00 00 EE 70
+01 00 A1 98 06 16 00 13 00 00 00 A2
+01 00 A2 98 06 17 00 70 40 73 E3 85
+01 00 A2 98 06 18 00 70 40 73 86 7C
+01 00 A2 98 06 19 00 70 40 73 2C 2D
+01 00 01 98 06 20 00 00 02 00 3B 71
+01 00 01 98 06 21 00 00 02 00 91 20
+01 00 01 98 06 22 00 00 02 00 7F F2
+01 00 02 98 06 23 00 03 48 45 BE E0
+01 00 02 98 06 24 00 03 48 45 D9 34
+
+*/
+
+static int     b(int bcd);
+
+
+static int
+b(int bcd)
+{
+       return ((bcd & 0x0F) + 10 * (((bcd)>> 4) & 0x0F));
+}
+
+static void
+testcrc()
+{
+       struct q q;
+       int     ocrc;
+       int     crc1;
+       int     crc2;
+
+       movebytes(&tq, &q, 12);
+       crc1 = q.crc1 & 0xFF;
+       crc2 = q.crc2 & 0xFF;
+
+       /*
+        * Per RED Book, CRC Bits on disk are inverted.
+        * Invert them again to make calcCRC() work.
+        */
+       q.crc1 ^= 0xFF;
+       q.crc2 ^= 0xFF;
+
+       ocrc = calcCRC((Uchar *)&q, 12);
+       printf("AC: %02X t: %3d (%02X) i: %3d (%02X) %d:%d:%d %d:%d:%d %02X%02X %X (%X)\n",
+               q.ctrl_adr,
+               b(q.track),
+               b(q.track) & 0xFF,
+               b(q.index),
+               q.index & 0xFF,
+               b(q.pmin),
+               b(q.psec),
+               b(q.pframe),
+               b(q.amin),
+               b(q.asec),
+               b(q.aframe),
+               crc1, crc2,
+               ocrc,
+               fillcrc((Uchar *)&q, 12) & 0xFFFF);
+}
+#endif /* TEST_CRC */
+
+#ifdef sss
+96 / 24 = 4
+
+index 1 < - > 18
+index 2 < - > 5
+index 3 < - > 23
+
+delay index mod 8
+#endif
+
+/*
+ * Sub 96 Bytes Interleave
+ */
+static void
+subinterleave(Uchar *sub)
+{
+       Uchar   *p;
+       int     i;
+
+       for (i = 0, p = sub; i < 4; i++) {
+               Uchar   save;
+
+               /*
+                * index 1 < - > 18
+                * index 2 < - > 5
+                * index 3 < - > 23
+                */
+               save  = p[1];
+               p[1]  = p[18];
+               p[18] = save;
+
+               save  = p[2];
+               p[2]  = p[5];
+               p[5]  = save;
+
+               save  = p[3];
+               p[3]  = p[23];
+               p[23] = save;
+
+               p += 24;
+       }
+}
diff --git a/wodim/wm_packet.c b/wodim/wm_packet.c
new file mode 100644 (file)
index 0000000..9566a52
--- /dev/null
@@ -0,0 +1,306 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)wm_packet.c     1.25 04/03/01 Copyright 1995, 1997, 2001-2004 J. Schilling */
+/*
+ *     CDR write method abtraction layer
+ *     packet writing intercace routines
+ *
+ *     Copyright (c) 1995, 1997, 2001-2004 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <mconfig.h>
+#include <stdio.h>
+#include <stdxlib.h>
+#include <unixstd.h>
+#include <timedefs.h>
+#include <standard.h>
+#include <utypes.h>
+#include <schily.h>
+
+#include <usal/scsitransp.h>
+#include "wodim.h"
+#include "xio.h"
+
+extern int     debug;
+extern int     verbose;
+extern int     lverbose;
+
+extern char    *buf;                   /* The transfer buffer */
+
+int    write_packet_data(SCSI *usalp, cdr_t *dp, track_t *trackp);
+
+int
+write_packet_data(SCSI *usalp, cdr_t *dp, track_t *trackp)
+{
+       int     track = trackp->trackno;
+       int     f = -1;
+       int     isaudio;
+       long    startsec;
+       Llong   bytes_read = 0;
+       Llong   bytes   = 0;
+       Llong   savbytes = 0;
+       int     count;
+       Llong   tracksize;
+       int     secsize;
+       int     secspt;
+       int     bytespt;
+       long    amount;
+       int     pad;
+       int     retried;
+       long    nextblock;
+       int     bytes_to_read;
+       BOOL    neednl  = FALSE;
+       BOOL    islast  = FALSE;
+       char    *bp     = buf;
+       struct timeval tlast;
+       struct timeval tcur;
+       float   secsps = 75.0;
+long bsize;
+long bfree;
+#define        BCAP
+#ifdef BCAP
+int per;
+#ifdef XBCAP
+int oper = -1;
+#endif
+#endif
+
+       if (dp->cdr_dstat->ds_flags & DSF_DVD)
+               secsps = 676.27;
+
+       usalp->silent++;
+       if ((*dp->cdr_buffer_cap)(usalp, &bsize, &bfree) < 0)
+               bsize = -1L;
+       if (bsize == 0)         /* If we have no (known) buffer, we cannot */
+               bsize = -1L;    /* retrieve the buffer fill ratio          */
+       else
+               dp->cdr_dstat->ds_buflow = 0;
+       usalp->silent--;
+
+       if (trackp->xfp != NULL)
+               f = xfileno(trackp->xfp);
+
+       isaudio = is_audio(trackp);
+       tracksize = trackp->tracksize;
+       startsec = trackp->trackstart;
+
+       secsize = trackp->secsize;
+       secspt = trackp->secspt;
+       bytespt = secsize * secspt;
+
+       pad = !isaudio && is_pad(trackp);       /* Pad only data tracks */
+
+       if (debug) {
+               printf("secsize:%d secspt:%d bytespt:%d audio:%d pad:%d\n",
+                       secsize, secspt, bytespt, isaudio, pad);
+       }
+
+       if (lverbose) {
+               if (tracksize > 0)
+                       printf("\rTrack %02d:    0 of %4lld MB written.",
+                               track, tracksize >> 20);
+               else
+                       printf("\rTrack %02d:    0 MB written.", track);
+               flush();
+               neednl = TRUE;
+       }
+
+       gettimeofday(&tlast, (struct timezone *)0);
+       do {
+               bytes_to_read = bytespt;
+               if (tracksize > 0) {
+                       if ((tracksize - bytes_read) > bytespt)
+                               bytes_to_read = bytespt;
+                       else
+                               bytes_to_read = tracksize - bytes_read;
+               }
+                                       /* XXX next wr addr ??? */
+               count = get_buf(f, trackp, startsec, &bp, bytes_to_read);
+               if (count < 0)
+                       comerr("read error on input file\n");
+               if (count == 0)
+                       break;
+               bytes_read += count;
+               if (tracksize >= 0 && bytes_read >= tracksize) {
+                       count -= bytes_read - tracksize;
+                       if (trackp->padsecs == 0 || (bytes_read/secsize) >= 300)
+                               islast = TRUE;
+               }
+
+               if (count < bytespt) {
+                       if (debug) {
+                               printf("\nNOTICE: reducing block size for last record.\n");
+                               neednl = FALSE;
+                       }
+
+                       if ((amount = count % secsize) != 0) {
+                               amount = secsize - amount;
+                               fillbytes(&bp[count], amount, '\0');
+                               count += amount;
+                               printf("\nWARNING: padding up to secsize.\n");
+                               neednl = FALSE;
+                       }
+                       if (is_packet(trackp) && trackp->pktsize > 0) {
+                               if (count < bytespt) {
+                                       amount = bytespt - count;
+                                       count += amount;
+                                       printf("\nWARNING: padding remainder of packet.\n");
+                                       neednl = FALSE;
+                               }
+                       }
+                       bytespt = count;
+                       secspt = count / secsize;
+                       if (trackp->padsecs == 0 || (bytes_read/secsize) >= 300)
+                               islast = TRUE;
+               }
+
+               retried = 0;
+               retry:
+               /* XXX Fixed-packet writes can be very slow*/
+               if (is_packet(trackp) && trackp->pktsize > 0)
+                       usal_settimeout(usalp, 100);
+               /* XXX */
+               if (is_packet(trackp) && trackp->pktsize == 0) {
+                       if ((*dp->cdr_next_wr_address)(usalp, trackp, &nextblock) == 0) {
+                               /*
+                                * Some drives (e.g. Ricoh MPS6201S) do not
+                                * increment the Next Writable Address value to
+                                * point to the beginning of a new packet if
+                                * their write buffer has underflowed.
+                                */
+                               if (retried && nextblock == startsec) {
+                                       startsec += 7;
+                               } else {
+                                       startsec = nextblock;
+                               }
+                       }
+               }
+
+               amount =  write_secs(usalp, dp, bp, startsec, bytespt, secspt, islast);
+               if (amount < 0) {
+                       if (is_packet(trackp) && trackp->pktsize == 0 && !retried) {
+                               printf("%swrite track data: error after %lld bytes, retry with new packet\n",
+                                       neednl?"\n":"", bytes);
+                               retried = 1;
+                               neednl = FALSE;
+                               goto retry;
+                       }
+                       printf("%swrite track data: error after %lld bytes\n",
+                                                       neednl?"\n":"", bytes);
+                       return (-1);
+               }
+               bytes += amount;
+               startsec += amount / secsize;
+
+               if (lverbose && (bytes >= (savbytes + 0x100000))) {
+                       int     fper;
+                       int     nsecs = (bytes - savbytes) / secsize;
+                       float   fspeed;
+
+                       gettimeofday(&tcur, (struct timezone *)0);
+                       printf("\rTrack %02d: %4lld", track, bytes >> 20);
+                       if (tracksize > 0)
+                               printf(" of %4lld MB", tracksize >> 20);
+                       else
+                               printf(" MB");
+                       printf(" written");
+                       fper = fifo_percent(TRUE);
+                       if (fper >= 0)
+                               printf(" (fifo %3d%%)", fper);
+#ifdef BCAP
+                       if (bsize > 0) {                        /* buffer size known */
+                               usalp->silent++;
+                               per = (*dp->cdr_buffer_cap)(usalp, (long *)0, &bfree);
+                               usalp->silent--;
+                               if (per >= 0) {
+                                       per = 100*(bsize - bfree) / bsize;
+                                       if (per < 5)
+                                               dp->cdr_dstat->ds_buflow++;
+                                       if (per < (int)dp->cdr_dstat->ds_minbuf &&
+                                           (startsec*secsize) > bsize) {
+                                               dp->cdr_dstat->ds_minbuf = per;
+                                       }
+                                       printf(" [buf %3d%%]", per);
+#ifdef BCAPDBG
+                                       printf(" %3ld %3ld", bsize >> 10, bfree >> 10);
+#endif
+                               }
+                       }
+#endif
+
+                       tlast.tv_sec = tcur.tv_sec - tlast.tv_sec;
+                       tlast.tv_usec = tcur.tv_usec - tlast.tv_usec;
+                       while (tlast.tv_usec < 0) {
+                               tlast.tv_usec += 1000000;
+                               tlast.tv_sec -= 1;
+                       }
+                       fspeed = (nsecs / secsps) /
+                               (tlast.tv_sec * 1.0 + tlast.tv_usec * 0.000001);
+                       if (fspeed > 999.0)
+                               fspeed = 999.0;
+                       printf(" %5.1fx", fspeed);
+                       printf(".");
+                       savbytes = (bytes >> 20) << 20;
+                       flush();
+                       neednl = TRUE;
+                       tlast = tcur;
+               }
+       } while (tracksize < 0 || bytes_read < tracksize);
+
+       if ((bytes / secsize) < 300) {
+               if ((trackp->padsecs + (bytes / secsize)) < 300)
+                       trackp->padsecs = 300 - (bytes / secsize);
+       }
+       if (trackp->padsecs > 0) {
+               Llong   padbytes;
+
+               /*
+                * pad_track() is based on secsize. Compute the amount of bytes
+                * assumed by pad_track().
+                */
+               padbytes = (Llong)trackp->padsecs * secsize;
+
+               if (neednl) {
+                       printf("\n");
+                       neednl = FALSE;
+               }
+               if ((padbytes >> 20) > 0) {
+                       neednl = TRUE;
+               } else if (lverbose) {
+                       printf("Track %02d: writing %3lld KB of pad data.\n",
+                                               track, (Llong)(padbytes >> 10));
+                       neednl = FALSE;
+               }
+               pad_track(usalp, dp, trackp, startsec, padbytes,
+                                       TRUE, &savbytes);
+               bytes += savbytes;
+               startsec += savbytes / secsize;
+       }
+       printf("%sTrack %02d: Total bytes read/written: %lld/%lld (%lld sectors).\n",
+               neednl?"\n":"", track, bytes_read, bytes, bytes/secsize);
+       return (0);
+}
diff --git a/wodim/wm_session.c b/wodim/wm_session.c
new file mode 100644 (file)
index 0000000..0505f9c
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)wm_session.c    1.4 02/07/07 Copyright 1995, 1997 J. Schilling */
+/*
+ *     CDR write method abtraction layer
+ *     session at once / disk at once writing intercace routines
+ *
+ *     Copyright (c) 1995, 1997 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <mconfig.h>
+#include <stdio.h>
+#include <stdxlib.h>
+#include <unixstd.h>
+#include <standard.h>
+#include <utypes.h>
+
+#include <usal/scsitransp.h>
+#include "wodim.h"
+
+extern int     debug;
+extern int     verbose;
+extern int     lverbose;
+
+extern char    *buf;                   /* The transfer buffer */
+
+int    write_session_data(SCSI *usalp, cdr_t *dp, track_t *trackp);
diff --git a/wodim/wm_track.c b/wodim/wm_track.c
new file mode 100644 (file)
index 0000000..a3f9196
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)wm_track.c      1.4 04/03/02 Copyright 1995, 1997, 2004 J. Schilling */
+/*
+ *     CDR write method abtraction layer
+ *     track at once writing intercace routines
+ *
+ *     Copyright (c) 1995, 1997, 2004 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <mconfig.h>
+#include <stdio.h>
+#include <stdxlib.h>
+#include <unixstd.h>
+#include <standard.h>
+#include <utypes.h>
+
+#include "wodim.h"
+
+extern int     debug;
+extern int     verbose;
+extern int     lverbose;
+
+extern char    *buf;                   /* The transfer buffer */
+
+int    write_track_data(cdr_t *dp, int track, track_t *trackp);
diff --git a/wodim/wodim.1 b/wodim/wodim.1
new file mode 100644 (file)
index 0000000..53e777c
--- /dev/null
@@ -0,0 +1,2369 @@
+.\" @(#)wodim.1         06/12/18 Copyright 2006 Cdrkit maintainers
+.\" derived from:
+.\" @(#)cdrecord.1     1.106 06/02/09 Copyright 1996 J. Schilling
+.\" 
+.\" This program is free software; you can redistribute it and/or modify
+.\" it under the terms of the GNU General Public License version 2
+.\" as published by the Free Software Foundation.
+.\"
+.\" The GNU General Public License's references to "object code"
+.\" and "executables" are to be interpreted as the output of any
+.\" document formatting or typesetting system, including
+.\" intermediate and printed output.
+.\"
+.\" This manual 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; see the file COPYING.  If not, write to the Free Software
+.\" Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+.\"
+.if t .ds a \v'-0.55m'\h'0.00n'\z.\h'0.40n'\z.\v'0.55m'\h'-0.40n'a
+.if t .ds o \v'-0.55m'\h'0.00n'\z.\h'0.45n'\z.\v'0.55m'\h'-0.45n'o
+.if t .ds u \v'-0.55m'\h'0.00n'\z.\h'0.40n'\z.\v'0.55m'\h'-0.40n'u
+.if t .ds A \v'-0.77m'\h'0.25n'\z.\h'0.45n'\z.\v'0.77m'\h'-0.70n'A
+.if t .ds O \v'-0.77m'\h'0.25n'\z.\h'0.45n'\z.\v'0.77m'\h'-0.70n'O
+.if t .ds U \v'-0.77m'\h'0.30n'\z.\h'0.45n'\z.\v'0.77m'\h'-0.75n'U
+.if t .ds s \\(*b
+.if t .ds S SS
+.if n .ds a ae
+.if n .ds o oe
+.if n .ds u ue
+.if n .ds s sz
+.if t .ds m \\(*m
+.if n .ds m micro
+.TH wodim 1 "Version 2.0" "" ""
+.SH NAME
+wodim \- write data to optical disk media
+.SH SYNOPSIS
+.B wodim
+.RI [ options "] " track1 .\|.\|. trackn
+.SH NOTE
+There may be similarities and differences between this program and other disk recording application(s). See the
+.B CREDITS
+and
+.B AUTHORS
+sections below to learn about the origin of
+.B wodim.
+
+.SH DESCRIPTION
+.B wodim
+is used to record data or audio Compact Discs on an Orange Book
+CD-Recorder or to write DVD media on a DVD-Recorder.
+.PP
+The
+.I device
+is the device file or label offered by the operating system to access the
+recorder with SCSI GENERIC (sg) interface. Note that some operating systems may
+provide separate device nodes for block\-oriented and sg access. For example, on
+older
+.I Linux
+systems, the sg access was available through
+.IR /dev/sg...
+files while the block oriented access was done through associated (but not identical)
+.IR /dev/hd...
+and 
+.IR /dev/sr...
+(or 
+.IR /dev/scd...
+) files.
+.PP
+In any case, the user running 
+.B wodim
+needs read and write access to the particular device file on a Linux system. It
+is recommended to be root or install the application as suid-root, because
+certain versions of Linux (kernel) limit the set of SCSI commands allowed for
+non-root users. Even if usage without root identity is possible in many cases,
+some device drivers still may fail, show unexplainable problems and generally
+the problems become harder to debug. The risk for buffer-underruns is also
+increased. See the
+.IR "PROCESS SCHEDULING PRIORITY"
+section below for more details.
+.PP
+There is an alternative way of specifying the device, using the traditional SCSI descriptions in form of
+.IR devicetype:bus/target/lun
+specification. However, the success of this method is not guaranteed since it
+requires an adaptation scheme for your architecture, and the numbers may vary
+depending on the hardware-internal numbering or on the order of hot-plug device
+detection. If your operating system does not provide a sufficient framework for
+keeping this numbers persistent, don't rely on them. See 
+.B \-scanbus
+and
+.B \-\-devices
+options below for details.
+.PP
+There are emulated SCSI compatible device systems, using the SCSI protocols
+transported over various hardware/media types. The most known examples is ATAPI
+("IDE burners") or USB storage ("external USB case"). If the pseudo-SCSI b/t/l
+device address specification is used instead of the native one, you need to
+prepend the "devicetype:" description to the emulated "bus/target/lun" device
+address.
+.PP
+If a file /etc/wodim.conf exists, the parameter to the
+.B dev=
+option may also be a drive name label in that file (see FILES section).
+.PP
+As a special exception, the device specification can be
+.IR -1
+or just omitted, which invokes automatic guessing of an appropriate device for
+the selected operation. However, this guessing is not available everywhere and
+is not reliable; it is only available for the user's convenience in simple
+environments.
+.PP
+In 
+.I Track At Once 
+mode, each
+.I track
+corresponds to a single file that contains the prepared data for that track.
+If the argument is 
+.RB ` \- ',
+standard input is used for that track. 
+Only one track may be taken from 
+.IR stdin .
+In the other write modes, the direct file to track relation may not be implemented.
+In 
+.B \-clone
+mode, a single file contains all data for the whole disk.
+To allow DVD writing on platforms that do not implement large file support,
+.B wodim
+concatenates all file arguments to a single track when writing to DVD media.
+
+.SH "PROCESS SCHEDULING PRIORITY"
+.PP
+Wodim tries to get higher process priority using different methods. This is
+important because the burn process is usually a realtime task, no long delays
+should occur while transmitting fresh data to the recorder. This is especially
+important on systems with insufficient RAM where swapping can create delays of
+many seconds.
+.PP
+A possible workaround on underpowered systems is the use of the burnfree or
+similar feature, allowing the recorder to resume.
+.PP
+Root permissions are usually required to get higher process scheduling priority.
+.PP
+On 
+.B SVr4 
+compliant systems, 
+.B wodim 
+uses the real time class to get the highest scheduling priority that is
+possible (higher than all kernel processes).
+On systems with 
+.B POSIX real time scheduling
+wodim uses real time scheduling too, 
+but may not be able to gain a priority that is higher than all kernel processes.
+.PP
+In order to be able to use the SCSI transport subsystem of the OS, run at highest
+priority and lock itself into core
+.B
+wodim
+either needs to be run as root, needs to be installed suid root or
+must be called via
+.B RBACs
+pfexec mechanism.
+
+.SH "GENERAL OPTIONS
+.PP
+General options must be before any track file name or track option.
+.TP
+.B \-version
+Print version information and exit.
+.TP
+.B \-v
+Increment the level of general verbosity by one.
+This is used e.g. to display the progress of the writing process.
+.TP
+.B \-V
+Increment the verbose level in respect of SCSI command transport by one.
+This helps to debug problems
+during the writing process, that occur in the CD/DVD-Recorder. 
+If you get incomprehensible error messages you should use this flag
+to get more detailed output.
+.B \-VV
+will show data buffer content in addition.
+Using
+.B \-V
+or
+.B \-VV
+slows down the process and may be the reason for a buffer underrun.
+.TP
+.BI debug= "#, " -d
+Set the misc debug value to # (with debug=#) or increment
+the misc debug level by one (with -d). If you specify
+.I -dd,
+this equals to 
+.BI debug= 2.
+This may help to find problems while opening a driver for libusal
+as well as with sector sizes and sector types.
+Using
+.B \-debug
+slows down the process and may be the reason for a buffer underrun.
+.TP
+.BR kdebug= "#, " kd= #
+Tell the 
+.BR usal -driver
+to modify the kernel debug value while SCSI commands are running.
+.TP
+.BR \-silent ", " \-s
+Do not print out a status report for failed SCSI commands.
+.TP
+.B \-force
+Force to continue on some errors. Be careful when using this option.
+.B wodim
+implements several checks that prevent you from doing unwanted things
+like damaging CD-RW media by improper drives. Many of the sanity checks are 
+disabled when the 
+.B \-force
+option is used.
+.sp
+This option also implements some tricks that will allow 
+you to blank bad CD-RW disks.
+.TP
+.B \-immed
+Tell wodim to set the
+.B "SCSI IMMED"
+flag in certain commands
+(load/eject/blank/close_track/close_session).
+This can be useful
+on broken systems with ATAPI harddisk and CD/DVD writer on the same bus or
+with SCSI systems that don't use disconnect/reconnect.
+These systems will freeze while blanking or fixating a CD/DVD or while a DVD
+writer is filling up a session to the minimum amount (approx. 800 MB).
+Setting the
+.B \-immed
+flag will request the command to return immediately
+while the operation proceeds in background, making
+the bus usable for the other devices and avoiding the system freeze.
+This is an experimental feature which may work or not, depending on the model
+of the CD/DVD writer.
+A correct solution would be to set up a correct cabling but there seem to be 
+notebooks around that have been set up the wrong way by the manufacturer.
+As it is impossible to fix this problem in notebooks, the
+.B \-immed
+option has been added.
+.sp
+A second experimental feature of the
+.B \-immed
+flag is to tell wodim to try to wait short times while writing to the
+media. This is expected to free the IDE bus if the CD/DVD writer and the
+data source are connected to the same IDE cable. In this case, the CD/DVD
+writer would otherwise usually block the IDE bus for nearly all the time
+making it impossible to fetch data from the source drive. See also
+.B minbuf=
+and
+.B \-v
+option.
+.sp
+Use both features at your own risk.
+If it turns out that it would make sense to have a separate option
+for the wait feature, write to the author and convince him.
+.TP
+.BI minbuf= value
+The #
+.B minbuf=
+option allows to define the minimum drive buffer fill ratio for the
+experimental ATAPI wait mode that is intended to free the IDE bus
+to allow hard disk and CD/DVD writer to be on the same IDE cable.
+As the wait mode currently only works when the verbose option
+.B \-v
+has been specified, 
+.B wodim
+implies the verbose option in case the 
+.B \-immed
+or
+.B minbuf=
+option have been specified.
+Valid values for 
+.B minbuf= 
+are between 25 and 95 for 25%.\|.\|.95% minimum drive buffer fill ratio.
+.TP
+.B \-dummy
+The CD/DVD-Recorder will go through all steps of the recording process,
+but the laser is turned off during this procedure.
+It is recommended to run several tests before actually writing to a 
+Compact Disk or Digital Versatile Disk,
+if the timing and load response of the system is not known.
+.TP
+.B \-clone
+Tells 
+.B wodim
+to handle images created by
+.IR "readom \-clone" .
+The
+.B \-clone
+may only be used in conjunction with with the
+.B \-raw96r
+or with the
+.B \-raw16
+option.
+Using
+.B \-clone
+together with
+.B \-raw96r
+is preferred as it allows to write all subchannel data.
+The option
+.B \-raw16
+should only be used with drives that do not support to write in
+.B \-raw96r
+mode.
+.TP
+.B \-dao
+.TP
+.B \-sao
+Set 
+.B "SAO (Session At Once)
+mode which is usually called
+.BR "Disk At Once " mode.
+This currently only works with MMC drives that support
+.B "Session At Once
+mode.
+Note that wodim needs to know the size of each track in advance for this mode
+(see the
+.B "genisoimage \-print-size"
+option and the 
+.I EXAMPLES
+section for more information).
+.TP
+.B \-tao
+Set
+.B "TAO (Track At Once) writing mode.
+This is the default write mode in previous
+.B wodim
+versions.
+With most drives, this write mode is required for multi session recording.
+.TP
+.B \-raw
+Set
+.B "RAW writing mode.
+Using this option defaults to 
+.BR \-raw96r .
+Note that wodim needs to know the size of each track in advance for this mode
+(see the
+.B "genisoimage \-print-size"
+option and the 
+.I EXAMPLES
+section for more information).
+.TP
+.B \-raw96r
+Select
+Set
+.B "RAW writing mode
+with 2352 byte sectors plus 96 bytes of raw P-W subchannel data resulting
+in a sector size of 2448 bytes.
+This is the preferred raw writing mode as it gives best control over the
+CD writing process.
+If you find any problems with the layout of a disk or with sub channel 
+content (e.g. wrong times on the display when playing the CD) and your drive
+supports to write in 
+.B \-raw96r
+or
+.B \-raw16
+mode, you should give it a try. There are several CD writers with bad firmware
+that result in broken disks when writing in TAO or SAO mode.
+Writing data disks in raw mode needs significantly more CPU time than other
+write modes. If your CPU is too slow, this may result in buffer underruns.
+Note that wodim needs to know the size of each track in advance for this mode
+(see the
+.B "genisoimage \-print-size"
+option and the 
+.I EXAMPLES
+section for more information).
+.TP
+.B \-raw96p
+Select
+Set
+.B "RAW writing mode
+with 2352 byte sectors plus 96 bytes of packed P-W subchannel data resulting
+in a sector size of 2448 bytes.
+This is the less preferred raw writing mode as only a few recorders support
+it and some of these recorders have bugs in the firmware implementation.
+Don't use this mode if your recorder supports
+.B \-raw96r
+or
+.BR \-raw16 .
+Writing data disks in raw mode needs significantly more CPU time than other
+write modes. If your CPU is too slow, this may result in buffer underruns.
+Note that wodim needs to know the size of each track in advance for this mode
+(see the
+.B "genisoimage \-print-size"
+option and the 
+.I EXAMPLES
+section for more information).
+.TP
+.B \-raw16
+Select
+Set
+.B "RAW writing mode
+with 2352 byte sectors plus 16 bytes of P-Q subchannel data resulting
+in a sector size of 2368 bytes.
+If a recorder does not support 
+.BR \-raw96r ,
+this is the preferred raw writing mode.
+It does not allow to write
+.I CD-Text
+or
+.I CD+Graphics
+but it is the only raw writing mode in cheap CD writers.
+As these cheap writers in most cases do not support
+.B \-dao
+mode.
+Don't use this mode if your recorder supports
+.BR \-raw96r .
+Writing data disks in raw mode needs significantly more CPU time than other
+write modes. If your CPU is too slow, this may result in buffer underruns.
+Note that wodim needs to know the size of each track in advance for this mode
+(see the
+.B "genisoimage \-print-size"
+option and the 
+.I EXAMPLES
+section for more information).
+.TP
+.B \-multi
+Allow multi session CDs to be made. This flag needs to be present
+on all sessions of a multi session disk,
+except you want to create a session that will be 
+the last session on the media.
+The fixation will be done in a way that allows the CD/DVD-Recorder to
+append additional sessions later. This is done by generation a TOC
+with a link to the next program area. The so generated media is not
+100% compatible to manufactured CDs (except for CDplus). 
+Use only for recording of multi session CDs.
+If this option is present, the default track type is
+.BR "CD-ROM XA mode 2 form 1"
+and the sector size is 2048 bytes. 
+The XA sector subheaders will be created by the drive. 
+The 
+.I Sony 
+drives have no hardware support for 
+.BR "CD-ROM XA mode 2 form 1" .
+You have to specify the 
+.B \-data 
+option in order to create multi session disks on these drives.
+As long as wodim does not have a coder for converting data sectors
+to audio sectors, you need to force 
+.B CD-ROM
+sectors by including the
+.B \-data
+option if you like to record a multisession disk in SAO mode.
+Not all drives allow multisession CDs in SAO mode.
+.TP
+.B \-msinfo
+Retrieve multi session info in a form suitable for 
+.B genisoimage
+and print it to standard output. See
+.B msifile=
+option for another version.
+.sp
+This option makes only sense with a CD that contains at least
+one closed session and is appendable (not finally closed yet). 
+Some drives create error messages if you try to get the multi 
+session info for a disk that is not suitable for this operation.
+.TP
+.BR msifile= filename
+Like 
+.B \-msinfo
+option but also stores the multi session info in a file.
+.TP
+.B \-toc
+Retrieve and print out the table of content or PMA of a CD.
+With this option, 
+.B wodim
+will work with CD-R drives and with CD-ROM drives.
+.TP
+.B \-atip
+Retrieve and print out the ATIP (absolute Time in Pre-groove) info of a CD/DVD
+recordable or CD/DVD re-writable media.
+With this option, 
+.B wodim
+will try to retrieve the ATIP info. If the actual drive does not support
+to read the ATIP info, it may be that only a reduced set of information
+records or even nothing is displayed. Only a limited number of MMC compliant
+drives support to read the ATIP info.
+.sp
+If 
+.B wodim
+is able to retrieve the lead-in start time for the first session, it will try to
+decode and print the manufacturer info from the media.
+DVD media does not have ATIP information but there is equivalent prerecorded
+information that is read out and printed.
+.TP
+.B \-fix
+The disk will only be fixated (i.e. a TOC for a CD-Reader will be written). 
+This may be used, if for some reason the disk has been written but not
+fixated. This option currently does not work with old TEAC drives (CD-R50S and
+CD-R55S).
+.TP
+.B \-nofix
+Do not fixate the disk after writing the tracks. This may be used
+to create an audio disk in steps. An un-fixated disk can usually not be used
+on a non CD-writer type drive but there are audio CD players that will
+be able to play such a disk.
+.TP
+.B \-waiti
+Wait for input to become available on standard input before trying to open
+the SCSI driver. This allows 
+.B wodim
+to read its input from a pipe even
+when writing additional sessions to a multi session disk.
+When writing another session to a multi session disk,
+.B genisoimage 
+needs to read the old session from the device before writing output.
+This cannot be done if
+.B wodim 
+opens the SCSI driver at the same time.
+.TP
+.B \-load
+Load the media and exit. This only works with a tray loading mechanism
+but seems to be useful when using the Kodak disk transporter.
+.TP
+.B \-lock
+Load the media, lock the door and exit. This only works with a tray loading mechanism
+but seems to be useful when using the Kodak disk transporter.
+.TP
+.B \-eject
+Eject disk after doing the work.
+Some devices (e.g. Philips) need to eject the medium before creating a new
+disk. Doing a \-dummy test and immediately creating a real disk would not
+work on these devices.
+.TP
+.BR speed= #
+Set the speed factor of the writing process to #.
+# is an integer, representing a multiple of the audio speed.
+This is about 150\ KB/s for CD-ROM, about 172\ KB/s for CD-Audio and about 1385\ kB/s
+for DVD media.
+If no 
+.I speed
+option is present,
+.B wodim
+will try to get a drive specific speed value from the file
+.B /etc/wodim.conf
+and if it cannot find one, it will try to get the speed value from the
+.B CDR_SPEED
+environment and later from the 
+.B CDR_SPEED=
+entry in
+.BR /etc/wodim.conf .
+If no speed value could be found, wodim uses a drive specific default speed.
+The default for all new (MMC compliant) drives is to use the maximum supported by the drive.
+If you use 
+.I "speed=0"
+with a MMC compliant drive,
+.B wodim
+will switch to the lowest possible speed for drive and medium.
+If you are using an old (non MMC) drive that has problems with
+.I "speed=2 
+or 
+.IR "speed=4" , 
+you should try 
+.IR "speed=0" .
+.TP
+.BI blank= type
+Blank a CD-RW and exit or blank a CD-RW before writing. The blanking type may be one of:
+.RS
+.TP 12
+help
+Display a list of possible blanking types.
+.TP
+all
+Blank the entire disk. This may take a long time.
+.TP
+fast
+Minimally blank the disk. This results in erasing the PMA, the TOC and the pregap.
+.TP
+track
+Blank a track.
+.TP
+unreserve
+Unreserve a reserved track.
+.TP
+trtail
+Blank the tail of a track.
+.TP
+unclose
+Unclose last session.
+.TP
+session
+Blank the last session.
+.RE
+Not all drives support all blanking types. It may be necessary to use
+.B "blank=all
+if a drive reports a specified command as being invalid.
+If used together with the 
+.B \-force
+flag, this option may be used to blank CD-RW disks that otherwise cannot be
+blanked. Note that you may need to specify
+.BI blank= all
+because some drives will not continue with certain types of bad CD-RW
+disks. Note also that
+.B wodim
+does its best if the 
+.B \-force 
+flag is used but it finally depends on the drive's firmware 
+whether the blanking operation will succeed or not.
+.TP
+.B \-format
+Format a CD-RW/DVD-RW/DVD+RW disc.
+Formatting is currently only implemented for DVD+RW media.
+A 'maiden' DVD+RW media needs to
+be formatted before you may write to it.
+However, as
+.B wodim
+autodetects the need for formatting in this case and auto formats the medium
+before it starts writing, the
+.B \-format
+option is only needed if you like to forcibly reformat a DVD+RW medium.
+.TP
+.BR fs= #
+Set the FIFO (ring buffer) size to #.
+You may use the same syntax as in 
+.BR dd (1),
+.BR sdd (1)
+or
+.BR star (1).
+The number representing the size is taken in bytes unless otherwise specified.
+If a number is followed directly by the letter `b', `k', `m', `s' or `f',
+the size is multiplied by 512, 1024, 1024*1024, 2048 or 2352.
+If the size consists of numbers separated by `x' or `*', multiplication of the 
+two numbers is performed.
+Thus 
+.I "fs=10x63k
+will specify a FIFO size of 630\ kBytes.
+.sp
+The size specified by the 
+.I fs=
+argument includes the shared memory that is needed for administration. This
+is at least one page of memory.
+If no
+.IR fs =
+option is present, 
+.B wodim
+will try to get the FIFO size value from the 
+.B CDR_FIFOSIZE
+environment.
+The default FIFO size is currently 4 MB.
+.sp
+The FIFO is used to increase buffering for the real time writing process.
+It allows to run a pipe from 
+.B genisoimage
+directly into 
+.BR wodim .
+If the FIFO is active and a pipe from 
+.B genisoimage
+into 
+.B wodim
+is used to create a CD, 
+.B wodim
+will abort prior to do any modifications on the disk if 
+.B genisoimage 
+dies before it starts writing.
+The recommended FIFO size is between 4 and 128\ MBytes.
+As a rule of thumb, the FIFO size should be at least equal to the size
+of the internal buffer of the CD/DVD-Recorder and no more than half of
+the physical amount of RAM available in the machine.
+If the FIFO size is big enough, the FIFO statistics will print a FIFO
+empty count of zero and the FIFO min fill is not below 20%.
+It is not wise to use too much space for the FIFO. If you need more
+than 8 MB to write a CD at a speed less than 20x from an image on a
+local file system on an idle machine, your machine is either underpowered,
+has hardware problems or is mis-configured.
+If you like to write DVDs or CDs at higher speed, it makes sense
+to use at least 16\ MB for the FIFO.
+.sp
+On old and small machines, you need to be more careful with the FIFO size.
+If your machine has less than 256\ MB of physical RAM, you should not
+set up a FIFO size that is more than 32\ MB.
+The sun4c architecture (e.g. a Sparcstation-2) has only MMU page table entries
+for 16\ MBytes per process. Using more than 14\ MBytes for the FIFO
+may cause the operating system in this case to spend much time to constantly
+reload the MMU tables. Newer machines from Sun do not have this MMU
+hardware problem. I have no information on PC-hardware reflecting
+this problem.
+.sp
+Old Linux systems for non x86 platforms have broken definitions for
+the shared memory size. You need to fix them and rebuild the kernel
+or manually tell
+.B wodim
+to use a smaller FIFO.
+.sp
+If you have buffer underruns or similar problems (like a constantly empty
+drive buffer) and observe a zero
+.IR "fifo empty count" ,
+you have hardware problems that prevents the data from flowing fast enough
+from the kernel memory to the drive. The FIFO size in this case is sufficient,
+but you should check for a working DMA setup.
+.TP
+.BR ts= #
+Set the maximum transfer size for a single SCSI command to #.
+The syntax for the 
+.B ts=
+option is the same as for wodim fs=# or sdd bs=#.
+.sp
+If no 
+.B ts=
+option has been specified,
+.B wodim
+defaults to a transfer size of 63\ kB. If libusal gets lower values from the
+operating system, the value is reduced to the maximum value that is possible
+with the current operating system.
+Sometimes, it may help to further reduce the transfer size or to enhance it,
+but note that it may take a long time to find a better value by experimenting
+with the
+.B ts=
+option.
+.TP
+.BI dev= target
+Sets the SCSI target for the CD/DVD-Recorder, see notes above.
+A typical device specification is
+.BI dev= 6,0
+\&.
+A filename or virtual device name can be passed instead of the symbolic SCSI
+numbers.  The correct device/filename in this case can be found in the system
+specific manuals of the target operating system.
+On a 
+.I FreeBSD
+system without 
+.I CAM
+support, you need to use the control device (e.g.
+.IR /dev/rcd0.ctl ).
+A correct device specification in this case may be
+.BI dev= /dev/rcd0.ctl:@
+\&.
+.sp
+On Linux and Windows 2000/XP, drives are accessible with their device (or
+drive) names or with the symbolic SCSI numbers (not recommended, mapping is not
+stable and could be completely removed in the future).
+.sp
+If no 
+.I dev
+option is present, 
+.B wodim
+will try to get the device from the 
+.B CDR_DEVICE
+environment.
+.sp
+If the argument to the
+.B dev=
+option does not contain the characters ',', '/', '@' or ':',
+it is interpreted as an label name that may be found in the file
+/etc/wodim.conf (see FILES section).
+.TP
+.BI gracetime= #
+Set the grace time before starting to write to
+.IR # " seconds.
+Values below 2 seconds are not recommended to give the kernel or volume
+management a chance to learn the new state.
+.TP
+.BI timeout= #
+Set the default SCSI command timeout value to 
+.IR # " seconds.
+The default SCSI command timeout is the minimum timeout used for sending
+SCSI commands.
+If a SCSI command fails due to a timeout, you may try to raise the
+default SCSI command timeout above the timeout value of the failed command.
+If the command runs correctly with a raised command timeout,
+please report the better timeout value and the corresponding command to 
+the author of the program.
+If no 
+.I timeout 
+option is present, a default timeout of 40 seconds is used.
+.TP
+.BI driver= name
+Allows the user to manually select a driver for the device.
+The reason for the existence of the
+.BI driver= name
+option is to allow users to use
+.B wodim
+with drives that are similar to supported drives but not known
+directly by
+.BR wodim .
+All drives made after 1997 should be MMC standard compliant and
+thus supported by one of the MMC drivers.
+It is most unlikely that
+.B wodim
+is unable to find the right driver automatically.
+Use this option with extreme care. If a wrong driver is used for a
+device, the possibility of creating corrupted disks is high.
+The minimum problem related to a wrong driver is that the 
+.B speed=
+or 
+.B \-dummy
+will not work.
+.br
+.RS
+.ne 8
+.PP
+The following driver names are supported:
+.TP
+.B help
+To get a list of possible drivers together with a short description.
+.TP
+.B mmc_cd
+The generic SCSI-3/mmc CD-ROM driver is auto-selected whenever
+.B wodim
+finds a MMC compliant drive that does not identify itself to support writing at
+all, or that only identifies to support media or write modes not implemented in
+.BR wodim .
+.TP
+.B mmc_cd_dvd
+The generic SCSI-3/mmc CD/DVD driver is auto-selected whenever
+.B wodim
+finds a MMC-2 or MMC-3 compliant drive that seems to support more than 
+one medium type and the tray is open or no medium could be found to select the
+right driver.
+This driver tries to close the tray, checks the medium found in the tray and then
+branches to the driver that matches the current medium.
+.TP
+.B mmc_cdr
+The generic SCSI-3/mmc CD-R/CD-RW driver is auto-selected whenever
+.B wodim
+find a MMC compliant drive that only supports to write CDs or a multi system
+drive that contains a CD as the current medium.
+.TP
+.B mmc_cdr_sony
+The generic SCSI-3/mmc CD-R/CD-RW driver is auto-selected whenever
+.B wodim
+would otherwise select the
+.B mmc_cdr
+driver but the device seems to be made by Sony.
+The
+.B mmc_cdr_sony
+is definitely needed for the Sony CDU 928 as this drive does not completely
+implement the MMC standard and some of the MMC SCSI commands have to be
+replaced by Sony proprietary commands. It seems that all Sony drives (even
+newer ones) still implement the Sony proprietary SCSI commands so it has
+not yet become a problem to use this driver for all Sony drives. If you find
+a newer Sony drive that does not work with this driver, please report.
+.TP
+.B mmc_dvd
+The generic SCSI-3/mmc-2 DVD-R/DVD-RW driver is auto-selected whenever
+.B wodim
+finds a MMC-2 or MMC-3 compliant drive that supports to write DVDs and
+an appropriate medium is loaded.
+There is no Track At Once mode for DVD writers.
+.TP
+.B mmc_dvdplus
+The generic SCSI-3/mmc-3 DVD+R/DVD+RW driver is auto-selected whenever
+one of the DVD+ media types that are incompatible to each other is found.
+It checks media and then 
+branches to the driver that matches the current medium.
+.TP
+.B mmc_dvdplusr
+The generic SCSI-3/mmc-3 DVD+R driver is auto-selected whenever
+a DVD+R medium is found in an appropriate writer.
+Note that for unknown reason, the DVD-Plus alliance does not
+like that there is a simulation mode for DVD+R media.
+The author of
+.B wodim
+tries to convince manufacturers to implement a simulation mode for DVD+R
+and implement support.
+DVD+R only supports one write mode that is somewhere between Track At Once
+and Packet writing; this mode is selected in 
+.B wodim
+via a the 
+.BR \-dao / \-sao
+option.
+.TP
+.B mmc_dvdplusrw
+The generic SCSI-3/mmc-3 DVD+RW driver is auto-selected whenever
+a DVD+RW medium is found in an appropriate writer.
+As DVD+RW media needs to be formatted before its first use, wodim
+auto-detects this media state and performs a format before it starts
+to write.
+Note that for unknown reason, the DVD-Plus alliance does not
+like that there is a simulation mode nor a way to erase DVD+RW media.
+DVD+RW only supports one write mode that is close to
+Packet writing; this mode is selected in 
+.B wodim
+via a the 
+.BR \-dao / \-sao
+option.
+.TP
+.B cw_7501
+The driver for Matsushita/Panasonic CW-7501 is auto-selected when
+.B wodim
+finds this old pre MMC drive.
+.B wodim
+supports all write modes for this drive type.
+.TP
+.B kodak_pcd_600
+The driver for Kodak PCD-600 is auto-selected when
+.B wodim
+finds this old pre MMC drive which has been the first high speed (6x)
+CD writer for a long time. This drive behaves similar to the
+Philips CDD-521 drive.
+.TP
+.B philips_cdd521
+The driver for Philips CDD-521 is auto-selected when
+.B wodim
+finds a Philips CDD-521 drive (which is the first CD writer ever made)
+or one of the other drives that are known to behave similar to this
+drive.
+All Philips CDD-521 or similar drives (see other drivers in this list)
+do not support Session At Once recording.
+.TP
+.B philips_cdd521_old
+The driver for Philips old CDD-521 is auto-selected when
+.B wodim
+finds a Philips CDD-521 with very old firmware which has some known limitations.
+.TP
+.B philips_cdd522
+The driver for Philips CDD-522 is auto-selected when
+.B wodim
+finds a Philips CDD-522 which is the successor of the 521 or one of its variants
+with Kodak label.
+.B wodim
+does not support Session At Once recording with these drives.
+.TP
+.B philips_dumb
+The driver for Philips CDD-521 with pessimistic assumptions is never auto-selected.
+It may be used by hand with drives that behave similar to the Philips CDD-521.
+.TP
+.B pioneer_dws114x
+The driver for Pioneer DW-S114X is auto-selected when
+.B wodim
+finds one of the old non MMC CD writers from Pioneer.
+.TP
+.B plasmon_rf4100
+The driver for Plasmon RF 4100 is auto-selected when
+.B wodim
+finds this specific variant of the Philips CDD-521.
+.TP
+.B ricoh_ro1060c
+The driver for Ricoh RO-1060C is auto-selected when
+.B wodim
+finds this drive. There is no real support for this drive yet.
+.TP
+.B ricoh_ro1420c
+The driver for Ricoh RO-1420C is auto-selected when
+.B wodim
+finds a drive with this specific variant of the Philips CDD-521 command set.
+.TP
+.B scsi2_cd
+The generic SCSI-2 CD-ROM driver is auto-selected whenever
+.B wodim
+finds a pre MMC drive that does not support writing or a pre MMC writer that is
+not supported by
+.BR wodim .
+.TP
+.B sony_cdu924
+The driver for Sony CDU-924 / CDU-948 is auto-selected whenever
+.B wodim
+finds one of the old pre MMC CD writers from Sony.
+.TP
+.B teac_cdr50
+The driver for Teac CD-R50S, Teac CD-R55S, JVC XR-W2010, Pinnacle RCD-5020
+is auto-selected whenever one of the drives is found that is known to the
+non MMC command set used by TEAC and JVC.
+Note that many drives from JVC will not work because they do not correctly implement
+the documented command set and JVC has been unwilling to fix or document the
+bugs.
+There is no support for the Session At Once write mode yet.
+.TP
+.B tyuden_ew50
+The driver for Taiyo Yuden EW-50 is auto-selected when
+.B wodim
+finds a drive with this specific variant of the Philips CDD-521 command set.
+.TP
+.B yamaha_cdr100
+The driver for Yamaha CDR-100 / CDR-102 is auto-selected when
+.B wodim
+finds one of the old pre MMC CD writers from Yamaha.
+There is no support for the Session At Once write mode yet.
+.TP
+.B cdr_simul
+The simulation CD-R driver allows to run timing and speed tests
+with parameters that match the behavior of CD writers.
+.TP
+.B dvd_simul
+The simulation DVD-R driver allows to run timing and speed tests
+with parameters that match the behavior of DVD writers.
+.PP
+
+.sp
+There are two special driver entries in the list:
+.B cdr_simul
+and
+.BR dvd_simul .
+These driver entries are designed to make timing tests at any speed
+or timing tests for drives that do not support the 
+.B \-dummy
+option.
+The simulation drivers implement a drive with a buffer size of 1\ MB
+that can be changed via the 
+.B CDR_SIMUL_BUFSIZE
+environment variable.
+The simulation driver correctly simulates even a buffer underrun condition.
+If the 
+.B \-dummy 
+option is present, the simulation is not aborted in case of a buffer underrun.
+.RE
+.TP
+.BI driveropts= "option list"
+Set driver specific options. The options are specified a comma separated list.
+To get a list of valid options use 
+.BI driveropts= help
+together with the 
+.I \-checkdrive
+option.
+If you like to set driver options without running a typical
+.B wodim
+task, you need to use the
+.B \-setdropts
+option in addition, otherwise the command line parser in
+.B wodim
+will complain.
+Currently implemented driver options are:
+.RS
+.TP
+.B burnfree 
+Turn the support for Buffer Underrun Free writing on.
+This only works for drives that support Buffer Underrun Free technology, which
+is available on most drives manufactured in this millennium. 
+This may be called:
+.BR "Sanyo BURN-Proof" ,
+.BR "Ricoh Just-Link" ,
+.B "Yamaha Lossless-Link"
+or similar.
+.sp
+This option is deprecated and is mentioned here for documentation purposes
+only. The BURN-Free feature is enabled by default if the drive supports it.
+However, use of BURN-Free may cause decreased burning quality. Therefore it can
+be useful to disable it for certain purposes, eg. when creating a master copy
+for mass CD production.
+.TP
+.B noburnfree 
+Turn the support for Buffer Underrun Free writing off.
+.TP
+.BI varirec= value
+Turn on the 
+.B "Plextor VariRec"
+writing mode. The mandatory parameter
+.I value
+is the laser power offset and currently may be selected from
+-2, -1, 0, 1, 2.
+In addition, you need to set the write speed to 4 in order to allow
+.B "VariRec"
+to work.
+.TP
+.BI gigarec= value
+Manage the
+.B "Plextor GigaRec"
+writing mode. The mandatory parameter
+.I value
+is the disk capacity ratio compared to normal recording and currently may be selected from
+0.6, 0.7, 0.8, 1.0, 1.2, 1.3, 1.4.
+If values < 1.0 are used, then the effect is similar to the
+.B "Yamaha Audio Master Q. R."
+feature. If values > 1.0 are used, then the disk capacity is 
+increased.
+.sp
+Not all drives support all 
+.B GigaRec
+values.
+When a drive uses the 
+.B GigaRec
+feature, the write speed is limited to 8x.
+.TP
+.B audiomaster
+Turn on the 
+.B "Yamaha Audio Master Q. R."
+feature which usually should result in high quality CDs that
+have less reading problems in Hi-Fi players.
+As this is implemented as a variant of the 
+Session at Once write mode, it will only work if you select 
+SAO write mode and there is no need to turn it off.
+The 
+.B "Audio Master"
+mode will work with a limited speed but
+may also be used with data CDs. In
+.B "Audio Master"
+mode, the pits on the CD will be written larger then usual so the capacity
+of the medium is reduced when turning this feature on.
+A 74 minute CD will only have a capacity of 63 minutes if
+.B "Audio Master"
+is active and the capacity of a 80 minute CD will be reduced to 68 minutes.
+.TP
+.B forcespeed
+Normally, modern drives know the highest possible speed for different
+media and may reduce the speed in order to grant best write quality.
+This technology may be called:
+.BR "Plextor PowerRec" ,
+.BR "Ricoh Just-Speed" ,
+.B "Yamaha Optimum Write Speed Control"
+or similar.
+Some drives (e.g. Plextor, Ricoh and Yamaha) allow to force the drive to
+use the selected speed even if the medium is so bad that the
+write quality would be poor. This option tells such a drive to
+force to use the selected speed regardless of the medium quality.
+.sp
+Use this option with extreme care and note that the drive should know better
+which medium will work at full speed.
+The default is to turn 
+.B forcespeed
+off, regardless of the defaults of the drive.
+.TP
+.B noforcespeed
+Turn off the 
+.B "force speed
+feature.
+.TP
+.B speedread
+Some ultra high speed drives such as 48x and faster drives from Plextor
+limit the read speed for unknown media to e.g. 40x in order to avoid
+damaged disks and drives.
+Using this option tells the drive to read any media as fast as possible.
+Be very careful as this may cause the media to break in the drive 
+while reading, resulting in a damaged media and drive! 
+.TP
+.B nospeedread
+Turn off unlimited read speed.
+.TP
+.B singlesession
+Turn the drive into a single session only drive.
+This allows to read defective or non-compliant (illegal) media with extremely
+non-standard additional (broken/illegal) TOC entries in the TOC from the second
+or higher session. Some of these disks become
+usable if only the information from the first session is used.
+You need to enable Single Session mode before you insert the defective disk!
+.TP
+.B nosinglesession
+Turn off single session mode. The drive will again behave as usual.
+.TP
+.B hidecdr
+Hide the fact that a medium might be a recordable medium.
+This allows to make CD-Rs look like CD-ROMs and applications believe 
+that the media in the drive is not a CD-R. 
+.TP
+.B nohidecdr
+Turn off hiding CD-R media.
+.TP
+.B tattooinfo
+Use this option together with
+.B \-checkdrive
+to retrieve the image size information for the
+.B "Yamaha DiskT@2
+feature. The images always have a line length of 3744 pixel.
+Line number 0 (radius 0) is mapped to the center of the disk.
+If you know the inner and outer radius you will be able to create a
+pre distorted image that later may appear undistorted on the disk.
+.TP
+.BI tattoofile= name
+Use this option together with
+.B \-checkdrive
+to write an image prepared for the
+.B "Yamaha DiskT@2
+feature to the medium.
+The file must be a file with raw image B&W data (one byte per pixel) 
+in a size as retrieved by a previous call to
+.BI tattoofile= name
+\&.
+If the size of the image equals the maximum possible size
+(3744 x 320 pixel), 
+.B wodim
+will use the first part of the file. This first part then will 
+be written to the leftover space on the CD.
+.sp
+Note that the image must be mirrored to be readable from the pick up
+side of the CD.
+.RE
+.TP
+.B \-setdropts
+Set the driveropts specified by
+.BI driveropts= "option list" ,
+the 
+.B speed
+of the drive and the 
+.B dummy
+flag and exit.
+This allows wodim to set drive specific parameters that are not directly 
+used by
+.B wodim
+like e.g.
+.BR "single session mode" ", " "hide cdr"
+and similar.
+It is needed in case that 
+.BI driveropts= "option list"
+should be called without planning to run a typical
+.B wodim
+task.
+.TP
+.B \-checkdrive
+Checks if a driver for the current drive is present and exit.
+If the drive is a known drive, 
+.B wodim
+uses exit code 0.
+.TP
+.B \-prcap
+Print the drive capabilities for SCSI-3/mmc compliant drives
+as obtained from mode page 0x2A. Values marked with 
+.I kB
+use 1000 bytes as kilo-byte, values marked with
+.I KB
+use 1024 bytes as Kilo-byte.
+.TP
+.B \-inq
+Do an inquiry for the drive, print the inquiry info and exit.
+.TP
+.B \-scanbus
+Scan all SCSI devices on all SCSI busses and print the inquiry
+strings. This option may be used to find SCSI address of the 
+CD/DVD-Recorder on a system. If some device types are invisible, try using
+.B dev=ATA:
+or similar option to give a hint about the device type you are looking for.
+The numbers printed out as labels are computed by: 
+.B "bus * 100 + target.
+On platforms and device systems without persistent SCSI number management the
+results are not reliable. Use the .B \-\-devices option instead.
+.TP
+.B \-\-devices
+Look for useable devices using the system specific functions, eg. probing with
+usual device nodes in /dev/*, and display the detections using symbolic device
+names in OS specific syntax.
+.TP
+.B \-reset
+Try to reset the SCSI bus where the CD recorder is located. This works not
+on all operating systems.
+.TP
+.B \-abort
+Try to send an 
+.B abort
+sequence to the drive.
+If you use 
+.B wodim
+only, this should never be needed; but other software may leave a drive 
+in an unusable condition.
+Calling
+.B "wodim \-reset
+may be needed if a previous write has been interrupted and the software did 
+not tell the drive that it will not continue to write.
+.TP
+.B \-overburn
+Allow 
+.B wodim 
+to write more than the official size of a medium. This feature is usually
+called 
+.I overburning
+and depends on the fact that most blank media may hold more space than the
+official size. As the official size of the lead-out area on the disk is
+90 seconds (6750 sectors) and a disk usually works if there are at least
+150 sectors of lead out, all media may be overburned by at least 88 seconds
+(6600 sectors).
+Most CD recorders only do overburning in 
+.B SAO
+or
+.B RAW
+mode. Known exceptions are TEAC CD-R50S, TEAC CD-R55S and the Panasonic
+CW-7502.
+Some drives do not allow to overburn as much as you might like and limit
+the size of a CD to e.g. 76 minutes. This problem may be circumvented by
+writing the CD in RAW mode because this way the drive has no chance to find
+the size before starting to burn.
+There is no guarantee that your drive supports overburning at all.
+Make a test to check if your drive implements the feature.
+.TP
+.B \-ignsize
+Ignore the known size of the medium. This option should be used with extreme
+care, it exists only for debugging purposes don't use it for other reasons.
+It is not needed to write disks with more than the nominal capacity.
+This option implies
+.BR \-overburn .
+.TP
+.B \-useinfo
+Use
+.B "*.inf
+files to overwrite audio options.
+If this option is used, the pregap size information is read from 
+the
+.B "*.inf
+file that is associated with the file that contains the audio
+data for a track.
+.sp
+If used together with the
+.B \-audio
+option,
+.B wodim
+may be used to write audio CDs from a pipe from
+.B icedax
+if you call
+.B wodim
+with the
+.B *.inf
+files as track parameter list instead of using audio files.
+The audio data is read from 
+.B stdin
+in this case.
+See
+.B EXAMPLES
+section below.
+.B wodim
+first verifies that 
+.B stdin
+is not connected to a terminal and runs some heuristic consistency checks
+on the
+.B *.inf
+files and then sets the track lengths from the information in
+the
+.B *.inf
+files.
+.sp
+If you like to write from 
+.BR stdin ,
+make sure that wodim is called with a large enough FIFO size, reduce the write
+speed to a value below the read speed of the source drive and switch the burn-free
+option for the recording drive on.
+.TP
+.BR defpregap= #
+Set the default pre-gap size for all tracks except track number 1.
+This option currently only makes sense with the TEAC drive when
+creating track-at-once disks without the 2 second silence before each track.
+.br
+This option may go away in future. 
+.TP
+.B \-packet
+Set 
+.B "Packet writing mode. 
+This is an experimental interface.
+.TP
+.BR pktsize= #
+Set the packet size to #, forces fixed packet mode.
+This is an experimental interface.
+.TP
+.B \-noclose
+Do not close the current track, useful only when in packet writing mode.
+This is an experimental interface.
+.TP
+.BI mcn= med_cat_nr
+Set the 
+.B "Media Catalog Number
+of the CD to 
+.IR med_cat_nr .
+.TP
+.B \-text
+Write CD-Text information
+based on information taken from a file that contains ascii information
+for the text strings. 
+.B wodim
+supports CD-Text information based on the content of the
+.B *.inf
+files created by 
+.B icedax 
+and CD-Text information based on the content from a
+.B "CUE sheet
+file.
+If a 
+.B "CUE sheet
+file contains both (binary CDTEXTFILE and text based SONGWRITER)
+entries, then the information based on the CDTEXTFILE entry will win.
+.sp
+You need to use the
+.B \-useinfo
+option in addition in order to tell 
+.B wodim
+to read the
+.B "*.inf
+files or
+.BI cuefile= filename
+in order to tell
+.B wodim
+to read a
+.B CUE sheet
+file in addition.
+If you like to write your own CD-Text information,
+edit the
+.B *.inf
+files or the
+.B "CUE sheet
+file with a text editor and change the fields
+that are relevant for CD-Text.
+.TP
+.BI textfile= filename
+Write CD-Text based on information found in the binary file
+.IR filename .
+This file must contain information in a data format defined in the
+SCSI-3 MMC-2 standard and in the Red Book. The four byte size header that is 
+defined in the SCSI standard is optional and allows to make the recognition of
+correct data less ambiguous.
+This is the best option to be used to copy CD-Text data from existing CDs
+that already carry CD-Text information. To get data in a format suitable
+for this option use 
+.B wodim \-vv \-toc
+to extract the information from disk.
+If both, 
+.BI textfile= filename
+and CD-Text information from
+.B *.inf
+or
+.B *.cue
+files are present,
+.BI textfile= filename
+will overwrite the other information.
+.TP
+.BI cuefile= filename
+Take all recording related information from a CDRWIN compliant
+.B "CUE sheet
+file.
+No track files are allowed when this option is present and the option
+.B \-dao
+is currently needed in addition.
+
+.SH "TRACK OPTIONS
+.PP
+Track options may be mixed with track file names.
+.TP
+.BI isrc= ISRC_number
+Set the 
+.B "International Standard Recording Number
+for the next track to
+.IR ISRC_number .
+.TP
+.BI index= list
+Sets an index list for the next track.
+In index list is a comma separated list of numbers that are counting
+from index 1. The first entry in this list must contain a 0, the following 
+numbers must be an ascending list of numbers (counting in 1/75 seconds) that 
+represent the start of the indices. An index list in the form:
+0,7500,15000 sets index 1 to the start of the track, index 2 100 seconds from
+the start of the track and index 3 200 seconds from the start of the track.
+.TP
+.B \-audio
+If this flag is present, all subsequent tracks are written in
+.B "CD-DA 
+(similar to Red Book) audio format.
+The file with data for this tracks should
+contain stereo, 16-bit digital audio with 44100 samples/s.
+The byte order should be the following: MSB left, LSB left, 
+MSB right, LSB right, MSB left and so on. The track should be a multiple of 
+2352 bytes. It is not possible to put the master image of an audio track 
+on a raw disk because 
+data will be read in multiple of 2352 bytes during the recording process.
+.sp
+If a filename ends in 
+.I .au
+or
+.I .wav
+the file is considered to be a structured audio data file.
+.B wodim
+assumes that the file in this case is a Sun audio file or a
+Microsoft .WAV file
+and extracts the audio data from the files by skipping over the
+non-audio header information.
+In all other cases, wodim will only work correctly if the
+audio data stream does not have any header.
+Because many structured audio files do not have an integral
+number of blocks (1/75th second) in length,
+it is often necessary to specify the
+.B \-pad
+option as well.
+.B wodim
+recognizes that audio data in a .WAV file is stored in Intel
+(little-endian) byte order, and will automatically byte-swap the data
+if the CD recorder requires big-endian data.  
+.B wodim
+will reject any audio file that does not match the Red Book requirements
+of 16-bit stereo samples in PCM coding at 44100 samples/second.
+.sp
+Using other structured audio data formats as input to 
+.B wodim
+will usually work if the structure of the data is the 
+structure described above (raw pcm data in big-endian byte order).
+However, if the data format includes a header,
+you will hear a click at the start of a track.
+.TP
+.I " "
+If neither 
+.I \-data 
+nor
+.I \-audio
+have been specified, 
+.B wodim
+defaults to 
+.I \-audio
+for all filenames that end in
+.I .au
+or 
+.I .wav
+and to
+.I \-data 
+for all other files.
+.TP
+.B \-swab
+If this flag is present, audio data is assumed to be in byte-swapped
+(little-endian) order.  Some types of CD-Writers e.g. Yamaha, Sony and the
+new SCSI-3/mmc drives require audio data to be presented in
+little-endian order,
+.\" (which is the order in which it's actually recorded on the CD) ????
+while other writers require audio data to be
+presented in the big-endian (network) byte order normally used by the
+SCSI protocol.
+.B wodim
+knows if a CD-Recorder needs audio data in big- or little-endian order,
+and corrects the byte order of the data stream to match the needs
+of the recorder.
+You only need the 
+.I \-swab 
+flag if your data stream is in Intel (little-endian) byte order.
+.sp
+Note that the verbose output of
+.B wodim
+will show you if swapping is necessary to make the byte order of 
+the input data fit the required byte order of the recorder.
+.B wodim
+will not show you if the 
+.I \-swab 
+flag was actually present for a track.
+.TP
+.B \-data
+If this flag is present, all subsequent tracks are written in
+.B "CD-ROM mode 1
+(Yellow Book) format. The data size is a multiple of 2048 bytes.
+The file with track data should contain an 
+.BR ISO-9660 " or " "Rock Ridge
+filesystem image (see 
+.B genisoimage
+for more details). If the track data is an
+.B ufs
+filesystem image, fragment size should be set to 2\ KB or more to allow
+CD-drives with 2\ KB sector size to be used for reading.
+.TP
+.I " "
+.I \-data
+is the default, if no other flag is present and the file does not
+appear to be of one of the well known audio file types.
+.TP
+.I " "
+If neither 
+.I \-data 
+nor
+.I \-audio
+have been specified, 
+.B wodim
+defaults to 
+.I \-audio
+for all filenames that end in
+.I .au
+or 
+.I .wav
+and to
+.I \-data 
+for all other files.
+.TP
+.B \-mode2
+If this flag is present, all subsequent tracks are written in
+.B "CD-ROM mode 2
+format. The data size is a multiple of 2336 bytes.
+.TP
+.B \-xa
+If this flag is present, all subsequent tracks are written in
+.B "CD-ROM XA mode 2 form 1
+format. The data size is a multiple of 2048 bytes.
+The XA sector sub headers will be created by the drive.
+With this option, the write mode is the same as with the
+.B \-multi
+option.
+.TP
+.B \-xa1
+If this flag is present, all subsequent tracks are written in
+.B "CD-ROM XA mode 2 form 1
+format. The data size is a multiple of 2056 bytes.
+The XA sector sub headers are part of the user data and have to be
+supplied by the application that prepares the data to be written.
+.TP
+.B \-xa2
+If this flag is present, all subsequent tracks are written in
+.B "CD-ROM XA mode 2 form 2
+format. The data is a multiple of 2324 bytes.
+The XA sector sub headers will be created by the drive.
+.TP
+.B \-xamix
+If this flag is present, all subsequent tracks are written in a way
+that allows a mix of 
+.B "CD-ROM XA mode 2 form 1/2
+format. The data size is a multiple of 2332 bytes.
+The XA sector sub headers are part of the user data and have to be
+supplied by the application that prepares the data to be written.
+The CRC and the P/Q parity ECC/EDC information (depending on the sector
+type) have to be supplied by the application that prepares the data to be written.
+.TP
+.B \-cdi
+If this flag is present, the TOC type for the disk is set to
+.BR CDI .
+This only makes sense with XA disks.
+.TP
+.B \-isosize
+Use the 
+.B "ISO-9660
+file system size as the size of the next track.
+This option is needed if you want 
+.B wodim
+to directly read the image of a track from
+a raw disk partition or from a 
+.I TAO 
+master CD. In the first case the option
+.B \-isosize
+is needed to limit the size of the CD to the size of the ISO filesystem.
+In the second case the option
+.B \-isosize
+is needed to prevent 
+.B wodim
+from reading the two run out blocks that are appended by each CD-recorder
+in track at once mode. These two run out blocks cannot be read and would
+cause a buffer underrun that would cause a defective copy.
+Do not use this option on files created by 
+.B genisoimage
+and in case
+.B wodim
+reads the track data from 
+.IR stdin .
+In the first case, you would prevent 
+.B wodim 
+from writing the amount of padding that has been appended by
+.B genisoimage
+and in the latter case, it will not work because 
+.I stdin
+is not seekable.
+.sp
+If 
+.B \-isosize
+is used for a track, 
+.B wodim
+will automatically add padding for this track as if the
+.B \-pad
+option has been used but the amount of padding may be less than the padding
+written by 
+.BR  genisoimage .
+Note that if you use
+.B \-isosize
+on a track that contains Sparc boot information, the boot information will
+be lost.
+.sp
+Note also that
+this option cannot be used to determine the size of a file system
+if the multi session option is present.
+.TP
+.B \-pad
+If the track is a data track, 15 sectors of zeroed data
+will be added to the end of this and each subsequent data track.
+In this case, the 
+.B \-pad 
+option is superseded by the 
+.B padsize=
+option. It will remain however as a shorthand for
+.BI padsize= 15s.
+If the 
+.I \-pad 
+option refers to an audio track,
+.B wodim 
+will pad the audio data to be a multiple of 2352 bytes. 
+The audio data padding is done with binary zeroes which is 
+equal to absolute silence.
+.sp
+.B \-pad 
+remains valid until disabled by 
+.BR \-nopad .
+.TP
+.BR padsize= #
+Set the amount of data to be appended as padding to the next track to #.
+Opposed to the behavior of the 
+.B \-pad
+option, the value for 
+.I padsize=
+is reset to zero for each new track.
+wodim assumes a sector size of 2048 bytes for the
+.I padsize=
+option, independent from the real 
+sector size and independent from the write mode.
+The megabytes mentioned in the verbose mode output however are counting
+the output sector size which is e.g. 2448 bytes when writing in RAW/RAW96
+mode.
+See
+.BR fs =
+option for possible arguments.
+To pad the equivalent of 20 minutes on a CD, you may write
+.BR padsize= 20x60x75s.
+Use this option if your CD-drive is not able to read the last sectors of
+a track or if you want to be able to read the CD
+on a 
+.B Linux 
+system with the ISO-9660 filesystem read ahead bug.
+If an empty file is used for track data, 
+this option may be used to create a disk that is entirely made of padding.
+This may e.g. be used to find out how much overburning is possible with a 
+specific media.
+.TP
+.B \-nopad
+Do not pad the following tracks \- the default.
+.TP
+.B \-shorttrack
+Allow all subsequent tracks to violate the Red Book track length standard
+which requires a minimum track length of 4 seconds.
+This option is only useful when used in SAO or RAW mode.
+Not all drives support this feature. The drive must accept the
+resulting CUE sheet or support RAW writing.
+.TP
+.B \-noshorttrack
+Re-enforce the Red Book track length standard. Tracks must be
+at least 4 seconds.
+.TP
+.BR pregap= #
+Set the  pre-gap size for the next track.
+This option currently only makes sense with the TEAC drive when
+creating track-at-once disks without the 2 second silence before each track.
+.br
+This option may go away in future. 
+.TP
+.B \-preemp
+If this flag is present, all TOC entries for subsequent audio tracks 
+will indicate that the audio data has been sampled with 50/15 \*msec
+pre-emphasis.
+The data, however is not modified during the process of transferring from file
+to disk. 
+This option has no effect on data tracks.
+.TP
+.B \-nopreemp
+If this flag is present, all TOC entries for subsequent audio tracks 
+will indicate that the audio data has been mastered with linear data \- 
+this is the default.
+.TP
+.B \-copy
+If this flag is present, all TOC entries for subsequent audio tracks
+of the resulting CD
+will indicate that the audio data has permission to be copied without limit.
+This option has no effect on data tracks.
+.TP
+.B \-nocopy
+If this flag is present, all TOC entries for subsequent audio tracks 
+of the resulting CD
+will indicate that the audio data has permission to be copied only once for
+personal use \-
+this is the default.
+.TP
+.B \-scms
+If this flag is present, all TOC entries for subsequent audio tracks 
+of the resulting CD
+will indicate that the audio data has no permission to be copied anymore.
+.TP
+.BR tsize= #
+If the master image for the next track has been stored on a raw disk, 
+use this option
+to specify the valid amount of data on this disk. If the image of the next 
+track is stored in a regular file, the size of that file is taken to determine
+the length of this track.
+If the track contains an ISO 9660 filesystem image use the 
+.I \-isosize
+option to determine the length of that filesystem image.
+.br
+In Disk at Once mode and with some drives that use
+the TEAC programming interface, even in Track at Once mode,
+.B wodim
+needs to know the size of each track before starting to write the disk.
+wodim now checks this and aborts before starting to write.
+If this happens you will need to run
+.B "genisoimage -print-size
+before and use the output (with `s' appended) as an argument to the 
+.BR tsize =
+option of 
+.B wodim
+(e.g. tsize=250000s).
+.br
+See
+.BR fs =
+option for possible arguments.
+
+.SH EXAMPLES
+.PP
+For all examples below, it will be assumed that the CD/DVD-Recorder is
+connected to the primary SCSI bus of the machine. The SCSI target id is
+set to 2.
+.PP
+To record a pure CD-ROM at double speed, using data from the file
+.IR cdimage.raw :
+.PP
+    wodim \-v speed=2 dev=2,0 cdimage.raw
+.PP
+To create an image for a ISO 9660 filesystem with Rock Ridge extensions:
+.PP
+    genisoimage \-R \-o cdimage.raw /home/joerg/master/tree
+.PP
+To check the resulting file before writing to CD on Solaris:
+.PP
+    mount \-r \-F fbk \-o type=hsfs /dev/fbk0:cdimage.raw /mnt
+.PP
+On Linux:
+.PP
+    mount cdimage.raw \-r \-t iso9660 \-o loop /mnt
+.PP
+Go on with:
+.br
+    ls \-lR /mnt
+.br
+    umount /mnt
+.PP
+If the overall speed of the system is sufficient and the structure of
+the filesystem is not too complex, wodim will run without creating an
+image of the ISO 9660 filesystem. Simply run the pipeline:
+.PP
+    genisoimage \-R /master/tree | wodim \-v fs=6m speed=2 dev=2,0 -
+.PP
+The recommended minimum FIFO size for running this pipeline is 4 MBytes.
+As the default FIFO size is 4 MB, the 
+.B fs=
+option needs only be present if you want to use a different FIFO size.
+If your system is loaded, you should run genisoimage in the real time class too.
+To raise the priority of 
+.B genisoimage
+replace the command
+.PP
+    genisoimage \-R /master/tree
+.br
+by
+.br
+    priocntl \-e \-c RT \-p 59 genisoimage \-R /master/tree
+.sp
+on Solaris and by
+.sp
+    nice --18 genisoimage \-R /master/tree
+.sp
+on systems that don't have
+.B "UNIX International
+compliant real-time scheduling.
+.PP
+wodim runs at priority 59 on Solaris, you should run genisoimage
+at no more than priority 58. On other systems, you should run genisoimage
+at no less than nice --18.
+.PP
+Creating a CD-ROM without file system image on disk has been tested
+on a Sparcstation-2 with a Yamaha CDR-400. It did work up to quad speed
+when the machine was not loaded.
+A faster machine may be able to handle quad speed also in the loaded case.
+.PP
+To record a pure CD-DA (audio) at single speed, with each track contained
+in a file named
+.IR track01.cdaudio ,
+.IR track02.cdaudio ,
+etc:
+.PP
+    wodim \-v speed=1 dev=/dev/cdrw -audio track*.cdaudio
+.PP
+To check if it will be ok to use double speed for the example above. 
+Use the dummy write option:
+.PP
+    wodim \-v \-dummy speed=2 dev=/dev/cdrw \-audio track*.cdaudio
+.PP
+To record a mixed-mode CD with an ISO 9660 filesystem from
+.I cdimage.raw
+on the first track, the other tracks being audio tracks from the files
+.IR track01.cdaudio ,
+.IR track02.cdaudio ,
+etc:
+.PP
+    wodim \-v dev=2,0 cdimage.raw \-audio track*.cdaudio
+.PP
+To handle drives that need to know the size of a track before starting to write,
+first run
+.PP
+    genisoimage -R -q -print-size /master/tree
+.PP
+and then run
+.PP
+    genisoimage -R /master/tree | wodim speed=2 dev=2,0 tsize=XXXs -
+.PP
+where 
+.I XXX
+is replaced by the output of the previous run of genisoimage.
+.PP
+To copy an audio CD in the most accurate way, first run
+.PP
+    icedax dev=/dev/cdrom \-vall cddb=0 -B \-Owav
+.PP
+and then run
+.PP
+    wodim dev=/dev/cdrw \-v \-dao \-useinfo \-text  *.wav
+.PP
+This will try to copy track indices and to read CD-Text information from disk.
+If there is no CD-Text information, 
+.B icedax
+will try to get the information from freedb.org instead.
+.PP
+To copy an audio CD from a pipe (without intermediate files), first run
+.PP
+    icedax dev=1,0 \-vall cddb=0 \-info-only
+.PP
+and then run
+.PP
+    icedax dev=1,0 \-no-infofile \-B \-Oraw \- | \\
+.br
+    wodim dev=2,0 \-v \-dao \-audio \-useinfo \-text *.inf
+.PP
+This will get all information (including track size info) from the
+.B *.inf
+files and then read the audio data from stdin.
+.sp
+If you like to write from 
+.BR stdin ,
+make sure that wodim is called with a large enough FIFO size (e.g.
+.BR fs=128m ),
+reduce the write speed to a value below the read speed of the source drive
+(e.g.
+.BR speed=12 ),
+and get a CD/DVD drive with BURN-Free feature if it is not available yet.
+.PP
+To set drive options without writing a CD (e.g. to switch a drive
+to single session mode), run
+.PP
+    wodim dev=1,0 \-setdropts driveropts=singlesession
+.PP
+If you like to do this when no CD is in the drive, call
+.PP
+    wodim dev=1,0 \-force \-setdropts driveropts=singlesession
+.PP
+To copy a CD in clone mode, first read the master CD using:
+.PP
+    readom dev=b,t,l \-clone f=somefile
+.PP
+or (in case the CD contains many sectors that are unreadable by intention)
+by calling:
+.PP
+    readom dev=1,0 -clone -nocorr f=somefile
+.PP
+will create the files
+.I somefile
+and
+.IR somefile.toc .
+Then write the CD using:
+.PP
+    wodim dev=1,0 -raw96r -clone -v somefile
+
+
+.SH ENVIRONMENT
+.TP
+.B CDR_DEVICE
+This may either hold a device identifier that is suitable to the open
+call of the SCSI transport library or a label in the file /etc/wodim.conf.
+.TP
+.B CDR_SPEED
+Sets the default speed value for writing (see also 
+.B speed=
+option).
+.TP
+.B CDR_FIFOSIZE
+Sets the default size of the FIFO (see also 
+.BR fs= #
+option).
+.TP
+.B CDR_FORCERAWSPEED
+If this environment variable is set, 
+.B wodim
+will allow you to write at the full RAW encoding speed a single CPU supports.
+This will create high potential of buffer underruns. Use with care.
+.TP
+.B CDR_FORCESPEED
+If this environment variable is set, 
+.B wodim
+will allow you to write at the full DMA speed the system supports.
+There is no DMA reserve for reading the data that is to be written from disk.
+This will create high potential of buffer underruns. Use with care.
+.TP
+.B RSH
+If the 
+.B RSH
+environment is present, the remote connection will not be created via
+.BR rcmd (3)
+but by calling the program pointed to by
+.BR RSH .
+Use e.g. 
+.BR RSH= /usr/bin/ssh
+to create a secure shell connection.
+.sp
+Note that this forces 
+.B wodim
+to create a pipe to the 
+.B rsh(1)
+program and disallows
+.B wodim
+to directly access the network socket to the remote server.
+This makes it impossible to set up performance parameters and slows down
+the connection compared to a 
+.B root
+initiated
+.B rcmd(3)
+connection.
+.TP
+.B RSCSI
+If the 
+.B RSCSI
+environment is present, the remote SCSI server will not be the program
+.B /opt/schily/sbin/rscsi
+but the program pointed to by
+.BR RSCSI .
+Note that the remote SCSI server program name will be ignored if you log in
+using an account that has been created with a remote SCSI server program as
+login shell.
+
+.SH FILES
+.TP
+/etc/wodim.conf
+Default values can be set for the following options in /etc/wodim.conf.
+For example:
+.SM CDR_FIFOSIZE=8m
+or
+.SM CDR_SPEED=2
+.RS
+.TP
+CDR_DEVICE
+This may either hold a device identifier that is suitable to the open
+call of the SCSI transport library or a label in the file /etc/wodim.conf 
+that allows to identify a specific drive on the system.
+.TP
+CDR_SPEED
+Sets the default speed value for writing (see also 
+.B speed=
+option).
+.TP
+CDR_FIFOSIZE
+Sets the default size of the FIFO (see also 
+.BR fs= #
+option).
+.TP
+CDR_MAXFIFOSIZE
+Sets the maximum size of the FIFO (see also 
+.BR fs= #
+option).
+.TP
+Any other keyword (label) is an identifier (symbolic name) for a specific drive
+on the system.  Such an identifier may not contain the characters ',', '/', '@'
+or ':'.
+.sp
+Each line that follows a label contains a whitespace separated list of items.
+Currently, four items are recognized: the drive's target specification, the
+default speed that should be used for this drive, the default FIFO size
+that should be used for this drive and drive specific options. The values for 
+.I speed
+and
+.I fifosize
+may be set to -1 to tell wodim to use the global defaults.
+.I target
+can be -1 to use the auto-guessing of the drive (see above).
+
+The value for driveropts may be omitted or set to "" if no driveropts are used.
+A typical line may look this way:
+.sp
+plex760= 0,5,0 12      50m     varirec=1
+.sp
+pioneer= /dev/hdd      -1      -1
+.sp
+This tells
+.B wodim
+that a drive named
+.I plex760
+is at scsibus 0, target 5, lun 0 and should be used with speed 12 and
+a FIFO size of 50 MB. It also uses some device specific parameter.
+A second drive may is accessible via the device file /dev/hdd and uses the
+default speed and the default FIFO size.
+.RE
+
+.SH SEE ALSO
+.BR icedax (1),
+.BR readom (1),
+.BR genisoimage (1),
+.BR ssh (1).
+
+.SH NOTES
+.PP
+On Solaris you need to stop the volume management if you like to use the USCSI
+fallback SCSI transport code. Even things like 
+.B "wodim -scanbus
+will not work if the volume management is running.
+.PP
+Disks made in 
+.B "Track At Once 
+mode are not suitable as a master for direct mass production by CD manufacturers.
+You will need the 
+.B "disk at once
+option to record such disks.
+Nevertheless the disks made in
+.B "Track At Once 
+will normally be read in all CD players. Some old
+audio CD players however may produce a two second click between two audio tracks.
+.PP
+The minimal size of a track is 4 seconds or 300 sectors. If you write 
+smaller tracks, the CD-Recorder will add dummy blocks. This is not an
+error, even though the SCSI-error message looks this way.
+.PP
+The Yamaha CDR-400 and all new SCSI-3/mmc conforming drives are supported
+in single and multi-session.
+.PP
+You should run several tests in all supported speeds of your drive with the
+.B \-dummy
+option turned on if you are using 
+.B wodim
+on an unknown system. Writing a CD is a real-time process. 
+.B NFS, CIFS
+and other network file systems
+won't always deliver constantly the needed data rates.
+If you want to use 
+.B wodim 
+with CD-images that are located on a
+.B NFS
+mounted filesystem, be sure that the FIFO size is big enough.
+If you want to make sure that buffer underruns are not
+caused by your source disk, you may use the command
+.PP
+.B "    wodim -dummy dev=2,0 padsize=600m /dev/null
+.PP
+to create a disk that is entirely made of dummy data.
+.PP
+There are also cases where you either need to be root or install
+.B wodim 
+executable with suid-root permissions. First, if you are using a device
+manufactured before 1999 which requires a non-MMC driver, you should run
+.B wodim
+in dummy mode before writing data. If you find a problem doing this, please
+report it to the
+.B cdrkit
+maintainers (see below).
+.PP
+Second, certain functionality may be unusable because of Linux's SCSI
+command filtering. When using
+.B wodim
+for anything except of pure data writing, you should also test the process in
+dummy mode and report trouble to the contact address below.
+.PP
+If you still want to run
+.B wodim
+with root permissions, you can set the permissions of the executable to
+suid-root. See the additional notes of your system/program distribution or
+README.suidroot which is part of the cdrkit source.
+.PP
+You should not connect old drives that do not support
+disconnect/reconnect to either the SCSI bus that is connected to the
+CD-Recorder or the source disk.
+.PP
+A Compact Disc can have no more than 99 tracks.
+.PP
+When creating a disc with both audio and data tracks, 
+the data should be on track 1 otherwise you should create
+a CDplus disk which is a multi session disk with the first session 
+containing the audio tracks and the following session containing the data track.
+.PP
+Many operating systems are not able to read more than a single data track, or
+need special software to do so.
+.PP
+If you have more information or SCSI command manuals for currently 
+unsupported CD/DVD/BR/HD-DVD-Recorders, please contact the
+.B cdrkit
+maintainers (see below).
+.PP
+Many CD recorders have bugs and often require a firmware update to work
+correctly. If you experience problems which cannot be solved or explained by the
+notes above, please look for instructions on the homepage of the particular
+manufacturer.
+.PP
+Some bugs will force you to power cycle the device or to reboot the machine.
+.PP
+The FIFO percent output is computed just after a block of data has been written
+to the CD/DVD-Recorder. For this reason, there will never be 100% FIFO fill ratio
+while the FIFO is in streaming mode.
+
+.SH DIAGNOSTICS
+.PP
+You have 4 seconds to abort
+.B wodim
+start after you see the message:
+.PP
+Starting to write CD at speed %d in %s mode for %s session.
+In most shells you can do that by pressing Ctrl-C.
+.PP
+A typical error message for a SCSI command looks like:
+.sp
+.RS
+.nf
+wodim: I/O error. test unit ready: scsi sendcmd: no error
+CDB:  00 20 00 00 00 00
+status: 0x2 (CHECK CONDITION)
+Sense Bytes: 70 00 05 00 00 00 00 0A 00 00 00 00 25 00 00 00 00 00
+Sense Key: 0x5 Illegal Request, Segment 0
+Sense Code: 0x25 Qual 0x00 (logical unit not supported) Fru 0x0
+Sense flags: Blk 0 (not valid)
+cmd finished after 0.002s timeout 40s
+.fi
+.RE
+.sp
+The first line gives information about the transport of the command.
+The text after the first colon gives the error text for the system call
+from the view of the kernel. It usually is:
+.B "I/O error
+unless other problems happen. The next words contain a short description for
+the SCSI command that fails. The rest of the line tells you if there were
+any problems for the transport of the command over the SCSI bus.
+.B "fatal error
+means that it was not possible to transport the command (i.e. no device present
+at the requested SCSI address).
+.PP
+The second line prints the SCSI command descriptor block for the failed command.
+.PP
+The third line gives information on the SCSI status code returned by the 
+command, if the transport of the command succeeds. 
+This is error information from the SCSI device.
+.PP
+The fourth line is a hex dump of the auto request sense information for the 
+command.
+.PP
+The fifth line is the error text for the sense key if available, followed
+by the segment number that is only valid if the command was a
+.I copy
+command. If the error message is not directly related to the current command,
+the text
+.I deferred error
+is appended.
+.PP
+The sixth line is the error text for the sense code and the sense qualifier if available.
+If the type of the device is known, the sense data is decoded from tables
+in
+.IR scsierrs.c " .
+The text is followed by the error value for a field replaceable unit.
+.PP
+The seventh line prints the block number that is related to the failed command
+and text for several error flags. The block number may not be valid.
+.PP
+The eight line reports the timeout set up for this command and the time
+that the command really needed to complete.
+.PP
+The following message is not an error:
+.sp
+.RS
+.nf
+Track 01: Total bytes read/written: 2048/2048 (1 sectors).
+wodim: I/O error. flush cache: scsi sendcmd: no error
+CDB:  35 00 00 00 00 00 00 00 00 00
+status: 0x2 (CHECK CONDITION)
+Sense Bytes: F0 00 05 80 00 00 27 0A 00 00 00 00 B5 00 00 00 00 00
+Sense Key: 0x5 Illegal Request, Segment 0
+Sense Code: 0xB5 Qual 0x00 (dummy data blocks added) Fru 0x0
+Sense flags: Blk -2147483609 (valid)
+cmd finished after 0.002s timeout 40s
+.fi
+.RE
+.sp
+It simply notifies, that a track that is smaller than the minimum size has been
+expanded to 300 sectors.
+.SH BUGS
+.PP
+.B netscsid
+does not work properly and is generally unmaintained. It is probably not
+compatible with rscsi from 
+.BR cdrtools
+either. Good bugfixes are welcome, talk to Cdrkit maintainers.
+.PP
+.B cuefile support is very limited, only one file is allowed. For volunteers,
+see TODO file in the source.
+.PP
+.B Specifying an audio file multiple times causes corruption of the second
+track (effectively no data plus minimum padding).
+.PP
+Some of the bugs may be fixed in Joerg Schilling's cdrtools. See there for
+details, URL attached below.
+
+.SH CREDITS
+.PP
+.TP 15
+Joerg Schilling (schilling@fokus.fhg.de)
+.br
+For writing cdrecord and libscg which represent the most parts of wodim's code.
+.PP
+.TP 15
+Bill Swartz    (Bill_Swartz@twolf.com)
+.br
+For helping me with the TEAC driver support
+.TP
+Aaron Newsome  (aaron.d.newsome@wdc.com)
+.br
+For letting me develop Sony support on his drive
+.TP
+Eric Youngdale (eric@andante.jic.com)
+.br
+For supplying mkisofs
+.TP
+Gadi Oxman     (gadio@netvision.net.il)
+.br
+For tips on the ATAPI standard
+.TP
+Finn Arne Gangstad     (finnag@guardian.no)
+.br
+For the first FIFO implementation.
+.TP
+Dave Platt     (dplatt@feghoot.ml.org)
+.br
+For creating the experimental packet writing support,
+the first implementation of CD-RW blanking support,
+the first .wav file decoder 
+and many nice discussions on cdrecord.
+.TP
+Chris P. Ross (cross@eng.us.uu.net)
+.br
+For the first implementation of a BSDI SCSI transport.
+.TP
+Grant R. Guenther   (grant@torque.net)
+.br
+For creating the first parallel port transport implementation
+for Linux.
+.TP
+Kenneth D. Merry (ken@kdm.org)
+.br
+for providing the CAM port for FreeBSD together with Michael Smith (msmith@freebsd.org)
+.TP
+Heiko Ei\*sfeldt (heiko@hexco.de)
+for making libedc_ecc available (needed to write RAW data sectors).
+
+.SH "MAILING LISTS
+If you want to actively take part on the development of wodim,
+you may join the developer mailing list via this URL:
+.sp
+.B
+https://alioth.debian.org/mail/?group_id=31006
+.PP
+The mail address of the list is:
+.B
+debburn-devel@lists.alioth.debian.org
+
+.SH AUTHORS
+.B wodim
+is currently maintained as part of the cdrkit project by its developers. Most of the code and this manual page was originally written by:
+.PP
+.nf
+Joerg Schilling
+Seestr. 110
+D-13353 Berlin
+Germany
+.fi
+.PP
+This application is derived from "cdrecord" as included
+in the cdrtools package [1] created by Joerg
+Schilling, who deserves most of the credit for its success. However, he is not
+involved into the development of this spinoff and therefore he shall not be
+held responsible for any problems caused by it. Do not refer to this application
+as "cdrecord", do not try to get support for wodim by contacting the original
+authors.
+.PP
+Additional information can be found on:
+.br
+https://alioth.debian.org/projects/debburn/
+.PP
+If you have support questions, send them to
+.PP
+.B
+debburn-devel@lists.alioth.debian.org
+.br
+.PP
+If you have definitely found a bug, send a mail to this list or to
+.PP
+.B
+submit@bugs.debian.org
+.br
+.PP
+writing at least a short description into the Subject and "Package: cdrkit" in the first line of the mail body.
+.SH SOURCES
+.PP
+.br
+[1] Cdrtools 2.01.01a08 from May 2006, http://cdrecord.berlios.de
+
diff --git a/wodim/wodim.c b/wodim/wodim.c
new file mode 100644 (file)
index 0000000..7a54ccc
--- /dev/null
@@ -0,0 +1,4701 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/*
+ *
+ * Modified by Eduard Bloch in 08/2006 and later
+ */
+
+/* @(#)cdrecord.c      1.310 06/02/09 Copyright 1995-2006 J. Schilling */
+/*
+ *     Record data on a CD/CVD-Recorder
+ *
+ *     Copyright (c) 1995-2006 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <mconfig.h>
+#include <stdio.h>
+#include <standard.h>
+#include <stdxlib.h>
+#include <fctldefs.h>
+#include <errno.h>
+#include <timedefs.h>
+#ifdef HAVE_SYS_RESOURCE_H
+#include <sys/resource.h>      /* for rlimit */
+#endif
+#include <statdefs.h>
+#include <unixstd.h>
+#ifdef HAVE_SYS_MMAN_H
+#include <sys/mman.h>
+#endif
+#include <strdefs.h>
+#include <utypes.h>
+#include <intcvt.h>
+#include <signal.h>
+#include <schily.h>
+#include <string.h>
+#include <getargs.h>
+#ifdef HAVE_PRIV_H
+#include <priv.h>
+#endif
+
+#include "xio.h"
+
+#include <usal/scsireg.h>      /* XXX wegen SC_NOT_READY */
+#include <usal/scsitransp.h>
+#include <usal/usalcmd.h>              /* XXX fuer read_buffer */
+#include "scsi_scan.h"
+
+#include "auheader.h"
+#include "wodim.h"
+#include "defaults.h"
+#include "movesect.h"
+
+#ifdef __linux__
+#include <sys/capability.h>    /* for rawio capability */
+#endif
+
+#if defined(_POSIX_PRIORITY_SCHEDULING) && _POSIX_PRIORITY_SCHEDULING -0 >= 0
+#ifdef  HAVE_SYS_PRIOCNTL_H    /* The preferred SYSvR4 schduler */
+#else
+#define        USE_POSIX_PRIORITY_SCHEDULING
+#endif
+#endif
+
+/*
+ * Map toc/track types into names.
+ */
+char   *toc2name[] = {
+               "CD-DA",
+               "CD-ROM",
+               "CD-ROM XA mode 1",
+               "CD-ROM XA mode 2",
+               "CD-I",
+               "Illegal toc type 5",
+               "Illegal toc type 6",
+               "Illegal toc type 7",
+};
+
+/*
+ * Map sector types into names.
+ */
+char   *st2name[] = {
+               "Illegal sector type 0",
+               "CD-ROM mode 1",
+               "CD-ROM mode 2",
+               "Illegal sector type 3",
+               "CD-DA without preemphasis",
+               "CD-DA with preemphasis",
+               "Illegal sector type 6",
+               "Illegal sector type 7",
+};
+
+/*
+ * Map data block types into names.
+ */
+char   *db2name[] = {
+               "Raw (audio)",
+               "Raw (audio) with P/Q sub channel",
+               "Raw (audio) with P/W packed sub channel",
+               "Raw (audio) with P/W raw sub channel",
+               "Reserved mode 4",
+               "Reserved mode 5",
+               "Reserved mode 6",
+               "Vendor unique mode 7",
+               "CD-ROM mode 1",
+               "CD-ROM mode 2",
+               "CD-ROM XA mode 2 form 1",
+               "CD-ROM XA mode 2 form 1 (with subheader)",
+               "CD-ROM XA mode 2 form 2",
+               "CD-ROM XA mode 2 form 1/2/mix",
+               "Reserved mode 14",
+               "Vendor unique mode 15",
+};
+
+/*
+ * Map write modes into names.
+ */
+static char    wm_none[] = "unknown";
+static char    wm_ill[]  = "illegal";
+
+char   *wm2name[] = {
+               wm_none,
+               "BLANK",
+               "FORMAT",
+               wm_ill,
+               "PACKET",
+               wm_ill,
+               wm_ill,
+               wm_ill,
+               "TAO",
+               wm_ill,
+               wm_ill,
+               wm_ill,
+               "SAO",
+               "SAO/RAW16",    /* Most liklely not needed */
+               "SAO/RAW96P",
+               "SAO/RAW96R",
+               "RAW",
+               "RAW/RAW16",
+               "RAW/RAW96P",
+               "RAW/RAW96R",
+};
+
+int            debug;          /* print debug messages */
+static int     kdebug;         /* print kernel debug messages */
+static int     scsi_verbose;   /* SCSI verbose flag */
+static int     silent;         /* SCSI silent flag */
+int            lverbose;       /* static verbose flag */
+int            xdebug;         /* extended debug flag */
+
+char   *buf;                   /* The transfer buffer */
+long   bufsize = -1;           /* The size of the transfer buffer */
+
+static int     gracetime = GRACE_TIME;
+static int     raw_speed = -1;
+static int     dma_speed = -1;
+static int     dminbuf = -1;   /* XXX Hack for now drive min buf fill */
+BOOL   isgui;
+static int     didintr;
+char   *driveropts;
+static char    *cuefilename = NULL;
+static uid_t   oeuid = (uid_t)-1;
+
+struct timeval starttime;
+struct timeval wstarttime;
+struct timeval stoptime;
+struct timeval fixtime;
+
+static long    fs = -1;        /* fifo (ring buffer) size */
+static Llong warn_minisize = -1L;
+
+static int     gracewait(cdr_t *dp, BOOL *didgracep);
+static void    cdrstats(cdr_t *dp);
+static void    susage(int);
+static void    usage(int);
+static void    blusage(int);
+static void    formattypeusage(int);
+static void    intr(int sig);
+static void    catchsig(int sig);
+static int     scsi_cb(void *arg);
+static void    intfifo(int sig);
+static void    exscsi(int excode, void *arg);
+static void    excdr(int excode, void *arg);
+int    read_buf(int f, char *bp, int size);
+int    fill_buf(int f, track_t *trackp, long secno, char *bp, int size);
+int    get_buf(int f, track_t *trackp, long secno, char **bpp, int size);
+int    write_secs(SCSI *usalp, cdr_t *dp, char *bp, long startsec, int bytespt,
+                                         int secspt, BOOL islast);
+static int     write_track_data(SCSI *usalp, cdr_t *, track_t *);
+int    pad_track(SCSI *usalp, cdr_t *dp, track_t *trackp, long startsec, 
+                                        Llong amt, BOOL dolast, Llong *bytesp);
+int    write_buf(SCSI *usalp, cdr_t *dp, track_t *trackp, char *bp, 
+                                        long startsec, Llong amt, int secsize, BOOL dolast, 
+                                        Llong *bytesp);
+static void    printdata(int, track_t *);
+static void    printaudio(int, track_t *);
+static void    checkfile(int, track_t *);
+static int     checkfiles(int, track_t *);
+static void    setleadinout(int, track_t *);
+static void    setpregaps(int, track_t *);
+static long    checktsize(int, track_t *);
+static void    opentracks(track_t *);
+static void    checksize(track_t *);
+static BOOL    checkdsize(SCSI *usalp, cdr_t *dp, long tsize, int flags);
+static void    raise_fdlim(void);
+static void    raise_memlock(void);
+static int     gargs(int, char **, int *, track_t *, char **, int *, cdr_t **,
+                                                       int *, long *, int *, int *);
+static void    set_trsizes(cdr_t *, int, track_t *);
+void           load_media(SCSI *usalp, cdr_t *, BOOL);
+void           unload_media(SCSI *usalp, cdr_t *, int);
+void           reload_media(SCSI *usalp, cdr_t *);
+void           set_secsize(SCSI *usalp, int secsize);
+static int     get_dmaspeed(SCSI *usalp, cdr_t *);
+static BOOL    do_opc(SCSI *usalp, cdr_t *, int);
+static void    check_recovery(SCSI *usalp, cdr_t *, int);
+void           audioread(SCSI *usalp, cdr_t *, int);
+static void    print_msinfo(SCSI *usalp, cdr_t *);
+static void    print_toc(SCSI *usalp, cdr_t *);
+static void    print_track(int, long, struct msf *, int, int, int);
+#if !defined(HAVE_SYS_PRIOCNTL_H)
+static int     rt_raisepri(int);
+#endif
+void           raisepri(int);
+static void    wait_input(void);
+static void    checkgui(void);
+static int     getbltype(char *optstr, long *typep);
+static int     getformattype(char *optstr, long *typep);
+static void    print_drflags(cdr_t *dp);
+static void    print_wrmodes(cdr_t *dp);
+static BOOL    check_wrmode(cdr_t *dp, int wmode, int tflags);
+static void    set_wrmode(cdr_t *dp, int wmode, int tflags);
+static void    linuxcheck(void);
+
+#ifdef __linux__
+static int get_cap(cap_value_t cap_array);
+#endif
+
+struct exargs {
+       SCSI    *usalp;
+       cdr_t   *dp;
+       int     old_secsize;
+       int     flags;
+       int     exflags;
+} exargs;
+
+void fifo_cleanup(void) {
+   kill_faio();
+}
+
+/* shared variables */
+int    scandevs = 0;
+char   *msifile = NULL;
+
+int main(int argc, char *argv[])
+{
+       char    *dev = NULL;
+       int     timeout = 40;   /* Set default timeout to 40s CW-7502 is slow*/
+       int     speed = -1;
+       long    flags = 0L;
+       int     blanktype = 0;
+       int     formattype = 0;
+       int     i;
+       int     tracks = 0;
+       int     trackno;
+       long    tsize;
+       track_t track[MAX_TRACK+2];     /* Max tracks + track 0 + track AA */
+       cdr_t   *dp = (cdr_t *)0;
+       long    startsec = 0L;
+       int     errs = 0;
+       SCSI    *usalp = NULL;
+       char    errstr[80];
+       BOOL    gracedone = FALSE;
+       int     ispacket;
+       BOOL    is_cdwr = FALSE;
+       BOOL    is_dvdwr = FALSE;
+
+       buf=strstr(argv[0], "cdrecord");
+       if(buf && '\0' == buf[8]) /* lame cheater detected */
+               argv[0]="wodim";
+
+#ifdef __EMX__
+       /* This gives wildcard expansion with Non-Posix shells with EMX */
+       _wildcard(&argc, &argv);
+#endif
+       save_args(argc, argv);
+       oeuid = geteuid();              /* Remember saved set uid       */
+
+       fillbytes(track, sizeof (track), '\0');
+       for (i = 0; i < MAX_TRACK+2; i++)
+               track[i].track = track[i].trackno = i;
+       track[0].tracktype = TOC_MASK;
+       raise_fdlim();
+       ispacket = gargs(argc, argv, &tracks, track, &dev, &timeout, &dp, &speed, &flags,
+                                                       &blanktype, &formattype);
+       if ((track[0].tracktype & TOC_MASK) == TOC_MASK)
+               comerrno(EX_BAD, "Internal error: Bad TOC type.\n");
+
+       if (flags & F_VERSION) {
+          fprintf(stderr,
+                        "Cdrecord-yelling-line-to-tell-frontends-to-use-it-like-version 2.01.01a03-dvd \n"
+                "Wodim " CDRKIT_VERSION "\n"
+                "Copyright (C) 2006 Cdrkit suite contributors\n"
+                "Based on works from Joerg Schilling, Copyright (C) 1995-2006, J. Schilling\n"
+                );
+          exit(0);
+       }
+
+       checkgui();
+
+       if (debug || lverbose) {
+               printf("TOC Type: %d = %s\n",
+                       track[0].tracktype & TOC_MASK,
+                       toc2name[track[0].tracktype & TOC_MASK]);
+       }
+
+       if ((flags & (F_MSINFO|F_TOC|F_PRATIP|F_FIX|F_VERSION|F_CHECKDRIVE|F_INQUIRY|F_SCANBUS|F_RESET)) == 0) {
+               /*
+                * Try to lock us im memory (will only work for root)
+                * but you need access to root anyway to send SCSI commands.
+                * We need to be root to open /dev/usal? or similar devices
+                * on other OS variants and we need to be root to be able
+                * to send SCSI commands at least on AIX and
+                * Solaris (USCSI only) regardless of the permissions for
+                * opening files
+                *
+                * XXX The following test used to be
+                * XXX #if defined(HAVE_MLOCKALL) || defined(_POSIX_MEMLOCK)
+                * XXX but the definition for _POSIX_MEMLOCK did change during
+                * XXX the last 8 years and the autoconf test is better for
+                * XXX the static case. sysconf() only makes sense if we like
+                * XXX to check dynamically.
+                */
+               raise_memlock();
+#if defined(HAVE_MLOCKALL)
+               /*
+                * XXX mlockall() needs root privilleges.
+                */
+               if (mlockall(MCL_CURRENT|MCL_FUTURE) < 0) {
+                       if(lverbose>2)
+                               fprintf(stderr,
+                                               "W: Cannot do mlockall(2). Possibly increased risk for buffer underruns.\n");
+               }
+#endif
+
+               /*
+                * XXX raisepri() needs root privilleges.
+                */
+               raisepri(0); /* max priority */
+               /*
+                * XXX shmctl(id, SHM_LOCK, 0) needs root privilleges.
+                * XXX So if we use SysV shared memory, wee need to be root.
+                *
+                * Note that not being able to set up a FIFO bombs us
+                * back to the DOS ages. Trying to run cdrecord without
+                * root privillegs is extremely silly, it breaks most
+                * of the advanced features. We need to be at least installed
+                * suid root or called by RBACs pfexec.
+                */
+               init_fifo(fs);  /* Attach shared memory (still one process) */
+       }
+
+       if ((flags & F_WAITI) != 0) {
+               if (lverbose)
+                       printf("Waiting for data on stdin...\n");
+               wait_input();
+       }
+
+       /*
+        * Call usal_remote() to force loading the remote SCSI transport library
+        * code that is located in librusal instead of the dummy remote routines
+        * that are located inside libusal.
+        */
+       usal_remote();
+       if (dev != NULL &&
+           ((strncmp(dev, "HELP", 4) == 0) ||
+           (strncmp(dev, "help", 4) == 0))) {
+               usal_help(stderr);
+               exit(0);
+       }
+
+       if( (!dev || *dev=='\0'|| 0==strcmp(dev, "-1")) && (flags & F_SCANBUS)==0 ) {
+               int64_t need_size=0L;
+               struct stat statbuf;
+               int t;
+
+               fprintf(stderr, "Device was not specified. Trying to find an appropriate drive...\n");
+
+               /* estimate how much data user wants to write */
+               for(t=1;t<=tracks;t++) { 
+                       if(track[t].tracksize>=0)
+                               need_size+=track[t].tracksize;
+                       else if(0==stat(track[t].filename, &statbuf))
+                               need_size+=statbuf.st_size;
+               }
+               usalp=open_auto(need_size, debug, lverbose);
+       }
+
+       if(!usalp)
+               usalp = usal_open(dev, errstr, sizeof(errstr), debug, lverbose);
+
+       if(!usalp)
+       {
+               errmsg("\nCannot open SCSI driver!\n"
+                               "For possible targets try 'wodim --devices' or 'wodim -scanbus'.\n"
+                               "For possible transport specifiers try 'wodim dev=help'.\n"
+                               "For IDE/ATAPI devices configuration, see the file README.ATAPI.setup from\n"
+                               "the wodim documentation.\n");
+               exit(EX_BAD);
+       }
+
+#ifdef HAVE_PRIV_SET
+#ifdef PRIV_DEBUG
+       fprintf(stderr, "file_dac_read: %d\n", priv_ineffect(PRIV_FILE_DAC_READ));
+#endif
+       /*
+        * Give up privs we do not need anymore.
+        * We no longer need:
+        *      file_dac_read,proc_lock_memory,proc_priocntl,net_privaddr
+        * We still need:
+        *      sys_devices
+        */
+       priv_set(PRIV_OFF, PRIV_EFFECTIVE,
+               PRIV_FILE_DAC_READ, PRIV_PROC_LOCK_MEMORY,
+               PRIV_PROC_PRIOCNTL, PRIV_NET_PRIVADDR, NULL);
+       priv_set(PRIV_OFF, PRIV_PERMITTED,
+               PRIV_FILE_DAC_READ, PRIV_PROC_LOCK_MEMORY,
+               PRIV_PROC_PRIOCNTL, PRIV_NET_PRIVADDR, NULL);
+       priv_set(PRIV_OFF, PRIV_INHERITABLE,
+               PRIV_FILE_DAC_READ, PRIV_PROC_LOCK_MEMORY,
+               PRIV_PROC_PRIOCNTL, PRIV_NET_PRIVADDR, PRIV_SYS_DEVICES, NULL);
+#endif
+       /*
+        * This is only for OS that do not support fine grained privs.
+        *
+        * XXX Below this point we do not need root privilleges anymore.
+        */
+       if (geteuid() != getuid()) {    /* AIX does not like to do this */
+                                       /* If we are not root           */
+#ifdef HAVE_SETREUID
+               if (setreuid(-1, getuid()) < 0)
+#else
+#ifdef HAVE_SETEUID
+               if (seteuid(getuid()) < 0)
+#else
+               if (setuid(getuid()) < 0)
+#endif
+#endif
+                       comerr("Panic cannot set back effective uid.\n");
+       }
+
+#ifdef __linux__
+       /* get the rawio capability */
+       if (get_cap(CAP_SYS_RAWIO) && (debug || lverbose>2)) 
+       {
+               perror("Warning: Cannot gain SYS_RAWIO capability");
+               fprintf(stderr, "Possible reason: wodim not installed SUID root.\n");
+       }
+#endif
+
+       /*
+        * WARNING: We now are no more able to do any privilleged operation
+        * unless we have been called by root.
+        *
+        * XXX It may be that we later get problems in init_faio() because
+        * XXX this function calls raisepri() to lower the priority slightly.
+        */
+       usal_settimeout(usalp, timeout);
+       usalp->verbose = scsi_verbose;
+       usalp->silent = silent;
+       usalp->debug = debug;
+       usalp->kdebug = kdebug;
+       usalp->cap->c_bsize = DATA_SEC_SIZE;
+
+       if ((flags & F_MSINFO) == 0 || lverbose) {
+               char    *vers;
+               char    *auth;
+
+
+               if(lverbose)
+                       fprintf(stderr, "Wodim version: " CDRKIT_VERSION "\n");
+
+               vers = usal_version(0, SCG_VERSION);
+               auth = usal_version(0, SCG_AUTHOR);
+               if(lverbose >1 && auth && vers)
+                       fprintf(stderr, "Using libusal version '%s-%s'.\n", auth, vers);
+
+
+               vers = usal_version(usalp, SCG_RVERSION);
+               auth = usal_version(usalp, SCG_RAUTHOR);
+               if (lverbose > 1 && vers && auth)
+                       fprintf(stderr, "Using remote transport code version '%s-%s'\n", auth, vers);
+       }
+
+       if (lverbose && driveropts)
+               printf("Driveropts: '%s'\n", driveropts);
+
+/*     bufsize = usal_bufsize(usalp, CDR_BUF_SIZE);*/
+       bufsize = usal_bufsize(usalp, bufsize);
+       if (lverbose || debug)
+               fprintf(stderr, "SCSI buffer size: %ld\n", bufsize);
+       if ((buf = usal_getbuf(usalp, bufsize)) == NULL)
+               comerr("Cannot get SCSI I/O buffer.\n");
+
+       if (scandevs)
+               return (list_devices(usalp, stdout, 0));
+
+       if ((flags & F_SCANBUS) != 0) {
+               select_target(usalp, stdout);
+               exit(0);
+       }
+       if ((flags & F_RESET) != 0) {
+               if (usal_reset(usalp, SCG_RESET_NOP) < 0)
+                       comerr("Cannot reset (OS does not implement reset).\n");
+               if (usal_reset(usalp, SCG_RESET_TGT) >= 0)
+                       exit(0);
+               if (usal_reset(usalp, SCG_RESET_BUS) < 0)
+                       comerr("Cannot reset target.\n");
+               exit(0);
+       }
+
+       /*
+        * First try to check which type of SCSI device we
+        * have.
+       if (debug || lverbose)
+               printf("atapi: %d\n", usal_isatapi(usalp));
+        */
+       usalp->silent++;
+       test_unit_ready(usalp); /* eat up unit attention */
+       usalp->silent--;
+       if (!do_inquiry(usalp, (flags & F_MSINFO) == 0 || lverbose)) {
+               errmsgno(EX_BAD, "Cannot do inquiry for CD/DVD-Recorder.\n");
+               if (unit_ready(usalp))
+                       errmsgno(EX_BAD, "The unit seems to be hung and needs power cycling.\n");
+               exit(EX_BAD);
+       }
+#ifdef GCONF
+       /*
+        * Debug only
+        */
+       {
+               extern  void    gconf(SCSI *);
+
+               if (lverbose > 2)
+                       gconf(usalp);
+       }
+#endif
+
+       if ((flags & F_PRCAP) != 0) {
+               print_capabilities(usalp);
+               print_capabilities_mmc4(usalp);
+               exit(0);
+       }
+       if ((flags & F_INQUIRY) != 0)
+               exit(0);
+
+       if (dp == (cdr_t *)NULL) {      /* No driver= option specified  */
+               dp = get_cdrcmds(usalp);        /* Calls dp->cdr_identify()     */
+       }
+       else if (!is_unknown_dev(usalp) && dp != get_cdrcmds(usalp)) {
+               errmsgno(EX_BAD, "WARNING: Trying to use other driver on known device.\n");
+       }
+        is_mmc(usalp, &is_cdwr, &is_dvdwr);
+       if (ispacket) {
+               if (is_dvdwr) {
+                       track[0].flags |= TI_PACKET; 
+                       /*XXX put here to only affect DVD writing, should be in gargs.
+                        * however if set in args for all mode, packet writing is then
+                        * broken for all disc as cdrecord assume that PACKET imply TAO which  
+                        * is not true at all???? */ 
+                       track[0].flags &= ~TI_TAO;
+               }
+       }
+
+       if (dp == (cdr_t *)0)
+               comerrno(EX_BAD, "Sorry, no supported CD/DVD-Recorder found on this target.\n");
+
+       /* DVD does not support TAO */
+       if (dp->is_dvd) {
+         if(lverbose>1)
+               fprintf(stderr, "Using Session At Once (SAO) for DVD mode.\n");
+         dp->cdr_flags |= F_SAO;
+         for (i = 0; i <= MAX_TRACK; i++) {
+               track[i].flags &= ~TI_TAO;
+               track[i].flags |= TI_SAO;
+         }
+       }
+
+       if (!is_cddrive(usalp))
+               comerrno(EX_BAD, "Sorry, no CD/DVD-Drive found on this target.\n");
+       /*
+        * The driver is known, set up data structures...
+        */
+       {
+               cdr_t   *ndp;
+               dstat_t *dsp;
+
+               ndp = malloc(sizeof (cdr_t));
+               dsp = malloc(sizeof (dstat_t));
+               if (ndp == NULL || dsp == NULL)
+                       comerr("Cannot allocate memory for driver structure.\n");
+               movebytes(dp, ndp, sizeof (cdr_t));
+               dp = ndp;
+               dp->cdr_flags |= CDR_ALLOC;
+               dp->cdr_cmdflags = flags;
+
+               fillbytes(dsp, sizeof (*dsp), '\0');
+               dsp->ds_minbuf = 0xFFFF;
+               dp->cdr_dstat = dsp;
+       }
+
+       if ((flags & (F_MSINFO|F_TOC|F_LOAD|F_DLCK|F_EJECT)) == 0 ||
+                       tracks > 0 ||
+                       cuefilename != NULL)
+       {
+               if ((dp->cdr_flags & CDR_ISREADER) != 0) {
+                       errmsgno(EX_BAD,
+                                       "Sorry, no CD/DVD-Recorder or unsupported CD/DVD-Recorder found on this target.\n");
+               }
+
+               if (!is_mmc(usalp, &is_cdwr, &is_dvdwr))
+                       is_cdwr = TRUE;                 /* If it is not MMC, it must be a CD writer */
+
+               if (is_dvdwr && !set_cdrcmds("mmc_mdvd", (cdr_t **)NULL)) {
+                       errmsgno(EX_BAD,
+                                       "Internal error, DVD driver failure. Please report to debburn-devel@lists.alioth.debian.org.\n");
+               }
+               /*
+                * Only exit if this is not the ProDVD test binary.
+                */
+               if (!is_cdwr)
+                       exit(EX_BAD);
+       }
+
+       /*
+        * Set up data structures for current drive state.
+        */
+       if ((*dp->cdr_attach)(usalp, dp) != 0)
+               comerrno(EX_BAD, "Cannot attach driver for CD/DVD-Recorder.\n");
+
+       if (lverbose > 1) {
+               printf("Drive current speed: %d\n", dp->cdr_dstat->ds_dr_cur_wspeed);
+               printf("Drive default speed: %d\n", dp->cdr_speeddef);
+               printf("Drive max speed    : %d\n", dp->cdr_speedmax);
+       }
+       if (speed > (int)dp->cdr_speedmax && (flags & F_FORCE) == 0)
+               speed = dp->cdr_speedmax;
+       if (speed < 0)
+               speed = dp->cdr_speeddef;
+
+       if (lverbose > 1) {
+               printf("Selected speed     : %d\n", speed);
+       }
+       dp->cdr_dstat->ds_wspeed = speed; /* XXX Remove 'speed' in future */
+
+       exargs.usalp       = usalp;
+       exargs.dp          = dp;
+       exargs.old_secsize = -1;
+       exargs.flags       = flags;
+
+       if ((flags & F_MSINFO) == 0 || lverbose) {
+               printf("Using %s (%s).\n", dp->cdr_drtext, dp->cdr_drname);
+               print_drflags(dp);
+               print_wrmodes(dp);
+       }
+       usalp->silent++;
+       if ((debug || lverbose)) {
+               tsize = -1;
+               if ((*dp->cdr_buffer_cap)(usalp, &tsize, (long *)0) < 0 || tsize < 0) {
+                       if (read_buffer(usalp, buf, 4, 0) >= 0)
+                               tsize = a_to_u_4_byte(buf);
+               }
+               if (tsize > 0) {
+                       printf("Drive buf size : %lu = %lu KB\n",
+                                               tsize, tsize >> 10);
+               }
+       }
+       usalp->silent--;
+
+       dma_speed = get_dmaspeed(usalp, dp);
+
+       if ((debug || lverbose) && dma_speed > 0) {
+               /*
+                * We do not yet know what medium type is in...
+                */
+               printf("Drive DMA Speed: %d kB/s %dx CD %dx DVD\n",
+                       dma_speed, dma_speed/176, dma_speed/1385);
+       }
+       if ((tracks > 0 || cuefilename != NULL) && (debug || lverbose))
+               printf("FIFO size      : %lu = %lu KB\n", fs, fs >> 10);
+
+#ifdef HAVE_LIB_EDC_ECC
+       if ((flags & F_RAW) != 0 && (dp->cdr_dstat->ds_flags & DSF_DVD) == 0)
+               raw_speed = encspeed(debug || lverbose);
+#endif
+
+       if ((flags & F_CHECKDRIVE) != 0)
+               exit(0);
+
+       if ((flags & F_ABORT) != 0) {
+               /*
+                * flush cache is not supported by CD-ROMs avoid prob with -toc
+                */
+               usalp->silent++;
+               scsi_flush_cache(usalp, FALSE);
+               (*dp->cdr_abort_session)(usalp, dp);
+               usalp->silent--;
+               exit(0);
+       }
+
+       if (tracks == 0 && cuefilename == NULL &&
+           (flags & (F_FIX|F_BLANK)) == 0 && (flags & F_EJECT) != 0) {
+               /*
+                * Do not check if the unit is ready here to allow to open
+                * an empty unit too.
+                */
+               unload_media(usalp, dp, flags);
+               exit(0);
+       }
+       flush();
+
+       if (cuefilename) {
+               parsecue(cuefilename, track);
+               tracks = track[0].tracks;
+       } else {
+               opentracks(track);
+       }
+
+       if (tracks > 1)
+               sleep(2);       /* Let the user watch the inquiry messages */
+
+       if (tracks > 0 && !check_wrmode(dp, flags, track[1].flags))
+               comerrno(EX_BAD, "Illegal write mode for this drive.\n");
+
+       if ((track[0].flags & TI_TEXT) == 0 &&  /* CD-Text not yet processed */
+           (track[MAX_TRACK+1].flags & TI_TEXT) != 0) {
+               /*
+                * CD-Text from textfile= or from CUE CDTEXTFILE will win
+                * over CD-Text from *.inf files and over CD-Text from
+                * CUE SONGWRITER, ...
+                */
+               packtext(tracks, track);
+               track[0].flags |= TI_TEXT;
+       }
+#ifdef CLONE_WRITE
+       if (flags & F_CLONE) {
+               clone_toc(track);
+               clone_tracktype(track);
+       }
+#endif
+       setleadinout(tracks, track);
+       set_trsizes(dp, tracks, track);
+       setpregaps(tracks, track);
+       checkfiles(tracks, track);
+       tsize = checktsize(tracks, track);
+
+       /*
+        * Make wm2name[wrmode] work.
+        * This must be done after the track flags have been set up
+        * by the functions above.
+        */
+       if (tracks == 0 && (flags & F_BLANK) != 0)
+               dp->cdr_dstat->ds_wrmode = WM_BLANK;
+       else if (tracks == 0 && (flags & F_FORMAT) != 0)
+               dp->cdr_dstat->ds_wrmode = WM_FORMAT;
+       else
+               set_wrmode(dp, flags, track[1].flags);
+
+       /*
+        * Debug only
+        */
+       {
+               void    *cp = NULL;
+
+               (*dp->cdr_gen_cue)(track, &cp, FALSE);
+               if (cp)
+                       free(cp);
+       }
+
+       /*
+        * Create Lead-in data. Only needed in RAW mode.
+        */
+       do_leadin(track);
+
+
+       /*
+        * Install exit handler before we change the drive status.
+        */
+       on_comerr(exscsi, &exargs);
+
+       if ((flags & F_FORCE) == 0)
+               load_media(usalp, dp, TRUE);
+
+       if ((flags & (F_LOAD|F_DLCK)) != 0) {
+               if ((flags & F_DLCK) == 0) {
+                       usalp->silent++;                /* silently             */
+                       scsi_prevent_removal(
+                               usalp, 0);      /* allow manual open    */
+                       usalp->silent--;                /* if load failed...    */
+               }
+               exit(0);                        /* we did not change status */
+       }
+       exargs.old_secsize = sense_secsize(usalp, 1);
+       if (exargs.old_secsize < 0)
+               exargs.old_secsize = sense_secsize(usalp, 0);
+       if (debug)
+               printf("Current Secsize: %d\n", exargs.old_secsize);
+       usalp->silent++;
+       if (read_capacity(usalp) < 0) {
+               if (exargs.old_secsize > 0)
+                       usalp->cap->c_bsize = exargs.old_secsize;
+       }
+       usalp->silent--;
+       if (exargs.old_secsize < 0)
+               exargs.old_secsize = usalp->cap->c_bsize;
+       if (exargs.old_secsize != usalp->cap->c_bsize)
+               errmsgno(EX_BAD, "Warning: blockdesc secsize %d differs from cap secsize %d\n",
+                               exargs.old_secsize, usalp->cap->c_bsize);
+
+       if (lverbose)
+               printf("Current Secsize: %d\n", exargs.old_secsize);
+
+       if (exargs.old_secsize > 0 && exargs.old_secsize != DATA_SEC_SIZE) {
+               /*
+                * Some drives (e.g. Plextor) don't like to write correctly
+                * in SAO mode if the sector size is set to 512 bytes.
+                * In addition, wodim -msinfo will not work properly
+                * if the sector size is not 2048 bytes.
+                */
+               set_secsize(usalp, DATA_SEC_SIZE);
+       }
+
+       /*
+        * Is this the right place to do this ?
+        */
+       check_recovery(usalp, dp, flags);
+
+/*audioread(dp, flags);*/
+/*unload_media(usalp, dp, flags);*/
+/*return 0;*/
+       if (flags & F_WRITE)
+               dp->cdr_dstat->ds_cdrflags |= RF_WRITE;
+       if (flags & F_BLANK)
+               dp->cdr_dstat->ds_cdrflags |= RF_BLANK;
+       if (flags & F_PRATIP || lverbose > 0) {
+               dp->cdr_dstat->ds_cdrflags |= RF_PRATIP;
+       }
+       if (flags & F_IMMED || dminbuf > 0) {
+               if (dminbuf <= 0)
+                       dminbuf = 50;
+               if (lverbose <= 0)      /* XXX Hack needed for now */
+                       lverbose++;
+               dp->cdr_dstat->ds_cdrflags |= RF_WR_WAIT;
+       }
+       if ((*dp->cdr_getdisktype)(usalp, dp) < 0) {
+               errmsgno(EX_BAD, "Cannot get disk type.\n");
+               if ((flags & F_FORCE) == 0)
+                       comexit(EX_BAD);
+       }
+       if (flags & F_PRATIP) {
+               comexit(0);
+       }
+       /*
+        * The next actions should depend on the disk type.
+        */
+       if (dma_speed > 0) {
+               if ((dp->cdr_dstat->ds_flags & DSF_DVD) == 0)
+                       dma_speed /= 176;
+               else
+                       dma_speed /= 1385;
+       }
+
+       /*
+        * Init drive to default modes:
+        *
+        * We set TAO unconditionally to make checkdsize() work
+        * currectly in SAO mode too.
+        *
+        * At least MMC drives will not return the next writable
+        * address we expect when the drive's write mode is set
+        * to SAO. We need this address for mkisofs and thus
+        * it must be the first user accessible sector and not the
+        * first sector of the pregap.
+        *
+        * XXX The ACER drive:
+        * XXX Vendor_info    : 'ATAPI   '
+        * XXX Identifikation : 'CD-R/RW 8X4X32  '
+        * XXX Revision       : '5.EW'
+        * XXX Will not return from -dummy to non-dummy without
+        * XXX opening the tray.
+        */
+       usalp->silent++;
+       if ((*dp->cdr_init)(usalp, dp) < 0)
+               comerrno(EX_BAD, "Cannot init drive.\n");
+       usalp->silent--;
+
+       if (flags & F_SETDROPTS) {
+               /*
+                * Note that the set speed function also contains
+                * drive option processing for speed related drive options.
+                */
+               if ((*dp->cdr_opt1)(usalp, dp) < 0) {
+                       errmsgno(EX_BAD, "Cannot set up 1st set of driver options.\n");
+               }
+               if ((*dp->cdr_set_speed_dummy)(usalp, dp, &speed) < 0) {
+                       errmsgno(EX_BAD, "Cannot set speed/dummy.\n");
+               }
+               dp->cdr_dstat->ds_wspeed = speed; /* XXX Remove 'speed' in future */
+               if ((*dp->cdr_opt2)(usalp, dp) < 0) {
+                       errmsgno(EX_BAD, "Cannot set up 2nd set of driver options.\n");
+               }
+               comexit(0);
+       }
+       /*
+        * XXX If dp->cdr_opt1() ever affects the result for
+        * XXX the multi session info we would need to move it here.
+        */
+       if (flags & F_MSINFO) {
+               print_msinfo(usalp, dp);
+               comexit(0);
+       }
+       if (flags & F_TOC) {
+               print_toc(usalp, dp);
+               comexit(0);
+       }
+#ifdef XXX
+       if ((*dp->cdr_check_session)() < 0) {
+               comexit(EX_BAD);
+       }
+#endif
+       {
+               Int32_t omb = dp->cdr_dstat->ds_maxblocks;
+
+               if ((*dp->cdr_opt1)(usalp, dp) < 0) {
+                       errmsgno(EX_BAD, "Cannot set up 1st set of driver options.\n");
+               }
+               if (tsize > 0 && omb != dp->cdr_dstat->ds_maxblocks) {
+                       printf("Disk size changed by user options.\n");
+                       printf("Checking disk capacity according to new values.\n");
+               }
+       }
+       if (tsize == 0) {
+               if (tracks > 0) {
+                       errmsgno(EX_BAD,
+                       "WARNING: Total disk size unknown. Data may not fit on disk.\n");
+               }
+       } else if (tracks > 0) {
+               /*
+                * XXX How do we let the user check the remaining
+                * XXX disk size witout starting the write process?
+                */
+               if (!checkdsize(usalp, dp, tsize, flags))
+                       comexit(EX_BAD);
+       }
+       if (tracks > 0 && fs > 0l) {
+#if defined(USE_POSIX_PRIORITY_SCHEDULING) && defined(HAVE_SETREUID)
+               /*
+                * Hack to work around the POSIX design bug in real time
+                * priority handling: we need to be root even to lower
+                * our priority.
+                * Note that we need to find a more general way that works
+                * even on OS that do not support getreuid() which is *BSD
+                * and SUSv3 only.
+                */
+               if (oeuid != getuid()) {
+                       if (setreuid(-1, oeuid) < 0)
+                               errmsg("Could set back effective uid.\n");
+               }
+
+#endif
+               /*
+                * fork() here to start the extra process needed for
+                * improved buffering.
+                */
+               if (!init_faio(track, bufsize))
+                       fs = 0L;
+               else
+                       on_comerr(excdr, &exargs);
+
+    atexit(fifo_cleanup);
+
+#if defined(USE_POSIX_PRIORITY_SCHEDULING) && defined(HAVE_SETREUID)
+               /*
+                * XXX Below this point we never need root privilleges anymore.
+                */
+               if (geteuid() != getuid()) {    /* AIX does not like to do this */
+                                               /* If we are not root           */
+                       if (setreuid(-1, getuid()) < 0)
+                               comerr("Panic cannot set back effective uid.\n");
+               }
+#ifdef __linux__
+               if (get_cap(CAP_SYS_RAWIO) && (debug || lverbose>2))
+                       perror("Error: Cannot gain SYS_RAWIO capability, is wodim installed SUID root? Reason");
+#endif
+
+#endif
+       }
+
+       if ((*dp->cdr_set_speed_dummy)(usalp, dp, &speed) < 0) {
+               errmsgno(EX_BAD, "Cannot set speed/dummy.\n");
+               if ((flags & F_FORCE) == 0)
+                       comexit(EX_BAD);
+       }
+       dp->cdr_dstat->ds_wspeed = speed; /* XXX Remove 'speed' in future */
+       if ((flags & F_WRITE) != 0 && raw_speed >= 0) {
+               int     max_raw = (flags & F_FORCE) != 0 ? raw_speed:raw_speed/2;
+
+               if (getenv("CDR_FORCERAWSPEED"))
+                       max_raw = raw_speed;
+
+               for (i = 1; i <= MAX_TRACK; i++) {
+                       /*
+                        * Check for Clone tracks
+                        */
+                       if ((track[i].sectype & ST_MODE_RAW) != 0)
+                               continue;
+                       /*
+                        * Check for non-data tracks
+                        */
+                       if ((track[i].sectype & ST_MODE_MASK) == ST_MODE_AUDIO)
+                               continue;
+
+                       if (speed > max_raw) {
+                               errmsgno(EX_BAD,
+                               "Processor too slow. Cannot write RAW data at speed %d.\n",
+                               speed);
+                               comerrno(EX_BAD, "Max RAW data speed on this processor is %d.\n",
+                               max_raw);
+                       }
+                       break;
+               }
+       }
+       if (tracks > 0 && (flags & F_WRITE) != 0 && dma_speed > 0) {
+               int max_dma = (dma_speed+1)*4/5; /* use an empirical formula to estimate available bandwith */
+
+        if((flags & F_FORCE) != 0 || getenv("CDR_FORCESPEED"))
+                       max_dma = dma_speed;
+
+               if (speed > max_dma) {
+                       errmsgno(EX_BAD,
+                       "DMA speed too slow (OK for %dx). Cannot write at speed %dx.\n",
+                                       max_dma, speed);
+                       if ((dp->cdr_dstat->ds_cdrflags & RF_BURNFREE) == 0) {
+                               errmsgno(EX_BAD, "Max DMA data speed is %d.\n", max_dma);
+                               comerrno(EX_BAD, "Try to use 'driveropts=burnfree'.\n");
+                       }
+               }
+       }
+       if ((flags & (F_WRITE|F_BLANK)) != 0 &&
+                               (dp->cdr_dstat->ds_flags & DSF_ERA) != 0) {
+               if (xdebug) {
+                       printf("Current speed %d, medium low speed: %d medium high speed: %d\n",
+                               speed,
+                               dp->cdr_dstat->ds_at_min_speed,
+                               dp->cdr_dstat->ds_at_max_speed);
+               }
+               if (dp->cdr_dstat->ds_at_max_speed > 0 &&
+                               speed <= 8 &&
+                               speed > (int)dp->cdr_dstat->ds_at_max_speed) {
+                       /*
+                        * Be careful here: 10x media may be written faster.
+                        * The current code will work as long as there is no
+                        * writer that can only write faster than 8x
+                        */
+                       if ((flags & F_FORCE) == 0) {
+                               errmsgno(EX_BAD,
+                               "Write speed %d of medium not sufficient for this writer.\n",
+                                       dp->cdr_dstat->ds_at_max_speed);
+                               comerrno(EX_BAD,
+                               "You may have used an ultra low speed medium on a high speed writer.\n");
+                       }
+               }
+
+               if ((dp->cdr_dstat->ds_flags & DSF_ULTRASPP_ERA) != 0 &&
+                   (speed < 16 || (dp->cdr_cdrw_support & CDR_CDRW_ULTRAP) == 0)) {
+                       if ((dp->cdr_cdrw_support & CDR_CDRW_ULTRAP) == 0) {
+                               comerrno(EX_BAD,
+                               "Trying to use ultra high speed+ medium on a writer which is not\ncompatible with ultra high speed+ media.\n");
+                       } else if ((flags & F_FORCE) == 0) {
+                               comerrno(EX_BAD,
+                               "Probably trying to use ultra high speed+ medium on improper writer.\n");
+                       }
+               } else if ((dp->cdr_dstat->ds_flags & DSF_ULTRASP_ERA) != 0 &&
+                   (speed < 16 || (dp->cdr_cdrw_support & CDR_CDRW_ULTRA) == 0)) {
+                       if ((dp->cdr_cdrw_support & CDR_CDRW_ULTRA) == 0) {
+                               comerrno(EX_BAD,
+                               "Trying to use ultra high speed medium on a writer which is not\ncompatible with ultra high speed media.\n");
+                       } else if ((flags & F_FORCE) == 0) {
+                               comerrno(EX_BAD,
+                               "Probably trying to use ultra high speed medium on improper writer.\n");
+                       }
+               }
+               if (dp->cdr_dstat->ds_at_min_speed >= 4 &&
+                               dp->cdr_dstat->ds_at_max_speed > 4 &&
+                               dp->cdr_dstat->ds_dr_max_wspeed <= 4) {
+                       if ((flags & F_FORCE) == 0) {
+                               comerrno(EX_BAD,
+                               "Trying to use high speed medium on low speed writer.\n");
+                       }
+               }
+               if ((int)dp->cdr_dstat->ds_at_min_speed > speed) {
+                       if ((flags & F_FORCE) == 0) {
+                               errmsgno(EX_BAD,
+                               "Write speed %d of writer not sufficient for this medium.\n",
+                                       speed);
+                               errmsgno(EX_BAD,
+                               "You did use a %s speed medium on an improper writer or\n",
+                               dp->cdr_dstat->ds_flags & DSF_ULTRASP_ERA ?
+                               "ultra high": "high");
+                               comerrno(EX_BAD,
+                               "you used a speed=# option with a speed too low for this medium.\n");
+                       }
+               }
+       }
+       if ((flags & (F_BLANK|F_FORCE)) == (F_BLANK|F_FORCE)) {
+               printf("Waiting for drive to calm down.\n");
+               wait_unit_ready(usalp, 120);
+               if (gracewait(dp, &gracedone) < 0) {
+                       /*
+                        * In case kill() did not work ;-)
+                        */
+                       errs++;
+                       goto restore_it;
+               }
+               scsi_blank(usalp, 0L, blanktype, FALSE);
+       }
+
+       /*
+        * Last chance to quit!
+        */
+       if (gracewait(dp, &gracedone) < 0) {
+               /*
+                * In case kill() did not work ;-)
+                */
+               errs++;
+               goto restore_it;
+       }
+       
+       if (dp->profile == 0x2B && flags & F_SAO && tsize > 0) {
+           printf("Preparing middle zone location for this DVD+R dual layer disc\n");
+           if (!dp->cdr_layer_split(usalp, dp, tsize)) {
+               errmsgno(EX_BAD, "Cannot send structure for middle zone location.\n");
+               comexit(EX_BAD);
+           }
+       }
+
+       if (tracks > 0 && fs > 0l) {
+               /*
+                * Wait for the read-buffer to become full.
+                * This should be take no extra time if the input is a file.
+                * If the input is a pipe (e.g. mkisofs) this can take a
+                * while. If mkisofs dumps core before it starts writing,
+                * we abort before the writing process started.
+                */
+               if (!await_faio()) {
+                       comerrno(EX_BAD, "Input buffer error, aborting.\n");
+               }
+       }
+       wait_unit_ready(usalp, 120);
+
+       starttime.tv_sec = 0;
+       wstarttime.tv_sec = 0;
+       stoptime.tv_sec = 0;
+       fixtime.tv_sec = 0;
+       if (gettimeofday(&starttime, (struct timezone *)0) < 0)
+               errmsg("Cannot get start time\n");
+
+       /*
+        * Blank the media if we were requested to do so
+        */
+       if (flags & F_BLANK) {
+               /*
+                * Do not abort if OPC failes. Just give it a chance
+                * for better laser power calibration than without OPC.
+                *
+                * Ricoh drives return with a vendor unique sense code.
+                * This is most likely because they refuse to do OPC
+                * on a non blank media.
+                */
+               usalp->silent++;
+               do_opc(usalp, dp, flags);
+               usalp->silent--;
+               wait_unit_ready(usalp, 120);
+               if (gettimeofday(&starttime, (struct timezone *)0) < 0)
+                       errmsg("Cannot get start time\n");
+
+               if ((*dp->cdr_blank)(usalp, dp, 0L, blanktype) < 0) {
+                       errmsgno(EX_BAD, "Cannot blank disk, aborting.\n");
+                       if (blanktype != BLANK_DISC) {
+                               errmsgno(EX_BAD, "Some drives do not support all blank types.\n");
+                               errmsgno(EX_BAD, "Try again with wodim blank=all.\n");
+                       }
+                       comexit(EX_BAD);
+               }
+               if (gettimeofday(&fixtime, (struct timezone *)0) < 0)
+                       errmsg("Cannot get blank time\n");
+               if (lverbose)
+                       prtimediff("Blanking time: ", &starttime, &fixtime);
+
+               /*
+                * XXX Erst blank und dann format?
+                * XXX Wenn ja, dann hier (flags & F_FORMAT) testen
+                *
+                * EB: nee, besser nicht
+                */
+               if (!wait_unit_ready(usalp, 240) || tracks == 0) {
+                       comexit(0);
+               }
+       }
+       if (flags & F_FORMAT) {
+               printf("wodim: media format asked\n");
+               /*
+               * Do not abort if OPC failes. Just give it a chance
+               * for better laser power calibration than without OPC.
+               *
+               * Ricoh drives return with a vendor unique sense code.
+               * This is most likely because they refuse to do OPC
+               * on a non blank media.
+               */
+               usalp->silent++;
+               do_opc(usalp, dp, flags);
+               usalp->silent--;
+               wait_unit_ready(usalp, 120);
+               if (gettimeofday(&starttime, (struct timezone *)0) < 0)
+                       errmsg("Cannot get start time\n");
+
+               if ((*dp->cdr_format)(usalp, dp, formattype) < 0) {
+                       errmsgno(EX_BAD, "Cannot format disk, aborting.\n");
+                       comexit(EX_BAD);
+               }
+               if (gettimeofday(&fixtime, (struct timezone *)0) < 0)
+                       errmsg("Cannot get format time\n");
+               if (lverbose)
+                       prtimediff("Formatting time: ", &starttime, &fixtime);
+
+               if (!wait_unit_ready(usalp, 240) || tracks == 0) {
+                       comexit(0);
+               }
+               if (gettimeofday(&starttime, (struct timezone *)0) < 0)
+                       errmsg("Cannot get start time\n");
+       }
+       /*
+       * Reset start time so we will not see blanking time and
+       * writing time counted together.
+       */
+       if (gettimeofday(&starttime, (struct timezone *)0) < 0)
+               errmsg("Cannot get start time\n");
+       if (tracks == 0 && (flags & F_FIX) == 0)
+       comerrno(EX_BAD, "No tracks found.\n");
+       /*
+        * Get the number of the next recordable track by reading the TOC and
+        * use the number the last current track number.
+        */
+       usalp->silent++;
+       if (read_tochdr(usalp, dp, NULL, &trackno) < 0) {
+               trackno = 0;
+       }
+       usalp->silent--;
+      
+       /* If it is DVD, the information in TOC is fabricated :)
+          The real information is from read disk info command*/
+       if((dp->cdr_dstat->ds_disktype&DT_DVD) && (dp->cdr_dstat->ds_trlast>0)){
+               trackno=dp->cdr_dstat->ds_trlast-1;
+               if (lverbose > 2)
+                       printf("trackno=%d\n",trackno);
+       }
+
+       if ((tracks + trackno) > MAX_TRACK) {
+               /*
+                * XXX How many tracks are allowed on a DVD?
+                */
+               comerrno(EX_BAD, "Too many tracks for this disk, last track number is %d.\n",
+                               tracks + trackno);
+       }
+
+       for (i = 0; i <= tracks+1; i++) {       /* Lead-in ... Lead-out */
+               track[i].trackno = i + trackno; /* Set up real track #  */
+       }
+
+       if ((*dp->cdr_opt2)(usalp, dp) < 0) {
+               errmsgno(EX_BAD, "Cannot set up 2nd set of driver options.\n");
+       }
+
+       /*
+        * Now we actually start writing to the CD/DVD.
+        * XXX Check total size of the tracks and remaining size of disk.
+        */
+       if ((*dp->cdr_open_session)(usalp, dp, track) < 0) {
+               comerrno(EX_BAD, "Cannot open new session.\n");
+       }
+       if (!do_opc(usalp, dp, flags))
+               comexit(EX_BAD);
+
+       /*
+        * As long as open_session() will do nothing but
+        * set up parameters, we may leave fix_it here.
+        * I case we have to add an open_session() for a drive
+        * that wants to do something that modifies the disk
+        * We have to think about a new solution.
+        */
+       if (flags & F_FIX)
+               goto fix_it;
+
+       /*
+        * This call may modify trackp[i].trackstart for all tracks.
+        */
+       if ((*dp->cdr_write_leadin)(usalp, dp, track) < 0)
+               comerrno(EX_BAD, "Could not write Lead-in.\n");
+
+       if (lverbose && (dp->cdr_dstat->ds_cdrflags & RF_LEADIN) != 0) {
+
+               if (gettimeofday(&fixtime, (struct timezone *)0) < 0)
+                       errmsg("Cannot get lead-in write time\n");
+               prtimediff("Lead-in write time: ", &starttime, &fixtime);
+       }
+
+       if (gettimeofday(&wstarttime, (struct timezone *)0) < 0)
+               errmsg("Cannot get start time\n");
+       for (i = 1; i <= tracks; i++) {
+               startsec = 0L;
+
+               if ((*dp->cdr_open_track)(usalp, dp, &track[i]) < 0) {
+                       errmsgno(EX_BAD, "Cannot open next track.\n");
+                       errs++;
+                       break;
+               }
+
+               if ((flags & (F_SAO|F_RAW)) == 0) {
+                       if ((*dp->cdr_next_wr_address)(usalp, &track[i], &startsec) < 0) {
+                               errmsgno(EX_BAD, "Cannot get next writable address.\n");
+                               errs++;
+                               break;
+                       }
+                       track[i].trackstart = startsec;
+               }
+               if (debug || lverbose) {
+                       printf("Starting new track at sector: %ld\n",
+                                               track[i].trackstart);
+                       flush();
+               }
+               if (write_track_data(usalp, dp, &track[i]) < 0) {
+                       if (cdr_underrun(usalp)) {
+                               errmsgno(EX_BAD,
+                               "The current problem looks like a buffer underrun.\n");
+                               if ((dp->cdr_dstat->ds_cdrflags & RF_BURNFREE) == 0)
+                                       errmsgno(EX_BAD, "Try to use 'driveropts=burnfree'.\n");
+                               else {
+                                       errmsgno(EX_BAD, "It looks like 'driveropts=burnfree' does not work for this drive.\n");
+                                       errmsgno(EX_BAD, "Please report.\n");
+                               }
+
+                               errmsgno(EX_BAD,
+                               "Make sure that you are root, enable DMA and check your HW/OS set up.\n");
+                       } else {
+                               errmsgno(EX_BAD, "A write error occured.\n");
+                               errmsgno(EX_BAD, "Please properly read the error message above.\n");
+                       }
+                       errs++;
+                       sleep(5);
+                       unit_ready(usalp);
+                       (*dp->cdr_close_track)(usalp, dp, &track[i]);
+                       break;
+               }
+               if ((*dp->cdr_close_track)(usalp, dp, &track[i]) < 0) {
+                       /*
+                        * Check for "Dummy blocks added" message first.
+                        */
+                       if (usal_sense_key(usalp) != SC_ILLEGAL_REQUEST ||
+                                       usal_sense_code(usalp) != 0xB5) {
+                               errmsgno(EX_BAD, "Cannot close track.\n");
+                               errs++;
+                               break;
+                       }
+               }
+       }
+fix_it:
+       if (gettimeofday(&stoptime, (struct timezone *)0) < 0)
+               errmsg("Cannot get stop time\n");
+       cdrstats(dp);
+
+       if (flags & F_RAW) {
+               if (lverbose) {
+                       printf("Writing Leadout...\n");
+                       flush();
+               }
+               write_leadout(usalp, dp, track);
+       }
+       if ((flags & F_NOFIX) == 0) {
+               if (lverbose) {
+                       printf("Fixating...\n");
+                       flush();
+               }
+               if ((*dp->cdr_fixate)(usalp, dp, track) < 0) {
+                       /*
+                        * Ignore fixating errors in dummy mode.
+                        */
+                       if ((flags & F_DUMMY) == 0) {
+                               errmsgno(EX_BAD, "Cannot fixate disk.\n");
+                               errs++;
+                       }
+               }
+               if (gettimeofday(&fixtime, (struct timezone *)0) < 0)
+                       errmsg("Cannot get fix time\n");
+               if (lverbose)
+                       prtimediff("Fixating time: ", &stoptime, &fixtime);
+       }
+       if ((dp->cdr_dstat->ds_cdrflags & RF_DID_CDRSTAT) == 0) {
+               dp->cdr_dstat->ds_cdrflags |= RF_DID_CDRSTAT;
+               (*dp->cdr_stats)(usalp, dp);
+       }
+       if ((flags & (F_RAW|F_EJECT)) == F_RAW) {
+               /*
+                * Most drives seem to forget to reread the TOC from disk
+                * if they are in RAW mode.
+                */
+               usalp->silent++;
+               if (read_tochdr(usalp, dp, NULL, NULL) < 0) {
+                       usalp->silent--;
+                       if ((flags & F_DUMMY) == 0)
+                               reload_media(usalp, dp);
+               } else {
+                       usalp->silent--;
+               }
+       }
+
+restore_it:
+       /*
+        * Try to restore the old sector size and stop FIFO.
+        */
+       kill_faio();
+       comexit(errs?-2:0);
+       return (0);
+}
+
+static int 
+gracewait(cdr_t *dp, BOOL *didgracep)
+{
+       int     i;
+       BOOL    didgrace = FALSE;
+
+       if (didgracep)
+               didgrace = *didgracep;
+
+       if(warn_minisize>=0) {
+               fprintf(stderr,  "\nWARNING: found a microscopic small track size (%lld bytes).\n"
+                               "         Do you really want to write this image? Press Ctrl-C to abort...\n\n",
+                               warn_minisize);
+               gracetime+=20;
+       }
+       if (gracetime < MIN_GRACE_TIME)
+               gracetime = MIN_GRACE_TIME;
+       if (gracetime > 999)
+               gracetime = 999;
+
+       printf("Starting to write CD/DVD at speed %5.1f in %s%s %s mode for %s session.\n",
+         (float)dp->cdr_dstat->ds_wspeed,
+               (dp->cdr_cmdflags & F_DUMMY) ? "dummy" : "real",
+               (dp->cdr_cmdflags & F_FORCE) ? " force" : "",
+               wm2name[dp->cdr_dstat->ds_wrmode],
+               (dp->cdr_cmdflags & F_MULTI) ? "multi" : "single");
+       if (didgrace) {
+               printf("No chance to quit anymore.");
+               goto grace_done;
+       }
+       printf("Last chance to quit, starting %s write in %4d seconds.",
+               (dp->cdr_cmdflags & F_DUMMY)?"dummy":"real", gracetime);
+       flush();
+       signal(SIGINT, intr);
+       signal(SIGHUP, intr);
+       signal(SIGTERM, intr);
+
+       for (i = gracetime; --i >= 0; ) {
+               sleep(1);
+               if (didintr) {
+                       printf("\n");
+                       excdr(SIGINT, &exargs);
+                       signal(SIGINT, SIG_DFL);
+                       kill(getpid(), SIGINT);
+                       /*
+                        * In case kill() did not work ;-)
+                        */
+                       if (didgracep)
+                               *didgracep = FALSE;
+                       return (-1);
+               }
+               printf("\b\b\b\b\b\b\b\b\b\b\b\b\b%4d seconds.", i);
+               flush();
+       }
+grace_done:
+       printf(" Operation starts.");
+       flush();
+       signal(SIGINT, SIG_DFL);
+       signal(SIGHUP, SIG_DFL);
+       signal(SIGTERM, SIG_DFL);
+       signal(SIGINT, intfifo);
+       signal(SIGHUP, intfifo);
+       signal(SIGTERM, intfifo);
+       printf("\n");
+
+       if (didgracep)
+               *didgracep = TRUE;
+       return (0);
+}
+
+static void 
+cdrstats(cdr_t *dp)
+{
+       float   secsps = 75.0;
+       int     nsecs;
+       float   fspeed;
+       struct timeval  tcur;
+       struct timeval  tlast;
+       BOOL    nostop = FALSE;
+
+       if (starttime.tv_sec == 0)
+               return;
+
+       if (stoptime.tv_sec == 0) {
+               gettimeofday(&stoptime, (struct timezone *)0);
+               nostop = TRUE;
+       }
+
+       if ((dp->cdr_dstat->ds_cdrflags & RF_DID_STAT) != 0)
+               return;
+       dp->cdr_dstat->ds_cdrflags |= RF_DID_STAT;
+
+       if (lverbose == 0)
+               return;
+
+       if (dp->cdr_cmdflags & F_FIX)
+               return;
+
+       if ((dp->cdr_cmdflags & (F_WRITE|F_BLANK)) == F_BLANK)
+               return;
+
+       tlast = wstarttime;
+       tcur = stoptime;
+
+       prtimediff("Writing  time: ", &starttime, &stoptime);
+
+       nsecs = dp->cdr_dstat->ds_endsec - dp->cdr_dstat->ds_startsec;
+
+       if (dp->cdr_dstat->ds_flags & DSF_DVD)
+               secsps = 676.27;
+
+       tlast.tv_sec = tcur.tv_sec - tlast.tv_sec;
+       tlast.tv_usec = tcur.tv_usec - tlast.tv_usec;
+       while (tlast.tv_usec < 0) {
+               tlast.tv_usec += 1000000;
+               tlast.tv_sec -= 1;
+       }
+       if (!nostop && nsecs != 0 && dp->cdr_dstat->ds_endsec > 0) {
+               /*
+                * May not be known (e.g. cdrecord -)
+                *
+                * XXX if we later allow this code to know how much has
+                * XXX actually been written, then we may remove the
+                * XXX dependance from nostop & nsecs != 0
+                */
+               fspeed = (nsecs / secsps) /
+                       (tlast.tv_sec * 1.0 + tlast.tv_usec * 0.000001);
+               if (fspeed > 999.0)
+                       fspeed = 999.0;
+      if (dp->is_dvd) fspeed /= 9;
+               printf("Average write speed %5.1fx.\n", fspeed);
+       }
+
+       if (dp->cdr_dstat->ds_minbuf <= 100) {
+               printf("Min drive buffer fill was %u%%\n",
+                       (unsigned int)dp->cdr_dstat->ds_minbuf);
+       }
+       if (dp->cdr_dstat->ds_buflow > 0) {
+               printf("Total of %ld possible drive buffer underruns predicted.\n",
+                       (long)dp->cdr_dstat->ds_buflow);
+       }
+}
+
+/*
+ * Short usage
+ */
+static void
+susage(int ret)
+{
+       fprintf(stderr, "Usage: %s [options] track1...trackn\n", get_progname());
+       fprintf(stderr, "\nUse\t%s -help\n", get_progname());
+       fprintf(stderr, "to get a list of valid options.\n");
+       fprintf(stderr, "\nUse\t%s blank=help\n", get_progname());
+       fprintf(stderr, "to get a list of valid blanking options.\n");
+       fprintf(stderr, "\nUse\t%s dev=b,t,l driveropts=help -checkdrive\n", get_progname());
+       fprintf(stderr, "to get a list of drive specific options.\n");
+       fprintf(stderr, "\nUse\t%s dev=help\n", get_progname());
+       fprintf(stderr, "to get a list of possible SCSI transport specifiers.\n");
+       exit(ret);
+       /* NOTREACHED */
+}
+
+static void 
+usage(int excode)
+{
+       fprintf(stderr, "Usage: %s [options] track1...trackn\n", get_progname());
+       fprintf(stderr, "Options:\n");
+       fprintf(stderr, "\t-version     print version information and exit\n");
+       fprintf(stderr, "\tdev=target   SCSI target to use as CD/DVD-Recorder\n");
+       fprintf(stderr, "\tgracetime=#  set the grace time before starting to write to #.\n");
+       fprintf(stderr, "\ttimeout=#    set the default SCSI command timeout to #.\n");
+       fprintf(stderr, "\tdebug=#,-d   Set to # or increment misc debug level\n");
+       fprintf(stderr, "\tkdebug=#,kd=#        do Kernel debugging\n");
+       fprintf(stderr, "\t-verbose,-v  increment general verbose level by one\n");
+       fprintf(stderr, "\t-Verbose,-V  increment SCSI command transport verbose level by one\n");
+       fprintf(stderr, "\t-silent,-s   do not print status of failed SCSI commands\n");
+       fprintf(stderr, "\tdriver=name  user supplied driver name, use with extreme care\n");
+       fprintf(stderr, "\tdriveropts=opt       a comma separated list of driver specific options\n");
+       fprintf(stderr, "\t-setdropts   set driver specific options and exit\n");
+       fprintf(stderr, "\t-checkdrive  check if a driver for the drive is present\n");
+       fprintf(stderr, "\t-prcap               print drive capabilities for MMC compliant drives\n");
+       fprintf(stderr, "\t-inq         do an inquiry for the drive and exit\n");
+       fprintf(stderr, "\t-scanbus     scan the SCSI and IDE buses and exit\n");
+       fprintf(stderr, "\t-reset               reset the SCSI bus with the cdrecorder (if possible)\n");
+       fprintf(stderr, "\t-abort               send an abort sequence to the drive (may help if hung)\n");
+       fprintf(stderr, "\t-overburn    allow to write more than the official size of a medium\n");
+       fprintf(stderr, "\t-ignsize     ignore the known size of a medium (may cause problems)\n");
+       fprintf(stderr, "\t-useinfo     use *.inf files to overwrite audio options.\n");
+       fprintf(stderr, "\tspeed=#              set speed of drive\n");
+       fprintf(stderr, "\tblank=type   blank a CD-RW disc (see blank=help)\n");
+       fprintf(stderr, "\t-format              format a CD-RW/DVD-RW/DVD+RW disc\n");
+   fprintf(stderr, "\tformattype=#     select the format method for DVD+RW disc\n");
+#ifdef FIFO
+       fprintf(stderr, "\tfs=#         Set fifo size to # (0 to disable, default is %ld MB)\n",
+                                                       DEFAULT_FIFOSIZE/(1024L*1024L));
+#endif
+       fprintf(stderr, "\tts=#         set maximum transfer size for a single SCSI command\n");
+       fprintf(stderr, "\t-load                load the disk and exit (works only with tray loader)\n");
+       fprintf(stderr, "\t-lock                load and lock the disk and exit (works only with tray loader)\n");
+       fprintf(stderr, "\t-eject               eject the disk after doing the work\n");
+       fprintf(stderr, "\t-dummy               do everything with laser turned off\n");
+       fprintf(stderr, "\t-msinfo              retrieve multi-session info for genisoimage\n");
+       fprintf(stderr, "\t-msifile=path        run -msinfo and copy output to file\n");
+       fprintf(stderr, "\t-toc         retrieve and print TOC/PMA data\n");
+       fprintf(stderr, "\t-atip                retrieve and print ATIP data\n");
+       fprintf(stderr, "\t-multi               generate a TOC that allows multi session\n");
+       fprintf(stderr, "\t             In this case default track type is CD-ROM XA mode 2 form 1 - 2048 bytes\n");
+       fprintf(stderr, "\t-fix         fixate a corrupt or unfixated disk (generate a TOC)\n");
+       fprintf(stderr, "\t-nofix               do not fixate disk after writing tracks\n");
+       fprintf(stderr, "\t-waiti               wait until input is available before opening SCSI\n");
+       fprintf(stderr, "\t-immed               Try to use the SCSI IMMED flag with certain long lasting commands\n");
+       fprintf(stderr, "\t-force               force to continue on some errors to allow blanking bad disks\n");
+       fprintf(stderr, "\t-tao         Write disk in TAO mode.\n");
+       fprintf(stderr, "\t-dao         Write disk in SAO mode.\n");
+       fprintf(stderr, "\t-sao         Write disk in SAO mode.\n");
+       fprintf(stderr, "\t-raw         Write disk in RAW mode.\n");
+       fprintf(stderr, "\t-raw96r              Write disk in RAW/RAW96R mode.\n");
+       fprintf(stderr, "\t-raw96p              Write disk in RAW/RAW96P mode.\n");
+       fprintf(stderr, "\t-raw16               Write disk in RAW/RAW16 mode.\n");
+#ifdef CLONE_WRITE
+       fprintf(stderr, "\t-clone               Write disk in clone write mode.\n");
+#endif
+       fprintf(stderr, "\ttsize=#              Length of valid data in next track\n");
+       fprintf(stderr, "\tpadsize=#    Amount of padding for next track\n");
+       fprintf(stderr, "\tpregap=#     Amount of pre-gap sectors before next track\n");
+       fprintf(stderr, "\tdefpregap=#  Amount of pre-gap sectors for all but track #1\n");
+       fprintf(stderr, "\tmcn=text     Set the media catalog number for this CD to 'text'\n");
+       fprintf(stderr, "\tisrc=text    Set the ISRC number for the next track to 'text'\n");
+       fprintf(stderr, "\tindex=list   Set the index list for the next track to 'list'\n");
+       fprintf(stderr, "\t-text                Write CD-Text from information from *.inf or *.cue files\n");
+       fprintf(stderr, "\ttextfile=name        Set the file with CD-Text data to 'name'\n");
+       fprintf(stderr, "\tcuefile=name Set the file with CDRWIN CUE data to 'name'\n");
+
+       fprintf(stderr, "\t-audio               Subsequent tracks are CD-DA audio tracks\n");
+       fprintf(stderr, "\t-data                Subsequent tracks are CD-ROM data mode 1 - 2048 bytes (default)\n");
+       fprintf(stderr, "\t-mode2               Subsequent tracks are CD-ROM data mode 2 - 2336 bytes\n");
+       fprintf(stderr, "\t-xa          Subsequent tracks are CD-ROM XA mode 2 form 1 - 2048 bytes\n");
+       fprintf(stderr, "\t-xa1         Subsequent tracks are CD-ROM XA mode 2 form 1 - 2056 bytes\n");
+       fprintf(stderr, "\t-xa2         Subsequent tracks are CD-ROM XA mode 2 form 2 - 2324 bytes\n");
+       fprintf(stderr, "\t-xamix               Subsequent tracks are CD-ROM XA mode 2 form 1/2 - 2332 bytes\n");
+       fprintf(stderr, "\t-cdi         Subsequent tracks are CDI tracks\n");
+       fprintf(stderr, "\t-isosize     Use iso9660 file system size for next data track\n");
+       fprintf(stderr, "\t-preemp              Audio tracks are mastered with 50/15 microseconds preemphasis\n");
+       fprintf(stderr, "\t-nopreemp    Audio tracks are mastered with no preemphasis (default)\n");
+       fprintf(stderr, "\t-copy                Audio tracks have unlimited copy permission\n");
+       fprintf(stderr, "\t-nocopy              Audio tracks may only be copied once for personal use (default)\n");
+       fprintf(stderr, "\t-scms                Audio tracks will not have any copy permission at all\n");
+       fprintf(stderr, "\t-pad         Pad data tracks with %d zeroed sectors\n", PAD_SECS);
+       fprintf(stderr, "\t             Pad audio tracks to a multiple of %d bytes\n", AUDIO_SEC_SIZE);
+       fprintf(stderr, "\t-nopad               Do not pad data tracks (default)\n");
+       fprintf(stderr, "\t-shorttrack  Subsequent tracks may be non Red Book < 4 seconds if in SAO or RAW mode\n");
+       fprintf(stderr, "\t-noshorttrack        Subsequent tracks must be >= 4 seconds\n");
+       fprintf(stderr, "\t-swab                Audio data source is byte-swapped (little-endian/Intel)\n");
+       fprintf(stderr, "The type of the first track is used for the toc type.\n");
+       fprintf(stderr, "Currently only form 1 tracks are supported.\n");
+       exit(excode);
+}
+
+static void 
+blusage(int ret)
+{
+       fprintf(stderr, "Blanking options:\n");
+       fprintf(stderr, "\tall\t\tblank the entire disk\n");
+       fprintf(stderr, "\tdisc\t\tblank the entire disk\n");
+       fprintf(stderr, "\tdisk\t\tblank the entire disk\n");
+       fprintf(stderr, "\tfast\t\tminimally blank the entire disk (PMA, TOC, pregap)\n");
+       fprintf(stderr, "\tminimal\t\tminimally blank the entire disk (PMA, TOC, pregap)\n");
+       fprintf(stderr, "\ttrack\t\tblank a track\n");
+       fprintf(stderr, "\tunreserve\tunreserve a track\n");
+       fprintf(stderr, "\ttrtail\t\tblank a track tail\n");
+       fprintf(stderr, "\tunclose\t\tunclose last session\n");
+       fprintf(stderr, "\tsession\t\tblank last session\n");
+
+       exit(ret);
+       /* NOTREACHED */
+}
+
+static void 
+formattypeusage(int ret)
+{
+       fprintf(stderr, "Formating options:\n");
+       fprintf(stderr, "\tfull\t\tstandard formating\n");
+       fprintf(stderr, "\tbackground\t\tbackground formating\n");
+       fprintf(stderr, "\tforce\t\tforce reformat\n");
+
+       exit(ret);
+       /* NOTREACHED */
+}
+
+/* ARGSUSED */
+static void
+intr(int sig)
+{
+       sig = 0;        /* Fake usage for gcc */
+
+       signal(SIGINT, intr);
+
+       didintr++;
+}
+
+static void 
+catchsig(int sig)
+{
+       signal(sig, catchsig);
+}
+
+static int 
+scsi_cb(void *arg)
+{
+       comexit(EX_BAD);
+       /* NOTREACHED */
+       return (0);     /* Keep lint happy */
+}
+
+static void 
+intfifo(int sig)
+{
+       errmsgno(EX_BAD, "Caught interrupt.\n");
+       if (exargs.usalp) {
+               SCSI    *usalp = exargs.usalp;
+
+               if (usalp->running) {
+                       if (usalp->cb_fun != NULL) {
+                               comerrno(EX_BAD, "Second interrupt. Doing hard abort.\n");
+                               /* NOTREACHED */
+                       }
+                       usalp->cb_fun = scsi_cb;
+                       usalp->cb_arg = &exargs;
+                       return;
+               }
+       }
+       comexit(sig);
+}
+
+/* ARGSUSED */
+static void 
+exscsi(int excode, void *arg)
+{
+       struct exargs   *exp = (struct exargs *)arg;
+
+       /*
+        * Try to restore the old sector size.
+        */
+       if (exp != NULL && exp->exflags == 0) {
+               if (exp->usalp->running) {
+                       return;
+               }
+               /*
+                * flush cache is not supported by CD-ROMs avoid prob with -toc
+                */
+               exp->usalp->silent++;
+               scsi_flush_cache(exp->usalp, FALSE);
+               (*exp->dp->cdr_abort_session)(exp->usalp, exp->dp);
+               exp->usalp->silent--;
+               set_secsize(exp->usalp, exp->old_secsize);
+               unload_media(exp->usalp, exp->dp, exp->flags);
+
+               exp->exflags++; /* Make sure that it only get called once */
+       }
+}
+
+static void 
+excdr(int excode, void *arg)
+{
+       struct exargs   *exp = (struct exargs *)arg;
+
+       exscsi(excode, arg);
+
+       cdrstats(exp->dp);
+       if ((exp->dp->cdr_dstat->ds_cdrflags & RF_DID_CDRSTAT) == 0) {
+               exp->dp->cdr_dstat->ds_cdrflags |= RF_DID_CDRSTAT;
+               (*exp->dp->cdr_stats)(exp->usalp, exp->dp);
+       }
+
+#ifdef FIFO
+       kill_faio();
+       wait_faio();
+       if (debug || lverbose)
+               fifo_stats();
+#endif
+}
+
+int 
+read_buf(int f, char *bp, int size)
+{
+       char    *p = bp;
+       int     amount = 0;
+       int     n;
+
+       do {
+               do {
+                       n = read(f, p, size-amount);
+               } while (n < 0 && (geterrno() == EAGAIN || geterrno() == EINTR));
+               if (n < 0)
+                       return (n);
+               amount += n;
+               p += n;
+
+       } while (amount < size && n > 0);
+       return (amount);
+}
+
+int 
+fill_buf(int f, track_t *trackp, long secno, char *bp, int size)
+{
+       int     amount = 0;
+       int     nsecs;
+       int     rsize;
+       int     rmod;
+       int     readoffset = 0;
+
+       nsecs = size / trackp->secsize;
+       if (nsecs < trackp->secspt) {
+               /*
+                * Clear buffer to prepare for last transfer.
+                * Make sure that a partial sector ends with NULs
+                */
+               fillbytes(bp, trackp->secspt * trackp->secsize, '\0');
+       }
+
+       if (!is_raw(trackp)) {
+               amount = read_buf(f, bp, size);
+               if (amount != size) {
+                       if (amount < 0)
+                               return (amount);
+                       /*
+                        * We got less than expected, clear rest of buf.
+                        */
+                       fillbytes(&bp[amount], size-amount, '\0');
+               }
+               if (is_swab(trackp))
+                       swabbytes(bp, amount);
+               return (amount);
+       }
+
+       rsize = nsecs * trackp->isecsize;
+       rmod  = size % trackp->secsize;
+       if (rmod > 0) {
+               rsize += rmod;
+               nsecs++;
+       }
+
+       readoffset = trackp->dataoff;
+       amount = read_buf(f, bp + readoffset, rsize);
+       if (is_swab(trackp))
+               swabbytes(bp + readoffset, amount);
+
+       if (trackp->isecsize == 2448 && trackp->secsize == 2368)
+               subrecodesecs(trackp, (Uchar *)bp, secno, nsecs);
+
+       scatter_secs(trackp, bp + readoffset, nsecs);
+
+       if (amount != rsize) {
+               if (amount < 0)
+                       return (amount);
+               /*
+                * We got less than expected, clear rest of buf.
+                */
+               fillbytes(&bp[amount], rsize-amount, '\0');
+               nsecs = amount / trackp->isecsize;
+               rmod  = amount % trackp->isecsize;
+               amount = nsecs * trackp->secsize;
+               if (rmod > 0) {
+                       nsecs++;
+                       amount += rmod;
+               }
+       } else {
+               amount = size;
+       }
+       if ((trackp->sectype & ST_MODE_RAW) == 0) {
+               encsectors(trackp, (Uchar *)bp, secno, nsecs);
+               fillsubch(trackp, (Uchar *)bp, secno, nsecs);
+       } else {
+               scrsectors(trackp, (Uchar *)bp, secno, nsecs);
+       }
+       return (amount);
+}
+
+int 
+get_buf(int f, track_t *trackp, long secno, char **bpp, int size)
+{
+       if (fs > 0) {
+/*             return (faio_read_buf(f, *bpp, size));*/
+               return (faio_get_buf(f, bpp, size));
+       } else {
+               return (fill_buf(f, trackp, secno, *bpp, size));
+       }
+}
+
+int 
+write_secs(SCSI *usalp, cdr_t *dp, char *bp, long startsec, int bytespt, 
+                       int secspt, BOOL islast)
+{
+       int     amount;
+
+again:
+       usalp->silent++;
+       amount = (*dp->cdr_write_trackdata)(usalp, bp, startsec, bytespt, secspt, islast);
+       usalp->silent--;
+       if (amount < 0) {
+               if (scsi_in_progress(usalp)) {
+                       /*
+                        * If we sleep too long, the drive buffer is empty
+                        * before we start filling it again. The max. CD speed
+                        * is ~ 10 MB/s (52x RAW writing). The max. DVD speed
+                        * is ~ 25 MB/s (18x DVD 1385 kB/s).
+                        * With 10 MB/s, a 1 MB buffer empties within 100ms.
+                        * With 25 MB/s, a 1 MB buffer empties within 40ms.
+                        */
+                       if ((dp->cdr_dstat->ds_flags & DSF_DVD) == 0) {
+                               usleep(60000);
+                       } else {
+#ifndef        _SC_CLK_TCK
+                               usleep(20000);
+#else
+                               if (sysconf(_SC_CLK_TCK) < 100)
+                                       usleep(20000);
+                               else
+                                       usleep(10000);
+
+#endif
+                       }
+                       goto again;
+               }
+               return (-1);
+       }
+       return (amount);
+}
+
+static int 
+write_track_data(SCSI *usalp, cdr_t *dp, track_t *trackp)
+{
+       int     track = trackp->trackno;
+       int     f = -1;
+       int     isaudio;
+       long    startsec;
+       Llong   bytes_read = 0;
+       Llong   bytes   = 0;
+       Llong   savbytes = 0;
+       int     count;
+       Llong   tracksize;
+       int     secsize;
+       int     secspt;
+       int     bytespt;
+       int     bytes_to_read;
+       long    amount;
+       int     pad;
+       BOOL    neednl  = FALSE;
+       BOOL    islast  = FALSE;
+       char    *bp     = buf;
+       struct timeval tlast;
+       struct timeval tcur;
+       float   secsps = 75.0;
+long bsize;
+long bfree;
+#define        BCAP
+#ifdef BCAP
+int per = 0;
+#ifdef XBCAP
+int oper = -1;
+#endif
+#endif
+
+       if (dp->cdr_dstat->ds_flags & DSF_DVD)
+               secsps = 676.27;
+
+       usalp->silent++;
+       if ((*dp->cdr_buffer_cap)(usalp, &bsize, &bfree) < 0)
+               bsize = -1L;
+       if (bsize == 0)         /* If we have no (known) buffer, we cannot */
+               bsize = -1L;    /* retrieve the buffer fill ratio          */
+       usalp->silent--;
+
+
+       if (is_packet(trackp))  /* XXX Ugly hack for now */
+               return (write_packet_data(usalp, dp, trackp));
+
+       if (trackp->xfp != NULL)
+               f = xfileno(trackp->xfp);
+
+       isaudio = is_audio(trackp);
+       tracksize = trackp->tracksize;
+       startsec = trackp->trackstart;
+
+       secsize = trackp->secsize;
+       secspt = trackp->secspt;
+       bytespt = secsize * secspt;
+
+       pad = !isaudio && is_pad(trackp);       /* Pad only data tracks */
+
+       if (debug) {
+               printf("secsize:%d secspt:%d bytespt:%d audio:%d pad:%d\n",
+                       secsize, secspt, bytespt, isaudio, pad);
+       }
+
+       if (lverbose) {
+               if (tracksize > 0)
+                       printf("\rTrack %02d:    0 of %4lld MB written.",
+                               track, tracksize >> 20);
+               else
+                       printf("\rTrack %02d:    0 MB written.", track);
+               flush();
+               neednl = TRUE;
+       }
+
+       gettimeofday(&tlast, (struct timezone *)0);
+       do {
+               bytes_to_read = bytespt;
+               if (tracksize > 0) {
+                       if ((tracksize - bytes_read) > bytespt)
+                               bytes_to_read = bytespt;
+                       else
+                               bytes_to_read = tracksize - bytes_read;
+               }
+               count = get_buf(f, trackp, startsec, &bp, bytes_to_read);
+
+               if (count < 0)
+                       comerr("read error on input file\n");
+               if (count == 0)
+                       break;
+               bytes_read += count;
+               if (tracksize >= 0 && bytes_read >= tracksize) {
+                       count -= bytes_read - tracksize;
+                       /*
+                        * Paranoia: tracksize is known (trackp->tracksize >= 0)
+                        * At this point, trackp->padsize should alway be set
+                        * if the tracksize is less than 300 sectors.
+                        */
+                       if (trackp->padsecs == 0 &&
+                           (is_shorttrk(trackp) || (bytes_read/secsize) >= 300))
+                               islast = TRUE;
+               }
+
+               if (count < bytespt) {
+                       if (debug) {
+                               printf("\nNOTICE: reducing block size for last record.\n");
+                               neednl = FALSE;
+                       }
+
+                       if ((amount = count % secsize) != 0) {
+                               amount = secsize - amount;
+                               count += amount;
+                               printf("\nWARNING: padding up to secsize.\n");
+                               neednl = FALSE;
+                       }
+                       bytespt = count;
+                       secspt = count / secsize;
+                       /*
+                        * If tracksize is not known (trackp->tracksize < 0)
+                        * we may need to set trackp->padsize
+                        * if the tracksize is less than 300 sectors.
+                        */
+                       if (trackp->padsecs == 0 &&
+                           (is_shorttrk(trackp) || (bytes_read/secsize) >= 300))
+                               islast = TRUE;
+               }
+
+               amount = write_secs(usalp, dp, bp, startsec, bytespt, secspt, islast);
+               if (amount < 0) {
+                       printf("%swrite track data: error after %lld bytes\n",
+                                                       neednl?"\n":"", bytes);
+                       return (-1);
+               }
+               bytes += amount;
+               startsec += amount / secsize;
+
+               if (lverbose && (bytes >= (savbytes + 0x100000))) {
+                       int     fper;
+                       int     nsecs = (bytes - savbytes) / secsize;
+                       float   fspeed;
+
+                       gettimeofday(&tcur, (struct timezone *)0);
+                       printf("\rTrack %02d: %4lld", track, bytes >> 20);
+                       if (tracksize > 0)
+                               printf(" of %4lld MB", tracksize >> 20);
+                       else
+                               printf(" MB");
+                       printf(" written");
+                       fper = fifo_percent(TRUE);
+                       if (fper >= 0)
+                               printf(" (fifo %3d%%)", fper);
+#ifdef BCAP
+                       if (bsize > 0) {                        /* buffer size known */
+                               usalp->silent++;
+                               per = (*dp->cdr_buffer_cap)(usalp, (long *)0, &bfree);
+                               usalp->silent--;
+                               if (per >= 0) {
+                                       per = 100*(bsize - bfree) / bsize;
+                                       if ((bsize - bfree) <= amount || per <= 5)
+                                               dp->cdr_dstat->ds_buflow++;
+                                       if (per < (int)dp->cdr_dstat->ds_minbuf &&
+                                           (startsec*secsize) > bsize) {
+                                               dp->cdr_dstat->ds_minbuf = per;
+                                       }
+                                       printf(" [buf %3d%%]", per);
+#ifdef BCAPDBG
+                                       printf(" %3ld %3ld", bsize >> 10, bfree >> 10);
+#endif
+                               }
+                       }
+#endif
+
+                       tlast.tv_sec = tcur.tv_sec - tlast.tv_sec;
+                       tlast.tv_usec = tcur.tv_usec - tlast.tv_usec;
+                       while (tlast.tv_usec < 0) {
+                               tlast.tv_usec += 1000000;
+                               tlast.tv_sec -= 1;
+                       }
+                       fspeed = (nsecs / secsps) /
+                               (tlast.tv_sec * 1.0 + tlast.tv_usec * 0.000001);
+                       if (fspeed > 999.0)
+                               fspeed = 999.0;
+#ifdef BCAP
+                       if (bsize > 0 && per > dminbuf &&
+                           dp->cdr_dstat->ds_cdrflags & RF_WR_WAIT) {
+                               int     wsecs = (per-dminbuf)*(bsize/secsize)/100;
+                               int     msecs = 0x100000/secsize;
+                               int     wt;
+                               int     mt;
+                               int     s = dp->cdr_dstat->ds_dr_cur_wspeed;
+
+
+                               if (s <= 0) {
+                                       if (dp->cdr_dstat->ds_flags & DSF_DVD)
+                                               s = 4;
+                                       else
+                                               s = 50;
+                               }
+                               if (wsecs > msecs)      /* Less that 1 MB */
+                                       wsecs = msecs;
+                               wt = wsecs * 1000 / secsps / fspeed;
+                               mt = (per-dminbuf)*(bsize/secsize)/100 * 1000 / secsps/s;
+
+                               if (wt > mt)
+                                       wt = mt;
+                               if (wt > 1000)          /* Max 1 second */
+                                       wt = 1000;
+                               if (wt < 20)            /* Min 20 ms */
+                                       wt = 0;
+
+                               if (xdebug)
+                                       printf(" |%3d %4dms %5dms|", wsecs, wt, mt);
+                               else
+                                       printf(" |%3d %4dms|", wsecs, wt);
+                               if (wt > 0)
+                                       usleep(wt*1000);
+                       }
+#endif
+         if (dp->is_dvd) fspeed /= 9;
+                       printf(" %5.1fx", fspeed);
+                       printf(".");
+                       savbytes = (bytes >> 20) << 20;
+                       flush();
+                       neednl = TRUE;
+                       tlast = tcur;
+               }
+#ifdef XBCAP
+               if (bsize > 0) {                        /* buffer size known */
+                       (*dp->cdr_buffer_cap)(usalp, (long *)0, &bfree);
+                       per = 100*(bsize - bfree) / bsize;
+                       if (per != oper)
+                               printf("[buf %3d%%] %3ld %3ld\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b",
+                                       per, bsize >> 10, bfree >> 10);
+                       oper = per;
+                       flush();
+               }
+
+
+#endif
+       } while (tracksize < 0 || bytes_read < tracksize);
+
+       if (!is_shorttrk(trackp) && (bytes / secsize) < 300) {
+               /*
+                * If tracksize is not known (trackp->tracksize < 0) or
+                * for some strange reason we did not set padsecs properly
+                * we may need to modify trackp->padsecs if
+                * tracksize+padsecs is less than 300 sectors.
+                */
+               if ((trackp->padsecs + (bytes / secsize)) < 300)
+                       trackp->padsecs = 300 - (bytes / secsize);
+       }
+       if (trackp->padsecs > 0) {
+               Llong   padbytes;
+
+               /*
+                * pad_track() is based on secsize. Compute the amount of bytes
+                * assumed by pad_track().
+                */
+               padbytes = (Llong)trackp->padsecs * secsize;
+
+               if (neednl) {
+                       printf("\n");
+                       neednl = FALSE;
+               }
+               if ((padbytes >> 20) > 0) {
+                       neednl = TRUE;
+               } else if (lverbose) {
+                       printf("Track %02d: writing %3lld KB of pad data.\n",
+                                       track, (Llong)(padbytes >> 10));
+                       neednl = FALSE;
+               }
+               pad_track(usalp, dp, trackp, startsec, padbytes,
+                                       TRUE, &savbytes);
+               bytes += savbytes;
+               startsec += savbytes / secsize;
+       }
+       printf("%sTrack %02d: Total bytes read/written: %lld/%lld (%lld sectors).\n",
+               neednl?"\n":"", track, bytes_read, bytes, bytes/secsize);
+       flush();
+       return (0);
+}
+
+int 
+pad_track(SCSI *usalp, cdr_t   *dp, track_t *trackp, long startsec, Llong amt,
+                               BOOL dolast, Llong *bytesp)
+{
+       int     track = trackp->trackno;
+       Llong   bytes   = 0;
+       Llong   savbytes = 0;
+       Llong   padsize = amt;
+       int     secsize;
+       int     secspt;
+       int     bytespt;
+       int     amount;
+       BOOL    neednl  = FALSE;
+       BOOL    islast  = FALSE;
+       struct timeval tlast;
+       struct timeval tcur;
+       float   secsps = 75.0;
+long bsize;
+long bfree;
+#define        BCAP
+#ifdef BCAP
+int per;
+#ifdef XBCAP
+int oper = -1;
+#endif
+#endif
+
+       if (dp->cdr_dstat->ds_flags & DSF_DVD)
+               secsps = 676.27;
+
+       usalp->silent++;
+       if ((*dp->cdr_buffer_cap)(usalp, &bsize, &bfree) < 0)
+               bsize = -1L;
+       if (bsize == 0)         /* If we have no (known) buffer, we cannot */
+               bsize = -1L;    /* retrieve the buffer fill ratio          */
+       usalp->silent--;
+
+       secsize = trackp->secsize;
+       secspt = trackp->secspt;
+       bytespt = secsize * secspt;
+
+       fillbytes(buf, bytespt, '\0');
+
+       if ((amt >> 20) > 0) {
+               printf("\rTrack %02d:    0 of %4lld MB pad written.",
+                                               track, amt >> 20);
+               flush();
+       }
+       gettimeofday(&tlast, (struct timezone *)0);
+       do {
+               if (amt < bytespt) {
+                       bytespt = roundup(amt, secsize);
+                       secspt = bytespt / secsize;
+               }
+               if (dolast && (amt - bytespt) <= 0)
+                       islast = TRUE;
+
+               if (is_raw(trackp)) {
+                       encsectors(trackp, (Uchar *)buf, startsec, secspt);
+                       fillsubch(trackp, (Uchar *)buf, startsec, secspt);
+               }
+
+               amount = write_secs(usalp, dp, buf, startsec, bytespt, secspt, islast);
+               if (amount < 0) {
+                       printf("%swrite track pad data: error after %lld bytes\n",
+                                                       neednl?"\n":"", bytes);
+                       if (bytesp)
+                               *bytesp = bytes;
+(*dp->cdr_buffer_cap)(usalp, (long *)0, (long *)0);
+                       return (-1);
+               }
+               amt -= amount;
+               bytes += amount;
+               startsec += amount / secsize;
+
+               if (lverbose && (bytes >= (savbytes + 0x100000))) {
+                       int     nsecs = (bytes - savbytes) / secsize;
+                       float   fspeed;
+
+                       gettimeofday(&tcur, (struct timezone *)0);
+                       printf("\rTrack %02d: %4lld", track, bytes >> 20);
+                       if (padsize > 0)
+                               printf(" of %4lld MB", padsize >> 20);
+                       else
+                               printf(" MB");
+                       printf(" pad written");
+                       savbytes = (bytes >> 20) << 20;
+
+#ifdef BCAP
+                       if (bsize > 0) {                        /* buffer size known */
+                               usalp->silent++;
+                               per = (*dp->cdr_buffer_cap)(usalp, (long *)0, &bfree);
+                               usalp->silent--;
+                               if (per >= 0) {
+                                       per = 100*(bsize - bfree) / bsize;
+                                       if ((bsize - bfree) <= amount || per <= 5)
+                                               dp->cdr_dstat->ds_buflow++;
+                                       if (per < (int)dp->cdr_dstat->ds_minbuf &&
+                                           (startsec*secsize) > bsize) {
+                                               dp->cdr_dstat->ds_minbuf = per;
+                                       }
+                                       printf(" [buf %3d%%]", per);
+#ifdef BCAPDBG
+                                       printf(" %3ld %3ld", bsize >> 10, bfree >> 10);
+#endif
+                               }
+                       }
+#endif
+                       tlast.tv_sec = tcur.tv_sec - tlast.tv_sec;
+                       tlast.tv_usec = tcur.tv_usec - tlast.tv_usec;
+                       while (tlast.tv_usec < 0) {
+                               tlast.tv_usec += 1000000;
+                               tlast.tv_sec -= 1;
+                       }
+                       fspeed = (nsecs / secsps) /
+                               (tlast.tv_sec * 1.0 + tlast.tv_usec * 0.000001);
+                       if (fspeed > 999.0)
+                               fspeed = 999.0;
+                       printf(" %5.1fx", fspeed);
+                       printf(".");
+                       flush();
+                       neednl = TRUE;
+                       tlast = tcur;
+               }
+       } while (amt > 0);
+
+       if (bytesp)
+               *bytesp = bytes;
+       if (bytes == 0)
+               return (0);
+       return (bytes > 0 ? 1:-1);
+}
+
+#ifdef USE_WRITE_BUF
+int 
+write_buf(SCSI *usalp, cdr_t *dp, track_t *trackp, char *bp, long startsec, 
+                 Llong amt, int secsize, BOOL dolast, Llong *bytesp)
+{
+       int     track = trackp->trackno;
+       Llong   bytes   = 0;
+       Llong   savbytes = 0;
+/*     int     secsize;*/
+       int     secspt;
+       int     bytespt;
+       int     amount;
+       BOOL    neednl  = FALSE;
+       BOOL    islast  = FALSE;
+
+/*     secsize = trackp->secsize;*/
+/*     secspt = trackp->secspt;*/
+
+       secspt = bufsize/secsize;
+       secspt = min(255, secspt);
+       bytespt = secsize * secspt;
+
+/*     fillbytes(buf, bytespt, '\0');*/
+
+       if ((amt >> 20) > 0) {
+               printf("\rTrack %02d:   0 of %4ld MB pad written.",
+                                               track, amt >> 20);
+               flush();
+       }
+       do {
+               if (amt < bytespt) {
+                       bytespt = roundup(amt, secsize);
+                       secspt = bytespt / secsize;
+               }
+               if (dolast && (amt - bytespt) <= 0)
+                       islast = TRUE;
+
+               amount = write_secs(usalp, dp, bp, startsec, bytespt, secspt, islast);
+               if (amount < 0) {
+                       printf("%swrite track data: error after %ld bytes\n",
+                                                       neednl?"\n":"", bytes);
+                       if (bytesp)
+                               *bytesp = bytes;
+(*dp->cdr_buffer_cap)(usalp, (long *)0, (long *)0);
+                       return (-1);
+               }
+               amt -= amount;
+               bytes += amount;
+               startsec += amount / secsize;
+
+               if (lverbose && (bytes >= (savbytes + 0x100000))) {
+                       printf("\rTrack %02d: %3ld", track, bytes >> 20);
+                       savbytes = (bytes >> 20) << 20;
+                       flush();
+                       neednl = TRUE;
+               }
+       } while (amt > 0);
+
+       if (bytesp)
+               *bytesp = bytes;
+       return (bytes);
+}
+#endif /* USE_WRITE_BUF */
+
+static void 
+printdata(int track, track_t *trackp)
+{
+       if (trackp->itracksize >= 0) {
+               printf("Track %02d: data  %4lld MB        ",
+                                       track, (Llong)(trackp->itracksize >> 20));
+       } else {
+               printf("Track %02d: data  unknown length",
+                                       track);
+       }
+       if (trackp->padsecs > 0) {
+               Llong   padbytes = (Llong)trackp->padsecs * trackp->isecsize;
+
+               if ((padbytes >> 20) > 0)
+                       printf(" padsize: %4lld MB", (Llong)(padbytes >> 20));
+               else
+                       printf(" padsize: %4lld KB", (Llong)(padbytes >> 10));
+       }
+       if (trackp->pregapsize != (trackp->flags & TI_DVD)? 0 : 150) {
+               printf(" pregapsize: %3ld", trackp->pregapsize);
+       }
+       if (xdebug)
+               printf(" START: %ld SECTORS: %ld INDEX0 %ld",
+                       trackp->trackstart, trackp->tracksecs, trackp->index0start);
+       printf("\n");
+}
+
+static void 
+printaudio(int track, track_t *trackp)
+{
+       if (trackp->itracksize >= 0) {
+               printf("Track %02d: audio %4lld MB (%02d:%02d.%02d) %spreemp%s%s",
+                       track, (Llong)(trackp->itracksize >> 20),
+                       minutes(trackp->itracksize),
+                       seconds(trackp->itracksize),
+                       hseconds(trackp->itracksize),
+                       is_preemp(trackp) ? "" : "no ",
+                       is_swab(trackp) ? " swab":"",
+                       ((trackp->itracksize < 300L*trackp->isecsize) ||
+                       (trackp->itracksize % trackp->isecsize)) &&
+                       is_pad(trackp) ? " pad" : "");
+       } else {
+               printf("Track %02d: audio unknown length    %spreemp%s%s",
+                       track, is_preemp(trackp) ? "" : "no ",
+                       is_swab(trackp) ? " swab":"",
+                       (trackp->itracksize % trackp->isecsize) && is_pad(trackp) ? " pad" : "");
+       }
+       if (is_scms(trackp))
+               printf(" scms");
+       else if (is_copy(trackp))
+               printf(" copy");
+       else
+               printf("     ");
+
+       if (trackp->padsecs > 0) {
+               Llong   padbytes = (Llong)trackp->padsecs * trackp->isecsize;
+
+               if ((padbytes >> 20) > 0)
+                       printf(" padsize: %4lld MB", (Llong)(padbytes >> 20));
+               else
+                       printf(" padsize: %4lld KB", (Llong)(padbytes >> 10));
+               printf(" (%02d:%02d.%02d)",
+                       Sminutes(trackp->padsecs),
+                       Sseconds(trackp->padsecs),
+                       Shseconds(trackp->padsecs));
+       }
+       if (trackp->pregapsize != ((trackp->flags & TI_DVD)? 0 : 150) || xdebug > 0) {
+               printf(" pregapsize: %3ld", trackp->pregapsize);
+       }
+       if (xdebug)
+               printf(" START: %ld SECTORS: %ld INDEX0 %ld",
+                       trackp->trackstart, trackp->tracksecs, trackp->index0start);
+       printf("\n");
+}
+
+static void 
+checkfile(int track, track_t *trackp)
+{
+       if (trackp->itracksize > 0 &&
+                       is_audio(trackp) &&
+                       ((!is_shorttrk(trackp) &&
+                       (trackp->itracksize < 300L*trackp->isecsize)) ||
+                       (trackp->itracksize % trackp->isecsize)) &&
+                                               !is_pad(trackp)) {
+               errmsgno(EX_BAD, "Bad audio track size %lld for track %02d.\n",
+                               (Llong)trackp->itracksize, track);
+               errmsgno(EX_BAD, "Audio tracks must be at least %ld bytes and a multiple of %d.\n",
+                               300L*trackp->isecsize, trackp->isecsize);
+
+               if (!is_shorttrk(trackp) && (trackp->itracksize < 300L*trackp->isecsize))
+                       comerrno(EX_BAD, "See -shorttrack option.\n");
+               if (!is_pad(trackp) && (trackp->itracksize % trackp->isecsize))
+                       comerrno(EX_BAD, "See -pad option.\n");
+       }
+
+       if (lverbose == 0 && xdebug == 0)
+               return;
+
+       if (is_audio(trackp))
+               printaudio(track, trackp);
+       else
+               printdata(track, trackp);
+}
+
+static int 
+checkfiles(int tracks, track_t *trackp)
+{
+       int     i;
+       int     isaudio = 1;
+       int     starttrack = 1;
+       int     endtrack = tracks;
+
+       if (xdebug) {
+               /*
+                * Include Lead-in & Lead-out.
+                */
+               starttrack--;
+               endtrack++;
+       }
+       for (i = starttrack; i <= endtrack; i++) {
+               if (!is_audio(&trackp[i]))
+                       isaudio = 0;
+               if (xdebug)
+                       printf("SECTYPE %X ", trackp[i].sectype);
+               checkfile(i, &trackp[i]);
+       }
+       return (isaudio);
+}
+
+static void 
+setleadinout(int tracks, track_t *trackp)
+{
+       /*
+        * Set some values for track 0 (the lead-in)
+        */
+       if (!is_clone(&trackp[0])) {
+               trackp[0].sectype = trackp[1].sectype;
+               trackp[0].dbtype  = trackp[1].dbtype;
+               trackp[0].dataoff = trackp[1].dataoff;
+
+               /*
+                * XXX Which other flags should be copied to Track 0 ?
+                */
+               if (is_audio(&trackp[1]))
+                       trackp[0].flags |= TI_AUDIO;
+       }
+
+       /*
+        * Set some values for track 0xAA (the lead-out)
+        */
+       trackp[tracks+1].pregapsize = 0;
+       trackp[tracks+1].isecsize   = trackp[tracks].isecsize;
+       trackp[tracks+1].secsize    = trackp[tracks].secsize;
+
+       if (!is_clone(&trackp[0])) {
+               trackp[tracks+1].tracktype = trackp[tracks].tracktype;
+               trackp[tracks+1].sectype   = trackp[tracks].sectype;
+               trackp[tracks+1].dbtype    = trackp[tracks].dbtype;
+               trackp[tracks+1].dataoff   = trackp[tracks].dataoff;
+       }
+
+       trackp[tracks+1].flags = trackp[tracks].flags;
+}
+
+static void 
+setpregaps(int tracks, track_t *trackp)
+{
+       int     i;
+       int     sectype;
+       long    pregapsize;
+       track_t *tp;
+
+       sectype = trackp[1].sectype;
+       sectype &= ST_MASK;
+
+       for (i = 1; i <= tracks; i++) {
+               tp = &trackp[i];
+               if (tp->pregapsize == -1L) {
+                       tp->pregapsize = 150;           /* Default CD Pre GAP*/
+                       if (trackp->flags & TI_DVD) {
+                               tp->pregapsize = 0;
+                       } else if (sectype != (tp->sectype & ST_MASK)) {
+                               tp->pregapsize = 255;   /* Pre GAP is 255 */
+                               tp->flags &= ~TI_PREGAP;
+                       }
+               }
+               sectype = tp->sectype & ST_MASK;        /* Save old sectype */
+       }
+       trackp[tracks+1].pregapsize = 0;
+       trackp[tracks+1].index0start = 0;
+
+       for (i = 1; i <= tracks; i++) {
+               /*
+                * index0start is set below tracksecks if this track contains
+                * the pregap (index 0) of the next track.
+                */
+               trackp[i].index0start = trackp[i].tracksecs;
+
+               pregapsize = trackp[i+1].pregapsize;
+               if (is_pregap(&trackp[i+1]) && pregapsize > 0)
+                       trackp[i].index0start -= pregapsize;
+       }
+}
+
+/*
+ * Check total size of the medium
+ */
+static long 
+checktsize(int tracks, track_t *trackp)
+{
+       int     i;
+       Llong   curr;
+       Llong   total = -150;   /* CD track #1 pregap compensation */
+       Ullong  btotal;
+       track_t *tp;
+
+       if (trackp->flags & TI_DVD)
+               total = 0;
+       for (i = 1; i <= tracks; i++) {
+               tp = &trackp[i];
+               if (!is_pregap(tp))
+                       total += tp->pregapsize;
+
+               if (lverbose > 1) {
+                       printf("track: %d start: %lld pregap: %ld\n",
+                                       i, total, tp->pregapsize);
+               }
+               tp->trackstart = total;
+               if (tp->itracksize >= 0) {
+                       curr = (tp->itracksize + (tp->isecsize-1)) / tp->isecsize;
+                       curr += tp->padsecs;
+                       /*
+                        * Minimum track size is 4s
+                        */
+                       if (!is_shorttrk(tp) && curr < 300)
+                               curr = 300;
+                       if ((trackp->flags & TI_DVD) == 0) {
+                               /*
+                                * XXX Was passiert hier bei is_packet() ???
+                                */
+                               if (is_tao(tp) && !is_audio(tp)) {
+                                       curr += 2;
+                               }
+                       }
+                       total += curr;
+               } else if (is_sao(tp) || is_raw(tp)) {
+                       errmsgno(EX_BAD, "Track %d has unknown length.\n", i);
+                       comerrno(EX_BAD,
+                       "Use tsize= option in %s mode to specify track size.\n",
+                       is_sao(tp) ? "SAO" : "RAW");
+               }
+       }
+       tp = &trackp[i];
+       tp->trackstart = total;
+       tp->tracksecs = 6750;           /* Size of first session Lead-Out */
+       if (!lverbose)
+               return (total);
+
+       if (trackp->flags & TI_DVD)
+               btotal = (Ullong)total * 2048;
+       else
+               btotal = (Ullong)total * 2352;
+/* XXX CD Sector Size ??? */
+       if (tracks > 0) {
+               if (trackp->flags & TI_DVD) {
+                       printf("Total size:     %4llu MB = %lld sectors\n",
+                               btotal >> 20, total);
+               } else {
+                       printf("Total size:     %4llu MB (%02d:%02d.%02d) = %lld sectors\n",
+                               btotal >> 20,
+                               minutes(btotal),
+                               seconds(btotal),
+                               hseconds(btotal), total);
+                       btotal += 150 * 2352;
+                       printf("Lout start:     %4llu MB (%02d:%02d/%02d) = %lld sectors\n",
+                               btotal >> 20,
+                               minutes(btotal),
+                               seconds(btotal),
+                               frames(btotal), total);
+               }
+       }
+       return (total);
+}
+
+static void 
+opentracks(track_t *trackp)
+{
+       track_t *tp;
+       int     i;
+       int     tracks = trackp[0].tracks;
+
+       Llong   tracksize;
+       int     secsize;
+
+       for (i = 1; i <= tracks; i++) {
+               tp = &trackp[i];
+
+               if (auinfosize(tp->filename, tp)) {
+                       /*
+                        * open stdin
+                        */
+                       tp->xfp = xopen(NULL, O_RDONLY|O_BINARY, 0);
+               } else if (strcmp("-", tp->filename) == 0) {
+                       /*
+                        * open stdin
+                        */
+                       tp->xfp = xopen(NULL, O_RDONLY|O_BINARY, 0);
+               } else {
+                       if ((tp->xfp = xopen(tp->filename,
+                                       O_RDONLY|O_BINARY, 0)) == NULL) {
+                               comerr("Cannot open '%s'.\n", tp->filename);
+                       }
+               }
+
+               checksize(tp);
+               tracksize = tp->itracksize;
+               secsize = tp->isecsize;
+               if (!is_shorttrk(tp) &&
+                   tracksize > 0 && (tracksize / secsize) < 300) {
+
+                       tracksize = roundup(tracksize, secsize);
+                       if ((tp->padsecs +
+                           (tracksize / secsize)) < 300) {
+                               tp->padsecs =
+                                       300 - tracksize / secsize;
+                       }
+                       if (xdebug) {
+                               printf("TRACK %d SECTORS: %ld",
+                                       i, tp->tracksecs);
+                               printf(" pasdize %lld (%ld sectors)\n",
+                                       (Llong)tp->padsecs * secsize,
+                                       tp->padsecs);
+                       }
+               }
+#ifdef AUINFO
+               if (tp->flags & TI_USEINFO) {
+                       auinfo(tp->filename, i, trackp);
+                       if (lverbose > 0 && i == 1)
+                               printf("pregap1: %ld\n", trackp[1].pregapsize);
+               }
+#endif
+               /*
+                * tracksecks is total numbers of sectors in track (starting from
+                * index 0).
+                */
+               if (tp->padsecs > 0)
+                       tp->tracksecs += tp->padsecs;
+
+               if (debug) {
+                       printf("File: '%s' itracksize: %lld isecsize: %d tracktype: %d = %s sectype: %X = %s dbtype: %s flags %X\n",
+                               tp->filename, (Llong)tp->itracksize,
+                               tp->isecsize,
+                               tp->tracktype & TOC_MASK, toc2name[tp->tracktype & TOC_MASK],
+                               tp->sectype, st2name[tp->sectype & ST_MASK], db2name[tp->dbtype], tp->flags);
+               }
+       }
+}
+
+static void 
+checksize(track_t *trackp)
+{
+       struct stat     st;
+       Llong           lsize;
+       int             f = -1;
+
+       if (trackp->xfp != NULL)
+               f = xfileno(trackp->xfp);
+
+       /*
+        * If the current input file is a regular file and
+        * 'padsize=' has not been specified,
+        * use fstat() or file parser to get the size of the file.
+        */
+       if (trackp->itracksize < 0 && (trackp->flags & TI_ISOSIZE) != 0) {
+               lsize = isosize(f);
+               trackp->itracksize = lsize;
+               if (trackp->itracksize != lsize)
+                       comerrno(EX_BAD, "This OS cannot handle large ISO-9660 images.\n");
+       }
+       if (trackp->itracksize < 0 && (trackp->flags & TI_NOAUHDR) == 0) {
+               lsize = ausize(f);
+               trackp->itracksize = lsize;
+               if (trackp->itracksize != lsize)
+                       comerrno(EX_BAD, "This OS cannot handle large audio images.\n");
+       }
+       if (trackp->itracksize < 0 && (trackp->flags & TI_NOAUHDR) == 0) {
+               lsize = wavsize(f);
+               trackp->itracksize = lsize;
+               if (trackp->itracksize != lsize)
+                       comerrno(EX_BAD, "This OS cannot handle large WAV images.\n");
+               if (trackp->itracksize > 0)     /* Force little endian input */
+                       trackp->flags |= TI_SWAB;
+       }
+       if (trackp->itracksize == AU_BAD_CODING) {
+               comerrno(EX_BAD, "Inappropriate audio coding in '%s'.\n",
+                                                       trackp->filename);
+       }
+       if (trackp->itracksize < 0 &&
+                       fstat(f, &st) >= 0 && S_ISREG(st.st_mode)) {
+               trackp->itracksize = st.st_size;
+       }
+       if (trackp->itracksize >= 0) {
+               /*
+                * We do not allow cdrecord to start if itracksize is not
+                * a multiple of isecsize or we are allowed to pad to secsize via -pad.
+                * For this reason, we may safely always assume padding.
+                */
+               trackp->tracksecs = (trackp->itracksize + trackp->isecsize -1) / trackp->isecsize;
+               trackp->tracksize = (trackp->itracksize / trackp->isecsize) * trackp->secsize
+                                       + trackp->itracksize % trackp->isecsize;
+       } else {
+               trackp->tracksecs = -1L;
+       }
+}
+
+static BOOL 
+checkdsize(SCSI *usalp, cdr_t *dp, long tsize, int flags)
+{
+       long    startsec = 0L;
+       long    endsec = 0L;
+       dstat_t *dsp = dp->cdr_dstat;
+       int     profile;
+
+       usalp->silent++;
+       (*dp->cdr_next_wr_address)(usalp, (track_t *)0, &startsec);
+       usalp->silent--;
+
+       /*
+        * This only should happen when the drive is currently in SAO mode.
+        * We rely on the drive being in TAO mode, a negative value for
+        * startsec is not correct here it may be caused by bad firmware or
+        * by a drive in SAO mode. In SAO mode the drive will report the
+        * pre-gap as part of the writable area.
+        */
+       if (startsec < 0)
+               startsec = 0;
+
+       /*
+        * Size limitations (sectors) for CD's:
+        *
+        *              404850 == 90 min        Red book calls this the
+        *                                      first negative time
+        *                                      allows lead out start up to
+        *                                      block 404700
+        *
+        *              449850 == 100 min       This is the first time that
+        *                                      is no more representable
+        *                                      in a two digit BCD number.
+        *                                      allows lead out start up to
+        *                                      block 449700
+        *
+        *              ~540000 == 120 min      The largest CD ever made.
+        *
+        *              ~650000 == 1.3 GB       a Double Density (DD) CD.
+        */
+
+       endsec = startsec + tsize;
+       dsp->ds_startsec = startsec;
+       dsp->ds_endsec = endsec;
+
+
+       if (dsp->ds_maxblocks > 0) {
+               /*
+                * dsp->ds_maxblocks > 0 (disk capacity is known).
+                */
+               if (lverbose)
+                       printf("Blocks total: %ld Blocks current: %ld Blocks remaining: %ld\n",
+                                       (long)dsp->ds_maxblocks,
+                                       (long)dsp->ds_maxblocks - startsec,
+                                       (long)dsp->ds_maxblocks - endsec);
+
+               if (endsec > dsp->ds_maxblocks) {
+                       if (dsp->ds_flags & DSF_DVD) {  /* A DVD and not a CD */
+                               /*
+                                * There is no overburning on DVD...
+                                */
+                               errmsgno(EX_BAD,
+                               "Data does not fit on current disk.\n");
+                               goto toolarge;
+                       }
+                       errmsgno(EX_BAD,
+                       "WARNING: Data may not fit on current disk.\n");
+
+                       /* XXX Check for flags & CDR_NO_LOLIMIT */
+/*                     goto toolarge;*/
+               }
+               if (lverbose && dsp->ds_maxrblocks > 0)
+                       printf("RBlocks total: %ld RBlocks current: %ld RBlocks remaining: %ld\n",
+                                       (long)dsp->ds_maxrblocks,
+                                       (long)dsp->ds_maxrblocks - startsec,
+                                       (long)dsp->ds_maxrblocks - endsec);
+               if (dsp->ds_maxrblocks > 0 && endsec > dsp->ds_maxrblocks) {
+                       errmsgno(EX_BAD,
+                       "Data does not fit on current disk.\n");
+                       goto toolarge;
+               }
+               if ((endsec > dsp->ds_maxblocks && endsec > 404700) ||
+                   (dsp->ds_maxrblocks > 404700 && 449850 > dsp->ds_maxrblocks)) {
+                       /*
+                        * Assume that this must be a CD and not a DVD.
+                        * So this is a non Red Book compliant CD with a
+                        * capacity between 90 and 99 minutes.
+                        */
+                       if (dsp->ds_maxrblocks > 404700)
+                               printf("RedBook total: %ld RedBook current: %ld RedBook remaining: %ld\n",
+                                       404700L,
+                                       404700L - startsec,
+                                       404700L - endsec);
+                       if (endsec > dsp->ds_maxblocks && endsec > 404700) {
+                               if ((flags & (F_IGNSIZE|F_FORCE)) == 0) {
+                                       errmsgno(EX_BAD,
+                                       "Notice: Most recorders cannot write CD's >= 90 minutes.\n");
+                                       errmsgno(EX_BAD,
+                                       "Notice: Use -ignsize option to allow >= 90 minutes.\n");
+                               }
+                               goto toolarge;
+                       }
+               }
+       } else {
+               /*
+                * dsp->ds_maxblocks == 0 (disk capacity is unknown).
+                */
+               profile = dp->profile;
+               if (endsec >= (4200000)) {
+                       errmsgno(EX_BAD,
+                       "ERROR: Could not manage to find medium size, and more than 8.0 GB of data.\n");
+                       goto toolarge;  
+               } else if (profile != 0x2B) { 
+                   if (endsec >= (2300000)) {
+                       errmsgno(EX_BAD,
+                               "ERROR: Could not manage to find medium size, and more than 4.3 GB of data for a non dual layer disc.\n");
+                       goto toolarge;
+                   } else if (endsec >= (405000-300)) {            /*<90 min disk or DVD*/
+                       errmsgno(EX_BAD,
+                               "WARNING: Could not manage to find medium size, and more than 90 mins of data.\n");
+                   } else if (endsec >= (333000-150)) {                /* 74 min disk*/
+                       errmsgno(EX_BAD,
+                               "WARNING: Data may not fit on standard 74min disk.\n");
+                   }
+               }
+       }
+       if (dsp->ds_maxblocks <= 0 || endsec <= dsp->ds_maxblocks)
+               return (TRUE);
+       /* FALLTHROUGH */
+toolarge:
+       if (dsp->ds_maxblocks > 0 && endsec > dsp->ds_maxblocks) {
+               if ((flags & (F_OVERBURN|F_IGNSIZE|F_FORCE)) != 0) {
+                       if (dsp->ds_flags & DSF_DVD) {  /* A DVD and not a CD */
+                               errmsgno(EX_BAD,
+                               "Notice: -overburn is not expected to work with DVD media.\n");
+                       }
+                       errmsgno(EX_BAD,
+                               "Notice: Overburning active. Trying to write more than the official disk capacity.\n");
+                       return (TRUE);
+               } else {
+                       if ((dsp->ds_flags & DSF_DVD) == 0) {   /* A CD and not a DVD */
+                               errmsgno(EX_BAD,
+                               "Notice: Use -overburn option to write more than the official disk capacity.\n");
+                               errmsgno(EX_BAD,
+                               "Notice: Most CD-writers do overburning only on SAO or RAW mode.\n");
+                       }
+                       return (FALSE);
+               }
+       }
+       if (dsp->ds_maxblocks < 449850) {
+               if ((dsp->ds_flags & DSF_DVD) == 0) {   /* A CD and not a DVD */
+                       if (endsec <= dsp->ds_maxblocks)
+                               return (TRUE);
+                       errmsgno(EX_BAD, "Cannot write more than remaining DVD capacity.\n");
+                       return (FALSE);
+               }
+               /*
+                * Assume that this must be a CD and not a DVD.
+                */
+               if (endsec > 449700) {
+                       errmsgno(EX_BAD, "Cannot write CD's >= 100 minutes.\n");
+                       return (FALSE);
+               }
+       }
+       if ((flags & (F_IGNSIZE|F_FORCE)) != 0)
+               return (TRUE);
+       return (FALSE);
+}
+
+static void 
+raise_fdlim()
+{
+#ifdef RLIMIT_NOFILE
+
+       struct rlimit   rlim;
+
+       /*
+        * Set max # of file descriptors to be able to hold all files open
+        */
+       getrlimit(RLIMIT_NOFILE, &rlim);
+       if (rlim.rlim_cur >= (MAX_TRACK + 10))
+               return;
+
+       rlim.rlim_cur = MAX_TRACK + 10;
+       if (rlim.rlim_cur > rlim.rlim_max)
+               errmsgno(EX_BAD,
+                       "Warning: low file descriptor limit (%lld)\n",
+                                               (Llong)rlim.rlim_max);
+       setrlimit(RLIMIT_NOFILE, &rlim);
+
+#endif /* RLIMIT_NOFILE */
+}
+
+static void 
+raise_memlock()
+{
+#ifdef RLIMIT_MEMLOCK
+       struct rlimit rlim;
+
+       rlim.rlim_cur = rlim.rlim_max = RLIM_INFINITY;
+
+       if (setrlimit(RLIMIT_MEMLOCK, &rlim) < 0)
+               errmsg("Warning: Cannot raise RLIMIT_MEMLOCK limits.\n");
+#endif /* RLIMIT_MEMLOCK */
+}
+
+char   *opts =
+"help,version,checkdrive,prcap,inq,devices,scanbus,reset,abort,overburn,ignsize,useinfo,dev*,timeout#,driver*,driveropts*,setdropts,tsize&,padsize&,pregap&,defpregap&,speed#,load,lock,eject,dummy,msinfo,toc,atip,multi,fix,nofix,waiti,immed,debug#,d+,kdebug#,kd#,verbose+,v+,Verbose+,V+,x+,xd#,silent,s,audio,data,mode2,xa,xa1,xa2,xamix,cdi,isosize,nopreemp,preemp,nocopy,copy,nopad,pad,swab,fs&,ts&,blank&,format,formattype&,pktsize#,packet,noclose,force,tao,dao,sao,raw,raw96r,raw96p,raw16,clone,scms,isrc*,mcn*,index*,cuefile*,textfile*,text,shorttrack,noshorttrack,gracetime#,minbuf#,msifile*";
+
+/*
+ * Defines used to find whether a write mode has been specified.
+ */
+#define        M_TAO           1       /* Track at Once mode */
+#define        M_SAO           2       /* Session at Once mode (also known as DAO) */
+#define        M_RAW           4       /* Raw mode */
+#define        M_PACKET        8       /* Packed mode */
+static int 
+gargs(int ac, char **av, int *tracksp, track_t *trackp, char **devp, 
+               int *timeoutp, cdr_t **dpp, int *speedp, long *flagsp, int *blankp, 
+               int *formatp)
+{
+       int     cac;
+       char    * const*cav;
+       char    *driver = NULL;
+       char    *dev = NULL;
+       char    *isrc = NULL;
+       char    *mcn = NULL;
+       char    *tindex = NULL;
+       char    *cuefile = NULL;
+       char    *textfile = NULL;
+       long    bltype = -1;
+       int     doformat = 0;
+       int     formattype = -1;
+       Llong   tracksize;
+       Llong   padsize;
+       long    pregapsize;
+       long    defpregap = -1L;
+       int     pktsize;
+       int     speed = -1;
+       int     help = 0;
+       int     version = 0;
+       int     checkdrive = 0;
+       int     setdropts = 0;
+       int     prcap = 0;
+       int     inq = 0;
+       int     scanbus = 0;
+       int     reset = 0;
+       int     doabort = 0;
+       int     overburn = 0;
+       int     ignsize = 0;
+       int     useinfo = 0;
+       int     load = 0;
+       int     lock = 0;
+       int     eject = 0;
+       int     dummy = 0;
+       int     msinfo = 0;
+       int     toc = 0;
+       int     atip = 0;
+       int     multi = 0;
+       int     fix = 0;
+       int     nofix = 0;
+       int     waiti = 0;
+       int     immed = 0;
+       int     audio;
+       int     autoaudio = 0;
+       int     data;
+       int     mode2;
+       int     xa;
+       int     xa1;
+       int     xa2;
+       int     xamix;
+       int     cdi;
+       int     isize;
+       int     ispacket = 0;
+       int     noclose = 0;
+       int     force = 0;
+       int     tao = 0;
+       int     dao = 0;
+       int     raw = 0;
+       int     raw96r = 0;
+       int     raw96p = 0;
+       int     raw16 = 0;
+       int     clone = 0;
+       int     scms = 0;
+       int     preemp = 0;
+       int     nopreemp;
+       int     copy = 0;
+       int     nocopy;
+       int     pad = 0;
+       int     bswab = 0;
+       int     nopad;
+       int     usetext = 0;
+       int     shorttrack = 0;
+       int     noshorttrack;
+       int     flags;
+       int     tracks = *tracksp;
+       int     tracktype = TOC_ROM;
+/*     int     sectype = ST_ROM_MODE1 | ST_MODE_1;*/
+       int     sectype = SECT_ROM;
+       int     dbtype = DB_ROM_MODE1;
+       int     secsize = DATA_SEC_SIZE;
+       int     dataoff = 16;
+       int     ga_ret;
+       int     wm = 0;
+
+       trackp[0].flags |= TI_TAO;
+       trackp[1].pregapsize = -1;
+       *flagsp |= F_WRITE;
+
+       cac = --ac;
+       cav = ++av;
+       for (; ; cac--, cav++) {
+               tracksize = (Llong)-1L;
+               padsize = (Llong)0L;
+               pregapsize = defpregap;
+               audio = data = mode2 = xa = xa1 = xa2 = xamix = cdi = 0;
+               isize = nopreemp = nocopy = nopad = noshorttrack = 0;
+               pktsize = 0;
+               isrc = NULL;
+               tindex = NULL;
+               /*
+                * Get options up to next file type arg.
+                */
+               if ((ga_ret = getargs(&cac, &cav, opts,
+                               &help, &version, &checkdrive, &prcap,
+                               &inq, &scandevs, &scanbus, &reset, &doabort, &overburn, &ignsize,
+                               &useinfo,
+                               devp, timeoutp, &driver, &driveropts, &setdropts,
+                               getllnum, &tracksize,
+                               getllnum, &padsize,
+                               getnum, &pregapsize,
+                               getnum, &defpregap,
+                               &speed,
+                               &load, &lock,
+                               &eject, &dummy, &msinfo, &toc, &atip,
+                               &multi, &fix, &nofix, &waiti, &immed,
+                               &debug, &debug,
+                               &kdebug, &kdebug,
+                               &lverbose, &lverbose,
+                               &scsi_verbose, &scsi_verbose,
+                               &xdebug, &xdebug,
+                               &silent, &silent,
+                               &audio, &data, &mode2,
+                               &xa, &xa1, &xa2, &xamix, &cdi,
+                               &isize,
+                               &nopreemp, &preemp,
+                               &nocopy, &copy,
+                               &nopad, &pad, &bswab, getnum, &fs, getnum, &bufsize,
+                               getbltype, &bltype, &doformat, getformattype, &formattype, &pktsize,
+                               &ispacket, &noclose, &force,
+                               &tao, &dao, &dao, &raw, &raw96r, &raw96p, &raw16,
+                               &clone,
+                               &scms, &isrc, &mcn, &tindex,
+                               &cuefile, &textfile, &usetext,
+                               &shorttrack, &noshorttrack,
+                               &gracetime, &dminbuf, &msifile)) < 0) {
+                       errmsgno(EX_BAD, "Bad Option: %s.\n", cav[0]);
+                       susage(EX_BAD);
+               }
+               if (help)
+                       usage(0);
+               if (tracks == 0) {
+                       if (driver)
+                               set_cdrcmds(driver, dpp);
+                       if (version)
+                               *flagsp |= F_VERSION;
+                       if (checkdrive)
+                               *flagsp |= F_CHECKDRIVE;
+                       if (prcap)
+                               *flagsp |= F_PRCAP;
+                       if (inq)
+                               *flagsp |= F_INQUIRY;
+                       if (scanbus || scandevs) /* scandevs behaves similarly WRT in the legacy code, just the scan operation is different */
+                               *flagsp |= F_SCANBUS;
+                       if (reset)
+                               *flagsp |= F_RESET;
+                       if (doabort)
+                               *flagsp |= F_ABORT;
+                       if (overburn)
+                               *flagsp |= F_OVERBURN;
+                       if (ignsize)
+                               *flagsp |= F_IGNSIZE;
+                       if (load)
+                               *flagsp |= F_LOAD;
+                       if (lock)
+                               *flagsp |= F_DLCK;
+                       if (eject)
+                               *flagsp |= F_EJECT;
+                       if (dummy)
+                               *flagsp |= F_DUMMY;
+                       if (setdropts)
+                               *flagsp |= F_SETDROPTS;
+                       if(msifile)
+                               msinfo++;
+                       if (msinfo)
+                               *flagsp |= F_MSINFO;
+                       if (toc) {
+                               *flagsp |= F_TOC;
+                               *flagsp &= ~F_WRITE;
+                       }
+                       if (atip) {
+                               *flagsp |= F_PRATIP;
+                               *flagsp &= ~F_WRITE;
+                       }
+                       if (multi) {
+                               /*
+                                * 2048 Bytes user data
+                                */
+                               *flagsp |= F_MULTI;
+                               tracktype = TOC_XA2;
+                               sectype = ST_ROM_MODE2 | ST_MODE_2_FORM_1;
+                               sectype = SECT_MODE_2_F1;
+                               dbtype = DB_XA_MODE2;   /* XXX -multi nimmt DB_XA_MODE2_F1 !!! */
+                               secsize = DATA_SEC_SIZE;        /* 2048 */
+                               dataoff = 24;
+                       }
+                       if (fix)
+                               *flagsp |= F_FIX;
+                       if (nofix)
+                               *flagsp |= F_NOFIX;
+                       if (waiti)
+                               *flagsp |= F_WAITI;
+                       if (immed)
+                               *flagsp |= F_IMMED;
+                       if (force)
+                               *flagsp |= F_FORCE;
+
+                       if (bltype >= 0) {
+                               *flagsp |= F_BLANK;
+                               *blankp = bltype;
+                       }
+                       if (doformat > 0) {
+                               *flagsp |= F_FORMAT;
+                               *formatp |= FULL_FORMAT;
+                       }
+                       if (formattype >= 0) {
+                               *flagsp |= F_FORMAT;
+                               *formatp |= formattype;
+                       }
+                       if (ispacket)
+                               wm |= M_PACKET;
+                       if (tao)
+                               wm |= M_TAO;
+                       if (dao) {
+                               *flagsp |= F_SAO;
+                               trackp[0].flags &= ~TI_TAO;
+                               trackp[0].flags |= TI_SAO;
+                               wm |= M_SAO;
+
+                       } else if ((raw == 0) && (raw96r + raw96p + raw16) > 0)
+                               raw = 1;
+                       if ((raw != 0) && (raw96r + raw96p + raw16) == 0)
+                               raw96r = 1;
+                       if (raw96r) {
+                               if (!dao)
+                                       *flagsp |= F_RAW;
+                               trackp[0].flags &= ~TI_TAO;
+                               trackp[0].flags |= TI_RAW;
+                               trackp[0].flags |= TI_RAW96R;
+                               wm |= M_RAW;
+                       }
+                       if (raw96p) {
+                               if (!dao)
+                                       *flagsp |= F_RAW;
+                               trackp[0].flags &= ~TI_TAO;
+                               trackp[0].flags |= TI_RAW;
+                               wm |= M_RAW;
+                       }
+                       if (raw16) {
+                               if (!dao)
+                                       *flagsp |= F_RAW;
+                               trackp[0].flags &= ~TI_TAO;
+                               trackp[0].flags |= TI_RAW;
+                               trackp[0].flags |= TI_RAW16;
+                               wm |= M_RAW;
+                       }
+                       if (mcn) {
+#ifdef AUINFO
+                               setmcn(mcn, &trackp[0]);
+#else
+                               trackp[0].isrc = malloc(16);
+                               fillbytes(trackp[0].isrc, 16, '\0');
+                               strncpy(trackp[0].isrc, mcn, 13);
+#endif
+                               mcn = NULL;
+                       }
+                       if ((raw96r + raw96p + raw16) > 1) {
+                               errmsgno(EX_BAD, "Too many raw modes.\n");
+                               comerrno(EX_BAD, "Only one of -raw16, -raw96p, -raw96r allowed.\n");
+                       }
+                       if ((tao + ispacket + dao + raw) > 1) {
+                               errmsgno(EX_BAD, "Too many write modes.\n");
+                               comerrno(EX_BAD, "Only one of -packet, -dao, -raw allowed.\n");
+                       }
+                       if (dao && (raw96r + raw96p + raw16) > 0) {
+                               if (raw16)
+                                       comerrno(EX_BAD, "SAO RAW writing does not allow -raw16.\n");
+                               if (!clone)
+                                       comerrno(EX_BAD, "SAO RAW writing only makes sense in clone mode.\n");
+#ifndef        CLONE_WRITE
+                               comerrno(EX_BAD, "SAO RAW writing not yet implemented.\n");
+#endif
+                               comerrno(EX_BAD, "SAO RAW writing not yet implemented.\n");
+                       }
+                       if (clone) {
+                               *flagsp |= F_CLONE;
+                               trackp[0].flags |= TI_CLONE;
+#ifndef        CLONE_WRITE
+                               comerrno(EX_BAD, "Clone writing not compiled in.\n");
+#endif
+                       }
+                       if (textfile) {
+                               if (!checktextfile(textfile)) {
+                                       if ((*flagsp & F_WRITE) != 0) {
+                                               comerrno(EX_BAD,
+                                                       "Cannot use '%s' as CD-Text file.\n",
+                                                       textfile);
+                                       }
+                               }
+                               if ((*flagsp & F_WRITE) != 0) {
+                                       if ((dao + raw96r + raw96p) == 0)
+                                               comerrno(EX_BAD,
+                                                       "CD-Text needs -dao, -raw96r or -raw96p.\n");
+                               }
+                               trackp[0].flags |= TI_TEXT;
+                       }
+                       version = checkdrive = prcap = inq = scanbus = reset = doabort =
+                       overburn = ignsize =
+                       load = lock = eject = dummy = msinfo = toc = atip = multi = fix = nofix =
+                       waiti = immed = force = dao = setdropts = 0;
+                       raw96r = raw96p = raw16 = clone = 0;
+               } else if ((version + checkdrive + prcap + inq + scanbus +
+                           reset + doabort + overburn + ignsize +
+                           load + lock + eject + dummy + msinfo + toc + atip + multi + fix + nofix +
+                           waiti + immed + force + dao + setdropts +
+                           raw96r + raw96p + raw16 + clone) > 0 ||
+                               mcn != NULL)
+                       comerrno(EX_BAD, "Badly placed option. Global options must be before any track.\n");
+
+               if (nopreemp)
+                       preemp = 0;
+               if (nocopy)
+                       copy = 0;
+               if (nopad)
+                       pad = 0;
+               if (noshorttrack)
+                       shorttrack = 0;
+
+               if ((audio + data + mode2 + xa + xa1 + xa2 + xamix) > 1) {
+                       errmsgno(EX_BAD, "Too many types for track %d.\n", tracks+1);
+                       comerrno(EX_BAD, "Only one of -audio, -data, -mode2, -xa, -xa1, -xa2, -xamix allowed.\n");
+               }
+               if (ispacket && audio) {
+                       comerrno(EX_BAD, "Audio data cannot be written in packet mode.\n");
+               }
+               /*
+                * Check whether the next argument is a file type arg.
+                * If this is true, then we got a track file name.
+                * If getargs() did previously return NOTAFLAG, we may have hit
+                * an argument that has been escaped via "--", so we may not
+                * call getfiles() again in this case. If we would call
+                * getfiles() and the current arg has been escaped and looks
+                * like an option, a call to getfiles() would skip it.
+                */
+               if (ga_ret != NOTAFLAG)
+                       ga_ret = getfiles(&cac, &cav, opts);
+               if (autoaudio) {
+                       autoaudio = 0;
+                       tracktype = TOC_ROM;
+                       sectype = ST_ROM_MODE1 | ST_MODE_1;
+                       sectype = SECT_ROM;
+                       dbtype = DB_ROM_MODE1;
+                       secsize = DATA_SEC_SIZE;        /* 2048 */
+                       dataoff = 16;
+               }
+               if (ga_ret == NOTAFLAG && (is_auname(cav[0]) || is_wavname(cav[0]))) {
+                       /*
+                        * We got a track and autodetection decided that it
+                        * is an audio track.
+                        */
+                       autoaudio++;
+                       audio++;
+               }
+               if (data) {
+                       /*
+                        * 2048 Bytes user data
+                        */
+                       tracktype = TOC_ROM;
+                       sectype = ST_ROM_MODE1 | ST_MODE_1;
+                       sectype = SECT_ROM;
+                       dbtype = DB_ROM_MODE1;
+                       secsize = DATA_SEC_SIZE;        /* 2048 */
+                       dataoff = 16;
+               }
+               if (mode2) {
+                       /*
+                        * 2336 Bytes user data
+                        */
+                       tracktype = TOC_ROM;
+                       sectype = ST_ROM_MODE2 | ST_MODE_2;
+                       sectype = SECT_MODE_2;
+                       dbtype = DB_ROM_MODE2;
+                       secsize = MODE2_SEC_SIZE;       /* 2336 */
+                       dataoff = 16;
+               }
+               if (audio) {
+                       /*
+                        * 2352 Bytes user data
+                        */
+                       tracktype = TOC_DA;
+                       sectype = preemp ? ST_AUDIO_PRE : ST_AUDIO_NOPRE;
+                       sectype |= ST_MODE_AUDIO;
+                       sectype = SECT_AUDIO;
+                       if (preemp)
+                               sectype |= ST_PREEMPMASK;
+                       dbtype = DB_RAW;
+                       secsize = AUDIO_SEC_SIZE;       /* 2352 */
+                       dataoff = 0;
+               }
+               if (xa) {
+                       /*
+                        * 2048 Bytes user data
+                        */
+                       if (tracktype != TOC_CDI)
+                               tracktype = TOC_XA2;
+                       sectype = ST_ROM_MODE2 | ST_MODE_2_FORM_1;
+                       sectype = SECT_MODE_2_F1;
+                       dbtype = DB_XA_MODE2;
+                       secsize = DATA_SEC_SIZE;        /* 2048 */
+                       dataoff = 24;
+               }
+               if (xa1) {
+                       /*
+                        * 8 Bytes subheader + 2048 Bytes user data
+                        */
+                       if (tracktype != TOC_CDI)
+                               tracktype = TOC_XA2;
+                       sectype = ST_ROM_MODE2 | ST_MODE_2_FORM_1;
+                       sectype = SECT_MODE_2_F1;
+                       dbtype = DB_XA_MODE2_F1;
+                       secsize = 2056;
+                       dataoff = 16;
+               }
+               if (xa2) {
+                       /*
+                        * 2324 Bytes user data
+                        */
+                       if (tracktype != TOC_CDI)
+                               tracktype = TOC_XA2;
+                       sectype = ST_ROM_MODE2 | ST_MODE_2_FORM_2;
+                       sectype = SECT_MODE_2_F2;
+                       dbtype = DB_XA_MODE2_F2;
+                       secsize = 2324;
+                       dataoff = 24;
+               }
+               if (xamix) {
+                       /*
+                        * 8 Bytes subheader + 2324 Bytes user data
+                        */
+                       if (tracktype != TOC_CDI)
+                               tracktype = TOC_XA2;
+                       sectype = ST_ROM_MODE2 | ST_MODE_2_MIXED;
+                       sectype = SECT_MODE_2_MIX;
+                       dbtype = DB_XA_MODE2_MIX;
+                       secsize = 2332;
+                       dataoff = 16;
+               }
+               if (cdi) {
+                       tracktype = TOC_CDI;
+               }
+               if (tracks == 0) {
+                       trackp[0].tracktype = tracktype;
+                       trackp[0].dbtype = dbtype;
+                       trackp[0].isecsize = secsize;
+                       trackp[0].secsize = secsize;
+                       if ((*flagsp & F_RAW) != 0) {
+                               trackp[0].secsize = is_raw16(&trackp[0]) ?
+                                               RAW16_SEC_SIZE:RAW96_SEC_SIZE;
+                       }
+                       if ((*flagsp & F_DUMMY) != 0)
+                               trackp[0].tracktype |= TOCF_DUMMY;
+                       if ((*flagsp & F_MULTI) != 0)
+                               trackp[0].tracktype |= TOCF_MULTI;
+               }
+
+               flags = trackp[0].flags;
+
+               if ((sectype & ST_AUDIOMASK) != 0)
+                       flags |= TI_AUDIO;
+               if (isize) {
+                       flags |= TI_ISOSIZE;
+                       if ((*flagsp & F_MULTI) != 0)
+                               comerrno(EX_BAD, "Cannot get isosize for multi session disks.\n");
+                       /*
+                        * As we do not get the padding from the ISO-9660
+                        * formatting utility, we need to force padding here.
+                        */
+                       flags |= TI_PAD;
+                       if (padsize == (Llong)0L)
+                               padsize = (Llong)PAD_SIZE;
+               }
+
+               if ((flags & TI_AUDIO) != 0) {
+                       if (preemp)
+                               flags |= TI_PREEMP;
+                       if (copy)
+                               flags |= TI_COPY;
+                       if (scms)
+                               flags |= TI_SCMS;
+               }
+               if (pad || ((flags & TI_AUDIO) == 0 && padsize > (Llong)0L)) {
+                       flags |= TI_PAD;
+                       if ((flags & TI_AUDIO) == 0 && padsize == (Llong)0L)
+                               padsize = (Llong)PAD_SIZE;
+               }
+               if (shorttrack && (*flagsp & (F_SAO|F_RAW)) != 0)
+                       flags |= TI_SHORT_TRACK;
+               if (noshorttrack)
+                       flags &= ~TI_SHORT_TRACK;
+               if (bswab)
+                       flags |= TI_SWAB;
+               if (ispacket) {
+                       flags |= TI_PACKET;
+                       trackp[0].flags &= ~TI_TAO;
+               }
+               if (noclose)
+                       flags |= TI_NOCLOSE;
+               if (useinfo)
+                       flags |= TI_USEINFO;
+
+               if (ga_ret == NOARGS) {
+                       /*
+                        * All options have already been parsed and no more
+                        * file type arguments are present.
+                        */
+                       break;
+               }
+               if (tracks == 0 && (wm == 0)) {
+                       errmsgno(EX_BAD, "No write mode specified.\n");
+                       errmsgno(EX_BAD, "Assuming -tao mode.\n");
+                       errmsgno(EX_BAD, "Future versions of wodim may have different drive dependent defaults.\n");
+                       tao = 1;
+               }
+               tracks++;
+
+               if (tracks > MAX_TRACK)
+                       comerrno(EX_BAD, "Track limit (%d) exceeded\n",
+                                                               MAX_TRACK);
+               /*
+                * Make 'tracks' immediately usable in track structure.
+                */
+               {       register int i;
+                       for (i = 0; i < MAX_TRACK+2; i++)
+                               trackp[i].tracks = tracks;
+               }
+
+               if (strcmp("-", cav[0]) == 0)
+                       *flagsp |= F_STDIN;
+
+               if (!is_auname(cav[0]) && !is_wavname(cav[0]))
+                       flags |= TI_NOAUHDR;
+
+               if ((*flagsp & (F_SAO|F_RAW)) != 0 && (flags & TI_AUDIO) != 0)
+                       flags |= TI_PREGAP;     /* Hack for now */
+               if (tracks == 1)
+                       flags &= ~TI_PREGAP;
+
+               if (tracks == 1 && (pregapsize != -1L && pregapsize != 150))
+                       pregapsize = -1L;
+               trackp[tracks].filename = cav[0];
+               trackp[tracks].trackstart = 0L;
+               trackp[tracks].itracksize = tracksize;
+               trackp[tracks].tracksize = tracksize;
+               trackp[tracks].tracksecs = -1L;
+               if (tracksize >= 0) {
+                       trackp[tracks].tracksecs = (tracksize+secsize-1)/secsize;
+                       if(tracksize<616448)
+                               warn_minisize=tracksize;
+               }
+               if (trackp[tracks].pregapsize < 0)
+                       trackp[tracks].pregapsize = pregapsize;
+               trackp[tracks+1].pregapsize = -1;
+               trackp[tracks].padsecs = (padsize+2047)/2048;
+               trackp[tracks].isecsize = secsize;
+               trackp[tracks].secsize = secsize;
+               trackp[tracks].flags = flags;
+               /*
+                * XXX Dies ist falsch: auch bei SAO/RAW kann
+                * XXX secsize != isecsize sein.
+                */
+               if ((*flagsp & F_RAW) != 0) {
+                       if (is_raw16(&trackp[tracks]))
+                               trackp[tracks].secsize = RAW16_SEC_SIZE;
+                       else
+                               trackp[tracks].secsize = RAW96_SEC_SIZE;
+#ifndef        HAVE_LIB_EDC_ECC
+                       if ((sectype & ST_MODE_MASK) != ST_MODE_AUDIO) {
+                               errmsgno(EX_BAD,
+                                       "EDC/ECC library not compiled in.\n");
+                               comerrno(EX_BAD,
+                                       "Data sectors are not supported in RAW mode.\n");
+                       }
+#endif
+               }
+               trackp[tracks].secspt = 0;      /* transfer size is set up in set_trsizes() */
+               trackp[tracks].pktsize = pktsize;
+               trackp[tracks].trackno = tracks;
+               trackp[tracks].sectype = sectype;
+#ifdef CLONE_WRITE
+               if ((*flagsp & F_CLONE) != 0) {
+                       trackp[tracks].isecsize = 2448;
+                       trackp[tracks].sectype |= ST_MODE_RAW;
+                       dataoff = 0;
+               }
+#endif
+               trackp[tracks].dataoff = dataoff;
+               trackp[tracks].tracktype = tracktype;
+               trackp[tracks].dbtype = dbtype;
+               trackp[tracks].flags = flags;
+               trackp[tracks].nindex = 1;
+               trackp[tracks].tindex = 0;
+               if (isrc) {
+#ifdef AUINFO
+                       setisrc(isrc, &trackp[tracks]);
+#else
+                       trackp[tracks].isrc = malloc(16);
+                       fillbytes(trackp[tracks].isrc, 16, '\0');
+                       strncpy(trackp[tracks].isrc, isrc, 12);
+#endif
+               }
+               if (tindex) {
+#ifdef AUINFO
+                       setindex(tindex, &trackp[tracks]);
+#endif
+               }
+       }
+
+       if (dminbuf >= 0) {
+               if (dminbuf < 25 || dminbuf > 95)
+                       comerrno(EX_BAD,
+                       "Bad minbuf=%d option (must be between 25 and 95)\n",
+                               dminbuf);
+       }
+
+       if (speed < 0 && speed != -1)
+               comerrno(EX_BAD, "Bad speed option.\n");
+
+       if (fs < 0L && fs != -1L)
+               comerrno(EX_BAD, "Bad fifo size option.\n");
+
+       if (bufsize < 0L && bufsize != -1L)
+               comerrno(EX_BAD, "Bad transfer size option.\n");
+       if (bufsize < 0L)
+               bufsize = CDR_BUF_SIZE;
+       if (bufsize > CDR_MAX_BUF_SIZE)
+               bufsize = CDR_MAX_BUF_SIZE;
+
+       dev = *devp;
+       cdr_defaults(&dev, &speed, &fs, &driveropts);
+       if (debug) {
+               printf("dev: '%s' speed: %d fs: %ld driveropts '%s'\n",
+                                       dev, speed, fs, driveropts);
+       }
+       if (speed >= 0)
+               *speedp = speed;
+
+       if (fs < 0L)
+               fs = DEFAULT_FIFOSIZE;
+       if (fs < 2*bufsize) {
+               errmsgno(EX_BAD, "Fifo size %ld too small, turning fifo off.\n", fs);
+               fs = 0L;
+       }
+
+       if (dev != *devp && (*flagsp & F_SCANBUS) == 0)
+               *devp = dev;
+
+       if (*devp &&
+           ((strncmp(*devp, "HELP", 4) == 0) ||
+           (strncmp(*devp, "help", 4) == 0))) {
+               *flagsp |= F_CHECKDRIVE; /* Set this for not calling mlockall() */
+               return ispacket;
+       }
+       if (*flagsp & (F_LOAD|F_DLCK|F_SETDROPTS|F_MSINFO|F_TOC|F_PRATIP|F_FIX|F_VERSION|F_CHECKDRIVE|F_PRCAP|F_INQUIRY|F_SCANBUS|F_RESET|F_ABORT)) {
+               if (tracks != 0) {
+       fprintf(stderr,
+             "No tracks allowed with -load, -lock, -setdropts, -msinfo, -toc, -atip, -fix,\n"
+             "-version, -checkdrive, -prcap, -inq, -scanbus, --devices, -reset and -abort options.\n" );
+       exit(EXIT_FAILURE);
+               }
+               return ispacket;
+       }
+       *tracksp = tracks;
+       if (*flagsp & F_SAO) {
+               /*
+                * Make sure that you change WRITER_MAXWAIT & READER_MAXWAIT
+                * too if you change this timeout.
+                */
+               if (*timeoutp < 200)            /* Lead in size is 2:30 */
+                       *timeoutp = 200;        /* 200s is 150s *1.33   */
+       }
+       if (usetext) {
+               trackp[MAX_TRACK+1].flags |= TI_TEXT;
+       }
+       if (cuefile) {
+#ifdef FUTURE
+               if ((*flagsp & F_SAO) == 0 &&
+                   (*flagsp & F_RAW) == 0) {
+#else
+               if ((*flagsp & F_SAO) == 0) {
+#endif
+                       errmsgno(EX_BAD, "The cuefile= option only works with -dao.\n");
+                       susage(EX_BAD);
+               }
+               if (tracks > 0) {
+                       errmsgno(EX_BAD, "No tracks allowed with the cuefile= option\n");
+                       susage(EX_BAD);
+               }
+               cuefilename = cuefile;
+               return ispacket;
+       }
+       if (tracks == 0 && (*flagsp & (F_LOAD|F_DLCK|F_EJECT|F_BLANK|F_FORMAT)) == 0) {
+               errmsgno(EX_BAD, "No tracks specified. Need at least one.\n");
+               susage(EX_BAD);
+       }
+       return ispacket;
+}
+
+static void 
+set_trsizes(cdr_t *dp, int tracks, track_t *trackp)
+{
+       int     i;
+       int     secsize;
+       int     secspt;
+
+       trackp[1].flags         |= TI_FIRST;
+       trackp[tracks].flags    |= TI_LAST;
+
+       if (xdebug)
+               printf("Set Transfersizes start\n");
+       for (i = 0; i <= tracks+1; i++) {
+               if ((dp->cdr_flags & CDR_SWABAUDIO) != 0 &&
+                                       is_audio(&trackp[i])) {
+                       trackp[i].flags ^= TI_SWAB;
+               }
+               if (!is_audio(&trackp[i]))
+                       trackp[i].flags &= ~TI_SWAB;    /* Only swab audio  */
+
+               /*
+                * Use the biggest sector size to compute how many
+                * sectors may fit into one single DMA buffer.
+                */
+               secsize = trackp[i].secsize;
+               if (trackp[i].isecsize > secsize)
+                       secsize = trackp[i].isecsize;
+
+               /*
+                * We are using SCSI Group 0 write
+                * and cannot write more than 255 secs at once.
+                */
+               secspt = bufsize/secsize;
+               secspt = min(255, secspt);
+               trackp[i].secspt = secspt;
+
+               if (is_packet(&trackp[i]) && trackp[i].pktsize > 0) {
+                       if (trackp[i].secspt >= trackp[i].pktsize) {
+                               trackp[i].secspt = trackp[i].pktsize;
+                       } else {
+                               comerrno(EX_BAD,
+                                       "Track %d packet size %d exceeds buffer limit of %d sectors",
+                                       i, trackp[i].pktsize, trackp[i].secspt);
+                       }
+               }
+               if (xdebug) {
+                       printf("Track %d flags %X secspt %d secsize: %d isecsize: %d\n",
+                               i, trackp[i].flags, trackp[i].secspt,
+                               trackp[i].secsize, trackp[i].isecsize);
+               }
+       }
+       if (xdebug)
+               printf("Set Transfersizes end\n");
+}
+
+void 
+load_media(SCSI *usalp, cdr_t *dp, BOOL doexit)
+{
+       int     code;
+       int     key;
+       BOOL    immed = (dp->cdr_cmdflags&F_IMMED) != 0;
+
+       /*
+        * Do some preparation before...
+        */
+       usalp->silent++;                        /* Be quiet if this fails               */
+       test_unit_ready(usalp);         /* First eat up unit attention          */
+       if ((*dp->cdr_load)(usalp, dp) < 0) {   /* now try to load media and    */
+               if (!doexit)
+                       return;
+               comerrno(EX_BAD, "Cannot load media.\n");
+       }
+       scsi_start_stop_unit(usalp, 1, 0, immed); /* start unit in silent mode  */
+       usalp->silent--;
+
+       if (!wait_unit_ready(usalp, 60)) {
+               code = usal_sense_code(usalp);
+               key = usal_sense_key(usalp);
+               usalp->silent++;
+               scsi_prevent_removal(usalp, 0); /* In case someone locked it */
+               usalp->silent--;
+
+               if (!doexit)
+                       return;
+               if (key == SC_NOT_READY && (code == 0x3A || code == 0x30))
+                       comerrno(EX_BAD, "No disk / Wrong disk!\n");
+               comerrno(EX_BAD, "CD/DVD-Recorder not ready.\n");
+       }
+
+       scsi_prevent_removal(usalp, 1);
+       scsi_start_stop_unit(usalp, 1, 0, immed);
+       wait_unit_ready(usalp, 120);
+       usalp->silent++;
+       if(geteuid() == 0) /* EB: needed? Not allowed for non-root, that is sure. */
+      rezero_unit(usalp);      /* Is this needed? Not supported by some drvives */
+       usalp->silent--;
+       test_unit_ready(usalp);
+       scsi_start_stop_unit(usalp, 1, 0, immed);
+       wait_unit_ready(usalp, 120);
+}
+
+void 
+unload_media(SCSI *usalp, cdr_t *dp, int flags)
+{
+       scsi_prevent_removal(usalp, 0);
+       if ((flags & F_EJECT) != 0) {
+               if ((*dp->cdr_unload)(usalp, dp) < 0)
+                       errmsgno(EX_BAD, "Cannot eject media.\n");
+       }
+}
+
+void 
+reload_media(SCSI *usalp, cdr_t *dp)
+{
+       char    ans[2];
+#ifdef F_GETFL
+       int     f = -1;
+#endif
+
+       errmsgno(EX_BAD, "Drive needs to reload the media to return to proper status.\n");
+       unload_media(usalp, dp, F_EJECT);
+
+       /*
+        * Note that even Notebook drives identify as CDR_TRAYLOAD
+        */
+       if ((dp->cdr_flags & CDR_TRAYLOAD) != 0) {
+               usalp->silent++;
+               load_media(usalp, dp, FALSE);
+               usalp->silent--;
+       }
+
+       usalp->silent++;
+       if (((dp->cdr_flags & CDR_TRAYLOAD) == 0) ||
+                               !wait_unit_ready(usalp, 5)) {
+               static FILE     *tty = NULL;
+
+               printf("Re-load disk and hit <CR>");
+               if (isgui)
+                       printf("\n");
+               flush();
+
+               if (tty == NULL) {
+                       tty = stdin;
+                       if ((dp->cdr_cmdflags & F_STDIN) != 0)
+                               tty = fileluopen(STDERR_FILENO, "rw");
+               }
+#ifdef F_GETFL
+               if (tty != NULL)
+                       f = fcntl(fileno(tty), F_GETFL, 0);
+               if (f < 0 || (f & O_ACCMODE) == O_WRONLY) {
+#ifdef SIGUSR1
+                       signal(SIGUSR1, catchsig);
+                       printf("Controlling file not open for reading, send SIGUSR1 to continue.\n");
+                       flush();
+                       pause();
+#endif
+               } else
+#endif
+               if (rols_fgetline(tty, ans, 1) < 0)
+                       comerrno(EX_BAD, "Aborted by EOF on input.\n");
+       }
+       usalp->silent--;
+
+       load_media(usalp, dp, TRUE);
+}
+
+void 
+set_secsize(SCSI *usalp, int secsize)
+{
+       if (secsize > 0) {
+               /*
+                * Try to restore the old sector size.
+                */
+               usalp->silent++;
+               select_secsize(usalp, secsize);
+               usalp->silent--;
+       }
+}
+
+static int 
+get_dmaspeed(SCSI *usalp, cdr_t *dp)
+{
+       int     i;
+       long    t;
+       int     bs;
+       int     tsize;
+
+  if(getenv("CDR_NODMATEST"))
+     return -1;
+
+  if (debug || lverbose)
+     fprintf( stderr, 
+           "Beginning DMA speed test. Set CDR_NODMATEST environment variable if device\n"
+           "communication breaks or freezes immediately after that.\n" );
+
+       fillbytes((caddr_t)buf, 4, '\0');
+       tsize = 0;
+       usalp->silent++;
+       i = read_buffer(usalp, buf, 4, 0);
+       usalp->silent--;
+       if (i < 0)
+               return (-1);
+       tsize = a_to_u_4_byte(buf);
+       if (tsize <= 0)
+               return (-1);
+
+       if (gettimeofday(&starttime, (struct timezone *)0) < 0)
+               return (-1);
+
+       bs = bufsize;
+       if (tsize < bs)
+               bs = tsize;
+       for (i = 0; i < 100; i++) {
+               if (read_buffer(usalp, buf, bs, 0) < 0)
+                       return (-1);
+       }
+       if (gettimeofday(&fixtime, (struct timezone *)0) < 0) {
+               errmsg("Cannot get DMA stop time\n");
+               return (-1);
+       }
+       timevaldiff(&starttime, &fixtime);
+       tsize = bs * 100;
+       t = fixtime.tv_sec * 1000 + fixtime.tv_usec / 1000;
+       if (t <= 0)
+               return (-1);
+#ifdef DEBUG
+       fprintf(stderr, "Read Speed: %lu %ld %ld kB/s %ldx CD %ldx DVD\n",
+               tsize, t, tsize/t, tsize/t/176, tsize/t/1385);
+#endif
+
+       return (tsize/t);
+}
+
+
+static BOOL 
+do_opc(SCSI *usalp, cdr_t *dp, int flags)
+{
+       if ((flags & F_DUMMY) == 0 && dp->cdr_opc) {
+               if (debug || lverbose) {
+                       printf("Performing OPC...\n");
+                       flush();
+               }
+               if (dp->cdr_opc(usalp, NULL, 0, TRUE) < 0) {
+                       errmsgno(EX_BAD, "OPC failed.\n");
+                       if ((flags & F_FORCE) == 0)
+                               return (FALSE);
+               }
+       }
+       return (TRUE);
+}
+
+static void 
+check_recovery(SCSI *usalp, cdr_t *dp, int flags)
+{
+       if ((*dp->cdr_check_recovery)(usalp, dp)) {
+               errmsgno(EX_BAD, "Recovery needed.\n");
+               unload_media(usalp, dp, flags);
+               comexit(EX_BAD);
+       }
+}
+
+#ifndef        DEBUG
+#define        DEBUG
+#endif
+void 
+audioread(SCSI *usalp, cdr_t *dp, int flags)
+{
+#ifdef DEBUG
+       int speed = 1;
+       int     oflags = dp->cdr_cmdflags;
+
+       dp->cdr_cmdflags &= ~F_DUMMY;
+       if ((*dp->cdr_set_speed_dummy)(usalp, dp, &speed) < 0)
+               comexit(-1);
+       dp->cdr_dstat->ds_wspeed = speed; /* XXX Remove 'speed' in future */
+       dp->cdr_cmdflags = oflags;
+
+       if ((*dp->cdr_set_secsize)(usalp, 2352) < 0)
+               comexit(-1);
+       usalp->cap->c_bsize = 2352;
+
+       read_scsi(usalp, buf, 1000, 1);
+       printf("XXX:\n");
+       write(1, buf, 512); /* FIXME: handle return value */
+       unload_media(usalp, dp, flags);
+       comexit(0);
+#endif
+}
+
+static void 
+print_msinfo(SCSI *usalp, cdr_t *dp)
+{
+       long    off;
+       long    fa;
+
+       if ((*dp->cdr_session_offset)(usalp, &off) < 0) {
+               errmsgno(EX_BAD, "Cannot read session offset\n");
+               return;
+       }
+       if (lverbose)
+               printf("session offset: %ld\n", off);
+
+       if (dp->cdr_next_wr_address(usalp, (track_t *)0, &fa) < 0) {
+               errmsgno(EX_BAD, "Cannot read first writable address\n");
+               return;
+       }
+       printf("%ld,%ld\n", off, fa);
+       if(msifile) {
+               FILE *f = fopen(msifile, "w");
+               if(f) {
+                       fprintf(f, "%ld,%ld", off, fa);
+                       fclose(f);
+               }
+               else {
+                       perror("Unable to write multi session info file");
+                       exit(EXIT_FAILURE);
+               }
+       }
+}
+
+static void 
+print_toc(SCSI *usalp, cdr_t *dp)
+{
+       int     first;
+       int     last;
+       long    lba;
+       long    xlba;
+       struct msf msf;
+       int     adr;
+       int     control;
+       int     mode;
+       int     i;
+
+       usalp->silent++;
+       if (read_capacity(usalp) < 0) {
+               usalp->silent--;
+               errmsgno(EX_BAD, "Cannot read capacity\n");
+               return;
+       }
+       usalp->silent--;
+       if (read_tochdr(usalp, dp, &first, &last) < 0) {
+               errmsgno(EX_BAD, "Cannot read TOC/PMA\n");
+               return;
+       }
+       printf("first: %d last %d\n", first, last);
+       for (i = first; i <= last; i++) {
+               read_trackinfo(usalp, i, &lba, &msf, &adr, &control, &mode);
+               xlba = -150 +
+                       msf.msf_frame + (75*msf.msf_sec) + (75*60*msf.msf_min);
+               if (xlba == lba/4)
+                       lba = xlba;
+               print_track(i, lba, &msf, adr, control, mode);
+       }
+       i = 0xAA;
+       read_trackinfo(usalp, i, &lba, &msf, &adr, &control, &mode);
+       xlba = -150 +
+               msf.msf_frame + (75*msf.msf_sec) + (75*60*msf.msf_min);
+       if (xlba == lba/4)
+               lba = xlba;
+       print_track(i, lba, &msf, adr, control, mode);
+       if (lverbose > 1) {
+               usalp->silent++;
+               if (read_cdtext(usalp) < 0)
+                       errmsgno(EX_BAD, "No CD-Text or CD-Text unaware drive.\n");
+               usalp->silent++;
+       }
+}
+
+static void 
+print_track(int track, long lba, struct msf *msp, int adr, 
+                               int control, int mode)
+{
+       long    lba_512 = lba*4;
+
+       if (track == 0xAA)
+               printf("track:lout ");
+       else
+               printf("track: %3d ", track);
+
+       printf("lba: %9ld (%9ld) %02d:%02d:%02d adr: %X control: %X mode: %d\n",
+                       lba, lba_512,
+                       msp->msf_min,
+                       msp->msf_sec,
+                       msp->msf_frame,
+                       adr, control, mode);
+}
+
+#ifdef HAVE_SYS_PRIOCNTL_H     /* The preferred SYSvR4 schduler */
+
+#include <sys/procset.h>       /* Needed for SCO Openserver */
+#include <sys/priocntl.h>
+#include <sys/rtpriocntl.h>
+
+void 
+raisepri(int pri)
+{
+       int             pid;
+       int             classes;
+       int             ret;
+       pcinfo_t        info;
+       pcparms_t       param;
+       rtinfo_t        rtinfo;
+       rtparms_t       rtparam;
+
+       pid = getpid();
+
+       /* get info */
+       strcpy(info.pc_clname, "RT");
+       classes = priocntl(P_PID, pid, PC_GETCID, (void *)&info);
+       if (classes == -1)
+               comerr("Cannot get priority class id priocntl(PC_GETCID)\n");
+
+       movebytes(info.pc_clinfo, &rtinfo, sizeof (rtinfo_t));
+
+       /* set priority to max */
+       rtparam.rt_pri = rtinfo.rt_maxpri - pri;
+       rtparam.rt_tqsecs = 0;
+       rtparam.rt_tqnsecs = RT_TQDEF;
+       param.pc_cid = info.pc_cid;
+       movebytes(&rtparam, param.pc_clparms, sizeof (rtparms_t));
+       ret = priocntl(P_PID, pid, PC_SETPARMS, (void *)&param);
+       if (ret == -1) {
+               errmsg("WARNING: Cannot set priority class parameters priocntl(PC_SETPARMS)\n");
+               errmsgno(EX_BAD, "WARNING: This causes a high risk for buffer underruns.\n");
+       }
+}
+
+#else  /* HAVE_SYS_PRIOCNTL_H */
+
+#if defined(_POSIX_PRIORITY_SCHEDULING) && _POSIX_PRIORITY_SCHEDULING -0 >= 0
+/*
+ * The second best choice: POSIX real time scheduling.
+ */
+/*
+ * XXX Ugly but needed because of a typo in /usr/iclude/sched.h on Linux.
+ * XXX This should be removed as soon as we are sure that Linux-2.0.29 is gone.
+ */
+#ifdef __linux
+#define        _P      __P
+#endif
+
+#include <sched.h>
+
+#ifdef __linux
+#undef _P
+#endif
+
+static int 
+rt_raisepri(int pri)
+{
+       struct sched_param scp;
+
+       /*
+        * Verify that scheduling is available
+        */
+#ifdef _SC_PRIORITY_SCHEDULING
+       if (sysconf(_SC_PRIORITY_SCHEDULING) == -1) {
+               errmsg("WARNING: RR-scheduler not available, disabling.\n");
+               return (-1);
+       }
+#endif
+       fillbytes(&scp, sizeof (scp), '\0');
+       scp.sched_priority = sched_get_priority_max(SCHED_RR) - pri;
+       if (sched_setscheduler(0, SCHED_RR, &scp) < 0) {
+               if(lverbose>2)
+       errmsg("WARNING: Cannot set RR-scheduler\n");
+               return (-1);
+       }
+       return (0);
+}
+
+#else  /* _POSIX_PRIORITY_SCHEDULING */
+
+#ifdef __CYGWIN32__
+/*
+ * Win32 specific priority settings.
+ */
+/*
+ * NOTE: Base.h from Cygwin-B20 has a second typedef for BOOL.
+ *      We define BOOL to make all static code use BOOL
+ *      from Windows.h and use the hidden __SBOOL for
+ *      our global interfaces.
+ *
+ * NOTE: windows.h from Cygwin-1.x includes a structure field named sample,
+ *      so me may not define our own 'sample' or need to #undef it now.
+ *      With a few nasty exceptions, Microsoft assumes that any global
+ *      defines or identifiers will begin with an Uppercase letter, so
+ *      there may be more of these problems in the future.
+ *
+ * NOTE: windows.h defines interface as an alias for struct, this
+ *      is used by COM/OLE2, I guess it is class on C++
+ *      We man need to #undef 'interface'
+ */
+#define        BOOL    WBOOL           /* This is the Win BOOL         */
+#define        format  __format        /* Avoid format parameter hides global ... */
+#include <windows.h>
+#undef format
+#undef interface
+
+static int 
+rt_raisepri(int pri)
+{
+       int prios[] = {THREAD_PRIORITY_TIME_CRITICAL, THREAD_PRIORITY_HIGHEST};
+
+       /* set priority class */
+       if (SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS) == FALSE) {
+               if(debug || lverbose>2)
+       errmsgno(EX_BAD, "No realtime priority class possible.\n");
+               return (-1);
+       }
+
+       /* set thread priority */
+       if (pri >= 0 && pri <= 1 && SetThreadPriority(GetCurrentThread(), prios[pri]) == FALSE) {
+               errmsgno(EX_BAD, "Could not set realtime priority.\n");
+               return (-1);
+       }
+       return (0);
+}
+
+#else
+/*
+ * This OS does not support real time scheduling.
+ */
+static int 
+rt_raisepri(int pri)
+{
+       return (-1);
+}
+
+#endif /* __CYGWIN32__ */
+
+#endif /* _POSIX_PRIORITY_SCHEDULING */
+
+void 
+raisepri(int pri)
+{
+       if (rt_raisepri(pri) >= 0)
+               return;
+#if    defined(HAVE_SETPRIORITY) && defined(PRIO_PROCESS)
+
+       if (setpriority(PRIO_PROCESS, getpid(), -20 + pri) < 0) {
+               if(debug || lverbose>2)
+       fprintf(stderr,
+             "WARNING: Cannot set priority using setpriority(),"
+             "increased risk for buffer underruns.\n");
+       }
+#else
+#ifdef HAVE_DOSSETPRIORITY     /* RT priority on OS/2 */
+       /*
+        * Set priority to timecritical 31 - pri (arg)
+        */
+       DosSetPriority(0, 3, 31, 0);
+       DosSetPriority(0, 3, -pri, 0);
+#else
+#if    defined(HAVE_NICE) && !defined(__DJGPP__) /* DOS has nice but no multitasking */
+       if (nice(-20 + pri) == -1) {
+               errmsg("WARNING: Cannot set priority using nice().\n");
+               errmsgno(EX_BAD, "WARNING: This causes a high risk for buffer underruns.\n");
+       }
+#else
+       errmsgno(EX_BAD, "WARNING: Cannot set priority on this OS.\n");
+       errmsgno(EX_BAD, "WARNING: This causes a high risk for buffer underruns.\n");
+#endif
+#endif
+#endif
+}
+
+#endif /* HAVE_SYS_PRIOCNTL_H */
+
+#ifdef HAVE_SELECT
+/*
+ * sys/types.h and sys/time.h are already included.
+ */
+#else
+#      include <stropts.h>
+#      include <poll.h>
+
+#ifndef        INFTIM
+#define        INFTIM  (-1)
+#endif
+#endif
+
+#if    defined(HAVE_SELECT) && defined(NEED_SYS_SELECT_H)
+#include <sys/select.h>
+#endif
+#if    defined(HAVE_SELECT) && defined(NEED_SYS_SOCKET_H)
+#include <sys/socket.h>
+#endif
+
+static void 
+wait_input()
+{
+#ifdef HAVE_SELECT
+       fd_set  in;
+
+       FD_ZERO(&in);
+       FD_SET(STDIN_FILENO, &in);
+       select(1, &in, NULL, NULL, 0);
+#else
+       struct pollfd pfd;
+
+       pfd.fd = STDIN_FILENO;
+       pfd.events = POLLIN;
+       pfd.revents = 0;
+       poll(&pfd, (unsigned long)1, INFTIM);
+#endif
+}
+
+static void 
+checkgui()
+{
+       struct stat st;
+
+       if (fstat(STDERR_FILENO, &st) >= 0 && !S_ISCHR(st.st_mode)) {
+               isgui = TRUE;
+               if (lverbose > 1)
+                       printf("Using remote (pipe) mode for interactive i/o.\n");
+       }
+}
+
+static int 
+getbltype(char *optstr, long *typep)
+{
+       if (streql(optstr, "all")) {
+               *typep = BLANK_DISC;
+       } else if (streql(optstr, "disc")) {
+               *typep = BLANK_DISC;
+       } else if (streql(optstr, "disk")) {
+               *typep = BLANK_DISC;
+       } else if (streql(optstr, "fast")) {
+               *typep = BLANK_MINIMAL;
+       } else if (streql(optstr, "minimal")) {
+               *typep = BLANK_MINIMAL;
+       } else if (streql(optstr, "track")) {
+               *typep = BLANK_TRACK;
+       } else if (streql(optstr, "unreserve")) {
+               *typep = BLANK_UNRESERVE;
+       } else if (streql(optstr, "trtail")) {
+               *typep = BLANK_TAIL;
+       } else if (streql(optstr, "unclose")) {
+               *typep = BLANK_UNCLOSE;
+       } else if (streql(optstr, "session")) {
+               *typep = BLANK_SESSION;
+       } else if (streql(optstr, "help")) {
+               blusage(0);
+       } else {
+               fprintf(stderr, "Illegal blanking type '%s'.\n", optstr);
+               blusage(EX_BAD);
+               return (-1);
+       }
+       return (TRUE);
+}
+
+static int 
+getformattype(char *optstr, long *typep)
+{
+       if (streql(optstr, "full")) {
+               *typep = FULL_FORMAT;
+       } else if (streql(optstr, "background")) {
+               *typep = BACKGROUND_FORMAT;
+       } else if (streql(optstr, "force")) {
+               *typep = FORCE_FORMAT;
+       } else if (streql(optstr, "help")) {
+               formattypeusage(0);
+       } else {
+               fprintf(stderr, "Illegal blanking type '%s'.\n", optstr);
+               formattypeusage(EX_BAD);
+               return (-1);
+       }
+       return (TRUE);
+}
+static void 
+print_drflags(cdr_t *dp)
+{
+       printf("Driver flags   : ");
+
+       if ((dp->cdr_flags & CDR_DVD) != 0)
+               printf("DVD ");
+
+       if ((dp->cdr_flags & CDR_MMC3) != 0)
+               printf("MMC-3 ");
+       else if ((dp->cdr_flags & CDR_MMC2) != 0)
+               printf("MMC-2 ");
+       else if ((dp->cdr_flags & CDR_MMC) != 0)
+               printf("MMC ");
+
+       if ((dp->cdr_flags & CDR_SWABAUDIO) != 0)
+               printf("SWABAUDIO ");
+       if ((dp->cdr_flags & CDR_BURNFREE) != 0)
+               printf("BURNFREE ");
+       if ((dp->cdr_flags & CDR_VARIREC) != 0)
+               printf("VARIREC ");
+       if ((dp->cdr_flags & CDR_GIGAREC) != 0)
+               printf("GIGAREC ");
+       if ((dp->cdr_flags & CDR_AUDIOMASTER) != 0)
+               printf("AUDIOMASTER ");
+       if ((dp->cdr_flags & CDR_FORCESPEED) != 0)
+               printf("FORCESPEED ");
+       if ((dp->cdr_flags & CDR_SPEEDREAD) != 0)
+               printf("SPEEDREAD ");
+       if ((dp->cdr_flags & CDR_DISKTATTOO) != 0)
+               printf("DISKTATTOO ");
+       if ((dp->cdr_flags & CDR_SINGLESESS) != 0)
+               printf("SINGLESESSION ");
+       if ((dp->cdr_flags & CDR_HIDE_CDR) != 0)
+               printf("HIDECDR ");
+       printf("\n");
+}
+
+static void 
+print_wrmodes(cdr_t *dp)
+{
+       BOOL    needblank = FALSE;
+
+       printf("Supported modes: ");
+       if ((dp->cdr_flags & CDR_TAO) != 0) {
+               printf("TAO");
+               needblank = TRUE;
+       }
+       if ((dp->cdr_flags & CDR_PACKET) != 0) {
+               printf("%sPACKET", needblank?" ":"");
+               needblank = TRUE;
+       }
+       if ((dp->cdr_flags & CDR_SAO) != 0) {
+               printf("%sSAO", needblank?" ":"");
+               needblank = TRUE;
+       }
+#ifdef __needed__
+       if ((dp->cdr_flags & (CDR_SAO|CDR_SRAW16)) == (CDR_SAO|CDR_SRAW16)) {
+               printf("%sSAO/R16", needblank?" ":"");
+               needblank = TRUE;
+       }
+#endif
+       if ((dp->cdr_flags & (CDR_SAO|CDR_SRAW96P)) == (CDR_SAO|CDR_SRAW96P)) {
+               printf("%sSAO/R96P", needblank?" ":"");
+               needblank = TRUE;
+       }
+       if ((dp->cdr_flags & (CDR_SAO|CDR_SRAW96R)) == (CDR_SAO|CDR_SRAW96R)) {
+               printf("%sSAO/R96R", needblank?" ":"");
+               needblank = TRUE;
+       }
+       if ((dp->cdr_flags & (CDR_RAW|CDR_RAW16)) == (CDR_RAW|CDR_RAW16)) {
+               printf("%sRAW/R16", needblank?" ":"");
+               needblank = TRUE;
+       }
+       if ((dp->cdr_flags & (CDR_RAW|CDR_RAW96P)) == (CDR_RAW|CDR_RAW96P)) {
+               printf("%sRAW/R96P", needblank?" ":"");
+               needblank = TRUE;
+       }
+       if ((dp->cdr_flags & (CDR_RAW|CDR_RAW96R)) == (CDR_RAW|CDR_RAW96R)) {
+               printf("%sRAW/R96R", needblank?" ":"");
+               needblank = TRUE;
+       }
+       printf("\n");
+}
+
+static BOOL 
+check_wrmode(cdr_t *dp, int wmode, int tflags)
+{
+       int     cdflags = dp->cdr_flags;
+
+       if ((tflags & TI_PACKET) != 0 && (cdflags & CDR_PACKET) == 0) {
+               errmsgno(EX_BAD, "Drive does not support PACKET recording.\n");
+               return (FALSE);
+       }
+       if ((tflags & TI_TAO) != 0 && (cdflags & CDR_TAO) == 0) {
+               errmsgno(EX_BAD, "Drive does not support TAO recording.\n");
+               return (FALSE);
+       }
+       if ((wmode & F_SAO) != 0) {
+               if ((cdflags & CDR_SAO) == 0) {
+                       errmsgno(EX_BAD, "Drive does not support SAO recording.\n");
+                       if ((cdflags & CDR_RAW) != 0)
+                               errmsgno(EX_BAD, "Try -raw option.\n");
+                       return (FALSE);
+               }
+#ifdef __needed__
+               if ((tflags & TI_RAW16) != 0 && (cdflags & CDR_SRAW16) == 0) {
+                       errmsgno(EX_BAD, "Drive does not support SAO/RAW16.\n");
+                       goto badsecs;
+               }
+#endif
+               if ((tflags & (TI_RAW|TI_RAW16|TI_RAW96R)) == TI_RAW && (cdflags & CDR_SRAW96P) == 0) {
+                       errmsgno(EX_BAD, "Drive does not support SAO/RAW96P.\n");
+                       goto badsecs;
+               }
+               if ((tflags & (TI_RAW|TI_RAW16|TI_RAW96R)) == (TI_RAW|TI_RAW96R) && (cdflags & CDR_SRAW96R) == 0) {
+                       errmsgno(EX_BAD, "Drive does not support SAO/RAW96R.\n");
+                       goto badsecs;
+               }
+       }
+       if ((wmode & F_RAW) != 0) {
+               if ((cdflags & CDR_RAW) == 0) {
+                       errmsgno(EX_BAD, "Drive does not support RAW recording.\n");
+                       return (FALSE);
+               }
+               if ((tflags & TI_RAW16) != 0 && (cdflags & CDR_RAW16) == 0) {
+                       errmsgno(EX_BAD, "Drive does not support RAW/RAW16.\n");
+                       goto badsecs;
+               }
+               if ((tflags & (TI_RAW|TI_RAW16|TI_RAW96R)) == TI_RAW && (cdflags & CDR_RAW96P) == 0) {
+                       errmsgno(EX_BAD, "Drive does not support RAW/RAW96P.\n");
+                       goto badsecs;
+               }
+               if ((tflags & (TI_RAW|TI_RAW16|TI_RAW96R)) == (TI_RAW|TI_RAW96R) && (cdflags & CDR_RAW96R) == 0) {
+                       errmsgno(EX_BAD, "Drive does not support RAW/RAW96R.\n");
+                       goto badsecs;
+               }
+       }
+       return (TRUE);
+
+badsecs:
+       if ((wmode & F_SAO) != 0)
+               cdflags &= ~(CDR_RAW16|CDR_RAW96P|CDR_RAW96R);
+       if ((wmode & F_RAW) != 0)
+               cdflags &= ~(CDR_SRAW96P|CDR_SRAW96R);
+
+       if ((cdflags & (CDR_SRAW96R|CDR_RAW96R)) != 0)
+               errmsgno(EX_BAD, "Try -raw96r option.\n");
+       else if ((cdflags & (CDR_SRAW96P|CDR_RAW96P)) != 0)
+               errmsgno(EX_BAD, "Try -raw96p option.\n");
+       else if ((cdflags & CDR_RAW16) != 0)
+               errmsgno(EX_BAD, "Try -raw16 option.\n");
+       return (FALSE);
+}
+
+static void 
+set_wrmode(cdr_t *dp, int wmode, int tflags)
+{
+       dstat_t *dsp = dp->cdr_dstat;
+
+       if ((tflags & TI_PACKET) != 0) {
+               dsp->ds_wrmode = WM_PACKET;
+               return;
+       }
+       if ((tflags & TI_TAO) != 0) {
+               dsp->ds_wrmode = WM_TAO;
+               return;
+       }
+       if ((wmode & F_SAO) != 0) {
+               if ((tflags & (TI_RAW|TI_RAW16|TI_RAW96R)) == 0) {
+                       dsp->ds_wrmode = WM_SAO;
+                       return;
+               }
+               if ((tflags & TI_RAW16) != 0) {         /* Is this needed? */
+                       dsp->ds_wrmode = WM_SAO_RAW16;
+                       return;
+               }
+               if ((tflags & (TI_RAW|TI_RAW16|TI_RAW96R)) == TI_RAW) {
+                       dsp->ds_wrmode = WM_SAO_RAW96P;
+                       return;
+               }
+               if ((tflags & (TI_RAW|TI_RAW16|TI_RAW96R)) == (TI_RAW|TI_RAW96R)) {
+                       dsp->ds_wrmode = WM_SAO_RAW96R;
+                       return;
+               }
+       }
+       if ((wmode & F_RAW) != 0) {
+               if ((tflags & TI_RAW16) != 0) {
+                       dsp->ds_wrmode = WM_RAW_RAW16;
+                       return;
+               }
+               if ((tflags & (TI_RAW|TI_RAW16|TI_RAW96R)) == TI_RAW) {
+                       dsp->ds_wrmode = WM_RAW_RAW96P;
+                       return;
+               }
+               if ((tflags & (TI_RAW|TI_RAW16|TI_RAW96R)) == (TI_RAW|TI_RAW96R)) {
+                       dsp->ds_wrmode = WM_RAW_RAW96R;
+                       return;
+               }
+       }
+       dsp->ds_wrmode = WM_NONE;
+}
+
+#if    defined(linux) || defined(__linux) || defined(__linux__)
+#ifdef HAVE_UNAME
+#include <sys/utsname.h>
+#endif
+#endif
+
+#ifdef __linux__
+static int 
+get_cap(cap_value_t cap_array)
+{ 
+         int ret;
+         cap_t capa;
+         capa = cap_get_proc();
+         cap_set_flag(capa, CAP_EFFECTIVE,  1, &cap_array, CAP_SET);
+         ret = cap_set_proc(capa);
+         cap_free(capa);
+         return ret; 
+}
+#endif
diff --git a/wodim/wodim.dfl b/wodim/wodim.dfl
new file mode 100644 (file)
index 0000000..41c4201
--- /dev/null
@@ -0,0 +1,48 @@
+# wodim.dfl Copyright 2006 E. Bloch
+# Based on cdrecord.dfl (Copyright 1998 J. Schilling)
+#
+# This file is /etc/wodim.conf
+# It contains defaults that are used if no command line option
+# or environment is present.
+# 
+# The default device, if not specified elsewhere.
+#
+#CDR_DEVICE=yamaha
+CDR_DEVICE=cdrom
+
+# 
+# The default speed, if not specified elswhere.
+#
+# For MMC compliant drives, the default is to write at maximum speed, so it in
+# general does not make sense to set up a default speed in /etc/wodim.conf.
+#
+#CDR_SPEED=40
+
+# 
+# The default FIFO size if, not specified elswhere.
+#
+CDR_FIFOSIZE=12m
+
+#
+# CDR_MAXFIFOSIZE can limit the maximum allowed FIFO size. This is useful to
+# not let mallicious users allocate too much system memory if no ulimit is set
+# or wodim runs with suid-root permissions.
+#
+# CDR_MAXFIFOSIZE=256m
+
+#
+# The following definitions allow abstract device names.  They are used if the
+# device name does not contain the the characters ',', ':', '/' and '@'
+#
+# Unless you have a good reason, use speed == -1 and let wodim use its internal
+# drive specific defaults.
+#
+# drive name   device  speed   fifosize driveropts
+#
+#default=      USCSI:1,0,0     -1      -1      burnfree
+#sanyo=                1,4,0   -1      -1      burnfree
+#cdrom=                0,6,0   2       1m      ""
+#remote=               REMOTE:rscsi@somehost:1,0,0     16      32m     burnfree
+#
+cdrom=          -1      -1      -1      burnfree
+
diff --git a/wodim/wodim.h b/wodim/wodim.h
new file mode 100644 (file)
index 0000000..0dfdfdc
--- /dev/null
@@ -0,0 +1,1212 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)cdrecord.h      1.165 05/06/11 Copyright 1995-2005 J. Schilling */
+/*
+ *     Definitions for cdrecord
+ *
+ *     Copyright (c) 1995-2005 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * Make sure it is there. We need it for off_t.
+ */
+#ifndef        _INCL_SYS_TYPES_H
+#include <sys/types.h>
+#define        _INCL_SYS_TYPES_H
+#endif
+
+#ifndef        _UTYPES_H
+#include <utypes.h>
+#endif
+
+/*
+ * Defines for command line option flags
+ */
+#define        F_DUMMY         0x00000001L     /* Do dummy (simulation) writes */
+#define        F_TOC           0x00000002L     /* Get TOC */
+#define        F_EJECT         0x00000004L     /* Eject disk after doing the work */
+#define        F_LOAD          0x00000008L     /* Load disk only */
+#define        F_MULTI         0x00000010L     /* Create linkable TOC/multi-session */
+#define        F_MSINFO        0x00000020L     /* Get multi-session info */
+#define        F_FIX           0x00000040L     /* Fixate disk only */
+#define        F_NOFIX         0x00000080L     /* Do not fixate disk */
+#define        F_VERSION       0x00000100L     /* Print version info */
+#define        F_CHECKDRIVE    0x00000200L     /* Check for driver */
+#define        F_INQUIRY       0x00000400L     /* Do inquiry */
+#define        F_PRCAP         0x00000800L     /* Print capabilities */
+#define        F_SCANBUS       0x00001000L     /* Scan SCSI Bus */
+#define        F_RESET         0x00002000L     /* Reset SCSI Bus */
+#define        F_BLANK         0x00004000L     /* Blank CD-RW */
+#define        F_PRATIP        0x00008000L     /* Print ATIP info */
+#define        F_PRDINFO       0x00010000L     /* Print disk info (XXX not yet used)  */
+#define        F_IGNSIZE       0x00020000L     /* Ignore disk size */
+#define        F_SAO           0x00040000L     /* Session at once */
+#define        F_RAW           0x00080000L     /* Raw mode */
+#define        F_WRITE         0x00100000L     /* Disk is going to be written */
+#define        F_FORCE         0x00200000L     /* Force things (e.g. blank on dead disk)  */
+#define        F_WAITI         0x00400000L     /* Wait until data is available on stdin */
+#define        F_OVERBURN      0x00800000L     /* Allow oveburning */
+#define        F_CLONE         0x01000000L     /* Do clone writing */
+#define        F_STDIN         0x02000000L     /* We are using stdin as CD data */
+#define        F_IMMED         0x04000000L     /* Try tu use IMMED SCSI flag if possible */
+#define        F_DLCK          0x08000000L     /* Load disk and lock door */
+#define        F_SETDROPTS     0x10000000L     /* Set driver opts and exit */
+#define        F_FORMAT        0x20000000L     /* Format media */
+#define        F_ABORT         0x40000000L     /* Send abort sequence to drive */
+
+#ifdef min
+#undef min
+#endif
+#define        min(a, b)       ((a) < (b) ? (a):(b))
+
+#ifdef max
+#undef max
+#endif
+#define        max(a, b)       ((a) < (b) ? (b):(a))
+
+#undef roundup
+#define        roundup(x, y)   ((((x)+((y)-1))/(y))*(y))
+
+/*
+ * NOTICE:     You should not make CDR_BUF_SIZE more than
+ *             the buffer size of the CD-Recorder.
+ *
+ * The Philips CDD 521 is the recorder with the smallest buffer.
+ * It only has 256kB of buffer RAM.
+ *
+ * WARNING:    Philips CDD 521 dies if CDR_BUF_SIZE is to big.
+ *             If you like to support the CDD 521 keep the buffer
+ *             at 63kB.
+ */
+/*#define      CDR_BUF_SIZE    (126*1024)*/
+#define        CDR_BUF_SIZE            (63*1024)
+#define        CDR_MAX_BUF_SIZE        (256*1024)
+
+/*
+ * Never set MIN_GRACE_TIME < 3 seconds. We need to give
+ * the volume management a chance to settle before we
+ * start writing.
+ */
+#ifndef        MIN_GRACE_TIME
+#define        MIN_GRACE_TIME  0               /* changed to 0, there is no point in forcing it in this application. Fix your volume management if it breaks because it could not read the medium. */
+#endif
+#ifndef        GRACE_TIME
+#define        GRACE_TIME      4
+#endif
+
+/*
+ * Some sector sizes used for reading/writing ...
+ */
+#define        DATA_SEC_SIZE   2048            /* 2048 bytes */
+#define        MODE2_SEC_SIZE  2336            /* 2336 bytes */
+#define        AUDIO_SEC_SIZE  2352            /* 2352 bytes */
+#define        RAW16_SEC_SIZE  (2352+16)       /* 2368 bytes */
+#define        RAW96_SEC_SIZE  (2352+96)       /* 2448 bytes */
+
+#define        MAX_TRACK       99      /* Red Book track limit */
+
+#define        PAD_SECS        15      /* NOTE: pad must be less than BUF_SIZE */
+#define        PAD_SIZE        (PAD_SECS * DATA_SEC_SIZE)
+
+/*
+ * FIFO size must be at least 2x CDR_MAX_BUF_SIZE
+ */
+#define        DEFAULT_FIFOSIZE (4L*1024L*1024L)
+
+#if    !defined(HAVE_LARGEFILES) && SIZEOF_LLONG > SIZEOF_LONG
+typedef        Llong   tsize_t;
+#else
+typedef        off_t   tsize_t;
+#endif
+
+#ifdef nono
+typedef struct tindex {
+       int     dummy;          /* Not yet implemented */
+} tindex_t;
+#endif
+
+typedef struct ofile {
+       struct ofile *next;     /* Next open file                       */
+       int     f;              /* Open file                            */
+       char    *filename;      /* File name                            */
+       int     refcnt;         /* open reference count                 */
+} ofile_t;
+
+typedef struct track {
+       void    *xfp;           /* Open file for this track from xopen()*/
+       char    *filename;      /* File name for this track             */
+
+       tsize_t itracksize;     /* Size of track bytes (-1 == until EOF)*/
+                               /* This is in units of isecsize         */
+       tsize_t tracksize;      /* Size of track bytes (-1 == until EOF)*/
+                               /* This is in units of secsize          */
+
+       long    trackstart;     /* Start sector # of this track         */
+       long    tracksecs;      /* Size of this track (sectors)         */
+       long    padsecs;        /* Pad size for this track (sectors)    */
+       long    pregapsize;     /* Pre-gap size for this track (sectors)*/
+       long    index0start;    /* Index 0 start within this tr(sectors)*/
+       int     isecsize;       /* Read input sector size for this track*/
+       int     secsize;        /* Sector size for this track (bytes)   */
+       int     secspt;         /* # of sectors to copy for one transfer*/
+       int     pktsize;        /* # of blocks per write packet         */
+       Uchar   dataoff;        /* offset of user data in raw sector    */
+       Uchar   tracks;         /* Number of tracks on this disk        */
+       Uchar   track;          /* Track # as offset in track[] array   */
+       Uchar   trackno;        /* Track # on disk for this track       */
+       Uchar   tracktype;      /* Track type (toc type)                */
+       Uchar   dbtype;         /* Data block type for this track       */
+       int     sectype;        /* Sector type                          */
+       int     flags;          /* Flags (see below)                    */
+       int     nindex;         /* Number of indices for track          */
+       long    *tindex;        /* Track index descriptor               */
+       char    *isrc;          /* ISRC code for this track / disk MCN  */
+       void    *text;          /* Opaque CD-Text data (txtptr_t *)     */
+} track_t;
+
+#define        track_base(tp)  ((tp) - (tp)->track)
+
+/*
+ * Defines for tp->flags
+ */
+#define        TI_AUDIO        0x00001 /* File is an audio track               */
+#define        TI_PREEMP       0x00002 /* Audio track recorded w/preemphasis   */
+#define        TI_MIX          0x00004 /* This is a mixed mode track           */
+#define        TI_RAW          0x00008 /* Write this track in raw mode         */
+#define        TI_PAD          0x00010 /* Pad data track                       */
+#define        TI_SWAB         0x00020 /* Swab audio data                      */
+#define        TI_ISOSIZE      0x00040 /* Use iso size for track               */
+#define        TI_NOAUHDR      0x00080 /* Don't look for audio header          */
+#define        TI_FIRST        0x00100 /* This is the first track              */
+#define        TI_LAST         0x00200 /* This is the last track               */
+#define        TI_PACKET       0x00400 /* Fixed- or variable-packet track      */
+#define        TI_NOCLOSE      0x00800 /* Don't close the track after writing  */
+#define        TI_TAO          0x01000 /* This track is written in TAO mode    */
+#define        TI_PREGAP       0x02000 /* Prev. track incl. pregap of this tr. */
+#define        TI_SCMS         0x04000 /* Force to follow the SCMS rules       */
+#define        TI_COPY         0x08000 /* Allow digital copy                   */
+#define        TI_SHORT_TRACK  0x10000 /* Ignore min 4 second Red Book std.    */
+#define        TI_RAW16        0x20000 /* This track uses 16 bytes subch.      */
+#define        TI_RAW96R       0x40000 /* This track uses 96 bytes RAW subch.  */
+#define        TI_CLONE        0x80000 /* Special clone treatment needed       */
+#define        TI_TEXT         0x100000 /* This track holds CD-Text information */
+#define        TI_DVD          0x200000 /* We are writing a DVD track          */
+#define        TI_SAO          0x400000 /* This track is written in SAO mode   */
+#define        TI_USEINFO      0x800000 /* Use information from *.inf files    */
+#define        TI_QUADRO       0x1000000 /* Four Channel Audio Data            */
+
+
+#define        is_audio(tp)    (((tp)->flags & TI_AUDIO) != 0)
+#define        is_preemp(tp)   (((tp)->flags & TI_PREEMP) != 0)
+#define        is_pad(tp)      (((tp)->flags & TI_PAD) != 0)
+#define        is_swab(tp)     (((tp)->flags & TI_SWAB) != 0)
+#define        is_first(tp)    (((tp)->flags & TI_FIRST) != 0)
+#define        is_last(tp)     (((tp)->flags & TI_LAST) != 0)
+#define        is_packet(tp)   (((tp)->flags & TI_PACKET) != 0)
+#define        is_noclose(tp)  (((tp)->flags & TI_NOCLOSE) != 0)
+#define        is_tao(tp)      (((tp)->flags & TI_TAO) != 0)
+#define        is_sao(tp)      (((tp)->flags & TI_SAO) != 0)
+#define        is_raw(tp)      (((tp)->flags & TI_RAW) != 0)
+#define        is_raw16(tp)    (((tp)->flags & TI_RAW16) != 0)
+#define        is_raw96(tp)    (((tp)->flags & (TI_RAW|TI_RAW16)) == TI_RAW)
+#define        is_raw96p(tp)   (((tp)->flags & (TI_RAW|TI_RAW16|TI_RAW96R)) == TI_RAW)
+#define        is_raw96r(tp)   (((tp)->flags & (TI_RAW|TI_RAW16|TI_RAW96R)) == (TI_RAW|TI_RAW96R))
+#define        is_pregap(tp)   (((tp)->flags & TI_PREGAP) != 0)
+#define        is_scms(tp)     (((tp)->flags & TI_SCMS) != 0)
+#define        is_copy(tp)     (((tp)->flags & TI_COPY) != 0)
+#define        is_shorttrk(tp) (((tp)->flags & TI_SHORT_TRACK) != 0)
+#define        is_clone(tp)    (((tp)->flags & TI_CLONE) != 0)
+#define        is_text(tp)     (((tp)->flags & TI_TEXT) != 0)
+#define        is_quadro(tp)   (((tp)->flags & TI_QUADRO) != 0)
+
+/*
+ * Defines for toc type / track type
+ */
+#define        TOC_DA          0       /* CD-DA                                */
+#define        TOC_ROM         1       /* CD-ROM                               */
+#define        TOC_XA1         2       /* CD_ROM XA with first track in mode 1 */
+#define        TOC_XA2         3       /* CD_ROM XA with first track in mode 2 */
+#define        TOC_CDI         4       /* CDI                                  */
+
+#define        TOC_MASK        7       /* Mask needed for toctname[]           */
+
+/*
+ * Additional flags in toc type / trackp->tracktype
+ * XXX TOCF_DUMMY istr schon in dp->cdr_cmdflags & F_DUMMY
+ * XXX TOCF_MULTI istr schon in dp->cdr_cmdflags & F_MULTI
+ */
+#define        TOCF_DUMMY      0x10    /* Write in dummy (simulation) mode     */
+#define        TOCF_MULTI      0x20    /* Multisession (Open Next Programarea) */
+
+#define        TOCF_MASK       0xF0    /* All possible flags in tracktype      */
+
+extern char    *toc2name[];    /* Convert toc type to name             */
+extern int     toc2sess[];     /* Convert toc type to session format   */
+
+/*
+ * Defines for sector type
+ *
+ * Mode is 2 bits
+ * Aud  is 1 bit
+ *
+ * Sector is: aud << 2 | mode
+ */
+#define        ST_ROM_MODE1    1       /* CD-ROM in mode 1 (vanilla cdrom)     */
+#define        ST_ROM_MODE2    2       /* CD-ROM in mode 2                     */
+#define        ST_AUDIO_NOPRE  4       /* CD-DA stereo without preemphasis     */
+#define        ST_AUDIO_PRE    5       /* CD-DA stereo with preemphasis        */
+
+#define        ST_PREEMPMASK   0x01    /* Mask for preemphasis bit             */
+#define        ST_AUDIOMASK    0x04    /* Mask for audio bit                   */
+#define        ST_MODEMASK     0x03    /* Mask for mode bits in sector type    */
+#define        ST_MASK         0x07    /* Mask needed for sectname[]           */
+
+/*
+ * There are 6 different generic basic sector types.
+ */
+#define        ST_MODE_AUDIO    0x00   /* Generic Audio mode                   */
+#define        ST_MODE_0        0x10   /* Generic Zero mode                    */
+#define        ST_MODE_1        0x20   /* Generic CD-ROM mode  (ISO/IEC 10149) */
+#define        ST_MODE_2        0x30   /* Generic Mode 2       (ISO/IEC 10149) */
+#define        ST_MODE_2_FORM_1 0x40   /* Generic Mode 2 form 1                */
+#define        ST_MODE_2_FORM_2 0x50   /* Generic Mode 2 form 2                */
+#define        ST_MODE_2_MIXED  0x60   /* Generic Mode 2 mixed form (1/2)      */
+
+#define        ST_MODE_MASK     0x70   /* Mask needed to get generic sectype   */
+
+#define        ST_MODE_RAW      0x08   /* Do not touch EDC & subchannels       */
+#define        ST_NOSCRAMBLE    0x80   /* Do not srcamble sectors              */
+
+#define        SECT_AUDIO      (ST_AUDIO_NOPRE  | ST_MODE_AUDIO)
+#define        SECT_AUDIO_NOPRE (ST_AUDIO_NOPRE | ST_MODE_AUDIO)
+#define        SECT_AUDIO_PRE  (ST_AUDIO_PRE    | ST_MODE_AUDIO)
+#define        SECT_MODE_0     (ST_ROM_MODE1    | ST_MODE_0)
+#define        SECT_ROM        (ST_ROM_MODE1    | ST_MODE_1)
+#define        SECT_MODE_2     (ST_ROM_MODE2    | ST_MODE_2)
+#define        SECT_MODE_2_F1  (ST_ROM_MODE2    | ST_MODE_2_FORM_1)
+#define        SECT_MODE_2_F2  (ST_ROM_MODE2    | ST_MODE_2_FORM_2)
+#define        SECT_MODE_2_MIX (ST_ROM_MODE2    | ST_MODE_2_MIXED)
+
+extern char    *st2name[];     /* Convert sector type to name          */
+extern int     st2mode[];      /* Convert sector type to control nibble*/
+
+/*
+ * Control nibble bits:
+ *
+ * 0   with preemphasis (audio) / incremental (data)
+ * 1   digital copy permitted
+ * 2   data (not audio) track
+ * 3   4 channels (not 2)
+ */
+#define        TM_PREEM        0x1     /* Audio track with preemphasis */
+#define        TM_INCREMENTAL  0x1     /* Incremental data track       */
+#define        TM_ALLOW_COPY   0x2     /* Digital copy permitted       */
+#define        TM_DATA         0x4     /* This is a data track         */
+#define        TM_QUADRO       0x8     /* Four channel audio           */
+
+/*
+ * Adr nibble:
+ */
+#define        ADR_NONE        0       /* Sub-Q mode info not supplied         */
+#define        ADR_POS         1       /* Sub-Q encodes position data          */
+#define        ADR_MCN         2       /* Sub-Q encodes Media Catalog Number   */
+#define        ADR_ISRC        3       /* Sub-Q encodes ISRC                   */
+
+/*
+ * Defines for write type (from SCSI-3/mmc)
+ */
+#define        WT_PACKET       0x0     /* Packet writing       */
+#define        WT_TAO          0x1     /* Track at once        */
+#define        WT_SAO          0x2     /* Session at once      */
+#define        WT_RAW          0x3     /* Raw                  */
+#define        WT_RES_4        0x4     /* Reserved             */
+#define        WT_RES_5        0x5     /* Reserved             */
+#define        WT_RES_6        0x6     /* Reserved             */
+#define        WT_RES_7        0x7     /* Reserved             */
+#define        WT_RES_8        0x8     /* Reserved             */
+#define        WT_RES_9        0x9     /* Reserved             */
+#define        WT_RES_A        0xA     /* Reserved             */
+#define        WT_RES_B        0xB     /* Reserved             */
+#define        WT_RES_C        0xC     /* Reserved             */
+#define        WT_RES_D        0xD     /* Reserved             */
+#define        WT_RES_E        0xE     /* Reserved             */
+#define        WT_RES_F        0xF     /* Reserved             */
+
+/*
+ * Data block layout:
+ *
+ *     -       Sync pattern 12 Bytes:  0x00 0xFF 0xFF ... 0xFF 0xFF 0x00
+ *     -       Block header 4  Bytes:  | minute | second | frame | mode |
+ *             Mode byte:
+ *                     Bits 7, 6, 5    Run-in/Run-out/Link
+ *                     Bits 4, 3, 2    Reserved
+ *                     Bits 1, 0       Mode
+ *     -       Rest of sector see below.
+ *
+ * Mode 0 Format:
+ *     0       12   Bytes Sync header
+ *     12      4    Bytes Block header with Data mode == 0
+ *     16      2336 Bytes of zero data
+ *
+ * Mode 1 Format:
+ *     0       12   Bytes Sync header
+ *     12      4    Bytes Block header with Data mode == 1
+ *     16      2048 Bytes of user data
+ *     2064    4    Bytes CRC for Bytes 0-2063
+ *     2068    8    Bytes Zero fill
+ *     2076    172  Bytes P parity symbols
+ *     2248    104  Bytes Q parity symbols
+ *
+ * Mode 2 Format (formless):
+ *     0       12   Bytes Sync header
+ *     12      4    Bytes Block header with Data mode == 2
+ *     16      2336 Bytes of user data
+ *
+ * Mode 2 form 1 Format:
+ *     0       12   Bytes Sync header
+ *     12      4    Bytes Block header with Data mode == 2
+ *     16      4    Bytes subheader first copy
+ *     20      4    Bytes subheader second copy
+ *     24      2048 Bytes of user data
+ *     2072    4    Bytes CRC for Bytes 16-2071
+ *     2076    172  Bytes P parity symbols
+ *     2248    104  Bytes Q parity symbols
+ *
+ * Mode 2 form 2 Format:
+ *     0       12   Bytes Sync header
+ *     12      4    Bytes Block header with Data mode == 2
+ *     16      4    Bytes subheader first copy
+ *     20      4    Bytes subheader second copy
+ *     24      2324 Bytes of user data
+ *     2348    4    Bytes Optional CRC for Bytes 16-2347
+ */
+
+/*
+ * Mode Byte definitions (the 4th Byte in the Block header)
+ */
+#define        SH_MODE_DATA    0x00    /* User Data Block      */
+#define        SH_MODE_RI4     0x20    /* Fourth run in Block  */
+#define        SH_MODE_RI3     0x40    /* Third run in Block   */
+#define        SH_MODE_RI2     0x60    /* Second run in Block  */
+#define        SH_MODE_RI1     0x80    /* First run in Block   */
+#define        SH_MODE_LINK    0xA0    /* Link Block           */
+#define        SH_MODE_RO2     0xC0    /* Second run out Block */
+#define        SH_MODE_RO1     0xE0    /* First run out Block  */
+#define        SH_MODE_M0      0x00    /* Mode 0 Data          */
+#define        SH_MODE_M1      0x01    /* Mode 1 Data          */
+#define        SH_MODE_M2      0x02    /* Mode 2 Data          */
+#define        SH_MODE_MR      0x03    /* Reserved             */
+
+/*
+ * Defines for data block type (from SCSI-3/mmc)
+ *
+ * Mandatory are only:
+ *     DB_ROM_MODE1    (8)     Mode 1     (ISO/IEC 10149)
+ *     DB_XA_MODE2     (10)    Mode 2-F1  (CD-ROM XA form 1)
+ *     DB_XA_MODE2_MIX (13)    Mode 2-MIX (CD-ROM XA 1/2+subhdr)
+ */
+#define        DB_RAW          0       /* 2352 bytes of raw data                 */
+#define        DB_RAW_PQ       1       /* 2368 bytes (raw data + P/Q Subchannel) */
+#define        DB_RAW_PW       2       /* 2448 bytes (raw data + P-W Subchannel) */
+#define        DB_RAW_PW_R     3       /* 2448 bytes (raw data + P-W raw Subchannel)*/
+#define        DB_RES_4        4       /* -    Reserved                          */
+#define        DB_RES_5        5       /* -    Reserved                          */
+#define        DB_RES_6        6       /* -    Reserved                          */
+#define        DB_VU_7         7       /* -    Vendor specific                   */
+#define        DB_ROM_MODE1    8       /* 2048 bytes Mode 1 (ISO/IEC 10149)      */
+#define        DB_ROM_MODE2    9       /* 2336 bytes Mode 2 (ISO/IEC 10149)      */
+#define        DB_XA_MODE2     10      /* 2048 bytes Mode 2 (CD-ROM XA form 1)   */
+#define        DB_XA_MODE2_F1  11      /* 2056 bytes Mode 2 (CD-ROM XA form 1)   */
+#define        DB_XA_MODE2_F2  12      /* 2324 bytes Mode 2 (CD-ROM XA form 2)   */
+#define        DB_XA_MODE2_MIX 13      /* 2332 bytes Mode 2 (CD-ROM XA 1/2+subhdr) */
+#define        DB_RES_14       14      /* -    Reserved                          */
+#define        DB_VU_15        15      /* -    Vendor specific                   */
+
+extern char    *db2name[];     /* Convert data block type to name        */
+
+/*
+ * Defines for multi session type (from SCSI-3/mmc)
+ */
+#define        MS_NONE         0       /* No B0 pointer. Next session not allowed*/
+#define        MS_FINAL        1       /* B0 = FF:FF:FF. Next session not allowed*/
+#define        MS_RES          2       /* Reserved                               */
+#define        MS_MULTI        3       /* B0 = Next PA.  Next session allowed    */
+
+/*
+ * Defines for session format (from SCSI-3/mmc)
+ */
+#define        SES_DA_ROM      0x00    /* CD-DA or CD-ROM disk                   */
+#define        SES_CDI         0x10    /* CD-I disk                              */
+#define        SES_XA          0x20    /* CD-ROM XA disk                         */
+#define        SES_UNDEF       0xFF    /* Undefined disk type (read disk info)   */
+
+/*
+ * Defines for blanking of CD-RW discs (from SCSI-3/mmc)
+ */
+#define        BLANK_DISC      0x00    /* Erase the entire disc                  */
+#define        BLANK_MINIMAL   0x01    /* Erase the PMA, 1st session TOC, pregap */
+#define        BLANK_TRACK     0x02    /* Erase an incomplete track              */
+#define        BLANK_UNRESERVE 0x03    /* Unreserve a track                      */
+#define        BLANK_TAIL      0x04    /* Erase the tail of a track              */
+#define        BLANK_UNCLOSE   0x05    /* Unclose the last session               */
+#define        BLANK_SESSION   0x06    /* Erase the last session                 */
+
+/*
+ * Defines for formating DVD (custom values)
+ */
+#define        FULL_FORMAT       0x00    /* Interactive format  */
+#define        BACKGROUND_FORMAT 0x01    /* Background format   */
+#define        FORCE_FORMAT      0x02    /* Force reformat      */
+
+/*
+ * Defines for formating DVD (custom values)
+ */
+#define        FULL_FORMAT       0x00    /* Interactive format  */
+#define        BACKGROUND_FORMAT 0x01    /* Background format   */
+#define        FORCE_FORMAT      0x02    /* Force reformat      */
+
+/*
+ * Useful definitions for audio tracks
+ */
+#define        msample         (44100 * 2)             /* one 16bit audio sample */
+#define        ssample         (msample * 2)           /* one stereo sample    */
+#define        samples(v)      ((v) / ssample)         /* # of stereo samples  */
+#define        hsamples(v)     ((v) / (ssample/100))   /* 100* # of stereo samples/s*/
+#define        fsamples(v)     ((v) / (ssample/75))    /* 75* # of stereo samples/s */
+
+#define        minutes(v)      ((int)(samples(v) / 60))
+#define        seconds(v)      ((int)(samples(v) % 60))
+#define        hseconds(v)     ((int)(hsamples(v) % 100))
+#define        frames(v)       ((int)(fsamples(v) % 75))
+
+/*
+ * sector based macros
+ */
+#define        Sminutes(s)     ((int)((s) / (60*75)))
+#define        Sseconds(s)     ((int)((s) / 75))
+#define        Shseconds(s)    ((int)(((s) % 75)*100)/75)
+#define        Sframes(s)      ((int)((s) % 75))
+
+typedef struct msf {
+       char    msf_min;
+       char    msf_sec;
+       char    msf_frame;
+} msf_t;
+
+/*
+ * Definitions for read TOC/PMA/ATIP command
+ */
+#define        FMT_TOC         0
+#define        FMT_SINFO       1
+#define        FMT_FULLTOC     2
+#define        FMT_PMA         3
+#define        FMT_ATIP        4
+#define        FMT_CDTEXT      5
+
+/*
+ * Definitions for read disk information "recording flags"
+ * used in UInt16_t "ds_cdrflags".
+ */
+#define        RF_WRITE        0x0001  /* Disk is going to be written          */
+#define        RF_BLANK        0x0002  /* Disk is going to be erased           */
+#define        RF_PRATIP       0x0004  /* Print ATIP info                      */
+#define        RF_LEADIN       0x0008  /* Lead-in has been "manually" written  */
+#define        RF_BURNFREE     0x0010  /* BUFFER underrun free recording       */
+#define        RF_VARIREC      0x0020  /* Plextor VariRec                      */
+#define        RF_AUDIOMASTER  0x0040  /* Yamaha AudioMaster                   */
+#define        RF_FORCESPEED   0x0080  /* WriteSpeed forced high               */
+#define        RF_DID_STAT     0x0100  /* Already did call cdrstats()          */
+#define        RF_DID_CDRSTAT  0x0200  /* Already did call (*dp->cdr_stats)()  */
+#define        RF_WR_WAIT      0x0400  /* Wait during writing to free bus      */
+#define        RF_SINGLESESS   0x0800  /* Plextor single sess. mode            */
+#define        RF_HIDE_CDR     0x1000  /* Plextor hide CDR features            */
+#define        RF_SPEEDREAD    0x2000  /* Plextor SpeedReed                    */
+#define        RF_GIGAREC      0x4000  /* Plextor GigaRec                      */
+
+/*
+ * Definitions for read disk information "disk status"
+ * used in "ds_diskstat".
+ */
+#define        DS_EMPTY        0       /* Empty disk                           */
+#define        DS_APPENDABLE   1       /* Incomplete disk (appendable)         */
+#define        DS_COMPLETE     2       /* Complete disk (closed/no B0 pointer) */
+#define        DS_RESERVED     3       /* Reserved                             */
+
+/*
+ * Definitions for read disk information "session status"
+ * used in "ds_sessstat".
+ */
+#define        SS_EMPTY        0       /* Empty session                        */
+#define        SS_APPENDABLE   1       /* Incomplete session                   */
+#define        SS_RESERVED     2       /* Reserved                             */
+#define        SS_COMPLETE     3       /* Complete session (needs DS_COMPLETE) */
+
+/*
+ * Definitions for disk_status write mode
+ * used in "ds_wrmode".
+ */
+#define        WM_NONE         0       /* No write mode selected               */
+#define        WM_BLANK        1       /* Blanking mode                        */
+#define        WM_FORMAT       2       /* Formatting                           */
+#define        WM_PACKET       4       /* Packet writing                       */
+#define        WM_TAO          8       /* Track at Once                        */
+#define        WM_SAO          12      /* Session at Once w/ cooked sectors    */
+#define        WM_SAO_RAW16    13      /* Session at Once RAW+16 byte sectors  */
+#define        WM_SAO_RAW96P   14      /* Session at Once RAW+96P byte sectors */
+#define        WM_SAO_RAW96R   15      /* Session at Once RAW+96R byte sectors */
+#define        WM_RAW          16      /* RAW with cooked sectors is impossible*/
+#define        WM_RAW_RAW16    17      /* RAW with RAW+16 byte sectors         */
+#define        WM_RAW_RAW96P   18      /* RAW with RAW+96P byte sectors        */
+#define        WM_RAW_RAW96R   19      /* RAW with RAW+96R byte sectors        */
+
+#define        wm_base(wm)     ((wm)/4*4) /* The basic write mode for this mode */
+
+/*
+ * Definitions for disk_status flags
+ * used in UInt16_t "ds_flags".
+ */
+#define        DSF_DID_V       0x0001  /* Disk id valid                        */
+#define        DSF_DBC_V       0x0002  /* Disk bar code valid                  */
+#define        DSF_URU         0x0004  /* Disk is for unrestricted use         */
+#define        DSF_ERA         0x0008  /* Disk is erasable                     */
+#define        DSF_HIGHSP_ERA  0x0010  /* Disk is high speed erasable          */
+#define        DSF_ULTRASP_ERA 0x0020  /* Disk is ultra speed erasable         */
+#define        DSF_ULTRASPP_ERA 0x0040 /* Disk is ultra speed+ erasable        */
+
+
+#define        DSF_DVD         0x0100  /* Disk is a DVD                        */
+#define        DSF_DVD_PLUS_R  0x0200  /* Disk is a DVD+R                      */
+#define        DSF_DVD_PLUS_RW 0x0400  /* Disk is a DVD+RW                     */
+#define        DSF_NEED_FORMAT 0x0800  /* Disk needs to be formatted           */
+
+/*
+ * Definitions for disktype flags
+ */
+#define DT_CD           0x001  /*is a CD                                */
+#define DT_DVD          0x002  /*is a DVD                               */
+
+/*
+ * Definitions for disktype flags
+ */
+#define DT_CD           0x001  /*is a CD                                */
+#define DT_DVD          0x002  /*is a DVD                               */
+
+/*
+ * Definitions for disk_status disk type
+ * used in "ds_type".
+ */
+/* None defined yet */
+
+typedef        struct disk_status      dstat_t;
+
+struct disk_status {
+       UInt32_t ds_diskid;             /* Disk identification          */
+       UInt16_t ds_cdrflags;           /* Recording flags from cdrecord*/
+       UInt16_t ds_flags;              /* Disk_status flags            */
+       Uchar    ds_wrmode;             /* Selected write mode          */
+       Uchar    ds_type;               /* Abstract disk type           */
+
+       Uchar    ds_disktype;           /* Disk type (from TOC/PMA)     */
+       Uchar    ds_diskstat;           /* Disk status (MMC)            */
+       Uchar    ds_sessstat;           /* Status of last sesion (MMC)  */
+       Uchar    ds_trfirst;            /* first track #                */
+       Uchar    ds_trlast;             /* last track #                 */
+       Uchar    ds_trfirst_ls;         /* first track # in last session*/
+       Uchar    ds_barcode[8];         /* Disk bar code                */
+
+       Int32_t  ds_first_leadin;       /* Start of first lead in (ATIP)*/
+       Int32_t  ds_last_leadout;       /* Start of last lead out (ATIP)*/
+       Int32_t  ds_curr_leadin;        /* Start of next lead in        */
+       Int32_t  ds_curr_leadout;       /* Start of next lead out       */
+
+       Int32_t  ds_maxblocks;          /* # of official blocks on disk */
+       Int32_t  ds_maxrblocks;         /* # real blocks on disk        */
+       Int32_t  ds_fwa;                /* first writable addr          */
+
+       Int32_t  ds_startsec;           /* Actual start sector          */
+       Int32_t  ds_endsec;             /* Actual end sector            */
+       Int32_t  ds_buflow;             /* # of times drive buffer empty*/
+
+       UInt16_t ds_minbuf;             /* Minimum drive bufer fill rt. */
+
+       UInt16_t ds_at_min_speed;       /* The minimal ATIP write speed */
+       UInt16_t ds_at_max_speed;       /* The maximal ATIP write speed */
+       UInt16_t ds_dr_cur_rspeed;      /* The drive's cur read speed   */
+       UInt16_t ds_dr_max_rspeed;      /* The drive's max read speed   */
+       UInt16_t ds_dr_cur_wspeed;      /* The drive's cur write speed  */
+       UInt16_t ds_dr_max_wspeed;      /* The drive's max write speed  */
+       UInt16_t ds_wspeed;             /* The selected/drive wr. speed */
+};
+
+/*
+ * First approach of a CDR device abstraction layer.
+ * This interface will change as long as I did not find the
+ * optimum that fits for all devices.
+ *
+ * Called with pointer to whole track array:
+ *     cdr_send_cue()
+ *     cdr_write_leadin()
+ *     cdr_open_session()
+ *     cdr_fixate()
+ *
+ * Called with (track_t *) 0 or pointer to current track:
+ *     cdr_next_wr_address()
+ *
+ * Called with pointer to current track:
+ *     cdr_open_track()
+ *     cdr_close_track()
+ *
+ * Calling sequence:
+ *     cdr_identify()                                  May modify driver
+ *     Here, the cdr_t will be allocated and
+ *     copied to a new writable area.
+ *     cdr_attach()                                    Get drive properties
+ *     cdr_buffer_cap()
+ *     cdr_getdisktype()                               GET ATIP
+ *     cdr_init()                                      set TAO for -msinfo
+ *     cdr_check_session                               XXX ????
+ *     cdr_opt1()                                      set early options
+ *     cdr_set_speed_dummy(usalp, dp, &speed)
+ *     <---    Grace time processing goes here
+ *     { do_opc(); cdr_blank() }
+ *     cdr_opt2()                                      set late options
+ *     cdr_open_session()                              set up params (no wrt.)
+ *     do_opc()
+ *     cdr_write_leadin()                              start writing
+ *     LOOP {
+ *             cdr_open_track()
+ *             cdr_next_wr_address()                   only TAO / Packet
+ *             write_track_data()
+ *             cdr_close_track()
+ *     }
+ *     write_leadout()                         XXX should go -> driver!
+ *     cdr_fixate()
+ *     cdr_stats()
+ */
+/*--------------------------------------------------------------------------*/
+typedef        struct cdr_cmd  cdr_t;
+
+#ifdef _SCG_SCSITRANSP_H
+struct cdr_cmd {
+       int     cdr_dev;                                                /* Numerical device type */
+       UInt32_t cdr_cmdflags;                  /* Command line options */
+       UInt32_t cdr_flags;                             /* Drive related flags  */
+       UInt8_t  cdr_cdrw_support;      /* CD-RW write media types */
+       UInt16_t cdr_speeddef;                  /* Default write speed  */
+       UInt16_t cdr_speedmax;                  /* Max. write speed     */
+
+       char    *cdr_drname;                            /* Driver ID string     */
+       char    *cdr_drtext;                            /* Driver ID text       */
+       struct cd_mode_page_2A *cdr_cdcap;
+       dstat_t *cdr_dstat;
+#ifdef _SCG_SCSIREG_H
+       /* identify drive */
+       cdr_t   *(*cdr_identify)(SCSI *usalp, cdr_t *, struct scsi_inquiry *);  
+#else
+       /* identify drive */
+       cdr_t   *(*cdr_identify)(SCSI *usalp, cdr_t *, void *);         
+#endif
+       /* init error decoding etc*/
+       int     (*cdr_attach)(SCSI *usalp, cdr_t *);
+       /* init drive to useful deflts */
+       int     (*cdr_init)(SCSI *usalp, cdr_t *);
+       /* get disk type */
+       int     (*cdr_getdisktype)(SCSI *usalp, cdr_t *);
+       /* load disk */
+       int     (*cdr_load)(SCSI *usalp, cdr_t *);
+       /* unload disk */
+       int     (*cdr_unload)(SCSI *usalp, cdr_t *);    
+       /* read buffer capacity */
+       int     (*cdr_buffer_cap)(SCSI *usalp, long *sizep, long *freep);
+       /* check if recover is needed */
+       int     (*cdr_check_recovery)(SCSI *usalp, cdr_t *);
+       /* do recover */
+       int     (*cdr_recover)(SCSI *usalp, cdr_t *, int track);
+       /* set recording speed & dummy write */
+       int     (*cdr_set_speed_dummy)(SCSI *usalp, cdr_t *, int *speedp);
+       /* set sector size */
+       int     (*cdr_set_secsize)(SCSI *usalp, int secsize);
+       /* get next writable addr. */
+       int     (*cdr_next_wr_address)(SCSI *usalp, track_t *trackp, long *ap);
+       /* reserve track for future use */
+       int     (*cdr_reserve_track)(SCSI *usalp, Ulong len);
+       int     (*cdr_write_trackdata)(SCSI *usalp, caddr_t buf, long daddr, long bytecnt, 
+                                                                                 int seccnt, BOOL islast);
+       /* generate cue sheet */
+       int     (*cdr_gen_cue)(track_t *trackp, void *cuep, BOOL needgap);
+       /* send cue sheet */
+       int     (*cdr_send_cue)(SCSI *usalp, cdr_t *, track_t *trackp);
+       /* write leadin */
+       int     (*cdr_write_leadin)(SCSI *usalp, cdr_t *, track_t *trackp);
+       /* open new track */
+       int     (*cdr_open_track)(SCSI *usalp, cdr_t *, track_t *trackp);
+       /* close written track */
+       int     (*cdr_close_track)(SCSI *usalp, cdr_t *, track_t *trackp);
+       /* open new session */
+       int     (*cdr_open_session)(SCSI *usalp, cdr_t *, track_t *trackp);
+       /* really needed ??? */
+       int     (*cdr_close_session)(SCSI *usalp, cdr_t *);
+       /* abort current write */
+       int     (*cdr_abort_session)(SCSI *usalp, cdr_t *);
+       /* read session offset*/
+       int     (*cdr_session_offset)(SCSI *usalp, long *soff);
+       /* write toc on disk */
+       int     (*cdr_fixate)(SCSI *usalp, cdr_t *, track_t *trackp);
+       /* final statistics printing*/
+       int     (*cdr_stats)(SCSI *usalp, cdr_t *);
+       /* blank something */
+       int     (*cdr_blank)(SCSI *usalp, cdr_t *, long addr, int blanktype);
+       /* format media */
+       int     (*cdr_format)(SCSI *usalp, cdr_t *, int fmtflags);
+       /* Do OPC */
+       int     (*cdr_opc)(SCSI *usalp, caddr_t bp, int cnt, int doopc);
+       /* do early option processing*/
+       int     (*cdr_opt1)(SCSI *usalp, cdr_t *);
+       /* do late option processing */
+       int     (*cdr_opt2)(SCSI *usalp, cdr_t *);
+       /* calculate optimale split */
+       int     (*cdr_layer_split)(SCSI *usalp, cdr_t *, long tsize);
+       int     profile;
+       BOOL    is_dvd;
+};
+#endif
+
+/*
+ * Definitions for cdr_flags
+ */
+#define        CDR_TAO         0x01            /* Drive supports Track at once */
+#define        CDR_SAO         0x02            /* Drive supports Sess at once  */
+#define        CDR_PACKET      0x04            /* Drive supports packet writing*/
+#define        CDR_RAW         0x08            /* Drive supports raw writing   */
+#define        CDR_RAW16       0x10            /* Drive supports RAW raw16     */
+#define        CDR_RAW96P      0x20            /* Drive supports RAW raw96 pak */
+#define        CDR_RAW96R      0x40            /* Drive supports RAW raw96 raw */
+#ifdef __needed__
+#define        CDR_SRAW16      0x100           /* Drive supports SAO raw16     */
+#endif
+#define        CDR_SRAW96P     0x200           /* Drive supports SAO raw96 pak */
+#define        CDR_SRAW96R     0x400           /* Drive supports SAO raw96 raw */
+#define        CDR_SWABAUDIO   0x1000          /* Drive swabs audio data       */
+#define        CDR_ISREADER    0x2000          /* Drive is s CD-ROM reader     */
+#define        CDR_TRAYLOAD    0x4000          /* Drive loads CD with tray     */
+#define        CDR_CADDYLOAD   0x8000          /* Drive loads CD with caddy    */
+#define        CDR_NO_LOLIMIT  0x10000         /* Drive ignores lead-out limit */
+#define        CDR_DVD         0x20000         /* Drive is a DVD drive         */
+#define        CDR_SIMUL       0x40000         /* Drive is simulated           */
+#define        CDR_BURNFREE    0x80000         /* Drive sup. BUFund. free rec. */
+#define        CDR_VARIREC     0x100000        /* Drive sup. VariRec    Plex.  */
+#define        CDR_AUDIOMASTER 0x200000        /* Drive sup. AudioMaster Yamah.*/
+#define        CDR_FORCESPEED  0x400000        /* Drive sup. WriteSpeed ctl.   */
+#define        CDR_DISKTATTOO  0x800000        /* Drive sup. Yamaha DiskT@2    */
+#define        CDR_SINGLESESS  0x1000000       /* Drive sup. single sess. mode */
+#define        CDR_HIDE_CDR    0x2000000       /* Drive sup. hide CDR features */
+#define        CDR_SPEEDREAD   0x4000000       /* Drive sup. SpeedReed         */
+#define        CDR_GIGAREC     0x8000000       /* Drive sup. GigaRec    Plex.  */
+#define        CDR_MMC         0x10000000      /* Drive is MMC compliant       */
+#define        CDR_MMC2        0x20000000      /* Drive is MMC-2 compliant     */
+#define        CDR_MMC3        0x40000000      /* Drive is MMC-3 compliant     */
+#ifdef PROTOTYPES
+#define        CDR_ALLOC       0x80000000UL    /* structure is allocated       */
+#else
+#define        CDR_ALLOC       0x80000000      /* structure is allocated       */
+#endif
+
+/*
+ * Definitions for cdr_cdrw_support
+ */
+#define        CDR_CDRW_NONE   0x00            /* CD-RW writing not supported */
+#define        CDR_CDRW_MULTI  0x01            /* CD-RW multi speed supported */
+#define        CDR_CDRW_HIGH   0x02            /* CD-RW high speed supported */
+#define        CDR_CDRW_ULTRA  0x04            /* CD-RW ultra high speed supported */
+#define        CDR_CDRW_ULTRAP 0x08            /* CD-RW ultra high speed+ supported */
+#define        CDR_CDRW_ALL    0xFF            /* All bits set: unknown - support all */
+
+/*
+ * cdrecord.c
+ */
+extern int     read_buf(int f, char *bp, int size);
+extern int     fill_buf(int f, track_t *trackp, long secno, char *bp, int size);
+extern int     get_buf(int f, track_t *trackp, long secno, char **bpp, int size);
+#ifdef _SCG_SCSITRANSP_H
+extern int     write_secs(SCSI *usalp, cdr_t *dp, char *bp, long startsec, 
+                                                                 int bytespt, int secspt, BOOL islast);
+extern int     pad_track(SCSI *usalp, cdr_t *dp, track_t *trackp,
+                                                                long startsec, Llong amt,
+                                                                BOOL dolast, Llong *bytesp);
+extern void    load_media(SCSI *usalp, cdr_t *, BOOL);
+extern void    unload_media(SCSI *usalp, cdr_t *, int);
+extern void    reload_media(SCSI *usalp, cdr_t *);
+#endif
+extern void    raisepri(int);
+extern int     getnum(char *arg, long *valp);
+
+/*
+ * cd_misc.c
+ */
+extern int     from_bcd(int b);
+extern int     to_bcd(int i);
+extern long    msf_to_lba(int m, int s, int f, BOOL force_positive);
+extern BOOL    lba_to_msf(long lba, msf_t *mp);
+extern void    sec_to_msf(long sec, msf_t *mp);
+extern void    print_min_atip(long li, long lo);
+
+/*
+ * fifo.c
+ */
+extern void    init_fifo(long);
+extern BOOL    init_faio(track_t *track, int);
+extern BOOL    await_faio(void);
+extern void    kill_faio(void);
+extern int     wait_faio(void);
+extern int     faio_read_buf(int f, char *bp, int size);
+extern int     faio_get_buf(int f, char **bpp, int size);
+extern void    fifo_stats(void);
+extern int     fifo_percent(BOOL addone);
+
+/*
+ * wm_session.c
+ */
+#ifdef _SCG_SCSITRANSP_H
+extern int     write_session_data(SCSI *usalp, cdr_t *dp, track_t *trackp);
+#endif
+
+/*
+ * wm_track.c
+ */
+#ifdef _SCG_SCSITRANSP_H
+/*extern       int     write_track_data __PR((SCSI *usalp, cdr_t *dp, track_t *trackp));*/
+#endif
+
+/*
+ * wm_packet.c
+ */
+#ifdef _SCG_SCSITRANSP_H
+extern int     write_packet_data(SCSI *usalp, cdr_t *dp, track_t *trackp);
+#endif
+
+/*
+ * modes.c
+ */
+#ifdef _SCG_SCSITRANSP_H
+extern BOOL    get_mode_params(SCSI *usalp, int page, char *pagename,
+                                                                                Uchar *modep, Uchar *cmodep,
+                                                                                Uchar *dmodep, Uchar *smodep,
+                                                                                int *lenp);
+extern BOOL    set_mode_params(SCSI *usalp, char *pagename, Uchar *modep,
+                                                                                int len, int save, int secsize);
+#endif
+
+/*
+ * misc.c
+ */
+#ifdef timerclear
+extern void    timevaldiff(struct timeval *start, struct timeval *stop);
+extern void    prtimediff(const char *fmt, struct timeval *start,
+                                                                 struct timeval *stop);
+#endif
+
+/*
+ * getnum.c
+ */
+extern int     getnum(char *arg, long *valp);
+extern int     getllnum(char *arg, Llong *lvalp);
+
+/*
+ * scsi_cdr.c
+ */
+#ifdef _SCG_SCSITRANSP_H
+extern BOOL    unit_ready(SCSI *usalp);
+extern BOOL    wait_unit_ready(SCSI *usalp, int secs);
+extern BOOL    scsi_in_progress(SCSI *usalp);
+extern BOOL    cdr_underrun(SCSI *usalp);
+extern int     test_unit_ready(SCSI *usalp);
+extern int     rezero_unit(SCSI *usalp);
+extern int     request_sense(SCSI *usalp);
+extern int     request_sense_b(SCSI *usalp, caddr_t bp, int cnt);
+extern int     inquiry(SCSI *usalp, caddr_t, int);
+extern int     read_capacity(SCSI *usalp);
+#ifdef EOF     /* stdio.h has been included */
+extern void    print_capacity(SCSI *usalp, FILE *f);
+#endif
+extern int     scsi_load_unload(SCSI *usalp, int);
+extern int     scsi_prevent_removal(SCSI *usalp, int);
+extern int     scsi_start_stop_unit(SCSI *usalp, int, int, BOOL immed);
+
+#define        ROTCTL_CLV      0       /* CLV or PCAV  */
+#define        ROTCTL_CAV      1       /* True CAV     */
+
+extern int     scsi_set_speed(SCSI *usalp, int readspeed, int writespeed, 
+                                                                               int rotctl);
+extern int     scsi_get_speed(SCSI *usalp, int *readspeedp, int *writespeedp);
+extern int     qic02(SCSI *usalp, int);
+extern int     write_xscsi(SCSI *usalp, caddr_t, long, long, int);
+extern int     write_xg0(SCSI *usalp, caddr_t, long, long, int);
+extern int     write_xg1(SCSI *usalp, caddr_t, long, long, int);
+extern int     write_xg5(SCSI *usalp, caddr_t, long, long, int);
+extern int     seek_scsi(SCSI *usalp, long addr);
+extern int     seek_g0(SCSI *usalp, long addr);
+extern int     seek_g1(SCSI *usalp, long addr);
+extern int     scsi_flush_cache(SCSI *usalp, BOOL immed);
+extern int     read_buffer(SCSI *usalp, caddr_t bp, int cnt, int mode);
+extern int     write_buffer(SCSI *usalp, char *buffer, long length, int mode, 
+                                                                        int bufferid, long offset);
+extern int     read_subchannel(SCSI *usalp, caddr_t bp, int track, int cnt, 
+                                                                                int msf, int subq, int fmt);
+extern int     read_toc(SCSI *usalp, caddr_t, int, int, int, int);
+extern int     read_toc_philips(SCSI *usalp, caddr_t, int, int, int, int);
+extern int     read_header(SCSI *usalp, caddr_t, long, int, int);
+extern int     read_disk_info(SCSI *usalp, caddr_t, int);
+
+#define        TI_TYPE_LBA     0       /* Address is LBA */
+#define        TI_TYPE_TRACK   1       /* Address: 0 -> TOC, xx -> Track xx, 0xFF -> Inv Track */
+#define        TI_TYPE_SESS    2       /* Address is session # */
+extern int     read_track_info(SCSI *usalp, caddr_t, int type, int addr, int cnt);
+extern int     read_rzone_info(SCSI *usalp, caddr_t bp, int cnt);
+extern int     reserve_tr_rzone(SCSI *usalp, long size);
+extern int     read_dvd_structure(SCSI *usalp, caddr_t bp, int cnt, int addr, 
+                                                                                        int layer, int fmt);
+extern int     send_dvd_structure(SCSI *usalp, caddr_t bp, int cnt, int layer, 
+                                                                                        int fmt);
+extern int     send_opc(SCSI *usalp, caddr_t, int cnt, int doopc);
+
+#define        CL_TYPE_STOP_DEICE      0       /* Stop De-icing a DVD+RW Media */
+#define        CL_TYPE_TRACK           1       /* Close Track # */
+#define        CL_TYPE_SESSION         2       /* Close Session/Border / Stop backgrnd. format */
+#define        CL_TYPE_INTER_BORDER    3       /* Close intermediate Border */
+#define        CL_TYPE_OPEN_SESSION    4       /* Close the Open Session and Record an Extended lead-out */
+#define        CL_TYPE_FINALISE_MINRAD 5       /* Finalize the Disc with a Minimum Recorded Radius */
+#define        CL_TYPE_FINALISE        6       /* Finalize the disc */
+extern int     scsi_close_tr_session(SCSI *usalp, int type, int track, 
+                                                                                                BOOL immed);
+extern int     read_master_cue(SCSI *usalp, caddr_t bp, int sheet, int cnt);
+extern int     send_cue_sheet(SCSI *usalp, caddr_t bp, long size);
+extern int     read_buff_cap(SCSI *usalp, long *, long *);
+extern int     scsi_blank(SCSI *usalp, long addr, int blanktype, BOOL immed);
+extern BOOL    allow_atapi(SCSI *usalp, BOOL new);
+extern int     mode_select(SCSI *usalp, Uchar *, int, int, int);
+extern int     mode_sense(SCSI *usalp, Uchar *dp, int cnt, int page, int pcf);
+extern int     mode_select_sg0(SCSI *usalp, Uchar *, int, int, int);
+extern int     mode_sense_sg0(SCSI *usalp, Uchar *dp, int cnt, int page, int pcf);
+extern int     mode_select_g0(SCSI *usalp, Uchar *, int, int, int);
+extern int     mode_select_g1(SCSI *usalp, Uchar *, int, int, int);
+extern int     mode_sense_g0(SCSI *usalp, Uchar *dp, int cnt, int page, int pcf);
+extern int     mode_sense_g1(SCSI *usalp, Uchar *dp, int cnt, int page, int pcf);
+extern int     read_tochdr(SCSI *usalp, cdr_t *, int *, int *);
+extern int     read_cdtext(SCSI *usalp);
+extern int     read_trackinfo(SCSI *usalp, int, long *, struct msf *, int *, 
+                                                                               int *, int *);
+extern int     read_B0(SCSI *usalp, BOOL isbcd, long *b0p, long *lop);
+extern int     read_session_offset(SCSI *usalp, long *);
+extern int     read_session_offset_philips(SCSI *usalp, long *);
+extern int     sense_secsize(SCSI *usalp, int current);
+extern int     select_secsize(SCSI *usalp, int);
+extern BOOL    is_cddrive(SCSI *usalp);
+extern BOOL    is_unknown_dev(SCSI *usalp);
+extern int     read_scsi(SCSI *usalp, caddr_t, long, int);
+extern int     read_g0(SCSI *usalp, caddr_t, long, int);
+extern int     read_g1(SCSI *usalp, caddr_t, long, int);
+extern BOOL    getdev(SCSI *usalp, BOOL);
+#ifdef EOF     /* stdio.h has been included */
+extern void    printinq(SCSI *usalp, FILE *f);
+#endif
+extern void    printdev(SCSI *usalp);
+extern BOOL    do_inquiry(SCSI *usalp, BOOL);
+extern BOOL    recovery_needed(SCSI *usalp, cdr_t *);
+extern int     scsi_load(SCSI *usalp, cdr_t *);
+extern int     scsi_unload(SCSI *usalp, cdr_t *);
+extern int     scsi_cdr_write(SCSI *usalp, caddr_t bp, long sectaddr, 
+                                                                               long size, int blocks, BOOL islast);
+extern struct cd_mode_page_2A *mmc_cap(SCSI *usalp, Uchar *modep);
+extern void    mmc_getval(struct cd_mode_page_2A *mp, BOOL *cdrrp, BOOL *cdwrp,
+                                                                 BOOL *cdrrwp, BOOL *cdwrwp, BOOL *dvdp, BOOL *dvdwp);
+extern BOOL    is_mmc(SCSI *usalp, BOOL *cdwp, BOOL *dvdwp);
+extern BOOL    mmc_check(SCSI *usalp, BOOL *cdrrp, BOOL *cdwrp, BOOL *cdrrwp, 
+                                                                BOOL *cdwrwp, BOOL *dvdp, BOOL *dvdwp);
+extern void    print_capabilities(SCSI *usalp);
+#endif
+
+/*
+ * scsi_cdr.c
+ */
+#ifdef _SCG_SCSITRANSP_H
+extern void    print_capabilities_mmc4(SCSI *usalp);
+#endif
+
+/*
+ * scsi_mmc.c
+ */
+#ifdef _SCG_SCSITRANSP_H
+extern int     get_configuration(SCSI *usalp, caddr_t bp, int cnt, 
+                                                                                       int st_feature, int rt);
+extern int     get_curprofile(SCSI *usalp);
+extern int     print_profiles(SCSI *usalp);
+extern int     get_proflist(SCSI *usalp, BOOL *wp, BOOL *cdp, BOOL *dvdp,
+                                                                        BOOL *dvdplusp, BOOL *ddcdp);
+extern int     get_wproflist(SCSI *usalp, BOOL *cdp, BOOL *dvdp,
+                                                                         BOOL *dvdplusp, BOOL *ddcdp);
+extern char *mmc_obtain_profile_name(int profile_number);
+#endif
+
+/*
+ * scsi_mmc.c
+ */
+#ifdef _SCG_SCSITRANSP_H
+extern int     get_supported_cdrw_media_types(SCSI *usalp);
+#endif
+
+/*
+ * mmc_misc.c
+ */
+#ifdef _SCG_SCSITRANSP_H
+extern int     check_writemodes_mmc(SCSI *usalp, cdr_t *dp);
+#endif /* _SCG_SCSITRANSP_H */
+
+/*
+ * cdr_drv.c
+ */
+#ifdef _SCG_SCSITRANSP_H
+#ifdef _SCG_SCSIREG_H
+extern cdr_t   *drive_identify(SCSI *usalp, cdr_t *, struct scsi_inquiry *ip);
+#else
+extern cdr_t   *drive_identify(SCSI *usalp, cdr_t *, void *ip);
+#endif
+extern int     drive_attach(SCSI *usalp, cdr_t *);
+#endif
+extern int     attach_unknown(void);
+#ifdef _SCG_SCSITRANSP_H
+extern int     blank_dummy(SCSI *usalp, cdr_t *, long addr, int blanktype);
+int    format_dummy(SCSI *usalp, cdr_t *, int fmtflags);
+extern int     drive_getdisktype(SCSI *usalp, cdr_t *dp);
+extern int     cmd_ill(SCSI *usalp);
+extern int     cmd_dummy(SCSI *usalp, cdr_t *);
+extern int     no_sendcue(SCSI *usalp, cdr_t *, track_t *trackp);
+extern int     buf_dummy(SCSI *usalp, long *sp, long *fp);
+#endif
+extern BOOL    set_cdrcmds(char *name, cdr_t **dpp);
+#ifdef _SCG_SCSITRANSP_H
+extern cdr_t   *get_cdrcmds(SCSI *usalp);
+#endif
+
+
+/*
+ * drv_mmc.c
+ */
+extern void    mmc_opthelp(cdr_t *dp, int excode);
+extern char    *hasdrvopt(char *optstr, char *optname);
+#ifdef _SCG_SCSITRANSP_H
+extern struct ricoh_mode_page_30 *get_justlink_ricoh(SCSI *usalp, Uchar *mode);
+#endif
+
+/*
+ * isosize.c
+ */
+extern Llong   isosize(int f);
+
+/*
+ * audiosize.c
+ */
+extern BOOL    is_auname(const char *name);
+extern off_t   ausize(int f);
+extern BOOL    is_wavname(const char *name);
+extern off_t   wavsize(int f);
+
+/*
+ * auinfo.c
+ */
+extern BOOL    auinfosize(char *name, track_t *trackp);
+extern void    auinfo(char *name, int track, track_t *trackp);
+#ifdef CDTEXT_H
+extern textptr_t *gettextptr(int track, track_t *trackp);
+#endif
+extern void    setmcn(char *mcn, track_t *trackp);
+extern void    setisrc(char *isrc, track_t *trackp);
+extern void    setindex(char *tindex, track_t *trackp);
+
+/*
+ * diskid.c
+ */
+extern void    pr_manufacturer(msf_t *mp, BOOL rw, BOOL audio);
+extern int     manufacturer_id(msf_t *mp);
+extern long    disk_rcap(msf_t *mp, long maxblock, BOOL rw, BOOL audio);
+
+/*--------------------------------------------------------------------------*/
+/* Test only                                                               */
+/*--------------------------------------------------------------------------*/
+#ifdef _SCSIMMC_H
+/*extern       int     do_cue          __PR((track_t *trackp, struct mmc_cue **cuep));*/
+#else
+/*extern       int     do_cue          __PR((track_t *trackp, void *cuep));*/
+#endif
+
+/*
+ * subchan.c
+ */
+extern int     do_leadin(track_t *trackp);
+#ifdef _SCG_SCSITRANSP_H
+extern int     write_leadin(SCSI *usalp, cdr_t *dp, track_t *trackp, 
+                                                                        int leadinstart);
+extern int     write_leadout(SCSI *usalp, cdr_t *dp, track_t *trackp);
+#endif
+extern void    fillsubch(track_t *trackp, Uchar *sp, int secno, int nsecs);
+extern void    filltpoint(Uchar *sub, int ctrl_adr, int point, msf_t *mp);
+extern void    fillttime(Uchar *sub, msf_t *mp);
+extern void    qpto96(Uchar *sub, Uchar *subq, int dop);
+extern void    addrw(Uchar *sub, Uchar *subrwptr);
+extern void    qwto16(Uchar *subq, Uchar *subptr);
+extern void    subrecodesecs(track_t *trackp, Uchar *bp, int address, int nsecs);
+
+/*
+ * sector.c
+ */
+extern int     encspeed(BOOL be_verbose);
+extern void    encsectors(track_t *trackp, Uchar *bp, int address, int nsecs);
+extern void    scrsectors(track_t *trackp, Uchar *bp, int address, int nsecs);
+extern void    encodesector(Uchar *sp, int sectype, int address);
+extern void    fillsector(Uchar *sp, int sectype, int address);
+
+/*
+ * clone.c
+ */
+extern void    clone_toc(track_t *trackp);
+extern void    clone_tracktype(track_t *trackp);
+
+/*
+ * cdtext.c
+ */
+extern BOOL    checktextfile(char *fname);
+extern void    packtext(int tracks, track_t *trackp);
+#ifdef _SCG_SCSITRANSP_H
+extern int     write_cdtext(SCSI *usalp, cdr_t *dp, long startsec);
+#endif
+
+/*
+ * cue.c
+ */
+extern int     parsecue(char *cuefname, track_t trackp[]);
+#ifdef EOF     /* stdio.h has been included */
+extern void    fparsecue(FILE *f, track_t trackp[]);
+#endif
diff --git a/wodim/xio.c b/wodim/xio.c
new file mode 100644 (file)
index 0000000..04118cd
--- /dev/null
@@ -0,0 +1,164 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)xio.c   1.11 04/07/11 Copyright 2003-2004 J. Schilling */
+/*
+ *     EXtended I/O functions for cdrecord
+ *
+ *     Copyright (c) 2003-2004 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <mconfig.h>
+#include <unixstd.h>
+#include <stdxlib.h>
+#include <strdefs.h>
+#include <standard.h>
+#include <fctldefs.h>
+
+#ifdef NEED_O_BINARY
+#include <io.h>                                        /* for setmode() prototype */
+#endif
+
+#include "xio.h"
+
+static xio_t   x_stdin = {
+       NULL,           /* x_next       */
+       NULL,           /* x_name       */
+       0,              /* x_off        */
+       STDIN_FILENO,   /* x_file       */
+       999,            /* x_refcnt     */
+       O_RDONLY,       /* x_oflag      */
+       0               /* x_omode      */
+};
+
+static xio_t   *x_root = &x_stdin;
+static xio_t   **x_tail = NULL;
+
+
+static xio_t   *xnewnode(char *name);
+void   *xopen(char *name, int oflag, int mode);
+int    xclose(void *vp);
+
+static xio_t *
+xnewnode(char *name)
+{
+       xio_t   *xp;
+
+       if ((xp = malloc(sizeof (xio_t))) == NULL)
+               return ((xio_t *) NULL);
+
+       xp->x_next = (xio_t *) NULL;
+       xp->x_name = strdup(name);
+       if (xp->x_name == NULL) {
+               free(xp);
+               return ((xio_t *) NULL);
+       }
+       xp->x_off = 0;
+       xp->x_file = -1;
+       xp->x_refcnt = 1;
+       xp->x_oflag = 0;
+       xp->x_omode = 0;
+       return (xp);
+}
+
+void *
+xopen(char *name, int oflag, int mode)
+{
+       int     f;
+       xio_t   *xp;
+       xio_t   *pp = x_root;
+
+       if (x_tail == NULL)
+               x_tail = &x_stdin.x_next;
+       if (name == NULL) {
+               xp = &x_stdin;
+               xp->x_refcnt++;
+#ifdef NEED_O_BINARY
+               if ((oflag & O_BINARY) != 0) {
+                       setmode(STDIN_FILENO, O_BINARY);
+               }
+#endif
+               return (xp);
+       }
+       for (; pp; pp = pp->x_next) {
+               if (pp->x_name == NULL) /* stdin avoid core dump in strcmp() */
+                       continue;
+               if ((strcmp(pp->x_name, name) == 0) &&
+                   (pp->x_oflag == oflag) && (pp->x_omode == mode)) {
+                       break;
+               }
+       }
+       if (pp) {
+               pp->x_refcnt++;
+               return ((void *)pp);
+       }
+       if ((f = open(name, oflag, mode)) < 0)
+               return (NULL);
+
+       if ((xp = xnewnode(name)) == NULL) {
+               close(f);
+               return (NULL);
+       }
+       xp->x_file = f;
+       xp->x_oflag = oflag;
+       xp->x_omode = mode;
+       *x_tail = xp;
+       x_tail = &xp->x_next;
+       return ((void *)xp);
+}
+
+int
+xclose(void *vp)
+{
+       xio_t   *xp = vp;
+       xio_t   *pp = x_root;
+       int     ret = 0;
+
+       if (xp == &x_stdin)
+               return (ret);
+       if (x_tail == NULL)
+               x_tail = &x_stdin.x_next;
+
+       if (--xp->x_refcnt <= 0) {
+               ret = close(xp->x_file);
+               while (pp) {
+                       if (pp->x_next == xp)
+                               break;
+                       if (pp->x_next == NULL)
+                               break;
+                       pp = pp->x_next;
+               }
+               if (pp->x_next == xp) {
+                       if (x_tail == &xp->x_next)
+                               x_tail = &pp->x_next;
+                       pp->x_next = xp->x_next;
+               }
+
+               free(xp->x_name);
+               free(xp);
+       }
+       return (ret);
+}
diff --git a/wodim/xio.h b/wodim/xio.h
new file mode 100644 (file)
index 0000000..a7836b2
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)xio.h   1.2 04/03/02 Copyright 2003-2004 J. Schilling */
+/*
+ *     EXtended I/O functions for cdrecord
+ *
+ *     Copyright (c) 2003-2004 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef        _XIO_H
+#define        _XIO_H
+
+#include <utypes.h>
+
+typedef struct xio {
+       struct xio      *x_next;
+       char            *x_name;
+       Ullong          x_off;
+       int             x_file;
+       int             x_refcnt;
+       int             x_oflag;
+       int             x_omode;
+} xio_t;
+
+#define        xfileno(p)      (((xio_t *)(p))->x_file)
+
+extern void    *xopen(char *name, int oflag, int mode);
+extern int     xclose(void *vp);
+
+#endif